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

« 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-03 16:35:14 UTC
  • Revision ID: package-import@ubuntu.com-20150203163514-u0cmjz42p04pu2lx
Tags: 5.3.2-0ubuntu4
Sync package with qtdeclarative-opensource-src - 5.3.2-3ubuntu3

Show diffs side-by-side

added added

removed removed

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