2012-11-17 20:54:26 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
|
|
|
** 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$
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
2013-03-14 11:48:00 +00:00
|
|
|
#include <qv4engine.h>
|
2013-03-14 21:05:57 +00:00
|
|
|
#include <qv4value.h>
|
2013-01-21 20:54:53 +00:00
|
|
|
#include <qv4object.h>
|
2013-01-21 21:17:55 +00:00
|
|
|
#include <qv4objectproto.h>
|
2013-01-21 21:03:14 +00:00
|
|
|
#include <qv4arrayobject.h>
|
2013-01-21 21:14:55 +00:00
|
|
|
#include <qv4booleanobject.h>
|
2013-01-21 20:26:25 +00:00
|
|
|
#include <qv4globalobject.h>
|
2013-01-21 20:36:12 +00:00
|
|
|
#include <qv4errorobject.h>
|
2013-01-21 20:26:25 +00:00
|
|
|
#include <qv4functionobject.h>
|
2013-01-21 20:48:51 +00:00
|
|
|
#include <qv4mathobject.h>
|
2013-01-21 21:12:05 +00:00
|
|
|
#include <qv4numberobject.h>
|
2013-01-21 20:43:15 +00:00
|
|
|
#include <qv4regexpobject.h>
|
2013-03-14 21:08:29 +00:00
|
|
|
#include <qv4runtime.h>
|
2012-12-04 12:40:18 +00:00
|
|
|
#include "qv4mm.h"
|
2013-01-18 11:47:43 +00:00
|
|
|
#include <qv4argumentsobject.h>
|
2013-01-21 10:57:17 +00:00
|
|
|
#include <qv4dateobject.h>
|
2013-01-18 21:19:33 +00:00
|
|
|
#include <qv4jsonobject.h>
|
2013-01-21 13:20:19 +00:00
|
|
|
#include <qv4stringobject.h>
|
2013-01-30 13:56:40 +00:00
|
|
|
#include <qv4identifier.h>
|
2013-02-21 13:30:35 +00:00
|
|
|
#include <qv4unwindhelper.h>
|
2013-03-05 15:11:22 +00:00
|
|
|
#include "qv4isel_masm_p.h"
|
|
|
|
#include "debugging.h"
|
2012-11-17 20:54:26 +00:00
|
|
|
|
|
|
|
namespace QQmlJS {
|
|
|
|
namespace VM {
|
|
|
|
|
2013-01-03 11:26:19 +00:00
|
|
|
ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
|
|
|
|
: memoryManager(new QQmlJS::VM::MemoryManager)
|
2013-03-14 13:03:04 +00:00
|
|
|
, contextStack(0)
|
|
|
|
, contextStackPosition(0)
|
|
|
|
, contextStackSize(0)
|
2012-11-29 13:41:26 +00:00
|
|
|
, debugger(0)
|
2012-12-04 12:40:18 +00:00
|
|
|
, globalObject(Value::nullValue())
|
2013-01-28 15:46:09 +00:00
|
|
|
, globalCode(0)
|
2013-03-06 13:01:07 +00:00
|
|
|
, externalResourceComparison(0)
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2012-12-04 12:40:18 +00:00
|
|
|
MemoryManager::GCBlocker gcBlocker(memoryManager);
|
|
|
|
|
2013-03-05 15:11:22 +00:00
|
|
|
if (!factory)
|
|
|
|
factory = new MASM::ISelFactory;
|
|
|
|
iselFactory.reset(factory);
|
|
|
|
|
2012-12-04 12:40:18 +00:00
|
|
|
memoryManager->setExecutionEngine(this);
|
2012-11-28 12:39:14 +00:00
|
|
|
|
2013-01-30 13:56:40 +00:00
|
|
|
identifierCache = new Identifiers(this);
|
|
|
|
|
2013-02-14 22:00:11 +00:00
|
|
|
id_undefined = newIdentifier(QStringLiteral("undefined"));
|
|
|
|
id_null = newIdentifier(QStringLiteral("null"));
|
|
|
|
id_true = newIdentifier(QStringLiteral("true"));
|
|
|
|
id_false = newIdentifier(QStringLiteral("false"));
|
|
|
|
id_boolean = newIdentifier(QStringLiteral("boolean"));
|
|
|
|
id_number = newIdentifier(QStringLiteral("number"));
|
|
|
|
id_string = newIdentifier(QStringLiteral("string"));
|
|
|
|
id_object = newIdentifier(QStringLiteral("object"));
|
|
|
|
id_function = newIdentifier(QStringLiteral("function"));
|
2013-01-30 13:56:40 +00:00
|
|
|
id_length = newIdentifier(QStringLiteral("length"));
|
|
|
|
id_prototype = newIdentifier(QStringLiteral("prototype"));
|
|
|
|
id_constructor = newIdentifier(QStringLiteral("constructor"));
|
|
|
|
id_arguments = newIdentifier(QStringLiteral("arguments"));
|
|
|
|
id_caller = newIdentifier(QStringLiteral("caller"));
|
|
|
|
id_this = newIdentifier(QStringLiteral("this"));
|
|
|
|
id___proto__ = newIdentifier(QStringLiteral("__proto__"));
|
|
|
|
id_enumerable = newIdentifier(QStringLiteral("enumerable"));
|
|
|
|
id_configurable = newIdentifier(QStringLiteral("configurable"));
|
|
|
|
id_writable = newIdentifier(QStringLiteral("writable"));
|
|
|
|
id_value = newIdentifier(QStringLiteral("value"));
|
|
|
|
id_get = newIdentifier(QStringLiteral("get"));
|
|
|
|
id_set = newIdentifier(QStringLiteral("set"));
|
|
|
|
id_eval = newIdentifier(QStringLiteral("eval"));
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2013-03-04 10:48:49 +00:00
|
|
|
emptyClass = new InternalClass(this);
|
|
|
|
arrayClass = emptyClass->addMember(id_length);
|
2013-03-14 13:03:04 +00:00
|
|
|
initRootContext();
|
2013-03-04 10:48:49 +00:00
|
|
|
|
2013-02-10 21:22:53 +00:00
|
|
|
objectPrototype = new (memoryManager) ObjectPrototype(this);
|
2012-12-04 12:40:18 +00:00
|
|
|
stringPrototype = new (memoryManager) StringPrototype(rootContext);
|
2013-02-10 21:22:53 +00:00
|
|
|
numberPrototype = new (memoryManager) NumberPrototype(this);
|
|
|
|
booleanPrototype = new (memoryManager) BooleanPrototype(this);
|
2013-01-11 13:33:10 +00:00
|
|
|
arrayPrototype = new (memoryManager) ArrayPrototype(rootContext);
|
2013-02-10 21:22:53 +00:00
|
|
|
datePrototype = new (memoryManager) DatePrototype(this);
|
2012-12-04 12:40:18 +00:00
|
|
|
functionPrototype = new (memoryManager) FunctionPrototype(rootContext);
|
2013-01-17 14:24:58 +00:00
|
|
|
regExpPrototype = new (memoryManager) RegExpPrototype(this);
|
2013-01-18 12:28:00 +00:00
|
|
|
errorPrototype = new (memoryManager) ErrorPrototype(this);
|
2012-12-04 12:40:18 +00:00
|
|
|
evalErrorPrototype = new (memoryManager) EvalErrorPrototype(rootContext);
|
|
|
|
rangeErrorPrototype = new (memoryManager) RangeErrorPrototype(rootContext);
|
|
|
|
referenceErrorPrototype = new (memoryManager) ReferenceErrorPrototype(rootContext);
|
|
|
|
syntaxErrorPrototype = new (memoryManager) SyntaxErrorPrototype(rootContext);
|
|
|
|
typeErrorPrototype = new (memoryManager) TypeErrorPrototype(rootContext);
|
|
|
|
uRIErrorPrototype = new (memoryManager) URIErrorPrototype(rootContext);
|
2012-11-17 20:54:26 +00:00
|
|
|
|
|
|
|
stringPrototype->prototype = objectPrototype;
|
|
|
|
numberPrototype->prototype = objectPrototype;
|
|
|
|
booleanPrototype->prototype = objectPrototype;
|
|
|
|
arrayPrototype->prototype = objectPrototype;
|
|
|
|
datePrototype->prototype = objectPrototype;
|
|
|
|
functionPrototype->prototype = objectPrototype;
|
|
|
|
regExpPrototype->prototype = objectPrototype;
|
|
|
|
errorPrototype->prototype = objectPrototype;
|
2013-01-14 16:13:25 +00:00
|
|
|
evalErrorPrototype->prototype = objectPrototype;
|
|
|
|
rangeErrorPrototype->prototype = objectPrototype;
|
|
|
|
referenceErrorPrototype->prototype = objectPrototype;
|
|
|
|
syntaxErrorPrototype->prototype = objectPrototype;
|
|
|
|
typeErrorPrototype->prototype = objectPrototype;
|
|
|
|
uRIErrorPrototype->prototype = objectPrototype;
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2012-12-04 12:40:18 +00:00
|
|
|
objectCtor = Value::fromObject(new (memoryManager) ObjectCtor(rootContext));
|
|
|
|
stringCtor = Value::fromObject(new (memoryManager) StringCtor(rootContext));
|
|
|
|
numberCtor = Value::fromObject(new (memoryManager) NumberCtor(rootContext));
|
|
|
|
booleanCtor = Value::fromObject(new (memoryManager) BooleanCtor(rootContext));
|
|
|
|
arrayCtor = Value::fromObject(new (memoryManager) ArrayCtor(rootContext));
|
|
|
|
functionCtor = Value::fromObject(new (memoryManager) FunctionCtor(rootContext));
|
|
|
|
dateCtor = Value::fromObject(new (memoryManager) DateCtor(rootContext));
|
|
|
|
regExpCtor = Value::fromObject(new (memoryManager) RegExpCtor(rootContext));
|
|
|
|
errorCtor = Value::fromObject(new (memoryManager) ErrorCtor(rootContext));
|
|
|
|
evalErrorCtor = Value::fromObject(new (memoryManager) EvalErrorCtor(rootContext));
|
|
|
|
rangeErrorCtor = Value::fromObject(new (memoryManager) RangeErrorCtor(rootContext));
|
|
|
|
referenceErrorCtor = Value::fromObject(new (memoryManager) ReferenceErrorCtor(rootContext));
|
|
|
|
syntaxErrorCtor = Value::fromObject(new (memoryManager) SyntaxErrorCtor(rootContext));
|
|
|
|
typeErrorCtor = Value::fromObject(new (memoryManager) TypeErrorCtor(rootContext));
|
|
|
|
uRIErrorCtor = Value::fromObject(new (memoryManager) URIErrorCtor(rootContext));
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2013-01-13 22:57:35 +00:00
|
|
|
objectCtor.objectValue()->prototype = functionPrototype;
|
2012-11-17 20:54:26 +00:00
|
|
|
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;
|
2013-01-14 13:02:03 +00:00
|
|
|
evalErrorCtor.objectValue()->prototype = functionPrototype;
|
|
|
|
rangeErrorCtor.objectValue()->prototype = functionPrototype;
|
|
|
|
referenceErrorCtor.objectValue()->prototype = functionPrototype;
|
|
|
|
syntaxErrorCtor.objectValue()->prototype = functionPrototype;
|
|
|
|
typeErrorCtor.objectValue()->prototype = functionPrototype;
|
|
|
|
uRIErrorCtor.objectValue()->prototype = functionPrototype;
|
2012-11-17 20:54:26 +00:00
|
|
|
|
|
|
|
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);
|
2012-12-01 13:05:07 +00:00
|
|
|
rootContext->activation = glo;
|
2012-12-10 18:30:08 +00:00
|
|
|
rootContext->thisObject = Value::fromObject(glo);
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2012-12-12 23:53:04 +00:00
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("Object"), objectCtor);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("String"), stringCtor);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("Number"), numberCtor);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("Boolean"), booleanCtor);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("Array"), arrayCtor);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("Function"), functionCtor);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("Date"), dateCtor);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("RegExp"), regExpCtor);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("Error"), errorCtor);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("EvalError"), evalErrorCtor);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("RangeError"), rangeErrorCtor);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("ReferenceError"), referenceErrorCtor);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("SyntaxError"), syntaxErrorCtor);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("TypeError"), typeErrorCtor);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("URIError"), uRIErrorCtor);
|
2013-01-30 15:25:57 +00:00
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("Math"), Value::fromObject(new (memoryManager) MathObject(rootContext)));
|
2013-01-18 21:19:33 +00:00
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("JSON"), Value::fromObject(new (memoryManager) JsonObject(rootContext)));
|
2012-12-12 23:53:04 +00:00
|
|
|
|
|
|
|
glo->defineReadonlyProperty(this, QStringLiteral("undefined"), Value::undefinedValue());
|
2013-02-08 08:39:25 +00:00
|
|
|
glo->defineReadonlyProperty(this, QStringLiteral("NaN"), Value::fromDouble(std::numeric_limits<double>::quiet_NaN()));
|
2013-02-07 15:52:18 +00:00
|
|
|
glo->defineReadonlyProperty(this, QStringLiteral("Infinity"), Value::fromDouble(Q_INFINITY));
|
2012-12-12 23:53:04 +00:00
|
|
|
|
2013-01-23 09:07:18 +00:00
|
|
|
evalFunction = new (memoryManager) EvalFunction(rootContext);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("eval"), Value::fromObject(evalFunction));
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2013-01-22 15:12:12 +00:00
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("parseFloat"), GlobalFunctions::method_parseFloat, 1);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("isNaN"), GlobalFunctions::method_isNaN, 1);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("isFinite"), GlobalFunctions::method_isFinite, 1);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("decodeURI"), GlobalFunctions::method_decodeURI, 1);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("decodeURIComponent"), GlobalFunctions::method_decodeURIComponent, 1);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("encodeURI"), GlobalFunctions::method_encodeURI, 1);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("encodeURIComponent"), GlobalFunctions::method_encodeURIComponent, 1);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("escape"), GlobalFunctions::method_escape, 1);
|
|
|
|
glo->defineDefaultProperty(rootContext, QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1);
|
2012-11-17 20:54:26 +00:00
|
|
|
}
|
|
|
|
|
2012-12-04 10:30:26 +00:00
|
|
|
ExecutionEngine::~ExecutionEngine()
|
|
|
|
{
|
|
|
|
delete globalObject.asObject();
|
|
|
|
delete rootContext;
|
2013-03-14 13:03:04 +00:00
|
|
|
delete [] contextStack;
|
2013-03-04 14:30:40 +00:00
|
|
|
UnwindHelper::deregisterFunctions(functions);
|
2012-12-11 09:03:40 +00:00
|
|
|
qDeleteAll(functions);
|
2013-01-03 11:26:19 +00:00
|
|
|
delete memoryManager;
|
2012-12-04 10:30:26 +00:00
|
|
|
}
|
|
|
|
|
2013-03-14 13:03:04 +00:00
|
|
|
void ExecutionEngine::initRootContext()
|
|
|
|
{
|
|
|
|
ensureContextStackSize();
|
2013-03-14 14:47:57 +00:00
|
|
|
rootContext = new (memoryManager) ExecutionContext();
|
2013-03-14 13:03:04 +00:00
|
|
|
rootContext->init(this);
|
|
|
|
current = rootContext;
|
|
|
|
contextStack[0] = rootContext;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ExecutionEngine::ensureContextStackSize()
|
|
|
|
{
|
|
|
|
if (contextStackPosition < contextStackSize - 1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const int stackSize = qMax(32, 2*contextStackSize);
|
|
|
|
ExecutionContext **newStack = new ExecutionContext *[stackSize];
|
|
|
|
if (contextStack)
|
|
|
|
memcpy(newStack, contextStack, contextStackSize*sizeof(ExecutionContext *));
|
|
|
|
memset(newStack + contextStackSize, 0, (stackSize - contextStackSize)*sizeof(ExecutionContext *));
|
|
|
|
contextStackSize = stackSize;
|
|
|
|
contextStack = newStack;
|
|
|
|
}
|
|
|
|
|
2013-03-14 11:59:11 +00:00
|
|
|
ExecutionContext *ExecutionEngine::newWithContext(Object *with)
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2013-03-14 13:03:04 +00:00
|
|
|
ensureContextStackSize();
|
|
|
|
assert(contextStack[contextStackPosition + 1] == 0);
|
|
|
|
|
2013-03-14 14:47:57 +00:00
|
|
|
ExecutionContext *ctx = new (memoryManager) ExecutionContext();
|
2013-03-14 13:03:04 +00:00
|
|
|
ctx->init(current, with);
|
|
|
|
current = ctx;
|
|
|
|
|
|
|
|
contextStack[++contextStackPosition] = current;
|
|
|
|
return current;
|
2013-03-14 11:59:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ExecutionContext *ExecutionEngine::newCatchContext(String *exceptionVarName, const Value &exceptionValue)
|
|
|
|
{
|
2013-03-14 13:03:04 +00:00
|
|
|
ensureContextStackSize();
|
|
|
|
assert(contextStack[contextStackPosition + 1] == 0);
|
|
|
|
|
2013-03-14 14:47:57 +00:00
|
|
|
ExecutionContext *ctx = new (memoryManager) ExecutionContext();
|
2013-03-14 13:03:04 +00:00
|
|
|
ctx->initForCatch(current, exceptionVarName, exceptionValue);
|
|
|
|
current = ctx;
|
|
|
|
|
|
|
|
contextStack[++contextStackPosition] = current;
|
|
|
|
return current;
|
2013-03-14 11:59:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ExecutionContext *ExecutionEngine::newCallContext(FunctionObject *f, const Value &thisObject, Value *args, int argc)
|
|
|
|
{
|
2013-03-14 13:03:04 +00:00
|
|
|
ensureContextStackSize();
|
|
|
|
assert(contextStack[contextStackPosition + 1] == 0);
|
|
|
|
|
2013-03-14 14:47:57 +00:00
|
|
|
current = new (memoryManager) ExecutionContext();
|
2013-03-14 13:03:04 +00:00
|
|
|
current->function = f;
|
|
|
|
current->thisObject = thisObject;
|
|
|
|
current->arguments = args;
|
|
|
|
current->argumentCount = argc;
|
|
|
|
current->initCallContext(this);
|
|
|
|
|
|
|
|
contextStack[++contextStackPosition] = current;
|
|
|
|
return current;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExecutionContext *ExecutionEngine::pushGlobalContext()
|
|
|
|
{
|
|
|
|
ensureContextStackSize();
|
|
|
|
assert(contextStack[contextStackPosition + 1] == 0);
|
|
|
|
|
|
|
|
current = rootContext;
|
|
|
|
|
|
|
|
contextStack[++contextStackPosition] = current;
|
|
|
|
return current;
|
2013-03-14 11:59:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ExecutionContext *ExecutionEngine::popContext()
|
|
|
|
{
|
2013-03-14 13:03:04 +00:00
|
|
|
assert(current == contextStack[contextStackPosition]);
|
2013-03-14 11:59:11 +00:00
|
|
|
|
|
|
|
if (debugger)
|
2013-03-14 13:03:04 +00:00
|
|
|
debugger->justLeft(current);
|
2013-03-14 11:59:11 +00:00
|
|
|
|
2013-03-21 01:08:36 +00:00
|
|
|
if (!current->needsOwnArguments()) {
|
|
|
|
current->arguments = 0;
|
|
|
|
current->argumentCount = 0;
|
|
|
|
}
|
|
|
|
|
2013-03-14 13:03:04 +00:00
|
|
|
contextStack[contextStackPosition] = 0;
|
|
|
|
current = contextStack[--contextStackPosition];
|
2013-03-14 11:59:11 +00:00
|
|
|
return current;
|
2012-11-17 20:54:26 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 09:03:40 +00:00
|
|
|
Function *ExecutionEngine::newFunction(const QString &name)
|
|
|
|
{
|
2013-01-30 13:56:40 +00:00
|
|
|
VM::Function *f = new VM::Function(newIdentifier(name));
|
2012-12-11 09:03:40 +00:00
|
|
|
functions.append(f);
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
2013-01-16 10:41:23 +00:00
|
|
|
FunctionObject *ExecutionEngine::newBuiltinFunction(ExecutionContext *scope, String *name, Value (*code)(ExecutionContext *))
|
2013-01-29 20:23:19 +00:00
|
|
|
{
|
|
|
|
BuiltinFunctionOld *f = new (memoryManager) BuiltinFunctionOld(scope, name, code);
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
FunctionObject *ExecutionEngine::newBuiltinFunction(ExecutionContext *scope, String *name, Value (*code)(ExecutionContext *, Value, Value *, int))
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2013-01-16 10:41:23 +00:00
|
|
|
BuiltinFunction *f = new (memoryManager) BuiltinFunction(scope, name, code);
|
2012-11-17 20:54:26 +00:00
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
2012-12-11 09:03:40 +00:00
|
|
|
FunctionObject *ExecutionEngine::newScriptFunction(ExecutionContext *scope, VM::Function *function)
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2012-12-11 09:03:40 +00:00
|
|
|
assert(function);
|
|
|
|
|
2012-12-04 12:40:18 +00:00
|
|
|
ScriptFunction *f = new (memoryManager) ScriptFunction(scope, function);
|
2012-11-17 20:54:26 +00:00
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
2013-01-13 22:57:35 +00:00
|
|
|
BoundFunction *ExecutionEngine::newBoundFunction(ExecutionContext *scope, FunctionObject *target, Value boundThis, const QVector<Value> &boundArgs)
|
|
|
|
{
|
|
|
|
assert(target);
|
|
|
|
|
|
|
|
BoundFunction *f = new (memoryManager) BoundFunction(scope, target, boundThis, boundArgs);
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-17 20:54:26 +00:00
|
|
|
Object *ExecutionEngine::newObject()
|
|
|
|
{
|
2013-02-10 21:22:53 +00:00
|
|
|
Object *object = new (memoryManager) Object(this);
|
2012-11-17 20:54:26 +00:00
|
|
|
object->prototype = objectPrototype;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
String *ExecutionEngine::newString(const QString &s)
|
|
|
|
{
|
2013-01-28 15:46:09 +00:00
|
|
|
return new (memoryManager) String(s);
|
2012-11-17 20:54:26 +00:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:56:40 +00:00
|
|
|
String *ExecutionEngine::newIdentifier(const QString &text)
|
|
|
|
{
|
|
|
|
return identifierCache->insert(text);
|
|
|
|
}
|
|
|
|
|
2013-01-14 13:51:53 +00:00
|
|
|
Object *ExecutionEngine::newStringObject(ExecutionContext *ctx, const Value &value)
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2013-01-14 13:51:53 +00:00
|
|
|
StringObject *object = new (memoryManager) StringObject(ctx, value);
|
2012-11-17 20:54:26 +00:00
|
|
|
object->prototype = stringPrototype;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
Object *ExecutionEngine::newNumberObject(const Value &value)
|
|
|
|
{
|
2013-02-10 21:22:53 +00:00
|
|
|
NumberObject *object = new (memoryManager) NumberObject(this, value);
|
2012-11-17 20:54:26 +00:00
|
|
|
object->prototype = numberPrototype;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
Object *ExecutionEngine::newBooleanObject(const Value &value)
|
|
|
|
{
|
2013-02-10 21:22:53 +00:00
|
|
|
Object *object = new (memoryManager) BooleanObject(this, value);
|
2012-11-17 20:54:26 +00:00
|
|
|
object->prototype = booleanPrototype;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
Object *ExecutionEngine::newFunctionObject(ExecutionContext *ctx)
|
|
|
|
{
|
2012-12-04 12:40:18 +00:00
|
|
|
Object *object = new (memoryManager) FunctionObject(ctx);
|
2012-11-17 20:54:26 +00:00
|
|
|
object->prototype = functionPrototype;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
2013-01-11 13:33:10 +00:00
|
|
|
ArrayObject *ExecutionEngine::newArrayObject(ExecutionContext *ctx)
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2013-01-11 13:33:10 +00:00
|
|
|
ArrayObject *object = new (memoryManager) ArrayObject(ctx);
|
2012-11-17 20:54:26 +00:00
|
|
|
object->prototype = arrayPrototype;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
Object *ExecutionEngine::newDateObject(const Value &value)
|
|
|
|
{
|
2013-02-10 21:22:53 +00:00
|
|
|
Object *object = new (memoryManager) DateObject(this, value);
|
2012-11-17 20:54:26 +00:00
|
|
|
object->prototype = datePrototype;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
2012-12-12 07:28:08 +00:00
|
|
|
RegExpObject *ExecutionEngine::newRegExpObject(const QString &pattern, int flags)
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2013-03-21 13:14:42 +00:00
|
|
|
bool global = (flags & V4IR::RegExp::RegExp_Global);
|
2013-01-14 15:53:43 +00:00
|
|
|
bool ignoreCase = false;
|
|
|
|
bool multiline = false;
|
2013-03-21 13:14:42 +00:00
|
|
|
if (flags & V4IR::RegExp::RegExp_IgnoreCase)
|
2013-01-14 15:53:43 +00:00
|
|
|
ignoreCase = true;
|
2013-03-21 13:14:42 +00:00
|
|
|
if (flags & V4IR::RegExp::RegExp_Multiline)
|
2013-01-14 15:53:43 +00:00
|
|
|
multiline = true;
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2013-01-14 15:53:43 +00:00
|
|
|
return newRegExpObject(RegExp::create(this, pattern, ignoreCase, multiline), global);
|
2012-12-12 07:28:08 +00:00
|
|
|
}
|
|
|
|
|
2013-01-14 15:53:43 +00:00
|
|
|
RegExpObject *ExecutionEngine::newRegExpObject(PassRefPtr<RegExp> re, bool global)
|
2012-12-12 07:28:08 +00:00
|
|
|
{
|
2013-01-17 14:24:58 +00:00
|
|
|
RegExpObject *object = new (memoryManager) RegExpObject(this, re, global);
|
2012-11-17 20:54:26 +00:00
|
|
|
object->prototype = regExpPrototype;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
Object *ExecutionEngine::newErrorObject(const Value &value)
|
|
|
|
{
|
2013-01-18 12:28:00 +00:00
|
|
|
ErrorObject *object = new (memoryManager) ErrorObject(this, value);
|
2012-11-17 20:54:26 +00:00
|
|
|
object->prototype = errorPrototype;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
2012-11-28 10:00:23 +00:00
|
|
|
Object *ExecutionEngine::newSyntaxErrorObject(ExecutionContext *ctx, DiagnosticMessage *message)
|
|
|
|
{
|
2013-01-14 16:13:25 +00:00
|
|
|
return new (memoryManager) SyntaxErrorObject(ctx, message);
|
2012-11-28 10:00:23 +00:00
|
|
|
}
|
|
|
|
|
2012-12-04 18:50:25 +00:00
|
|
|
Object *ExecutionEngine::newReferenceErrorObject(ExecutionContext *ctx, const QString &message)
|
|
|
|
{
|
2013-01-14 16:13:25 +00:00
|
|
|
return new (memoryManager) ReferenceErrorObject(ctx, message);
|
2012-12-04 18:50:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Object *ExecutionEngine::newTypeErrorObject(ExecutionContext *ctx, const QString &message)
|
|
|
|
{
|
2013-01-14 16:13:25 +00:00
|
|
|
return new (memoryManager) TypeErrorObject(ctx, message);
|
2012-12-04 18:50:25 +00:00
|
|
|
}
|
|
|
|
|
2013-01-11 08:56:56 +00:00
|
|
|
Object *ExecutionEngine::newRangeErrorObject(ExecutionContext *ctx, const QString &message)
|
|
|
|
{
|
2013-01-14 16:13:25 +00:00
|
|
|
return new (memoryManager) RangeErrorObject(ctx, message);
|
2013-01-11 08:56:56 +00:00
|
|
|
}
|
|
|
|
|
2013-01-22 14:13:15 +00:00
|
|
|
Object *ExecutionEngine::newURIErrorObject(ExecutionContext *ctx, Value message)
|
|
|
|
{
|
|
|
|
return new (memoryManager) URIErrorObject(ctx, message);
|
|
|
|
}
|
|
|
|
|
2013-01-10 16:33:06 +00:00
|
|
|
Object *ExecutionEngine::newForEachIteratorObject(ExecutionContext *ctx, Object *o)
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2013-01-10 16:33:06 +00:00
|
|
|
return new (memoryManager) ForEachIteratorObject(ctx, o);
|
2012-11-17 20:54:26 +00:00
|
|
|
}
|
|
|
|
|
2013-01-18 11:47:43 +00:00
|
|
|
void ExecutionEngine::requireArgumentsAccessors(int n)
|
|
|
|
{
|
|
|
|
if (n <= argumentsAccessors.size())
|
|
|
|
return;
|
|
|
|
|
|
|
|
uint oldSize = argumentsAccessors.size();
|
|
|
|
argumentsAccessors.resize(n);
|
|
|
|
for (int i = oldSize; i < n; ++i) {
|
|
|
|
FunctionObject *get = new (memoryManager) ArgumentsGetterFunction(rootContext, i);
|
|
|
|
get->prototype = functionPrototype;
|
|
|
|
FunctionObject *set = new (memoryManager) ArgumentsSetterFunction(rootContext, i);
|
|
|
|
set->prototype = functionPrototype;
|
|
|
|
PropertyDescriptor pd = PropertyDescriptor::fromAccessor(get, set);
|
|
|
|
pd.configurable = PropertyDescriptor::Enabled;
|
2013-03-07 11:25:59 +00:00
|
|
|
pd.enumerable = PropertyDescriptor::Enabled;
|
2013-01-18 11:47:43 +00:00
|
|
|
argumentsAccessors[i] = pd;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-28 15:46:09 +00:00
|
|
|
void ExecutionEngine::markObjects()
|
|
|
|
{
|
2013-01-30 13:56:40 +00:00
|
|
|
identifierCache->mark();
|
|
|
|
|
2013-01-28 15:46:09 +00:00
|
|
|
globalObject.mark();
|
|
|
|
|
|
|
|
if (globalCode)
|
|
|
|
globalCode->mark();
|
|
|
|
|
|
|
|
for (int i = 0; i < argumentsAccessors.size(); ++i) {
|
|
|
|
const PropertyDescriptor &pd = argumentsAccessors.at(i);
|
|
|
|
pd.get->mark();
|
|
|
|
pd.set->mark();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < functions.size(); ++i)
|
|
|
|
functions.at(i)->mark();
|
|
|
|
|
|
|
|
id_length->mark();
|
|
|
|
id_prototype->mark();
|
|
|
|
id_constructor->mark();
|
|
|
|
id_arguments->mark();
|
|
|
|
id_caller->mark();
|
|
|
|
id_this->mark();
|
|
|
|
id___proto__->mark();
|
|
|
|
id_enumerable->mark();
|
|
|
|
id_configurable->mark();
|
|
|
|
id_writable->mark();
|
|
|
|
id_value->mark();
|
|
|
|
id_get->mark();
|
|
|
|
id_set->mark();
|
|
|
|
id_eval->mark();
|
|
|
|
}
|
|
|
|
|
2013-03-05 15:11:22 +00:00
|
|
|
Value ExecutionEngine::run(Function *function, ExecutionContext *ctx)
|
|
|
|
{
|
|
|
|
if (!ctx)
|
|
|
|
ctx = rootContext;
|
|
|
|
|
|
|
|
TemporaryAssignment<Function*>(globalCode, function);
|
|
|
|
|
|
|
|
// ### Would be better to have a SavedExecutionState object that
|
|
|
|
// saves this and restores it in the destructor (to survive an exception).
|
|
|
|
ctx->strictMode = function->isStrict;
|
|
|
|
ctx->lookups = function->lookups;
|
|
|
|
|
|
|
|
if (debugger)
|
|
|
|
debugger->aboutToCall(0, ctx);
|
|
|
|
QQmlJS::VM::Value result = function->code(ctx, function->codeData);
|
|
|
|
if (debugger)
|
|
|
|
debugger->justLeft(ctx);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-11-17 20:54:26 +00:00
|
|
|
} // namespace VM
|
|
|
|
} // namespace QQmlJS
|