2012-11-17 20:54:26 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
2013-06-24 11:50:51 +00:00
|
|
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
2012-11-17 20:54:26 +00:00
|
|
|
** Contact: http://www.qt-project.org/legal
|
|
|
|
**
|
2013-06-24 11:50:51 +00:00
|
|
|
** This file is part of the QtQml module of the Qt Toolkit.
|
2012-11-17 20:54:26 +00:00
|
|
|
**
|
|
|
|
** $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-04-15 09:50:16 +00:00
|
|
|
#include <qv4engine_p.h>
|
|
|
|
#include <qv4value_p.h>
|
|
|
|
#include <qv4object_p.h>
|
|
|
|
#include <qv4objectproto_p.h>
|
|
|
|
#include <qv4arrayobject_p.h>
|
|
|
|
#include <qv4booleanobject_p.h>
|
|
|
|
#include <qv4globalobject_p.h>
|
|
|
|
#include <qv4errorobject_p.h>
|
|
|
|
#include <qv4functionobject_p.h>
|
2013-05-08 12:24:30 +00:00
|
|
|
#include "qv4function_p.h"
|
2013-04-15 09:50:16 +00:00
|
|
|
#include <qv4mathobject_p.h>
|
|
|
|
#include <qv4numberobject_p.h>
|
|
|
|
#include <qv4regexpobject_p.h>
|
2013-05-14 00:01:04 +00:00
|
|
|
#include <qv4variantobject_p.h>
|
2013-04-15 09:50:16 +00:00
|
|
|
#include <qv4runtime_p.h>
|
|
|
|
#include "qv4mm_p.h"
|
|
|
|
#include <qv4argumentsobject_p.h>
|
|
|
|
#include <qv4dateobject_p.h>
|
|
|
|
#include <qv4jsonobject_p.h>
|
|
|
|
#include <qv4stringobject_p.h>
|
2013-06-27 21:02:45 +00:00
|
|
|
#include <qv4identifiertable_p.h>
|
2013-04-15 09:50:16 +00:00
|
|
|
#include <qv4unwindhelper_p.h>
|
|
|
|
#include "qv4debugging_p.h"
|
|
|
|
#include "qv4executableallocator_p.h"
|
2013-05-21 15:06:36 +00:00
|
|
|
#include "qv4sequenceobject_p.h"
|
2013-06-07 09:21:18 +00:00
|
|
|
#include "qv4qobjectwrapper_p.h"
|
2013-06-20 09:32:45 +00:00
|
|
|
#include "qv4qmlextensions_p.h"
|
2013-07-09 11:42:09 +00:00
|
|
|
#include "qv4stacktrace_p.h"
|
2013-05-28 07:36:04 +00:00
|
|
|
|
2013-05-07 09:54:45 +00:00
|
|
|
#ifdef V4_ENABLE_JIT
|
2013-07-24 08:29:04 +00:00
|
|
|
#include "qv4isel_masm_p.h"
|
2013-05-07 09:54:45 +00:00
|
|
|
#endif // V4_ENABLE_JIT
|
|
|
|
|
2013-07-24 08:29:04 +00:00
|
|
|
#include "qv4isel_moth_p.h"
|
|
|
|
|
2013-06-24 13:28:00 +00:00
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
|
2013-04-19 11:03:42 +00:00
|
|
|
using namespace QV4;
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2013-06-04 08:05:51 +00:00
|
|
|
static QBasicAtomicInt engineSerial = Q_BASIC_ATOMIC_INITIALIZER(1);
|
|
|
|
|
2013-09-18 07:30:45 +00:00
|
|
|
static ReturnedValue throwTypeError(SimpleCallContext *ctx)
|
|
|
|
{
|
|
|
|
ctx->throwTypeError();
|
2013-09-25 10:24:36 +00:00
|
|
|
return Primitive::undefinedValue().asReturnedValue();
|
2013-09-18 07:30:45 +00:00
|
|
|
}
|
|
|
|
|
2013-04-19 11:03:42 +00:00
|
|
|
ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
|
|
|
|
: memoryManager(new QV4::MemoryManager)
|
|
|
|
, executableAllocator(new QV4::ExecutableAllocator)
|
2013-05-12 10:07:15 +00:00
|
|
|
, regExpAllocator(new QV4::ExecutableAllocator)
|
2013-04-19 09:47:50 +00:00
|
|
|
, bumperPointerAllocator(new WTF::BumpPointerAllocator)
|
2013-09-03 10:40:07 +00:00
|
|
|
, jsStack(new WTF::PageAllocation)
|
2012-11-29 13:41:26 +00:00
|
|
|
, debugger(0)
|
2013-04-08 07:08:02 +00:00
|
|
|
, globalObject(0)
|
2013-01-28 15:46:09 +00:00
|
|
|
, globalCode(0)
|
2013-06-04 08:05:51 +00:00
|
|
|
, m_engineId(engineSerial.fetchAndAddOrdered(1))
|
2013-03-30 16:43:03 +00:00
|
|
|
, regExpCache(0)
|
2013-06-04 12:28:13 +00:00
|
|
|
, m_multiplyWrappedQObjects(0)
|
2013-06-20 09:32:45 +00:00
|
|
|
, m_qmlExtensions(0)
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2012-12-04 12:40:18 +00:00
|
|
|
MemoryManager::GCBlocker gcBlocker(memoryManager);
|
|
|
|
|
2013-09-23 13:52:10 +00:00
|
|
|
exceptionValue = Encode::undefined();
|
|
|
|
|
2013-05-07 09:54:45 +00:00
|
|
|
if (!factory) {
|
2013-09-09 14:07:01 +00:00
|
|
|
|
2013-08-12 14:45:47 +00:00
|
|
|
#ifdef V4_ENABLE_JIT
|
2013-09-09 14:07:01 +00:00
|
|
|
static const bool forceMoth = !qgetenv("QV4_FORCE_INTERPRETER").isEmpty();
|
|
|
|
if (forceMoth)
|
|
|
|
factory = new QQmlJS::Moth::ISelFactory;
|
|
|
|
else
|
|
|
|
factory = new QQmlJS::MASM::ISelFactory;
|
2013-05-07 09:54:45 +00:00
|
|
|
#else // !V4_ENABLE_JIT
|
|
|
|
factory = new QQmlJS::Moth::ISelFactory;
|
|
|
|
#endif // V4_ENABLE_JIT
|
|
|
|
}
|
2013-03-05 15:11:22 +00:00
|
|
|
iselFactory.reset(factory);
|
|
|
|
|
2012-12-04 12:40:18 +00:00
|
|
|
memoryManager->setExecutionEngine(this);
|
2012-11-28 12:39:14 +00:00
|
|
|
|
2013-09-03 10:40:07 +00:00
|
|
|
// reserve 8MB for the JS stack
|
|
|
|
*jsStack = WTF::PageAllocation::allocate(8*1024*1024, WTF::OSAllocator::JSVMStackPages, true);
|
2013-09-25 09:53:03 +00:00
|
|
|
jsStackBase = (SafeValue *)jsStack->base();
|
2013-09-03 10:40:07 +00:00
|
|
|
jsStackTop = jsStackBase;
|
|
|
|
|
2013-06-27 06:57:47 +00:00
|
|
|
identifierTable = new IdentifierTable(this);
|
2013-01-30 13:56:40 +00:00
|
|
|
|
2013-05-12 13:00:48 +00:00
|
|
|
emptyClass = new (classPool.allocate(sizeof(InternalClass))) InternalClass(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"));
|
2013-08-16 06:53:47 +00:00
|
|
|
id_callee = newIdentifier(QStringLiteral("callee"));
|
2013-01-30 13:56:40 +00:00
|
|
|
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"));
|
2013-05-03 20:40:58 +00:00
|
|
|
id_uintMax = newIdentifier(QStringLiteral("4294967295"));
|
2013-05-04 08:26:54 +00:00
|
|
|
id_name = newIdentifier(QStringLiteral("name"));
|
2013-09-02 12:25:15 +00:00
|
|
|
id_index = newIdentifier(QStringLiteral("index"));
|
|
|
|
id_input = newIdentifier(QStringLiteral("input"));
|
2013-09-18 13:34:13 +00:00
|
|
|
id_toString = newIdentifier(QStringLiteral("toString"));
|
|
|
|
id_valueOf = newIdentifier(QStringLiteral("valueOf"));
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2013-08-30 09:22:00 +00:00
|
|
|
ObjectPrototype *objectPrototype = new (memoryManager) ObjectPrototype(emptyClass);
|
2013-08-29 12:31:32 +00:00
|
|
|
objectClass = emptyClass->changePrototype(objectPrototype);
|
|
|
|
|
|
|
|
arrayClass = objectClass->addMember(id_length, Attr_NotConfigurable|Attr_NotEnumerable);
|
2013-08-30 07:18:03 +00:00
|
|
|
ArrayPrototype *arrayPrototype = new (memoryManager) ArrayPrototype(arrayClass);
|
2013-08-29 12:31:32 +00:00
|
|
|
arrayClass = arrayClass->changePrototype(arrayPrototype);
|
|
|
|
|
|
|
|
InternalClass *argsClass = objectClass->addMember(id_length, Attr_NotEnumerable);
|
2013-08-16 06:53:47 +00:00
|
|
|
argumentsObjectClass = argsClass->addMember(id_callee, Attr_Data|Attr_NotEnumerable);
|
|
|
|
strictArgumentsObjectClass = argsClass->addMember(id_callee, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
|
|
|
|
strictArgumentsObjectClass = strictArgumentsObjectClass->addMember(id_caller, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
|
2013-03-14 13:03:04 +00:00
|
|
|
initRootContext();
|
2013-03-04 10:48:49 +00:00
|
|
|
|
2013-08-29 19:23:04 +00:00
|
|
|
StringPrototype *stringPrototype = new (memoryManager) StringPrototype(objectClass);
|
|
|
|
stringClass = emptyClass->changePrototype(stringPrototype);
|
|
|
|
|
|
|
|
NumberPrototype *numberPrototype = new (memoryManager) NumberPrototype(objectClass);
|
|
|
|
numberClass = emptyClass->changePrototype(numberPrototype);
|
|
|
|
|
|
|
|
BooleanPrototype *booleanPrototype = new (memoryManager) BooleanPrototype(objectClass);
|
|
|
|
booleanClass = emptyClass->changePrototype(booleanPrototype);
|
|
|
|
|
|
|
|
DatePrototype *datePrototype = new (memoryManager) DatePrototype(objectClass);
|
|
|
|
dateClass = emptyClass->changePrototype(datePrototype);
|
|
|
|
|
|
|
|
FunctionPrototype *functionPrototype = new (memoryManager) FunctionPrototype(objectClass);
|
|
|
|
functionClass = emptyClass->changePrototype(functionPrototype);
|
2013-09-01 19:22:57 +00:00
|
|
|
uint index;
|
|
|
|
functionWithProtoClass = functionClass->addMember(id_prototype, Attr_NotEnumerable|Attr_NotConfigurable, &index);
|
|
|
|
Q_ASSERT(index == FunctionObject::Index_Prototype);
|
|
|
|
protoClass = objectClass->addMember(id_constructor, Attr_NotEnumerable, &index);
|
|
|
|
Q_ASSERT(index == FunctionObject::Index_ProtoConstructor);
|
2013-08-29 19:23:04 +00:00
|
|
|
|
|
|
|
RegExpPrototype *regExpPrototype = new (memoryManager) RegExpPrototype(objectClass);
|
|
|
|
regExpClass = emptyClass->changePrototype(regExpPrototype);
|
2013-09-02 12:25:15 +00:00
|
|
|
regExpExecArrayClass = arrayClass->addMember(id_index, Attr_Data, &index);
|
|
|
|
Q_ASSERT(index == RegExpObject::Index_ArrayIndex);
|
|
|
|
regExpExecArrayClass = regExpExecArrayClass->addMember(id_input, Attr_Data, &index);
|
|
|
|
Q_ASSERT(index == RegExpObject::Index_ArrayInput);
|
2013-08-29 19:23:04 +00:00
|
|
|
|
|
|
|
ErrorPrototype *errorPrototype = new (memoryManager) ErrorPrototype(objectClass);
|
|
|
|
errorClass = emptyClass->changePrototype(errorPrototype);
|
2013-08-30 07:18:03 +00:00
|
|
|
EvalErrorPrototype *evalErrorPrototype = new (memoryManager) EvalErrorPrototype(errorClass);
|
|
|
|
evalErrorClass = emptyClass->changePrototype(evalErrorPrototype);
|
|
|
|
RangeErrorPrototype *rangeErrorPrototype = new (memoryManager) RangeErrorPrototype(errorClass);
|
|
|
|
rangeErrorClass = emptyClass->changePrototype(rangeErrorPrototype);
|
|
|
|
ReferenceErrorPrototype *referenceErrorPrototype = new (memoryManager) ReferenceErrorPrototype(errorClass);
|
|
|
|
referenceErrorClass = emptyClass->changePrototype(referenceErrorPrototype);
|
|
|
|
SyntaxErrorPrototype *syntaxErrorPrototype = new (memoryManager) SyntaxErrorPrototype(errorClass);
|
|
|
|
syntaxErrorClass = emptyClass->changePrototype(syntaxErrorPrototype);
|
|
|
|
TypeErrorPrototype *typeErrorPrototype = new (memoryManager) TypeErrorPrototype(errorClass);
|
|
|
|
typeErrorClass = emptyClass->changePrototype(typeErrorPrototype);
|
|
|
|
URIErrorPrototype *uRIErrorPrototype = new (memoryManager) URIErrorPrototype(errorClass);
|
|
|
|
uriErrorClass = emptyClass->changePrototype(uRIErrorPrototype);
|
2013-08-29 12:31:32 +00:00
|
|
|
|
2013-08-30 09:22:00 +00:00
|
|
|
VariantPrototype *variantPrototype = new (memoryManager) VariantPrototype(objectClass);
|
|
|
|
variantClass = emptyClass->changePrototype(variantPrototype);
|
|
|
|
|
|
|
|
SequencePrototype *sequencePrototype = new (memoryManager) SequencePrototype(arrayClass->changePrototype(arrayPrototype));
|
|
|
|
sequenceClass = emptyClass->changePrototype(sequencePrototype);
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2013-09-26 10:34:53 +00:00
|
|
|
objectCtor = new (memoryManager) ObjectCtor(rootContext);
|
|
|
|
stringCtor = new (memoryManager) StringCtor(rootContext);
|
|
|
|
numberCtor = new (memoryManager) NumberCtor(rootContext);
|
|
|
|
booleanCtor = new (memoryManager) BooleanCtor(rootContext);
|
|
|
|
arrayCtor = new (memoryManager) ArrayCtor(rootContext);
|
|
|
|
functionCtor = new (memoryManager) FunctionCtor(rootContext);
|
|
|
|
dateCtor = new (memoryManager) DateCtor(rootContext);
|
|
|
|
regExpCtor = new (memoryManager) RegExpCtor(rootContext);
|
|
|
|
errorCtor = new (memoryManager) ErrorCtor(rootContext);
|
|
|
|
evalErrorCtor = new (memoryManager) EvalErrorCtor(rootContext);
|
|
|
|
rangeErrorCtor = new (memoryManager) RangeErrorCtor(rootContext);
|
|
|
|
referenceErrorCtor = new (memoryManager) ReferenceErrorCtor(rootContext);
|
|
|
|
syntaxErrorCtor = new (memoryManager) SyntaxErrorCtor(rootContext);
|
|
|
|
typeErrorCtor = new (memoryManager) TypeErrorCtor(rootContext);
|
|
|
|
uRIErrorCtor = new (memoryManager) URIErrorCtor(rootContext);
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2013-09-18 10:31:55 +00:00
|
|
|
objectPrototype->init(this, objectCtor);
|
2013-06-13 11:17:45 +00:00
|
|
|
stringPrototype->init(this, stringCtor);
|
2013-09-18 10:31:55 +00:00
|
|
|
numberPrototype->init(this, numberCtor);
|
|
|
|
booleanPrototype->init(this, booleanCtor);
|
|
|
|
arrayPrototype->init(this, arrayCtor);
|
|
|
|
datePrototype->init(this, dateCtor);
|
|
|
|
functionPrototype->init(this, functionCtor);
|
|
|
|
regExpPrototype->init(this, regExpCtor);
|
2013-05-02 19:37:20 +00:00
|
|
|
errorPrototype->init(this, errorCtor);
|
|
|
|
evalErrorPrototype->init(this, evalErrorCtor);
|
|
|
|
rangeErrorPrototype->init(this, rangeErrorCtor);
|
|
|
|
referenceErrorPrototype->init(this, referenceErrorCtor);
|
|
|
|
syntaxErrorPrototype->init(this, syntaxErrorCtor);
|
|
|
|
typeErrorPrototype->init(this, typeErrorCtor);
|
|
|
|
uRIErrorPrototype->init(this, uRIErrorCtor);
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2013-09-18 10:31:55 +00:00
|
|
|
variantPrototype->init();
|
|
|
|
sequencePrototype->init();
|
2013-05-14 00:01:04 +00:00
|
|
|
|
2012-11-17 20:54:26 +00:00
|
|
|
//
|
|
|
|
// set up the global object
|
|
|
|
//
|
2013-09-16 20:02:27 +00:00
|
|
|
globalObject = newObject()->getPointer();
|
2013-04-08 07:08:02 +00:00
|
|
|
rootContext->global = globalObject;
|
2013-09-26 10:34:53 +00:00
|
|
|
rootContext->callData->thisObject = globalObject;
|
2013-04-08 07:08:02 +00:00
|
|
|
|
2013-09-18 10:31:55 +00:00
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("Object"), objectCtor);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("String"), stringCtor);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("Number"), numberCtor);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("Boolean"), booleanCtor);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("Array"), arrayCtor);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("Function"), functionCtor);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("Date"), dateCtor);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("RegExp"), regExpCtor);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("Error"), errorCtor);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("EvalError"), evalErrorCtor);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("RangeError"), rangeErrorCtor);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("ReferenceError"), referenceErrorCtor);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("SyntaxError"), syntaxErrorCtor);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("TypeError"), typeErrorCtor);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("URIError"), uRIErrorCtor);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("Math"), Value::fromObject(new (memoryManager) MathObject(this)));
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("JSON"), Value::fromObject(new (memoryManager) JsonObject(this)));
|
|
|
|
|
2013-09-25 10:24:36 +00:00
|
|
|
globalObject->defineReadonlyProperty(QStringLiteral("undefined"), Primitive::undefinedValue());
|
|
|
|
globalObject->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(std::numeric_limits<double>::quiet_NaN()));
|
|
|
|
globalObject->defineReadonlyProperty(QStringLiteral("Infinity"), Primitive::fromDouble(Q_INFINITY));
|
2012-12-12 23:53:04 +00:00
|
|
|
|
2013-01-23 09:07:18 +00:00
|
|
|
evalFunction = new (memoryManager) EvalFunction(rootContext);
|
2013-09-18 10:31:55 +00:00
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("eval"), Value::fromObject(evalFunction));
|
|
|
|
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("parseFloat"), GlobalFunctions::method_parseFloat, 1);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("isNaN"), GlobalFunctions::method_isNaN, 1);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("isFinite"), GlobalFunctions::method_isFinite, 1);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("decodeURI"), GlobalFunctions::method_decodeURI, 1);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("decodeURIComponent"), GlobalFunctions::method_decodeURIComponent, 1);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("encodeURI"), GlobalFunctions::method_encodeURI, 1);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("encodeURIComponent"), GlobalFunctions::method_encodeURIComponent, 1);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("escape"), GlobalFunctions::method_escape, 1);
|
|
|
|
globalObject->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1);
|
2013-09-18 07:30:45 +00:00
|
|
|
|
|
|
|
Scope scope(this);
|
|
|
|
Scoped<String> name(scope, newString(QStringLiteral("thrower")));
|
|
|
|
thrower = newBuiltinFunction(rootContext, name, throwTypeError)->getPointer();
|
2012-11-17 20:54:26 +00:00
|
|
|
}
|
|
|
|
|
2012-12-04 10:30:26 +00:00
|
|
|
ExecutionEngine::~ExecutionEngine()
|
|
|
|
{
|
2013-07-24 08:29:04 +00:00
|
|
|
delete debugger;
|
2013-06-04 12:28:13 +00:00
|
|
|
delete m_multiplyWrappedQObjects;
|
|
|
|
m_multiplyWrappedQObjects = 0;
|
2013-08-12 14:13:37 +00:00
|
|
|
delete identifierTable;
|
2013-05-29 12:58:52 +00:00
|
|
|
delete memoryManager;
|
2013-09-19 07:32:42 +00:00
|
|
|
|
|
|
|
QSet<QV4::CompiledData::CompilationUnit*> remainingUnits;
|
|
|
|
qSwap(compilationUnits, remainingUnits);
|
|
|
|
foreach (QV4::CompiledData::CompilationUnit *unit, remainingUnits)
|
|
|
|
unit->unlink();
|
|
|
|
|
2013-06-20 09:32:45 +00:00
|
|
|
delete m_qmlExtensions;
|
2013-05-06 11:29:24 +00:00
|
|
|
emptyClass->destroy();
|
2013-04-19 09:47:50 +00:00
|
|
|
delete bumperPointerAllocator;
|
2013-03-30 16:43:03 +00:00
|
|
|
delete regExpCache;
|
2013-05-12 10:07:15 +00:00
|
|
|
delete regExpAllocator;
|
2013-03-25 16:31:38 +00:00
|
|
|
delete executableAllocator;
|
2013-09-03 10:40:07 +00:00
|
|
|
jsStack->deallocate();
|
|
|
|
delete jsStack;
|
2012-12-04 10:30:26 +00:00
|
|
|
}
|
|
|
|
|
2013-07-24 08:29:04 +00:00
|
|
|
void ExecutionEngine::enableDebugger()
|
|
|
|
{
|
|
|
|
Q_ASSERT(!debugger);
|
|
|
|
debugger = new Debugging::Debugger(this);
|
|
|
|
iselFactory.reset(new QQmlJS::Moth::ISelFactory);
|
|
|
|
}
|
|
|
|
|
2013-03-14 13:03:04 +00:00
|
|
|
void ExecutionEngine::initRootContext()
|
|
|
|
{
|
2013-09-25 08:09:26 +00:00
|
|
|
rootContext = static_cast<GlobalContext *>(memoryManager->allocContext(sizeof(GlobalContext) + sizeof(CallData)));
|
2013-03-14 13:03:04 +00:00
|
|
|
current = rootContext;
|
2013-04-07 15:23:36 +00:00
|
|
|
current->parent = 0;
|
2013-05-13 08:25:01 +00:00
|
|
|
rootContext->initGlobalContext(this);
|
2013-03-14 13:03:04 +00:00
|
|
|
}
|
|
|
|
|
2013-05-06 11:29:24 +00:00
|
|
|
InternalClass *ExecutionEngine::newClass(const InternalClass &other)
|
|
|
|
{
|
|
|
|
return new (classPool.allocate(sizeof(InternalClass))) InternalClass(other);
|
|
|
|
}
|
|
|
|
|
2013-03-14 13:03:04 +00:00
|
|
|
ExecutionContext *ExecutionEngine::pushGlobalContext()
|
|
|
|
{
|
2013-04-07 15:23:36 +00:00
|
|
|
GlobalContext *g = static_cast<GlobalContext *>(memoryManager->allocContext(sizeof(GlobalContext)));
|
2013-06-28 21:59:23 +00:00
|
|
|
ExecutionContext *oldNext = g->next;
|
2013-04-07 15:23:36 +00:00
|
|
|
*g = *rootContext;
|
2013-06-28 21:59:23 +00:00
|
|
|
g->next = oldNext;
|
2013-04-07 15:23:36 +00:00
|
|
|
g->parent = current;
|
|
|
|
current = g;
|
2013-03-14 13:03:04 +00:00
|
|
|
|
2013-03-14 11:59:11 +00:00
|
|
|
return current;
|
2012-11-17 20:54:26 +00:00
|
|
|
}
|
|
|
|
|
2013-09-18 08:02:04 +00:00
|
|
|
Returned<FunctionObject> *ExecutionEngine::newBuiltinFunction(ExecutionContext *scope, const StringRef name, ReturnedValue (*code)(SimpleCallContext *))
|
2013-01-29 20:23:19 +00:00
|
|
|
{
|
2013-09-19 14:05:25 +00:00
|
|
|
BuiltinFunction *f = new (memoryManager) BuiltinFunction(scope, name, code);
|
2013-09-17 20:33:48 +00:00
|
|
|
return f->asReturned<FunctionObject>();
|
2013-01-29 20:23:19 +00:00
|
|
|
}
|
|
|
|
|
2013-09-16 20:02:27 +00:00
|
|
|
Returned<BoundFunction> *ExecutionEngine::newBoundFunction(ExecutionContext *scope, FunctionObject *target, Value boundThis, const QVector<Value> &boundArgs)
|
2013-01-13 22:57:35 +00:00
|
|
|
{
|
|
|
|
assert(target);
|
|
|
|
|
|
|
|
BoundFunction *f = new (memoryManager) BoundFunction(scope, target, boundThis, boundArgs);
|
2013-09-16 20:02:27 +00:00
|
|
|
return f->asReturned<BoundFunction>();
|
2013-01-13 22:57:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-16 20:02:27 +00:00
|
|
|
Returned<Object> *ExecutionEngine::newObject()
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2013-02-10 21:22:53 +00:00
|
|
|
Object *object = new (memoryManager) Object(this);
|
2013-09-16 20:02:27 +00:00
|
|
|
return object->asReturned<Object>();
|
2012-11-17 20:54:26 +00:00
|
|
|
}
|
|
|
|
|
2013-09-16 20:02:27 +00:00
|
|
|
Returned<Object> *ExecutionEngine::newObject(InternalClass *internalClass)
|
2013-04-23 05:31:02 +00:00
|
|
|
{
|
2013-08-29 11:06:22 +00:00
|
|
|
Object *object = new (memoryManager) Object(internalClass);
|
2013-09-16 20:02:27 +00:00
|
|
|
return object->asReturned<Object>();
|
2013-04-23 05:31:02 +00:00
|
|
|
}
|
|
|
|
|
2013-09-25 13:24:50 +00:00
|
|
|
Returned<String> *ExecutionEngine::newString(const QString &s)
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2013-09-25 13:24:50 +00:00
|
|
|
return (new (memoryManager) String(this, s))->asReturned<String>();
|
2012-11-17 20:54:26 +00:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:56:40 +00:00
|
|
|
String *ExecutionEngine::newIdentifier(const QString &text)
|
|
|
|
{
|
2013-06-27 07:04:11 +00:00
|
|
|
return identifierTable->insertString(text);
|
2013-01-30 13:56:40 +00:00
|
|
|
}
|
|
|
|
|
2013-09-25 13:24:50 +00:00
|
|
|
Returned<Object> *ExecutionEngine::newStringObject(const ValueRef value)
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2013-05-02 19:37:20 +00:00
|
|
|
StringObject *object = new (memoryManager) StringObject(this, value);
|
2013-09-13 19:54:21 +00:00
|
|
|
return object->asReturned<Object>();
|
2012-11-17 20:54:26 +00:00
|
|
|
}
|
|
|
|
|
2013-09-19 11:17:55 +00:00
|
|
|
Returned<Object> *ExecutionEngine::newNumberObject(const ValueRef value)
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2013-02-10 21:22:53 +00:00
|
|
|
NumberObject *object = new (memoryManager) NumberObject(this, value);
|
2013-09-13 12:11:55 +00:00
|
|
|
return object->asReturned<Object>();
|
2012-11-17 20:54:26 +00:00
|
|
|
}
|
|
|
|
|
2013-09-19 11:17:55 +00:00
|
|
|
Returned<Object> *ExecutionEngine::newBooleanObject(const ValueRef value)
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2013-02-10 21:22:53 +00:00
|
|
|
Object *object = new (memoryManager) BooleanObject(this, value);
|
2013-09-13 12:11:55 +00:00
|
|
|
return object->asReturned<Object>();
|
2012-11-17 20:54:26 +00:00
|
|
|
}
|
|
|
|
|
2013-09-14 09:25:02 +00:00
|
|
|
Returned<ArrayObject> *ExecutionEngine::newArrayObject(int count)
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2013-05-02 20:33:47 +00:00
|
|
|
ArrayObject *object = new (memoryManager) ArrayObject(this);
|
2013-05-31 14:40:12 +00:00
|
|
|
|
|
|
|
if (count) {
|
|
|
|
if (count < 0x1000)
|
|
|
|
object->arrayReserve(count);
|
|
|
|
object->setArrayLengthUnchecked(count);
|
|
|
|
}
|
2013-09-14 09:25:02 +00:00
|
|
|
return object->asReturned<ArrayObject>();
|
2012-11-17 20:54:26 +00:00
|
|
|
}
|
|
|
|
|
2013-09-14 09:25:02 +00:00
|
|
|
Returned<ArrayObject> *ExecutionEngine::newArrayObject(const QStringList &list)
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2013-05-02 20:33:47 +00:00
|
|
|
ArrayObject *object = new (memoryManager) ArrayObject(this, list);
|
2013-09-14 09:25:02 +00:00
|
|
|
return object->asReturned<ArrayObject>();
|
2012-11-17 20:54:26 +00:00
|
|
|
}
|
|
|
|
|
2013-09-14 09:25:02 +00:00
|
|
|
Returned<ArrayObject> *ExecutionEngine::newArrayObject(InternalClass *ic)
|
2013-09-02 12:25:15 +00:00
|
|
|
{
|
|
|
|
ArrayObject *object = new (memoryManager) ArrayObject(ic);
|
2013-09-14 09:25:02 +00:00
|
|
|
return object->asReturned<ArrayObject>();
|
2013-09-02 12:25:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-13 15:07:44 +00:00
|
|
|
Returned<DateObject> *ExecutionEngine::newDateObject(const Value &value)
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2013-04-30 21:02:33 +00:00
|
|
|
DateObject *object = new (memoryManager) DateObject(this, value);
|
2013-09-13 15:07:44 +00:00
|
|
|
return object->asReturned<DateObject>();
|
2012-11-17 20:54:26 +00:00
|
|
|
}
|
|
|
|
|
2013-09-13 15:07:44 +00:00
|
|
|
Returned<DateObject> *ExecutionEngine::newDateObject(const QDateTime &dt)
|
2013-05-02 20:33:47 +00:00
|
|
|
{
|
|
|
|
DateObject *object = new (memoryManager) DateObject(this, dt);
|
2013-09-13 15:07:44 +00:00
|
|
|
return object->asReturned<DateObject>();
|
2013-05-02 20:33:47 +00:00
|
|
|
}
|
|
|
|
|
2013-09-13 15:07:44 +00:00
|
|
|
Returned<RegExpObject> *ExecutionEngine::newRegExpObject(const QString &pattern, int flags)
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2013-04-19 11:03:42 +00:00
|
|
|
bool global = (flags & QQmlJS::V4IR::RegExp::RegExp_Global);
|
2013-01-14 15:53:43 +00:00
|
|
|
bool ignoreCase = false;
|
|
|
|
bool multiline = false;
|
2013-04-19 11:03:42 +00:00
|
|
|
if (flags & QQmlJS::V4IR::RegExp::RegExp_IgnoreCase)
|
2013-01-14 15:53:43 +00:00
|
|
|
ignoreCase = true;
|
2013-04-19 11:03:42 +00:00
|
|
|
if (flags & QQmlJS::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-09-13 15:07:44 +00:00
|
|
|
Returned<RegExpObject> *ExecutionEngine::newRegExpObject(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);
|
2013-09-13 15:07:44 +00:00
|
|
|
return object->asReturned<RegExpObject>();
|
2012-11-17 20:54:26 +00:00
|
|
|
}
|
|
|
|
|
2013-09-13 15:07:44 +00:00
|
|
|
Returned<RegExpObject> *ExecutionEngine::newRegExpObject(const QRegExp &re)
|
2013-05-02 20:33:47 +00:00
|
|
|
{
|
|
|
|
RegExpObject *object = new (memoryManager) RegExpObject(this, re);
|
2013-09-13 15:07:44 +00:00
|
|
|
return object->asReturned<RegExpObject>();
|
2013-05-02 20:33:47 +00:00
|
|
|
}
|
|
|
|
|
2013-09-25 20:42:58 +00:00
|
|
|
Returned<Object> *ExecutionEngine::newErrorObject(const ValueRef value)
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2013-08-30 07:18:03 +00:00
|
|
|
ErrorObject *object = new (memoryManager) ErrorObject(errorClass, value);
|
2013-09-13 19:54:21 +00:00
|
|
|
return object->asReturned<Object>();
|
2012-11-17 20:54:26 +00:00
|
|
|
}
|
|
|
|
|
2013-09-13 19:54:21 +00:00
|
|
|
Returned<Object> *ExecutionEngine::newSyntaxErrorObject(const QString &message)
|
2012-11-28 10:00:23 +00:00
|
|
|
{
|
2013-09-25 20:42:58 +00:00
|
|
|
Scope scope(this);
|
|
|
|
ScopedString s(scope, newString(message));
|
|
|
|
Object *error = new (memoryManager) SyntaxErrorObject(this, s);
|
2013-09-13 19:54:21 +00:00
|
|
|
return error->asReturned<Object>();
|
2012-11-28 10:00:23 +00:00
|
|
|
}
|
|
|
|
|
2013-09-13 19:54:21 +00:00
|
|
|
Returned<Object> *ExecutionEngine::newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column)
|
2012-12-04 18:50:25 +00:00
|
|
|
{
|
2013-09-13 19:54:21 +00:00
|
|
|
Object *error = new (memoryManager) SyntaxErrorObject(this, message, fileName, line, column);
|
|
|
|
return error->asReturned<Object>();
|
2012-12-04 18:50:25 +00:00
|
|
|
}
|
|
|
|
|
2013-05-02 19:37:20 +00:00
|
|
|
|
2013-09-14 09:25:02 +00:00
|
|
|
Returned<Object> *ExecutionEngine::newReferenceErrorObject(const QString &message)
|
2013-05-02 19:37:20 +00:00
|
|
|
{
|
2013-09-14 09:25:02 +00:00
|
|
|
Object *o = new (memoryManager) ReferenceErrorObject(this, message);
|
|
|
|
return o->asReturned<Object>();
|
2013-05-02 19:37:20 +00:00
|
|
|
}
|
|
|
|
|
2013-09-14 09:25:02 +00:00
|
|
|
Returned<Object> *ExecutionEngine::newReferenceErrorObject(const QString &message, const QString &fileName, int lineNumber, int columnNumber)
|
2013-06-14 11:08:13 +00:00
|
|
|
{
|
2013-09-14 09:25:02 +00:00
|
|
|
Object *o = new (memoryManager) ReferenceErrorObject(this, message, fileName, lineNumber, columnNumber);
|
|
|
|
return o->asReturned<Object>();
|
2013-06-14 11:08:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-14 09:25:02 +00:00
|
|
|
Returned<Object> *ExecutionEngine::newTypeErrorObject(const QString &message)
|
2012-12-04 18:50:25 +00:00
|
|
|
{
|
2013-09-14 09:25:02 +00:00
|
|
|
Object *o = new (memoryManager) TypeErrorObject(this, message);
|
|
|
|
return o->asReturned<Object>();
|
2012-12-04 18:50:25 +00:00
|
|
|
}
|
|
|
|
|
2013-09-14 09:25:02 +00:00
|
|
|
Returned<Object> *ExecutionEngine::newRangeErrorObject(const QString &message)
|
2013-01-11 08:56:56 +00:00
|
|
|
{
|
2013-09-14 09:25:02 +00:00
|
|
|
Object *o = new (memoryManager) RangeErrorObject(this, message);
|
|
|
|
return o->asReturned<Object>();
|
2013-01-11 08:56:56 +00:00
|
|
|
}
|
|
|
|
|
2013-09-25 20:42:58 +00:00
|
|
|
Returned<Object> *ExecutionEngine::newURIErrorObject(const ValueRef message)
|
2013-01-22 14:13:15 +00:00
|
|
|
{
|
2013-09-14 09:25:02 +00:00
|
|
|
Object *o = new (memoryManager) URIErrorObject(this, message);
|
|
|
|
return o->asReturned<Object>();
|
2013-01-22 14:13:15 +00:00
|
|
|
}
|
|
|
|
|
2013-09-14 09:25:02 +00:00
|
|
|
Returned<Object> *ExecutionEngine::newVariantObject(const QVariant &v)
|
2013-05-14 00:01:04 +00:00
|
|
|
{
|
2013-09-14 09:25:02 +00:00
|
|
|
Object *o = new (memoryManager) VariantObject(this, v);
|
|
|
|
return o->asReturned<Object>();
|
2013-05-14 00:01:04 +00:00
|
|
|
}
|
|
|
|
|
2013-09-14 09:25:02 +00:00
|
|
|
Returned<Object> *ExecutionEngine::newForEachIteratorObject(ExecutionContext *ctx, Object *o)
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2013-09-14 09:25:02 +00:00
|
|
|
Object *obj = new (memoryManager) ForEachIteratorObject(ctx, o);
|
|
|
|
return obj->asReturned<Object>();
|
2013-05-03 14:51:32 +00:00
|
|
|
}
|
|
|
|
|
2013-09-14 09:25:02 +00:00
|
|
|
Returned<Object> *ExecutionEngine::qmlContextObject() const
|
2013-05-03 14:51:32 +00:00
|
|
|
{
|
|
|
|
ExecutionContext *ctx = current;
|
2013-05-27 18:40:33 +00:00
|
|
|
|
|
|
|
if (ctx->type == QV4::ExecutionContext::Type_SimpleCallContext)
|
|
|
|
ctx = ctx->parent;
|
|
|
|
|
2013-05-03 14:51:32 +00:00
|
|
|
if (!ctx->outer)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
while (ctx->outer && ctx->outer->type != ExecutionContext::Type_GlobalContext)
|
|
|
|
ctx = ctx->outer;
|
|
|
|
|
|
|
|
assert(ctx);
|
|
|
|
if (ctx->type != ExecutionContext::Type_QmlContext)
|
|
|
|
return 0;
|
|
|
|
|
2013-09-14 09:25:02 +00:00
|
|
|
return static_cast<CallContext *>(ctx)->activation->asReturned<Object>();
|
2012-11-17 20:54:26 +00:00
|
|
|
}
|
|
|
|
|
2013-05-25 13:31:23 +00:00
|
|
|
namespace {
|
2013-06-02 12:12:26 +00:00
|
|
|
struct LineNumberResolver {
|
|
|
|
const ExecutionEngine* engine;
|
2013-07-09 11:42:09 +00:00
|
|
|
QScopedPointer<QV4::NativeStackTrace> nativeTrace;
|
2013-06-02 12:12:26 +00:00
|
|
|
|
|
|
|
LineNumberResolver(const ExecutionEngine *engine)
|
|
|
|
: engine(engine)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void resolve(ExecutionEngine::StackFrame *frame, ExecutionContext *context, Function *function)
|
|
|
|
{
|
|
|
|
if (context->interpreterInstructionPointer) {
|
|
|
|
qptrdiff offset = *context->interpreterInstructionPointer - 1 - function->codeData;
|
|
|
|
frame->line = function->lineNumberForProgramCounter(offset);
|
|
|
|
} else {
|
|
|
|
if (!nativeTrace)
|
2013-07-09 11:42:09 +00:00
|
|
|
nativeTrace.reset(new QV4::NativeStackTrace(engine->current));
|
2013-06-02 12:12:26 +00:00
|
|
|
|
|
|
|
NativeFrame nativeFrame = nativeTrace->nextFrame();
|
|
|
|
if (nativeFrame.function == function)
|
|
|
|
frame->line = nativeFrame.line;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2013-05-25 13:31:23 +00:00
|
|
|
}
|
|
|
|
|
2013-05-22 08:47:36 +00:00
|
|
|
QVector<ExecutionEngine::StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
|
|
|
|
{
|
2013-06-02 12:12:26 +00:00
|
|
|
LineNumberResolver lineNumbers(this);
|
2013-05-25 13:31:23 +00:00
|
|
|
|
2013-05-22 08:47:36 +00:00
|
|
|
QVector<StackFrame> stack;
|
|
|
|
|
|
|
|
QV4::ExecutionContext *c = current;
|
|
|
|
while (c && frameLimit) {
|
2013-05-25 13:31:23 +00:00
|
|
|
if (CallContext *callCtx = c->asCallContext()) {
|
2013-05-22 08:47:36 +00:00
|
|
|
StackFrame frame;
|
2013-05-25 13:31:23 +00:00
|
|
|
if (callCtx->function->function)
|
2013-08-14 14:02:56 +00:00
|
|
|
frame.source = callCtx->function->function->sourceFile();
|
2013-05-25 13:31:23 +00:00
|
|
|
frame.function = callCtx->function->name->toQString();
|
2013-05-22 08:47:36 +00:00
|
|
|
frame.line = -1;
|
|
|
|
frame.column = -1;
|
2013-05-25 13:31:23 +00:00
|
|
|
|
2013-06-02 12:12:26 +00:00
|
|
|
if (callCtx->function->function)
|
|
|
|
lineNumbers.resolve(&frame, callCtx, callCtx->function->function);
|
2013-05-25 13:31:23 +00:00
|
|
|
|
2013-05-22 08:47:36 +00:00
|
|
|
stack.append(frame);
|
|
|
|
--frameLimit;
|
|
|
|
}
|
|
|
|
c = c->parent;
|
|
|
|
}
|
2013-05-25 13:31:23 +00:00
|
|
|
|
|
|
|
if (frameLimit && globalCode) {
|
|
|
|
StackFrame frame;
|
2013-08-14 14:02:56 +00:00
|
|
|
frame.source = globalCode->sourceFile();
|
2013-05-25 13:31:23 +00:00
|
|
|
frame.function = globalCode->name->toQString();
|
|
|
|
frame.line = -1;
|
|
|
|
frame.column = -1;
|
|
|
|
|
2013-06-02 12:12:26 +00:00
|
|
|
lineNumbers.resolve(&frame, rootContext, globalCode);
|
2013-05-25 13:31:23 +00:00
|
|
|
|
|
|
|
stack.append(frame);
|
|
|
|
}
|
2013-05-22 08:47:36 +00:00
|
|
|
return stack;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExecutionEngine::StackFrame ExecutionEngine::currentStackFrame() const
|
|
|
|
{
|
|
|
|
StackFrame frame;
|
|
|
|
frame.line = -1;
|
|
|
|
frame.column = -1;
|
|
|
|
|
2013-05-25 13:31:23 +00:00
|
|
|
QVector<StackFrame> trace = stackTrace(/*limit*/ 1);
|
|
|
|
if (!trace.isEmpty())
|
|
|
|
frame = trace.first();
|
|
|
|
|
2013-05-22 08:47:36 +00:00
|
|
|
return frame;
|
|
|
|
}
|
|
|
|
|
2013-05-29 07:59:40 +00:00
|
|
|
QUrl ExecutionEngine::resolvedUrl(const QString &file)
|
|
|
|
{
|
|
|
|
QUrl src(file);
|
|
|
|
if (!src.isRelative())
|
|
|
|
return src;
|
|
|
|
|
|
|
|
QUrl base;
|
|
|
|
QV4::ExecutionContext *c = current;
|
|
|
|
while (c) {
|
|
|
|
if (CallContext *callCtx = c->asCallContext()) {
|
|
|
|
if (callCtx->function->function)
|
2013-08-14 14:02:56 +00:00
|
|
|
base.setUrl(callCtx->function->function->sourceFile());
|
2013-05-29 07:59:40 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
c = c->parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (base.isEmpty() && globalCode)
|
2013-08-14 14:02:56 +00:00
|
|
|
base.setUrl(globalCode->sourceFile());
|
2013-05-29 07:59:40 +00:00
|
|
|
|
|
|
|
if (base.isEmpty())
|
|
|
|
return src;
|
|
|
|
|
|
|
|
return base.resolved(src);
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
FunctionObject *set = new (memoryManager) ArgumentsSetterFunction(rootContext, i);
|
2013-04-10 08:46:23 +00:00
|
|
|
Property pd = Property::fromAccessor(get, set);
|
2013-01-18 11:47:43 +00:00
|
|
|
argumentsAccessors[i] = pd;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-28 15:46:09 +00:00
|
|
|
void ExecutionEngine::markObjects()
|
|
|
|
{
|
2013-06-27 06:57:47 +00:00
|
|
|
identifierTable->mark();
|
2013-01-30 13:56:40 +00:00
|
|
|
|
2013-04-08 07:08:02 +00:00
|
|
|
globalObject->mark();
|
2013-01-28 15:46:09 +00:00
|
|
|
|
|
|
|
if (globalCode)
|
|
|
|
globalCode->mark();
|
|
|
|
|
|
|
|
for (int i = 0; i < argumentsAccessors.size(); ++i) {
|
2013-04-10 08:46:23 +00:00
|
|
|
const Property &pd = argumentsAccessors.at(i);
|
2013-06-28 10:13:06 +00:00
|
|
|
if (FunctionObject *getter = pd.getter())
|
|
|
|
getter->mark();
|
|
|
|
if (FunctionObject *setter = pd.setter())
|
|
|
|
setter->mark();
|
2013-01-28 15:46:09 +00:00
|
|
|
}
|
|
|
|
|
2013-04-07 15:23:36 +00:00
|
|
|
ExecutionContext *c = current;
|
|
|
|
while (c) {
|
|
|
|
c->mark();
|
|
|
|
c = c->parent;
|
|
|
|
}
|
2013-01-28 15:46:09 +00:00
|
|
|
|
|
|
|
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-05-03 20:40:58 +00:00
|
|
|
id_uintMax->mark();
|
2013-05-04 08:26:54 +00:00
|
|
|
id_name->mark();
|
2013-09-02 12:25:15 +00:00
|
|
|
id_index->mark();
|
|
|
|
id_input->mark();
|
2013-09-18 13:34:13 +00:00
|
|
|
id_toString->mark();
|
|
|
|
id_valueOf->mark();
|
2013-05-14 00:33:03 +00:00
|
|
|
|
|
|
|
objectCtor.mark();
|
|
|
|
stringCtor.mark();
|
|
|
|
numberCtor.mark();
|
|
|
|
booleanCtor.mark();
|
|
|
|
arrayCtor.mark();
|
|
|
|
functionCtor.mark();
|
|
|
|
dateCtor.mark();
|
|
|
|
regExpCtor.mark();
|
|
|
|
errorCtor.mark();
|
|
|
|
evalErrorCtor.mark();
|
|
|
|
rangeErrorCtor.mark();
|
|
|
|
referenceErrorCtor.mark();
|
|
|
|
syntaxErrorCtor.mark();
|
|
|
|
typeErrorCtor.mark();
|
|
|
|
uRIErrorCtor.mark();
|
|
|
|
|
2013-09-23 13:52:10 +00:00
|
|
|
exceptionValue.mark();
|
|
|
|
|
2013-09-18 07:30:45 +00:00
|
|
|
thrower->mark();
|
|
|
|
|
2013-06-20 09:32:45 +00:00
|
|
|
if (m_qmlExtensions)
|
|
|
|
m_qmlExtensions->markObjects();
|
2013-08-15 12:11:19 +00:00
|
|
|
|
2013-08-29 11:24:38 +00:00
|
|
|
emptyClass->markObjects();
|
|
|
|
|
2013-08-15 12:11:19 +00:00
|
|
|
for (QSet<CompiledData::CompilationUnit*>::ConstIterator it = compilationUnits.constBegin(), end = compilationUnits.constEnd();
|
|
|
|
it != end; ++it)
|
|
|
|
(*it)->markObjects();
|
2013-01-28 15:46:09 +00:00
|
|
|
}
|
2013-05-25 13:31:23 +00:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
struct FindHelper
|
|
|
|
{
|
|
|
|
bool operator()(Function *function, quintptr pc)
|
|
|
|
{
|
2013-09-06 11:48:33 +00:00
|
|
|
return reinterpret_cast<quintptr>(function->codePtr) < pc
|
|
|
|
&& (reinterpret_cast<quintptr>(function->codePtr) + function->codeSize) < pc;
|
2013-05-25 13:31:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool operator()(quintptr pc, Function *function)
|
|
|
|
{
|
2013-09-06 11:48:33 +00:00
|
|
|
return pc < reinterpret_cast<quintptr>(function->codePtr);
|
2013-05-25 13:31:23 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
Function *ExecutionEngine::functionForProgramCounter(quintptr pc) const
|
|
|
|
{
|
2013-08-30 08:29:16 +00:00
|
|
|
// ### Use this code path instead of the "else" when the number of compilation units went down to
|
|
|
|
// one per (qml) file.
|
|
|
|
#if 0
|
2013-08-16 16:35:29 +00:00
|
|
|
for (QSet<QV4::CompiledData::CompilationUnit*>::ConstIterator unitIt = compilationUnits.constBegin(), unitEnd = compilationUnits.constEnd();
|
|
|
|
unitIt != unitEnd; ++unitIt) {
|
|
|
|
const QVector<Function*> &functions = (*unitIt)->runtimeFunctionsSortedByAddress;
|
|
|
|
QVector<Function*>::ConstIterator it = qBinaryFind(functions.constBegin(),
|
|
|
|
functions.constEnd(),
|
|
|
|
pc, FindHelper());
|
|
|
|
if (it != functions.constEnd())
|
|
|
|
return *it;
|
2013-05-25 13:31:23 +00:00
|
|
|
}
|
|
|
|
return 0;
|
2013-08-30 08:29:16 +00:00
|
|
|
#else
|
|
|
|
QMap<quintptr, Function*>::ConstIterator it = allFunctions.lowerBound(pc);
|
|
|
|
if (it != allFunctions.begin() && allFunctions.count() > 0)
|
|
|
|
--it;
|
|
|
|
if (it == allFunctions.end())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (pc < it.key() || pc >= it.key() + (*it)->codeSize)
|
|
|
|
return 0;
|
|
|
|
return *it;
|
|
|
|
#endif
|
2013-05-25 13:31:23 +00:00
|
|
|
}
|
|
|
|
|
2013-06-20 09:32:45 +00:00
|
|
|
QmlExtensions *ExecutionEngine::qmlExtensions()
|
|
|
|
{
|
|
|
|
if (!m_qmlExtensions)
|
|
|
|
m_qmlExtensions = new QmlExtensions;
|
|
|
|
return m_qmlExtensions;
|
|
|
|
}
|
|
|
|
|
2013-06-24 13:28:00 +00:00
|
|
|
QT_END_NAMESPACE
|