~ubuntu-branches/ubuntu/vivid/qtdeclarative-opensource-src-gles/vivid

« back to all changes in this revision

Viewing changes to .pc/QML-Compilation-unit-caching-and-JIT-changes.patch/src/qml/compiler/qv4isel_p.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2015-02-26 09:12:59 UTC
  • Revision ID: package-import@ubuntu.com-20150226091259-krq068zh9bwi20or
Tags: 5.4.0-0ubuntu2
Sync package with qtdeclarative-opensource-src - 5.4.0-4ubuntu2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the QtQml module of the Qt Toolkit.
 
7
**
 
8
** $QT_BEGIN_LICENSE:LGPL21$
 
9
** Commercial License Usage
 
10
** Licensees holding valid commercial Qt licenses may use this file in
 
11
** accordance with the commercial license agreement provided with the
 
12
** Software or, alternatively, in accordance with the terms contained in
 
13
** a written agreement between you and Digia. For licensing terms and
 
14
** conditions see http://qt.digia.com/licensing. For further information
 
15
** use the contact form at http://qt.digia.com/contact-us.
 
16
**
 
17
** GNU Lesser General Public License Usage
 
18
** Alternatively, this file may be used under the terms of the GNU Lesser
 
19
** General Public License version 2.1 or version 3 as published by the Free
 
20
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
 
21
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
 
22
** following information to ensure the GNU Lesser General Public License
 
23
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
 
24
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
25
**
 
26
** In addition, as a special exception, Digia gives you certain additional
 
27
** rights. These rights are described in the Digia Qt LGPL Exception
 
28
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
29
**
 
30
** $QT_END_LICENSE$
 
31
**
 
32
****************************************************************************/
 
33
 
 
34
#include "qv4jsir_p.h"
 
35
#include "qv4isel_p.h"
 
36
#include "qv4isel_util_p.h"
 
37
#include <private/qv4value_inl_p.h>
 
38
#ifndef V4_BOOTSTRAP
 
39
#include <private/qqmlpropertycache_p.h>
 
40
#endif
 
41
 
 
42
#include <QString>
 
43
 
 
44
namespace {
 
45
Q_GLOBAL_STATIC_WITH_ARGS(QTextStream, qout, (stderr, QIODevice::WriteOnly));
 
46
#define qout *qout()
 
47
} // anonymous namespace
 
48
 
 
49
using namespace QV4;
 
50
using namespace QV4::IR;
 
51
 
 
52
EvalInstructionSelection::EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
 
53
    : useFastLookups(true)
 
54
    , useTypeInference(true)
 
55
    , executableAllocator(execAllocator)
 
56
    , irModule(module)
 
57
{
 
58
    if (!jsGenerator) {
 
59
        jsGenerator = new QV4::Compiler::JSUnitGenerator(module);
 
60
        ownJSGenerator.reset(jsGenerator);
 
61
    }
 
62
    this->jsGenerator = jsGenerator;
 
63
#ifndef V4_BOOTSTRAP
 
64
    Q_ASSERT(execAllocator);
 
65
#endif
 
66
    Q_ASSERT(module);
 
67
}
 
68
 
 
69
EvalInstructionSelection::~EvalInstructionSelection()
 
70
{}
 
71
 
 
72
EvalISelFactory::~EvalISelFactory()
 
73
{}
 
74
 
 
75
QQmlRefPointer<CompiledData::CompilationUnit> EvalInstructionSelection::compile(bool generateUnitData)
 
76
{
 
77
    for (int i = 0; i < irModule->functions.size(); ++i)
 
78
        run(i);
 
79
 
 
80
    QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = backendCompileStep();
 
81
    if (generateUnitData)
 
82
        unit->data = jsGenerator->generateUnit();
 
83
    return unit;
 
84
}
 
85
 
 
86
void IRDecoder::visitMove(IR::Move *s)
 
87
{
 
88
    if (IR::Name *n = s->target->asName()) {
 
89
        if (s->source->asTemp() || s->source->asConst() || s->source->asArgLocal()) {
 
90
            setActivationProperty(s->source, *n->id);
 
91
            return;
 
92
        }
 
93
    } else if (s->target->asTemp() || s->target->asArgLocal()) {
 
94
        if (IR::Name *n = s->source->asName()) {
 
95
            if (n->id && *n->id == QStringLiteral("this")) // TODO: `this' should be a builtin.
 
96
                loadThisObject(s->target);
 
97
            else if (n->builtin == IR::Name::builtin_qml_id_array)
 
98
                loadQmlIdArray(s->target);
 
99
            else if (n->builtin == IR::Name::builtin_qml_context_object)
 
100
                loadQmlContextObject(s->target);
 
101
            else if (n->builtin == IR::Name::builtin_qml_scope_object)
 
102
                loadQmlScopeObject(s->target);
 
103
            else if (n->builtin == IR::Name::builtin_qml_imported_scripts_object)
 
104
                loadQmlImportedScripts(s->target);
 
105
            else if (n->qmlSingleton)
 
106
                loadQmlSingleton(*n->id, s->target);
 
107
            else
 
108
                getActivationProperty(n, s->target);
 
109
            return;
 
110
        } else if (IR::Const *c = s->source->asConst()) {
 
111
            loadConst(c, s->target);
 
112
            return;
 
113
        } else if (s->source->asTemp() || s->source->asArgLocal()) {
 
114
            if (s->swap)
 
115
                swapValues(s->source, s->target);
 
116
            else
 
117
                copyValue(s->source, s->target);
 
118
            return;
 
119
        } else if (IR::String *str = s->source->asString()) {
 
120
            loadString(*str->value, s->target);
 
121
            return;
 
122
        } else if (IR::RegExp *re = s->source->asRegExp()) {
 
123
            loadRegexp(re, s->target);
 
124
            return;
 
125
        } else if (IR::Closure *clos = s->source->asClosure()) {
 
126
            initClosure(clos, s->target);
 
127
            return;
 
128
        } else if (IR::New *ctor = s->source->asNew()) {
 
129
            if (Name *func = ctor->base->asName()) {
 
130
                constructActivationProperty(func, ctor->args, s->target);
 
131
                return;
 
132
            } else if (IR::Member *member = ctor->base->asMember()) {
 
133
                constructProperty(member->base, *member->name, ctor->args, s->target);
 
134
                return;
 
135
            } else if (ctor->base->asTemp() || ctor->base->asArgLocal()) {
 
136
                constructValue(ctor->base, ctor->args, s->target);
 
137
                return;
 
138
            }
 
139
        } else if (IR::Member *m = s->source->asMember()) {
 
140
            if (m->property) {
 
141
#ifdef V4_BOOTSTRAP
 
142
                Q_UNIMPLEMENTED();
 
143
#else
 
144
                bool captureRequired = true;
 
145
 
 
146
                Q_ASSERT(m->kind != IR::Member::MemberOfEnum);
 
147
                const int attachedPropertiesId = m->attachedPropertiesIdOrEnumValue;
 
148
                const bool isSingletonProperty = m->kind == IR::Member::MemberOfSingletonObject;
 
149
 
 
150
                if (_function && attachedPropertiesId == 0 && !m->property->isConstant()) {
 
151
                    if (m->kind == IR::Member::MemberOfQmlContextObject) {
 
152
                        _function->contextObjectPropertyDependencies.insert(m->property->coreIndex, m->property->notifyIndex);
 
153
                        captureRequired = false;
 
154
                    } else if (m->kind == IR::Member::MemberOfQmlScopeObject) {
 
155
                        _function->scopeObjectPropertyDependencies.insert(m->property->coreIndex, m->property->notifyIndex);
 
156
                        captureRequired = false;
 
157
                    }
 
158
                }
 
159
                getQObjectProperty(m->base, m->property->coreIndex, captureRequired, isSingletonProperty, attachedPropertiesId, s->target);
 
160
#endif // V4_BOOTSTRAP
 
161
                return;
 
162
            } else if (m->base->asTemp() || m->base->asConst() || m->base->asArgLocal()) {
 
163
                getProperty(m->base, *m->name, s->target);
 
164
                return;
 
165
            }
 
166
        } else if (IR::Subscript *ss = s->source->asSubscript()) {
 
167
            getElement(ss->base, ss->index, s->target);
 
168
            return;
 
169
        } else if (IR::Unop *u = s->source->asUnop()) {
 
170
            unop(u->op, u->expr, s->target);
 
171
            return;
 
172
        } else if (IR::Binop *b = s->source->asBinop()) {
 
173
            binop(b->op, b->left, b->right, s->target);
 
174
            return;
 
175
        } else if (IR::Call *c = s->source->asCall()) {
 
176
            if (c->base->asName()) {
 
177
                callBuiltin(c, s->target);
 
178
                return;
 
179
            } else if (Member *member = c->base->asMember()) {
 
180
                callProperty(member->base, *member->name, c->args, s->target);
 
181
                return;
 
182
            } else if (Subscript *ss = c->base->asSubscript()) {
 
183
                callSubscript(ss->base, ss->index, c->args, s->target);
 
184
                return;
 
185
            } else if (c->base->asTemp() || c->base->asArgLocal()) {
 
186
                callValue(c->base, c->args, s->target);
 
187
                return;
 
188
            }
 
189
        } else if (IR::Convert *c = s->source->asConvert()) {
 
190
            Q_ASSERT(c->expr->asTemp() || c->expr->asArgLocal());
 
191
            convertType(c->expr, s->target);
 
192
            return;
 
193
        }
 
194
    } else if (IR::Member *m = s->target->asMember()) {
 
195
        if (m->base->asTemp() || m->base->asConst() || m->base->asArgLocal()) {
 
196
            if (s->source->asTemp() || s->source->asConst() || s->source->asArgLocal()) {
 
197
                Q_ASSERT(m->kind != IR::Member::MemberOfEnum);
 
198
                const int attachedPropertiesId = m->attachedPropertiesIdOrEnumValue;
 
199
                if (m->property && attachedPropertiesId == 0) {
 
200
#ifdef V4_BOOTSTRAP
 
201
                    Q_UNIMPLEMENTED();
 
202
#else
 
203
                    setQObjectProperty(s->source, m->base, m->property->coreIndex);
 
204
#endif
 
205
                    return;
 
206
                } else {
 
207
                    setProperty(s->source, m->base, *m->name);
 
208
                    return;
 
209
                }
 
210
            }
 
211
        }
 
212
    } else if (IR::Subscript *ss = s->target->asSubscript()) {
 
213
        if (s->source->asTemp() || s->source->asConst() || s->source->asArgLocal()) {
 
214
            setElement(s->source, ss->base, ss->index);
 
215
            return;
 
216
        }
 
217
    }
 
218
 
 
219
    // For anything else...:
 
220
    Q_UNIMPLEMENTED();
 
221
    IRPrinter(&qout).print(s);
 
222
    qout << endl;
 
223
    Q_ASSERT(!"TODO");
 
224
}
 
225
 
 
226
IRDecoder::~IRDecoder()
 
227
{
 
228
}
 
229
 
 
230
void IRDecoder::visitExp(IR::Exp *s)
 
231
{
 
232
    if (IR::Call *c = s->expr->asCall()) {
 
233
        // These are calls where the result is ignored.
 
234
        if (c->base->asName()) {
 
235
            callBuiltin(c, 0);
 
236
        } else if (c->base->asTemp() || c->base->asArgLocal() || c->base->asConst()) {
 
237
            callValue(c->base, c->args, 0);
 
238
        } else if (Member *member = c->base->asMember()) {
 
239
            Q_ASSERT(member->base->asTemp() || member->base->asArgLocal());
 
240
            callProperty(member->base, *member->name, c->args, 0);
 
241
        } else if (Subscript *s = c->base->asSubscript()) {
 
242
            callSubscript(s->base, s->index, c->args, 0);
 
243
        } else {
 
244
            Q_UNREACHABLE();
 
245
        }
 
246
    } else {
 
247
        Q_UNREACHABLE();
 
248
    }
 
249
}
 
250
 
 
251
void IRDecoder::callBuiltin(IR::Call *call, Expr *result)
 
252
{
 
253
    IR::Name *baseName = call->base->asName();
 
254
    Q_ASSERT(baseName != 0);
 
255
 
 
256
    switch (baseName->builtin) {
 
257
    case IR::Name::builtin_invalid:
 
258
        callBuiltinInvalid(baseName, call->args, result);
 
259
        return;
 
260
 
 
261
    case IR::Name::builtin_typeof: {
 
262
        if (IR::Member *m = call->args->expr->asMember()) {
 
263
            callBuiltinTypeofMember(m->base, *m->name, result);
 
264
            return;
 
265
        } else if (IR::Subscript *ss = call->args->expr->asSubscript()) {
 
266
            callBuiltinTypeofSubscript(ss->base, ss->index, result);
 
267
            return;
 
268
        } else if (IR::Name *n = call->args->expr->asName()) {
 
269
            callBuiltinTypeofName(*n->id, result);
 
270
            return;
 
271
        } else if (call->args->expr->asTemp() ||
 
272
                   call->args->expr->asConst() ||
 
273
                   call->args->expr->asArgLocal()) {
 
274
            callBuiltinTypeofValue(call->args->expr, result);
 
275
            return;
 
276
        }
 
277
    } break;
 
278
 
 
279
    case IR::Name::builtin_delete: {
 
280
        if (IR::Member *m = call->args->expr->asMember()) {
 
281
            callBuiltinDeleteMember(m->base, *m->name, result);
 
282
            return;
 
283
        } else if (IR::Subscript *ss = call->args->expr->asSubscript()) {
 
284
            callBuiltinDeleteSubscript(ss->base, ss->index, result);
 
285
            return;
 
286
        } else if (IR::Name *n = call->args->expr->asName()) {
 
287
            callBuiltinDeleteName(*n->id, result);
 
288
            return;
 
289
        } else if (call->args->expr->asTemp() ||
 
290
                   call->args->expr->asArgLocal()) {
 
291
            // TODO: should throw in strict mode
 
292
            callBuiltinDeleteValue(result);
 
293
            return;
 
294
        }
 
295
    } break;
 
296
 
 
297
    case IR::Name::builtin_throw: {
 
298
        IR::Expr *arg = call->args->expr;
 
299
        Q_ASSERT(arg->asTemp() || arg->asConst() || arg->asArgLocal());
 
300
        callBuiltinThrow(arg);
 
301
    } return;
 
302
 
 
303
    case IR::Name::builtin_rethrow: {
 
304
        callBuiltinReThrow();
 
305
    } return;
 
306
 
 
307
    case IR::Name::builtin_unwind_exception: {
 
308
        callBuiltinUnwindException(result);
 
309
    } return;
 
310
 
 
311
    case IR::Name::builtin_push_catch_scope: {
 
312
        IR::String *s = call->args->expr->asString();
 
313
        Q_ASSERT(s);
 
314
        callBuiltinPushCatchScope(*s->value);
 
315
    } return;
 
316
 
 
317
    case IR::Name::builtin_foreach_iterator_object: {
 
318
        IR::Expr *arg = call->args->expr;
 
319
        Q_ASSERT(arg != 0);
 
320
        callBuiltinForeachIteratorObject(arg, result);
 
321
    } return;
 
322
 
 
323
    case IR::Name::builtin_foreach_next_property_name: {
 
324
        IR::Expr *arg = call->args->expr;
 
325
        Q_ASSERT(arg != 0);
 
326
        callBuiltinForeachNextPropertyname(arg, result);
 
327
    } return;
 
328
    case IR::Name::builtin_push_with_scope: {
 
329
        if (call->args->expr->asTemp() || call->args->expr->asArgLocal())
 
330
            callBuiltinPushWithScope(call->args->expr);
 
331
        else
 
332
            Q_UNIMPLEMENTED();
 
333
    } return;
 
334
 
 
335
    case IR::Name::builtin_pop_scope:
 
336
        callBuiltinPopScope();
 
337
        return;
 
338
 
 
339
    case IR::Name::builtin_declare_vars: {
 
340
        if (!call->args)
 
341
            return;
 
342
        IR::Const *deletable = call->args->expr->asConst();
 
343
        Q_ASSERT(deletable->type == IR::BoolType);
 
344
        for (IR::ExprList *it = call->args->next; it; it = it->next) {
 
345
            IR::Name *arg = it->expr->asName();
 
346
            Q_ASSERT(arg != 0);
 
347
            callBuiltinDeclareVar(deletable->value != 0, *arg->id);
 
348
        }
 
349
    } return;
 
350
 
 
351
    case IR::Name::builtin_define_array:
 
352
        callBuiltinDefineArray(result, call->args);
 
353
        return;
 
354
 
 
355
    case IR::Name::builtin_define_object_literal: {
 
356
        IR::ExprList *args = call->args;
 
357
        const int keyValuePairsCount = args->expr->asConst()->value;
 
358
        args = args->next;
 
359
 
 
360
        IR::ExprList *keyValuePairs = args;
 
361
        for (int i = 0; i < keyValuePairsCount; ++i) {
 
362
            args = args->next; // name
 
363
            bool isData = args->expr->asConst()->value;
 
364
            args = args->next; // isData flag
 
365
            args = args->next; // value or getter
 
366
            if (!isData)
 
367
                args = args->next; // setter
 
368
        }
 
369
 
 
370
        IR::ExprList *arrayEntries = args;
 
371
        bool needSparseArray = false;
 
372
        for (IR::ExprList *it = arrayEntries; it; it = it->next) {
 
373
            uint index = it->expr->asConst()->value;
 
374
            if (index > 16)  {
 
375
                needSparseArray = true;
 
376
                break;
 
377
            }
 
378
            it = it->next;
 
379
            bool isData = it->expr->asConst()->value;
 
380
            it = it->next;
 
381
            if (!isData)
 
382
                it = it->next;
 
383
        }
 
384
 
 
385
        callBuiltinDefineObjectLiteral(result, keyValuePairsCount, keyValuePairs, arrayEntries, needSparseArray);
 
386
    } return;
 
387
 
 
388
    case IR::Name::builtin_setup_argument_object:
 
389
        callBuiltinSetupArgumentObject(result);
 
390
        return;
 
391
 
 
392
    case IR::Name::builtin_convert_this_to_object:
 
393
        callBuiltinConvertThisToObject();
 
394
        return;
 
395
 
 
396
    default:
 
397
        break;
 
398
    }
 
399
 
 
400
    Q_UNIMPLEMENTED();
 
401
    IRPrinter(&qout).print(call); qout << endl;
 
402
    Q_ASSERT(!"TODO!");
 
403
    Q_UNREACHABLE();
 
404
}