Move the engine and context classes into their own files
authorLars Knoll <lars.knoll@digia.com>
Sat, 17 Nov 2012 20:54:26 +0000 (21:54 +0100)
committerSimon Hausmann <simon.hausmann@digia.com>
Mon, 19 Nov 2012 09:29:07 +0000 (10:29 +0100)
Change-Id: Ie20138990908a921ca3d7475618275ed82d9cb5c
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
llvm_runtime.cpp
qmljs_engine.cpp [new file with mode: 0644]
qmljs_engine.h [new file with mode: 0644]
qmljs_environment.cpp [new file with mode: 0644]
qmljs_environment.h [new file with mode: 0644]
qmljs_objects.cpp
qmljs_objects.h
qmljs_runtime.cpp
qmljs_runtime.h
v4.pro

index aa5d70c..b911ad4 100644 (file)
@@ -40,6 +40,7 @@
 ****************************************************************************/
 
 #include "qmljs_runtime.h"
+#include "qmljs_environment.h"
 #include <stdio.h>
 #include <setjmp.h>
 
diff --git a/qmljs_engine.cpp b/qmljs_engine.cpp
new file mode 100644 (file)
index 0000000..9229dbd
--- /dev/null
@@ -0,0 +1,339 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the V4VM module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qmljs_engine.h>
+#include <qmljs_objects.h>
+#include <qv4ecmaobjects_p.h>
+
+namespace QQmlJS {
+namespace VM {
+
+ExecutionEngine::ExecutionEngine()
+{
+    rootContext = newContext();
+    rootContext->init(this);
+
+    id_length = identifier(QStringLiteral("length"));
+    id_prototype = identifier(QStringLiteral("prototype"));
+    id_constructor = identifier(QStringLiteral("constructor"));
+    id_arguments = identifier(QStringLiteral("arguments"));
+    id___proto__ = identifier(QStringLiteral("__proto__"));
+
+    objectPrototype = new ObjectPrototype();
+    stringPrototype = new StringPrototype(rootContext);
+    numberPrototype = new NumberPrototype();
+    booleanPrototype = new BooleanPrototype();
+    arrayPrototype = new ArrayPrototype();
+    datePrototype = new DatePrototype();
+    functionPrototype = new FunctionPrototype(rootContext);
+    regExpPrototype = new RegExpPrototype();
+    errorPrototype = new ErrorPrototype();
+    evalErrorPrototype = new EvalErrorPrototype(rootContext);
+    rangeErrorPrototype = new RangeErrorPrototype(rootContext);
+    referenceErrorPrototype = new ReferenceErrorPrototype(rootContext);
+    syntaxErrorPrototype = new SyntaxErrorPrototype(rootContext);
+    typeErrorPrototype = new TypeErrorPrototype(rootContext);
+    uRIErrorPrototype = new URIErrorPrototype(rootContext);
+
+    stringPrototype->prototype = objectPrototype;
+    numberPrototype->prototype = objectPrototype;
+    booleanPrototype->prototype = objectPrototype;
+    arrayPrototype->prototype = objectPrototype;
+    datePrototype->prototype = objectPrototype;
+    functionPrototype->prototype = objectPrototype;
+    regExpPrototype->prototype = objectPrototype;
+    errorPrototype->prototype = objectPrototype;
+    evalErrorPrototype->prototype = errorPrototype;
+    rangeErrorPrototype->prototype = errorPrototype;
+    referenceErrorPrototype->prototype = errorPrototype;
+    syntaxErrorPrototype->prototype = errorPrototype;
+    typeErrorPrototype->prototype = errorPrototype;
+    uRIErrorPrototype->prototype = errorPrototype;
+
+    objectCtor = Value::fromObject(new ObjectCtor(rootContext));
+    stringCtor = Value::fromObject(new StringCtor(rootContext));
+    numberCtor = Value::fromObject(new NumberCtor(rootContext));
+    booleanCtor = Value::fromObject(new BooleanCtor(rootContext));
+    arrayCtor = Value::fromObject(new ArrayCtor(rootContext));
+    functionCtor = Value::fromObject(new FunctionCtor(rootContext));
+    dateCtor = Value::fromObject(new DateCtor(rootContext));
+    regExpCtor = Value::fromObject(new RegExpCtor(rootContext));
+    errorCtor = Value::fromObject(new ErrorCtor(rootContext));
+    evalErrorCtor = Value::fromObject(new EvalErrorCtor(rootContext));
+    rangeErrorCtor = Value::fromObject(new RangeErrorCtor(rootContext));
+    referenceErrorCtor = Value::fromObject(new ReferenceErrorCtor(rootContext));
+    syntaxErrorCtor = Value::fromObject(new SyntaxErrorCtor(rootContext));
+    typeErrorCtor = Value::fromObject(new TypeErrorCtor(rootContext));
+    uRIErrorCtor = Value::fromObject(new URIErrorCtor(rootContext));
+
+    stringCtor.objectValue()->prototype = functionPrototype;
+    numberCtor.objectValue()->prototype = functionPrototype;
+    booleanCtor.objectValue()->prototype = functionPrototype;
+    arrayCtor.objectValue()->prototype = functionPrototype;
+    functionCtor.objectValue()->prototype = functionPrototype;
+    dateCtor.objectValue()->prototype = functionPrototype;
+    regExpCtor.objectValue()->prototype = functionPrototype;
+    errorCtor.objectValue()->prototype = functionPrototype;
+    evalErrorCtor.objectValue()->prototype = errorPrototype;
+    rangeErrorCtor.objectValue()->prototype = errorPrototype;
+    referenceErrorCtor.objectValue()->prototype = errorPrototype;
+    syntaxErrorCtor.objectValue()->prototype = errorPrototype;
+    typeErrorCtor.objectValue()->prototype = errorPrototype;
+    uRIErrorCtor.objectValue()->prototype = errorPrototype;
+
+    objectPrototype->init(rootContext, objectCtor);
+    stringPrototype->init(rootContext, stringCtor);
+    numberPrototype->init(rootContext, numberCtor);
+    booleanPrototype->init(rootContext, booleanCtor);
+    arrayPrototype->init(rootContext, arrayCtor);
+    datePrototype->init(rootContext, dateCtor);
+    functionPrototype->init(rootContext, functionCtor);
+    regExpPrototype->init(rootContext, regExpCtor);
+    errorPrototype->init(rootContext, errorCtor);
+    evalErrorPrototype->init(rootContext, evalErrorCtor);
+    rangeErrorPrototype->init(rootContext, rangeErrorCtor);
+    referenceErrorPrototype->init(rootContext, referenceErrorCtor);
+    syntaxErrorPrototype->init(rootContext, syntaxErrorCtor);
+    typeErrorPrototype->init(rootContext, typeErrorCtor);
+    uRIErrorPrototype->init(rootContext, uRIErrorCtor);
+
+    //
+    // set up the global object
+    //
+    VM::Object *glo = newObject(/*rootContext*/);
+    globalObject = Value::fromObject(glo);
+    rootContext->activation = glo;
+
+    glo->__put__(rootContext, identifier(QStringLiteral("Object")), objectCtor);
+    glo->__put__(rootContext, identifier(QStringLiteral("String")), stringCtor);
+    glo->__put__(rootContext, identifier(QStringLiteral("Number")), numberCtor);
+    glo->__put__(rootContext, identifier(QStringLiteral("Boolean")), booleanCtor);
+    glo->__put__(rootContext, identifier(QStringLiteral("Array")), arrayCtor);
+    glo->__put__(rootContext, identifier(QStringLiteral("Function")), functionCtor);
+    glo->__put__(rootContext, identifier(QStringLiteral("Date")), dateCtor);
+    glo->__put__(rootContext, identifier(QStringLiteral("RegExp")), regExpCtor);
+    glo->__put__(rootContext, identifier(QStringLiteral("Error")), errorCtor);
+    glo->__put__(rootContext, identifier(QStringLiteral("EvalError")), evalErrorCtor);
+    glo->__put__(rootContext, identifier(QStringLiteral("RangeError")), rangeErrorCtor);
+    glo->__put__(rootContext, identifier(QStringLiteral("ReferenceError")), referenceErrorCtor);
+    glo->__put__(rootContext, identifier(QStringLiteral("SyntaxError")), syntaxErrorCtor);
+    glo->__put__(rootContext, identifier(QStringLiteral("TypeError")), typeErrorCtor);
+    glo->__put__(rootContext, identifier(QStringLiteral("URIError")), uRIErrorCtor);
+    glo->__put__(rootContext, identifier(QStringLiteral("Math")), Value::fromObject(newMathObject(rootContext)));
+    glo->__put__(rootContext, identifier(QStringLiteral("undefined")), Value::undefinedValue());
+    glo->__put__(rootContext, identifier(QStringLiteral("NaN")), Value::fromDouble(nan("")));
+    glo->__put__(rootContext, identifier(QStringLiteral("Infinity")), Value::fromDouble(INFINITY));
+    glo->__put__(rootContext, identifier(QStringLiteral("eval")), Value::fromObject(new EvalFunction(rootContext)));
+
+
+}
+
+ExecutionContext *ExecutionEngine::newContext()
+{
+    return new ExecutionContext();
+}
+
+String *ExecutionEngine::identifier(const QString &s)
+{
+    String *&id = identifiers[s];
+    if (! id)
+        id = newString(s);
+    return id;
+}
+
+FunctionObject *ExecutionEngine::newNativeFunction(ExecutionContext *scope, void (*code)(ExecutionContext *))
+{
+    NativeFunction *f = new NativeFunction(scope, code);
+    f->prototype = scope->engine->functionPrototype;
+    return f;
+}
+
+FunctionObject *ExecutionEngine::newScriptFunction(ExecutionContext *scope, IR::Function *function)
+{
+    ScriptFunction *f = new ScriptFunction(scope, function);
+    Object *proto = scope->engine->newObject();
+    proto->__put__(scope, scope->engine->id_constructor, Value::fromObject(f));
+    f->__put__(scope, scope->engine->id_prototype, Value::fromObject(proto));
+    f->prototype = scope->engine->functionPrototype;
+    return f;
+}
+
+Object *ExecutionEngine::newObject()
+{
+    Object *object = new Object();
+    object->prototype = objectPrototype;
+    return object;
+}
+
+FunctionObject *ExecutionEngine::newObjectCtor(ExecutionContext *ctx)
+{
+    return new ObjectCtor(ctx);
+}
+
+String *ExecutionEngine::newString(const QString &s)
+{
+    return new String(s);
+}
+
+Object *ExecutionEngine::newStringObject(const Value &value)
+{
+    StringObject *object = new StringObject(value);
+    object->prototype = stringPrototype;
+    return object;
+}
+
+FunctionObject *ExecutionEngine::newStringCtor(ExecutionContext *ctx)
+{
+    return new StringCtor(ctx);
+}
+
+Object *ExecutionEngine::newNumberObject(const Value &value)
+{
+    NumberObject *object = new NumberObject(value);
+    object->prototype = numberPrototype;
+    return object;
+}
+
+FunctionObject *ExecutionEngine::newNumberCtor(ExecutionContext *ctx)
+{
+    return new NumberCtor(ctx);
+}
+
+Object *ExecutionEngine::newBooleanObject(const Value &value)
+{
+    Object *object = new BooleanObject(value);
+    object->prototype = booleanPrototype;
+    return object;
+}
+
+FunctionObject *ExecutionEngine::newBooleanCtor(ExecutionContext *ctx)
+{
+    return new BooleanCtor(ctx);
+}
+
+Object *ExecutionEngine::newFunctionObject(ExecutionContext *ctx)
+{
+    Object *object = new FunctionObject(ctx);
+    object->prototype = functionPrototype;
+    return object;
+}
+
+FunctionObject *ExecutionEngine::newFunctionCtor(ExecutionContext *ctx)
+{
+    return new FunctionCtor(ctx);
+}
+
+Object *ExecutionEngine::newArrayObject()
+{
+    ArrayObject *object = new ArrayObject();
+    object->prototype = arrayPrototype;
+    return object;
+}
+
+Object *ExecutionEngine::newArrayObject(const Array &value)
+{
+    ArrayObject *object = new ArrayObject(value);
+    object->prototype = arrayPrototype;
+    return object;
+}
+
+FunctionObject *ExecutionEngine::newArrayCtor(ExecutionContext *ctx)
+{
+    return new ArrayCtor(ctx);
+}
+
+Object *ExecutionEngine::newDateObject(const Value &value)
+{
+    Object *object = new DateObject(value);
+    object->prototype = datePrototype;
+    return object;
+}
+
+FunctionObject *ExecutionEngine::newDateCtor(ExecutionContext *ctx)
+{
+    return new DateCtor(ctx);
+}
+
+Object *ExecutionEngine::newRegExpObject(const QString &pattern, int flags)
+{
+    bool global = (flags & IR::RegExp::RegExp_Global);
+    QRegularExpression::PatternOptions options = 0;
+    if (flags & IR::RegExp::RegExp_IgnoreCase)
+        options |= QRegularExpression::CaseInsensitiveOption;
+    if (flags & IR::RegExp::RegExp_Multiline)
+        options |= QRegularExpression::MultilineOption;
+
+    Object *object = new RegExpObject(QRegularExpression(pattern, options), global);
+    object->prototype = regExpPrototype;
+    return object;
+}
+
+FunctionObject *ExecutionEngine::newRegExpCtor(ExecutionContext *ctx)
+{
+    return new RegExpCtor(ctx);
+}
+
+Object *ExecutionEngine::newErrorObject(const Value &value)
+{
+    ErrorObject *object = new ErrorObject(value);
+    object->prototype = errorPrototype;
+    return object;
+}
+
+Object *ExecutionEngine::newMathObject(ExecutionContext *ctx)
+{
+    MathObject *object = new MathObject(ctx);
+    object->prototype = objectPrototype;
+    return object;
+}
+
+Object *ExecutionEngine::newActivationObject(ExecutionContext *ctx)
+{
+    return new ActivationObject(ctx);
+}
+
+Object *ExecutionEngine::newForEachIteratorObject(Object *o)
+{
+    return new ForEachIteratorObject(o);
+}
+
+
+} // namespace VM
+} // namespace QQmlJS
diff --git a/qmljs_engine.h b/qmljs_engine.h
new file mode 100644 (file)
index 0000000..ed4b0d4
--- /dev/null
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the V4VM module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QMLJS_ENGINE_H
+#define QMLJS_ENGINE_H
+
+#include <qmljs_objects.h>
+#include <setjmp.h>
+
+namespace QQmlJS {
+namespace VM {
+
+struct Value;
+struct Array;
+struct Object;
+struct BooleanObject;
+struct NumberObject;
+struct StringObject;
+struct ArrayObject;
+struct DateObject;
+struct FunctionObject;
+struct RegExpObject;
+struct ErrorObject;
+struct ActivationObject;
+struct ArgumentsObject;
+struct ExecutionContext;
+struct ExecutionEngine;
+
+struct ObjectPrototype;
+struct StringPrototype;
+struct NumberPrototype;
+struct BooleanPrototype;
+struct ArrayPrototype;
+struct FunctionPrototype;
+struct DatePrototype;
+struct RegExpPrototype;
+struct ErrorPrototype;
+struct EvalErrorPrototype;
+struct RangeErrorPrototype;
+struct ReferenceErrorPrototype;
+struct SyntaxErrorPrototype;
+struct TypeErrorPrototype;
+struct URIErrorPrototype;
+
+struct ExecutionEngine
+{
+    ExecutionContext *rootContext;
+    Value globalObject;
+
+    Value objectCtor;
+    Value stringCtor;
+    Value numberCtor;
+    Value booleanCtor;
+    Value arrayCtor;
+    Value functionCtor;
+    Value dateCtor;
+    Value regExpCtor;
+    Value errorCtor;
+    Value evalErrorCtor;
+    Value rangeErrorCtor;
+    Value referenceErrorCtor;
+    Value syntaxErrorCtor;
+    Value typeErrorCtor;
+    Value uRIErrorCtor;
+
+    ObjectPrototype *objectPrototype;
+    StringPrototype *stringPrototype;
+    NumberPrototype *numberPrototype;
+    BooleanPrototype *booleanPrototype;
+    ArrayPrototype *arrayPrototype;
+    FunctionPrototype *functionPrototype;
+    DatePrototype *datePrototype;
+    RegExpPrototype *regExpPrototype;
+    ErrorPrototype *errorPrototype;
+    EvalErrorPrototype *evalErrorPrototype;
+    RangeErrorPrototype *rangeErrorPrototype;
+    ReferenceErrorPrototype *referenceErrorPrototype;
+    SyntaxErrorPrototype *syntaxErrorPrototype;
+    TypeErrorPrototype *typeErrorPrototype;
+    URIErrorPrototype *uRIErrorPrototype;
+
+    QHash<QString, String *> identifiers;
+
+    String *id_length;
+    String *id_prototype;
+    String *id_constructor;
+    String *id_arguments;
+    String *id___proto__;
+
+    struct ExceptionHandler {
+        ExecutionContext *context;
+        const uchar *code; // Interpreter state
+        int targetTempIndex; // Interpreter state
+        jmp_buf stackFrame;
+    };
+
+    QVector<ExceptionHandler> unwindStack;
+
+    ExecutionEngine();
+
+    ExecutionContext *newContext();
+
+    String *identifier(const QString &s);
+
+    FunctionObject *newNativeFunction(ExecutionContext *scope, void (*code)(ExecutionContext *));
+    FunctionObject *newScriptFunction(ExecutionContext *scope, IR::Function *function);
+
+    Object *newObject();
+    FunctionObject *newObjectCtor(ExecutionContext *ctx);
+
+    String *newString(const QString &s);
+    Object *newStringObject(const Value &value);
+    FunctionObject *newStringCtor(ExecutionContext *ctx);
+
+    Object *newNumberObject(const Value &value);
+    FunctionObject *newNumberCtor(ExecutionContext *ctx);
+
+    Object *newBooleanObject(const Value &value);
+    FunctionObject *newBooleanCtor(ExecutionContext *ctx);
+
+    Object *newFunctionObject(ExecutionContext *ctx);
+    FunctionObject *newFunctionCtor(ExecutionContext *ctx);
+
+    Object *newArrayObject();
+    Object *newArrayObject(const Array &value);
+    FunctionObject *newArrayCtor(ExecutionContext *ctx);
+
+    Object *newDateObject(const Value &value);
+    FunctionObject *newDateCtor(ExecutionContext *ctx);
+
+    Object *newRegExpObject(const QString &pattern, int flags);
+    FunctionObject *newRegExpCtor(ExecutionContext *ctx);
+
+    Object *newErrorObject(const Value &value);
+    Object *newMathObject(ExecutionContext *ctx);
+    Object *newActivationObject(ExecutionContext *ctx);
+
+    Object *newForEachIteratorObject(Object *o);
+};
+
+
+} // namespace VM
+} // namespace QQmlJS
+
+#endif
diff --git a/qmljs_environment.cpp b/qmljs_environment.cpp
new file mode 100644 (file)
index 0000000..550d619
--- /dev/null
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the V4VM module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qmljs_environment.h>
+#include <qmljs_objects.h>
+#include <qv4ecmaobjects_p.h>
+
+namespace QQmlJS {
+namespace VM {
+
+void ExecutionContext::init(ExecutionEngine *eng)
+{
+    engine = eng;
+    parent = 0;
+    arguments = 0;
+    argumentCount = 0;
+    locals = 0;
+    activation = 0;
+    thisObject = Value::nullValue();
+    result = Value::undefinedValue();
+    formals = 0;
+    formalCount = 0;
+    vars = 0;
+    varCount = 0;
+}
+
+PropertyDescriptor *ExecutionContext::lookupPropertyDescriptor(String *name, PropertyDescriptor *tmp)
+{
+    for (ExecutionContext *ctx = this; ctx; ctx = ctx->parent) {
+        if (ctx->activation) {
+            if (PropertyDescriptor *pd = ctx->activation->__getPropertyDescriptor__(this, name, tmp))
+                return pd;
+        }
+    }
+    return 0;
+}
+
+void ExecutionContext::inplaceBitOp(Value value, String *name, BinOp op)
+{
+    for (ExecutionContext *ctx = this; ctx; ctx = ctx->parent) {
+        if (ctx->activation) {
+            if (ctx->activation->inplaceBinOp(value, name, op, this))
+                return;
+        }
+    }
+    throwReferenceError(Value::fromString(name));
+}
+
+void ExecutionContext::throwError(Value value)
+{
+    result = value;
+    __qmljs_builtin_throw(value, this);
+}
+
+void ExecutionContext::throwError(const QString &message)
+{
+    Value v = Value::fromString(this, message);
+    throwError(Value::fromObject(engine->newErrorObject(v)));
+}
+
+void ExecutionContext::throwTypeError()
+{
+    Value v = Value::fromString(this, QStringLiteral("Type error"));
+    throwError(Value::fromObject(engine->newErrorObject(v)));
+}
+
+void ExecutionContext::throwUnimplemented(const QString &message)
+{
+    Value v = Value::fromString(this, QStringLiteral("Unimplemented ") + message);
+    throwError(Value::fromObject(engine->newErrorObject(v)));
+}
+
+void ExecutionContext::throwReferenceError(Value value)
+{
+    String *s = value.toString(this);
+    QString msg = s->toQString() + QStringLiteral(" is not defined");
+    throwError(Value::fromObject(engine->newErrorObject(Value::fromString(this, msg))));
+}
+
+void ExecutionContext::initCallContext(ExecutionContext *parent, const Value that, FunctionObject *f, Value *args, unsigned argc)
+{
+    engine = parent->engine;
+    this->parent = f->scope;
+    assert(this->parent == f->scope);
+    result = Value::undefinedValue();
+
+    if (f->needsActivation)
+        activation = engine->newActivationObject(this);
+    else
+        activation = 0;
+
+    thisObject = that;
+
+    formals = f->formalParameterList;
+    formalCount = f->formalParameterCount;
+    arguments = args;
+    argumentCount = argc;
+    if (f->needsActivation || argc < formalCount){
+        arguments = new Value[qMax(argc, formalCount)];
+        if (argc)
+            std::copy(args, args + argc, arguments);
+        if (argc < formalCount)
+            std::fill(arguments + argc, arguments + formalCount, Value::undefinedValue());
+    }
+    vars = f->varList;
+    varCount = f->varCount;
+    locals = varCount ? new Value[varCount] : 0;
+    if (varCount)
+        std::fill(locals, locals + varCount, Value::undefinedValue());
+}
+
+void ExecutionContext::leaveCallContext()
+{
+    if (activation) {
+        delete[] locals;
+        locals = 0;
+    }
+}
+
+void ExecutionContext::initConstructorContext(ExecutionContext *parent, Value that, FunctionObject *f, Value *args, unsigned argc)
+{
+    initCallContext(parent, that, f, args, argc);
+}
+
+void ExecutionContext::leaveConstructorContext(FunctionObject *f)
+{
+    wireUpPrototype(f);
+    leaveCallContext();
+}
+
+void ExecutionContext::wireUpPrototype(FunctionObject *f)
+{
+    assert(thisObject.isObject());
+    result = thisObject;
+
+    Value proto = f->__get__(this, engine->id_prototype);
+    thisObject.objectValue()->prototype = proto.objectValue();
+    if (! thisObject.isObject())
+        thisObject.objectValue()->prototype = engine->objectPrototype;
+
+}
+
+} // namespace VM
+} // namespace QQmlJS
diff --git a/qmljs_environment.h b/qmljs_environment.h
new file mode 100644 (file)
index 0000000..74568cd
--- /dev/null
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the V4VM module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QMLJS_ENVIRONMENT_H
+#define QMLJS_ENVIRONMENT_H
+
+#include <qmljs_runtime.h>
+
+namespace QQmlJS {
+namespace VM {
+
+struct Value;
+struct Object;
+struct ExecutionEngine;
+struct ExecutionContext;
+
+struct ExecutionContext {
+    ExecutionEngine *engine;
+    ExecutionContext *parent;
+    Object *activation;
+    Value thisObject;
+    Value *arguments;
+    unsigned int argumentCount;
+    Value *locals;
+    Value result;
+    String **formals;
+    unsigned int formalCount;
+    String **vars;
+    unsigned int varCount;
+
+    PropertyDescriptor *lookupPropertyDescriptor(String *name, PropertyDescriptor *tmp);
+    void inplaceBitOp(Value value, String *name, BinOp op);
+
+    inline Value argument(unsigned int index = 0)
+    {
+        if (index < argumentCount)
+            return arguments[index];
+        return Value::undefinedValue();
+    }
+
+    void init(ExecutionEngine *eng);
+
+    void initCallContext(ExecutionContext *parent, const Value that, FunctionObject *f, Value *args, unsigned argc);
+    void leaveCallContext();
+
+    void initConstructorContext(ExecutionContext *parent, Value that, FunctionObject *f, Value *args, unsigned argc);
+    void leaveConstructorContext(FunctionObject *f);
+    void wireUpPrototype(FunctionObject *f);
+
+    void throwError(Value value);
+    void throwError(const QString &message);
+    void throwTypeError();
+    void throwReferenceError(Value value);
+    void throwUnimplemented(const QString &message);
+};
+
+
+} // namespace VM
+} // namespace QQmlJS
+
+#endif
index d352774..7552a83 100644 (file)
@@ -686,292 +686,3 @@ PropertyDescriptor *ArgumentsObject::__getPropertyDescriptor__(ExecutionContext
 
     return Object::__getPropertyDescriptor__(ctx, name, to_fill);
 }
-
-ExecutionEngine::ExecutionEngine()
-{
-    rootContext = newContext();
-    rootContext->init(this);
-
-    id_length = identifier(QStringLiteral("length"));
-    id_prototype = identifier(QStringLiteral("prototype"));
-    id_constructor = identifier(QStringLiteral("constructor"));
-    id_arguments = identifier(QStringLiteral("arguments"));
-    id___proto__ = identifier(QStringLiteral("__proto__"));
-
-    objectPrototype = new ObjectPrototype();
-    stringPrototype = new StringPrototype(rootContext);
-    numberPrototype = new NumberPrototype();
-    booleanPrototype = new BooleanPrototype();
-    arrayPrototype = new ArrayPrototype();
-    datePrototype = new DatePrototype();
-    functionPrototype = new FunctionPrototype(rootContext);
-    regExpPrototype = new RegExpPrototype();
-    errorPrototype = new ErrorPrototype();
-    evalErrorPrototype = new EvalErrorPrototype(rootContext);
-    rangeErrorPrototype = new RangeErrorPrototype(rootContext);
-    referenceErrorPrototype = new ReferenceErrorPrototype(rootContext);
-    syntaxErrorPrototype = new SyntaxErrorPrototype(rootContext);
-    typeErrorPrototype = new TypeErrorPrototype(rootContext);
-    uRIErrorPrototype = new URIErrorPrototype(rootContext);
-
-    stringPrototype->prototype = objectPrototype;
-    numberPrototype->prototype = objectPrototype;
-    booleanPrototype->prototype = objectPrototype;
-    arrayPrototype->prototype = objectPrototype;
-    datePrototype->prototype = objectPrototype;
-    functionPrototype->prototype = objectPrototype;
-    regExpPrototype->prototype = objectPrototype;
-    errorPrototype->prototype = objectPrototype;
-    evalErrorPrototype->prototype = errorPrototype;
-    rangeErrorPrototype->prototype = errorPrototype;
-    referenceErrorPrototype->prototype = errorPrototype;
-    syntaxErrorPrototype->prototype = errorPrototype;
-    typeErrorPrototype->prototype = errorPrototype;
-    uRIErrorPrototype->prototype = errorPrototype;
-
-    objectCtor = Value::fromObject(new ObjectCtor(rootContext));
-    stringCtor = Value::fromObject(new StringCtor(rootContext));
-    numberCtor = Value::fromObject(new NumberCtor(rootContext));
-    booleanCtor = Value::fromObject(new BooleanCtor(rootContext));
-    arrayCtor = Value::fromObject(new ArrayCtor(rootContext));
-    functionCtor = Value::fromObject(new FunctionCtor(rootContext));
-    dateCtor = Value::fromObject(new DateCtor(rootContext));
-    regExpCtor = Value::fromObject(new RegExpCtor(rootContext));
-    errorCtor = Value::fromObject(new ErrorCtor(rootContext));
-    evalErrorCtor = Value::fromObject(new EvalErrorCtor(rootContext));
-    rangeErrorCtor = Value::fromObject(new RangeErrorCtor(rootContext));
-    referenceErrorCtor = Value::fromObject(new ReferenceErrorCtor(rootContext));
-    syntaxErrorCtor = Value::fromObject(new SyntaxErrorCtor(rootContext));
-    typeErrorCtor = Value::fromObject(new TypeErrorCtor(rootContext));
-    uRIErrorCtor = Value::fromObject(new URIErrorCtor(rootContext));
-
-    stringCtor.objectValue()->prototype = functionPrototype;
-    numberCtor.objectValue()->prototype = functionPrototype;
-    booleanCtor.objectValue()->prototype = functionPrototype;
-    arrayCtor.objectValue()->prototype = functionPrototype;
-    functionCtor.objectValue()->prototype = functionPrototype;
-    dateCtor.objectValue()->prototype = functionPrototype;
-    regExpCtor.objectValue()->prototype = functionPrototype;
-    errorCtor.objectValue()->prototype = functionPrototype;
-    evalErrorCtor.objectValue()->prototype = errorPrototype;
-    rangeErrorCtor.objectValue()->prototype = errorPrototype;
-    referenceErrorCtor.objectValue()->prototype = errorPrototype;
-    syntaxErrorCtor.objectValue()->prototype = errorPrototype;
-    typeErrorCtor.objectValue()->prototype = errorPrototype;
-    uRIErrorCtor.objectValue()->prototype = errorPrototype;
-
-    objectPrototype->init(rootContext, objectCtor);
-    stringPrototype->init(rootContext, stringCtor);
-    numberPrototype->init(rootContext, numberCtor);
-    booleanPrototype->init(rootContext, booleanCtor);
-    arrayPrototype->init(rootContext, arrayCtor);
-    datePrototype->init(rootContext, dateCtor);
-    functionPrototype->init(rootContext, functionCtor);
-    regExpPrototype->init(rootContext, regExpCtor);
-    errorPrototype->init(rootContext, errorCtor);
-    evalErrorPrototype->init(rootContext, evalErrorCtor);
-    rangeErrorPrototype->init(rootContext, rangeErrorCtor);
-    referenceErrorPrototype->init(rootContext, referenceErrorCtor);
-    syntaxErrorPrototype->init(rootContext, syntaxErrorCtor);
-    typeErrorPrototype->init(rootContext, typeErrorCtor);
-    uRIErrorPrototype->init(rootContext, uRIErrorCtor);
-
-    //
-    // set up the global object
-    //
-    VM::Object *glo = newObject(/*rootContext*/);
-    globalObject = Value::fromObject(glo);
-    rootContext->activation = glo;
-
-    glo->__put__(rootContext, identifier(QStringLiteral("Object")), objectCtor);
-    glo->__put__(rootContext, identifier(QStringLiteral("String")), stringCtor);
-    glo->__put__(rootContext, identifier(QStringLiteral("Number")), numberCtor);
-    glo->__put__(rootContext, identifier(QStringLiteral("Boolean")), booleanCtor);
-    glo->__put__(rootContext, identifier(QStringLiteral("Array")), arrayCtor);
-    glo->__put__(rootContext, identifier(QStringLiteral("Function")), functionCtor);
-    glo->__put__(rootContext, identifier(QStringLiteral("Date")), dateCtor);
-    glo->__put__(rootContext, identifier(QStringLiteral("RegExp")), regExpCtor);
-    glo->__put__(rootContext, identifier(QStringLiteral("Error")), errorCtor);
-    glo->__put__(rootContext, identifier(QStringLiteral("EvalError")), evalErrorCtor);
-    glo->__put__(rootContext, identifier(QStringLiteral("RangeError")), rangeErrorCtor);
-    glo->__put__(rootContext, identifier(QStringLiteral("ReferenceError")), referenceErrorCtor);
-    glo->__put__(rootContext, identifier(QStringLiteral("SyntaxError")), syntaxErrorCtor);
-    glo->__put__(rootContext, identifier(QStringLiteral("TypeError")), typeErrorCtor);
-    glo->__put__(rootContext, identifier(QStringLiteral("URIError")), uRIErrorCtor);
-    glo->__put__(rootContext, identifier(QStringLiteral("Math")), Value::fromObject(newMathObject(rootContext)));
-    glo->__put__(rootContext, identifier(QStringLiteral("undefined")), Value::undefinedValue());
-    glo->__put__(rootContext, identifier(QStringLiteral("NaN")), Value::fromDouble(nan("")));
-    glo->__put__(rootContext, identifier(QStringLiteral("Infinity")), Value::fromDouble(INFINITY));
-    glo->__put__(rootContext, identifier(QStringLiteral("eval")), Value::fromObject(new EvalFunction(rootContext)));
-
-
-}
-
-ExecutionContext *ExecutionEngine::newContext()
-{
-    return new ExecutionContext();
-}
-
-String *ExecutionEngine::identifier(const QString &s)
-{
-    String *&id = identifiers[s];
-    if (! id)
-        id = newString(s);
-    return id;
-}
-
-FunctionObject *ExecutionEngine::newNativeFunction(ExecutionContext *scope, void (*code)(ExecutionContext *))
-{
-    NativeFunction *f = new NativeFunction(scope, code);
-    f->prototype = scope->engine->functionPrototype;
-    return f;
-}
-
-FunctionObject *ExecutionEngine::newScriptFunction(ExecutionContext *scope, IR::Function *function)
-{
-    ScriptFunction *f = new ScriptFunction(scope, function);
-    Object *proto = scope->engine->newObject();
-    proto->__put__(scope, scope->engine->id_constructor, Value::fromObject(f));
-    f->__put__(scope, scope->engine->id_prototype, Value::fromObject(proto));
-    f->prototype = scope->engine->functionPrototype;
-    return f;
-}
-
-Object *ExecutionEngine::newObject()
-{
-    Object *object = new Object();
-    object->prototype = objectPrototype;
-    return object;
-}
-
-FunctionObject *ExecutionEngine::newObjectCtor(ExecutionContext *ctx)
-{
-    return new ObjectCtor(ctx);
-}
-
-String *ExecutionEngine::newString(const QString &s)
-{
-    return new String(s);
-}
-
-Object *ExecutionEngine::newStringObject(const Value &value)
-{
-    StringObject *object = new StringObject(value);
-    object->prototype = stringPrototype;
-    return object;
-}
-
-FunctionObject *ExecutionEngine::newStringCtor(ExecutionContext *ctx)
-{
-    return new StringCtor(ctx);
-}
-
-Object *ExecutionEngine::newNumberObject(const Value &value)
-{
-    NumberObject *object = new NumberObject(value);
-    object->prototype = numberPrototype;
-    return object;
-}
-
-FunctionObject *ExecutionEngine::newNumberCtor(ExecutionContext *ctx)
-{
-    return new NumberCtor(ctx);
-}
-
-Object *ExecutionEngine::newBooleanObject(const Value &value)
-{
-    Object *object = new BooleanObject(value);
-    object->prototype = booleanPrototype;
-    return object;
-}
-
-FunctionObject *ExecutionEngine::newBooleanCtor(ExecutionContext *ctx)
-{
-    return new BooleanCtor(ctx);
-}
-
-Object *ExecutionEngine::newFunctionObject(ExecutionContext *ctx)
-{
-    Object *object = new FunctionObject(ctx);
-    object->prototype = functionPrototype;
-    return object;
-}
-
-FunctionObject *ExecutionEngine::newFunctionCtor(ExecutionContext *ctx)
-{
-    return new FunctionCtor(ctx);
-}
-
-Object *ExecutionEngine::newArrayObject()
-{
-    ArrayObject *object = new ArrayObject();
-    object->prototype = arrayPrototype;
-    return object;
-}
-
-Object *ExecutionEngine::newArrayObject(const Array &value)
-{
-    ArrayObject *object = new ArrayObject(value);
-    object->prototype = arrayPrototype;
-    return object;
-}
-
-FunctionObject *ExecutionEngine::newArrayCtor(ExecutionContext *ctx)
-{
-    return new ArrayCtor(ctx);
-}
-
-Object *ExecutionEngine::newDateObject(const Value &value)
-{
-    Object *object = new DateObject(value);
-    object->prototype = datePrototype;
-    return object;
-}
-
-FunctionObject *ExecutionEngine::newDateCtor(ExecutionContext *ctx)
-{
-    return new DateCtor(ctx);
-}
-
-Object *ExecutionEngine::newRegExpObject(const QString &pattern, int flags)
-{
-    bool global = (flags & IR::RegExp::RegExp_Global);
-    QRegularExpression::PatternOptions options = 0;
-    if (flags & IR::RegExp::RegExp_IgnoreCase)
-        options |= QRegularExpression::CaseInsensitiveOption;
-    if (flags & IR::RegExp::RegExp_Multiline)
-        options |= QRegularExpression::MultilineOption;
-
-    Object *object = new RegExpObject(QRegularExpression(pattern, options), global);
-    object->prototype = regExpPrototype;
-    return object;
-}
-
-FunctionObject *ExecutionEngine::newRegExpCtor(ExecutionContext *ctx)
-{
-    return new RegExpCtor(ctx);
-}
-
-Object *ExecutionEngine::newErrorObject(const Value &value)
-{
-    ErrorObject *object = new ErrorObject(value);
-    object->prototype = errorPrototype;
-    return object;
-}
-
-Object *ExecutionEngine::newMathObject(ExecutionContext *ctx)
-{
-    MathObject *object = new MathObject(ctx);
-    object->prototype = objectPrototype;
-    return object;
-}
-
-Object *ExecutionEngine::newActivationObject(ExecutionContext *ctx)
-{
-    return new ActivationObject(ctx);
-}
-
-Object *ExecutionEngine::newForEachIteratorObject(Object *o)
-{
-    return new ForEachIteratorObject(o);
-}
index 963b763..ce26089 100644 (file)
@@ -42,6 +42,8 @@
 #define QMLJS_OBJECTS_H
 
 #include "qmljs_runtime.h"
+#include "qmljs_engine.h"
+#include "qmljs_environment.h"
 #include "qv4array_p.h"
 #include "qv4codegen_p.h"
 
@@ -50,7 +52,6 @@
 #include <QtCore/QRegularExpression>
 #include <cstdio>
 #include <cassert>
-#include <setjmp.h>
 
 namespace QQmlJS {
 
@@ -600,102 +601,6 @@ struct ArgumentsObject: Object {
     virtual PropertyDescriptor *__getPropertyDescriptor__(ExecutionContext *ctx, String *name, PropertyDescriptor *to_fill);
 };
 
-struct ExecutionEngine
-{
-    ExecutionContext *rootContext;
-    Value globalObject;
-
-    Value objectCtor;
-    Value stringCtor;
-    Value numberCtor;
-    Value booleanCtor;
-    Value arrayCtor;
-    Value functionCtor;
-    Value dateCtor;
-    Value regExpCtor;
-    Value errorCtor;
-    Value evalErrorCtor;
-    Value rangeErrorCtor;
-    Value referenceErrorCtor;
-    Value syntaxErrorCtor;
-    Value typeErrorCtor;
-    Value uRIErrorCtor;
-
-    ObjectPrototype *objectPrototype;
-    StringPrototype *stringPrototype;
-    NumberPrototype *numberPrototype;
-    BooleanPrototype *booleanPrototype;
-    ArrayPrototype *arrayPrototype;
-    FunctionPrototype *functionPrototype;
-    DatePrototype *datePrototype;
-    RegExpPrototype *regExpPrototype;
-    ErrorPrototype *errorPrototype;
-    EvalErrorPrototype *evalErrorPrototype;
-    RangeErrorPrototype *rangeErrorPrototype;
-    ReferenceErrorPrototype *referenceErrorPrototype;
-    SyntaxErrorPrototype *syntaxErrorPrototype;
-    TypeErrorPrototype *typeErrorPrototype;
-    URIErrorPrototype *uRIErrorPrototype;
-
-    QHash<QString, String *> identifiers;
-
-    String *id_length;
-    String *id_prototype;
-    String *id_constructor;
-    String *id_arguments;
-    String *id___proto__;
-
-    struct ExceptionHandler {
-        ExecutionContext *context;
-        const uchar *code; // Interpreter state
-        int targetTempIndex; // Interpreter state
-        jmp_buf stackFrame;
-    };
-
-    QVector<ExceptionHandler> unwindStack;
-
-    ExecutionEngine();
-
-    ExecutionContext *newContext();
-
-    String *identifier(const QString &s);
-
-    FunctionObject *newNativeFunction(ExecutionContext *scope, void (*code)(ExecutionContext *));
-    FunctionObject *newScriptFunction(ExecutionContext *scope, IR::Function *function);
-
-    Object *newObject();
-    FunctionObject *newObjectCtor(ExecutionContext *ctx);
-
-    String *newString(const QString &s);
-    Object *newStringObject(const Value &value);
-    FunctionObject *newStringCtor(ExecutionContext *ctx);
-
-    Object *newNumberObject(const Value &value);
-    FunctionObject *newNumberCtor(ExecutionContext *ctx);
-
-    Object *newBooleanObject(const Value &value);
-    FunctionObject *newBooleanCtor(ExecutionContext *ctx);
-
-    Object *newFunctionObject(ExecutionContext *ctx);
-    FunctionObject *newFunctionCtor(ExecutionContext *ctx);
-
-    Object *newArrayObject();
-    Object *newArrayObject(const Array &value);
-    FunctionObject *newArrayCtor(ExecutionContext *ctx);
-
-    Object *newDateObject(const Value &value);
-    FunctionObject *newDateCtor(ExecutionContext *ctx);
-
-    Object *newRegExpObject(const QString &pattern, int flags);
-    FunctionObject *newRegExpCtor(ExecutionContext *ctx);
-
-    Object *newErrorObject(const Value &value);
-    Object *newMathObject(ExecutionContext *ctx);
-    Object *newActivationObject(ExecutionContext *ctx);
-
-    Object *newForEachIteratorObject(Object *o);
-};
-
 } // namespace VM
 } // namespace QQmlJS
 
index ec97864..d660aaf 100644 (file)
@@ -230,138 +230,6 @@ Value Value::property(ExecutionContext *ctx, String *name) const
     return isObject() ? objectValue()->__get__(ctx, name) : undefinedValue();
 }
 
-void ExecutionContext::init(ExecutionEngine *eng)
-{
-    engine = eng;
-    parent = 0;
-    arguments = 0;
-    argumentCount = 0;
-    locals = 0;
-    activation = 0;
-    thisObject = Value::nullValue();
-    result = Value::undefinedValue();
-    formals = 0;
-    formalCount = 0;
-    vars = 0;
-    varCount = 0;
-}
-
-PropertyDescriptor *ExecutionContext::lookupPropertyDescriptor(String *name, PropertyDescriptor *tmp)
-{
-    for (ExecutionContext *ctx = this; ctx; ctx = ctx->parent) {
-        if (ctx->activation) {
-            if (PropertyDescriptor *pd = ctx->activation->__getPropertyDescriptor__(this, name, tmp))
-                return pd;
-        }
-    }
-    return 0;
-}
-
-void ExecutionContext::inplaceBitOp(Value value, String *name, BinOp op)
-{
-    for (ExecutionContext *ctx = this; ctx; ctx = ctx->parent) {
-        if (ctx->activation) {
-            if (ctx->activation->inplaceBinOp(value, name, op, this))
-                return;
-        }
-    }
-    throwReferenceError(Value::fromString(name));
-}
-
-void ExecutionContext::throwError(Value value)
-{
-    result = value;
-    __qmljs_builtin_throw(value, this);
-}
-
-void ExecutionContext::throwError(const QString &message)
-{
-    Value v = Value::fromString(this, message);
-    throwError(Value::fromObject(engine->newErrorObject(v)));
-}
-
-void ExecutionContext::throwTypeError()
-{
-    Value v = Value::fromString(this, QStringLiteral("Type error"));
-    throwError(Value::fromObject(engine->newErrorObject(v)));
-}
-
-void ExecutionContext::throwUnimplemented(const QString &message)
-{
-    Value v = Value::fromString(this, QStringLiteral("Unimplemented ") + message);
-    throwError(Value::fromObject(engine->newErrorObject(v)));
-}
-
-void ExecutionContext::throwReferenceError(Value value)
-{
-    String *s = value.toString(this);
-    QString msg = s->toQString() + QStringLiteral(" is not defined");
-    throwError(Value::fromObject(engine->newErrorObject(Value::fromString(this, msg))));
-}
-
-void ExecutionContext::initCallContext(ExecutionContext *parent, const Value that, FunctionObject *f, Value *args, unsigned argc)
-{
-    engine = parent->engine;
-    this->parent = f->scope;
-    assert(this->parent == f->scope);
-    result = Value::undefinedValue();
-
-    if (f->needsActivation)
-        activation = engine->newActivationObject(this);
-    else
-        activation = 0;
-
-    thisObject = that;
-
-    formals = f->formalParameterList;
-    formalCount = f->formalParameterCount;
-    arguments = args;
-    argumentCount = argc;
-    if (f->needsActivation || argc < formalCount){
-        arguments = new Value[qMax(argc, formalCount)];
-        if (argc)
-            std::copy(args, args + argc, arguments);
-        if (argc < formalCount)
-            std::fill(arguments + argc, arguments + formalCount, Value::undefinedValue());
-    }
-    vars = f->varList;
-    varCount = f->varCount;
-    locals = varCount ? new Value[varCount] : 0;
-    if (varCount)
-        std::fill(locals, locals + varCount, Value::undefinedValue());
-}
-
-void ExecutionContext::leaveCallContext()
-{
-    if (activation) {
-        delete[] locals;
-        locals = 0;
-    }
-}
-
-void ExecutionContext::initConstructorContext(ExecutionContext *parent, Value that, FunctionObject *f, Value *args, unsigned argc)
-{
-    initCallContext(parent, that, f, args, argc);
-}
-
-void ExecutionContext::leaveConstructorContext(FunctionObject *f)
-{
-    wireUpPrototype(f);
-    leaveCallContext();
-}
-
-void ExecutionContext::wireUpPrototype(FunctionObject *f)
-{
-    assert(thisObject.isObject());
-    result = thisObject;
-
-    Value proto = f->__get__(this, engine->id_prototype);
-    thisObject.objectValue()->prototype = proto.objectValue();
-    if (! thisObject.isObject())
-        thisObject.objectValue()->prototype = engine->objectPrototype;
-
-}
-
 extern "C" {
 
 Value __qmljs_init_closure(IR::Function *clos, ExecutionContext *ctx)
index 98c628c..56cc953 100644 (file)
@@ -570,47 +570,6 @@ inline bool Value::sameValue(Value other) {
 
 #include <qmljs_math.h>
 
-struct ExecutionContext {
-    ExecutionEngine *engine;
-    ExecutionContext *parent;
-    Object *activation;
-    Value thisObject;
-    Value *arguments;
-    unsigned int argumentCount;
-    Value *locals;
-    Value result;
-    String **formals;
-    unsigned int formalCount;
-    String **vars;
-    unsigned int varCount;
-
-    PropertyDescriptor *lookupPropertyDescriptor(String *name, PropertyDescriptor *tmp);
-    void inplaceBitOp(Value value, String *name, BinOp op);
-
-    inline Value argument(unsigned int index = 0)
-    {
-        if (index < argumentCount)
-            return arguments[index];
-        return Value::undefinedValue();
-    }
-
-    void init(ExecutionEngine *eng);
-
-    void initCallContext(ExecutionContext *parent, const Value that, FunctionObject *f, Value *args, unsigned argc);
-    void leaveCallContext();
-
-    void initConstructorContext(ExecutionContext *parent, Value that, FunctionObject *f, Value *args, unsigned argc);
-    void leaveConstructorContext(FunctionObject *f);
-    void wireUpPrototype(FunctionObject *f);
-
-    void throwError(Value value);
-    void throwError(const QString &message);
-    void throwTypeError();
-    void throwReferenceError(Value value);
-    void throwUnimplemented(const QString &message);
-};
-
-
 
 extern "C" {
 
diff --git a/v4.pro b/v4.pro
index c2790f0..159e4d8 100644 (file)
--- a/v4.pro
+++ b/v4.pro
@@ -13,6 +13,8 @@ LIBS += -rdynamic
 SOURCES += main.cpp \
     qv4codegen.cpp \
     qv4ir.cpp \
+    qmljs_engine.cpp \
+    qmljs_environment.cpp \
     qmljs_runtime.cpp \
     qmljs_objects.cpp \
     qv4syntaxchecker.cpp \
@@ -24,6 +26,8 @@ SOURCES += main.cpp \
 HEADERS += \
     qv4codegen_p.h \
     qv4ir_p.h \
+    qmljs_engine.h \
+    qmljs_environment.h \
     qmljs_runtime.h \
     qmljs_objects.h \
     qmljs_math.h \