From 30e3664bf3668bda9a211fe7d1404f8f806dbf7b Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 7 Aug 2017 08:37:45 +0200 Subject: Avoid creating a CallContext for simple functions This cuts out quite a bit of overhead when entering and leaving functions. Change-Id: I32670c98a4087ea3b2d45853d9cabff9066399e8 Reviewed-by: Simon Hausmann --- src/qml/compiler/qv4codegen.cpp | 27 ++++++++++++++++++-- src/qml/jsapi/qjsengine.cpp | 6 ++++- src/qml/jsruntime/qv4arrayobject.cpp | 3 +-- src/qml/jsruntime/qv4context.cpp | 20 +++++++-------- src/qml/jsruntime/qv4engine.cpp | 11 ++++---- src/qml/jsruntime/qv4enginebase_p.h | 5 ++-- src/qml/jsruntime/qv4function_p.h | 3 ++- src/qml/jsruntime/qv4functionobject.cpp | 20 +++++++-------- src/qml/jsruntime/qv4lookup.cpp | 14 +++++----- src/qml/jsruntime/qv4object.cpp | 4 +-- src/qml/jsruntime/qv4runtime.cpp | 44 ++++++++++++++++---------------- src/qml/jsruntime/qv4scopedvalue_p.h | 2 +- src/qml/jsruntime/qv4vme_moth.cpp | 16 +++++++----- src/qml/qml/qqmljavascriptexpression.cpp | 3 ++- src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 8 +++--- 15 files changed, 109 insertions(+), 77 deletions(-) (limited to 'src/qml') diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 52e908d4f3..2a474eaad5 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -1263,6 +1263,29 @@ Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs) int scope = 0; Context *c = _context; + // skip the innermost context if it's simple (as the runtime won't + // create a context for it + if (c->canUseSimpleCall()) { + Context::Member m = c->findMember(name); + if (m.type != Context::UndefinedMember) { + Q_ASSERT((!m.canEscape)); + Reference r = Reference::fromStackSlot(this, m.index, true /*isLocal*/); + if (name == QLatin1String("arguments") || name == QLatin1String("eval")) { + r.isArgOrEval = true; + if (isLhs && c->isStrict) + // ### add correct source location + throwSyntaxError(SourceLocation(), QStringLiteral("Variable name may not be eval or arguments in strict mode")); + } + return r; + } + const int argIdx = c->findArgument(name); + if (argIdx != -1) { + Q_ASSERT(!c->argumentsCanEscape && c->usesArgumentsObject != Context::ArgumentsObjectUsed); + return Reference::fromArgument(this, argIdx); + } + c = c->parent; + } + while (c->parent) { if (c->forceLookupByName() || (c->isNamedFunctionExpression && c->name == name)) goto loadByName; @@ -1771,8 +1794,8 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, savedBytecodeGenerator = bytecodeGenerator; bytecodeGenerator = &bytecode; - // allocate the js stack frame (Context & js Function) - bytecodeGenerator->newRegisterArray(2); + // allocate the js stack frame (Context & js Function & accumulator) + bytecodeGenerator->newRegisterArray(sizeof(EngineBase::JSStackFrame)/sizeof(Value)); int returnAddress = bytecodeGenerator->newRegister(); diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp index 61cc0294e2..5027975d84 100644 --- a/src/qml/jsapi/qjsengine.cpp +++ b/src/qml/jsapi/qjsengine.cpp @@ -446,7 +446,11 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in QV4::ScopedValue result(scope); QV4::Script script(ctx, program, fileName, lineNumber); - script.strictMode = ctx->d()->v4Function ? ctx->d()->v4Function->isStrict() : false; + script.strictMode = false; + if (v4->currentStackFrame) + script.strictMode = v4->currentStackFrame->v4Function->isStrict(); + else if (v4->globalCode) + script.strictMode = v4->globalCode->isStrict(); script.inheritContext = true; script.parse(); if (!scope.engine->hasException) diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index 5201924bcc..b269b39ff3 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -929,12 +929,11 @@ ReturnedValue ArrayPrototype::method_filter(const BuiltinFunction *b, CallData * a->arrayReserve(len); ScopedValue selected(scope); + ScopedValue v(scope); ScopedCallData cData(scope, 3); cData->thisObject = callData->argument(1); cData->args[2] = instance; - ScopedValue v(scope); - uint to = 0; for (uint k = 0; k < len; ++k) { bool exists; diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index e18d8bce83..ddb5dc4ea5 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -253,24 +253,24 @@ ReturnedValue QV4::ExecutionContext::simpleCall(ExecutionEngine *engine, CallDat { Q_ASSERT(function->canUseSimpleFunction()); - ExecutionContextSaver ctxSaver(engine); - - CallContext::Data *ctx = engine->memoryManager->allocSimpleCallContext(); - - ctx->callData = callData; - ctx->v4Function = function; - ctx->outer.set(engine, this->d()); + Value *jsStackTop = engine->jsStackTop; + engine->jsStackTop = reinterpret_cast(callData) + 2 + (int)function->nFormals; for (int i = callData->argc; i < (int)function->nFormals; ++i) callData->args[i] = Encode::undefined(); - engine->pushContext(ctx); - Q_ASSERT(engine->current == ctx); + ExecutionContext *old = engine->currentContext; + engine->currentContext = this; + engine->current = d(); ReturnedValue res = Q_V4_PROFILE(engine, function, 0); if (function->hasQmlDependencies) QQmlPropertyCapture::registerQmlDependencies(engine, function->compiledFunction); - engine->memoryManager->freeSimpleCallContext(); + + engine->currentContext = old; + engine->current = old->d(); + + engine->jsStackTop = jsStackTop; return res; } diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index ad090682cc..08f4f29763 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -875,14 +875,13 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file) return src; QUrl base; - ExecutionContext *c = currentContext; - while (c) { - CallContext *callCtx = c->asCallContext(); - if (callCtx && callCtx->d()->v4Function) { - base.setUrl(callCtx->d()->v4Function->sourceFile()); + StackFrame *f = currentStackFrame; + while (f) { + if (f->v4Function) { + base.setUrl(f->v4Function->sourceFile()); break; } - c = parentContext(c); + f = f->parent; } if (base.isEmpty() && globalCode) diff --git a/src/qml/jsruntime/qv4enginebase_p.h b/src/qml/jsruntime/qv4enginebase_p.h index a713e8eab4..2aa6910a1c 100644 --- a/src/qml/jsruntime/qv4enginebase_p.h +++ b/src/qml/jsruntime/qv4enginebase_p.h @@ -65,8 +65,9 @@ namespace QV4 { struct EngineBase { struct JSStackFrame { // callData is directly before this - QV4::Value jsFunction; - QV4::Value context; + Value jsFunction; + Value context; + Value accumulator; // ### // registers follow }; diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h index 17311ca3c1..a6b2c0c5d0 100644 --- a/src/qml/jsruntime/qv4function_p.h +++ b/src/qml/jsruntime/qv4function_p.h @@ -100,7 +100,8 @@ struct Q_QML_EXPORT Function { inline unsigned int Heap::CallContext::formalParameterCount() const { - return v4Function ? v4Function->nFormals : 0; + Q_ASSERT(v4Function); + return v4Function->nFormals; } diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index f314d02912..f175e2cd5d 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -359,28 +359,28 @@ ReturnedValue ScriptFunction::construct(const Managed *that, CallData *callData) return Encode::undefined(); CHECK_STACK_LIMITS(v4); - Scope scope(v4); - Scoped f(scope, static_cast(that)); + const ScriptFunction *f = static_cast(that); InternalClass *ic = f->classForConstructor(); - ScopedObject proto(scope, ic->prototype); - callData->thisObject = v4->newObject(ic, proto); + Scope scope(v4); + callData->thisObject = v4->memoryManager->allocObject(ic); QV4::Function *v4Function = f->function(); Q_ASSERT(v4Function); - ScopedContext c(scope, f->scope()); - ScopedValue result(scope); + Value s = Value::fromHeapObject(f->scope()); + ExecutionContext *outer = static_cast(&s); + ReturnedValue result; if (v4Function->canUseSimpleCall) - result = c->simpleCall(scope.engine, callData, v4Function); + result = outer->simpleCall(scope.engine, callData, v4Function); else - result = c->call(scope.engine, callData, v4Function, f); + result = outer->call(scope.engine, callData, v4Function, f); if (Q_UNLIKELY(v4->hasException)) return Encode::undefined(); - else if (!result->isObject()) + else if (!Value::fromReturnedValue(result).isObject()) return callData->thisObject.asReturnedValue(); - return result->asReturnedValue(); + return result; } ReturnedValue ScriptFunction::call(const Managed *that, CallData *callData) diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index 8d2d18fa2a..0fa8e1fc3d 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -49,7 +49,7 @@ using namespace QV4; ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttributes *attrs) { ExecutionEngine *engine = o->engine(); - Identifier *name = engine->current->v4Function->compilationUnit->runtimeStrings[nameIndex]->identifier; + Identifier *name = engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]->identifier; int i = 0; Heap::Object *obj = o->d(); while (i < Size && obj) { @@ -85,7 +85,7 @@ ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs { Heap::Object *obj = thisObject->d(); ExecutionEngine *engine = thisObject->engine(); - Identifier *name = engine->current->v4Function->compilationUnit->runtimeStrings[nameIndex]->identifier; + Identifier *name = engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]->identifier; int i = 0; while (i < Size && obj) { classList[i] = obj->internalClass; @@ -133,7 +133,7 @@ ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Va Q_ASSERT(object.isString()); proto = engine->stringPrototype(); Scope scope(engine); - ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[l->nameIndex]); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]); if (name->equals(engine->id_length())) { // special case, as the property is on the object itself l->getter = stringLengthGetter; @@ -234,7 +234,7 @@ ReturnedValue Lookup::getterFallback(Lookup *l, ExecutionEngine *engine, const V QV4::ScopedObject o(scope, object.toObject(scope.engine)); if (!o) return Encode::undefined(); - ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[l->nameIndex]); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]); return o->get(name); } @@ -580,7 +580,7 @@ ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionEngine *engine) } } Scope scope(engine); - ScopedString n(scope, engine->current->v4Function->compilationUnit->runtimeStrings[l->nameIndex]); + ScopedString n(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]); return engine->throwReferenceError(n); } @@ -697,7 +697,7 @@ bool Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, co o = RuntimeHelpers::convertToObject(scope.engine, object); if (!o) // type error return false; - ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[l->nameIndex]); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]); return o->put(name, value); } return o->setLookup(l, value); @@ -730,7 +730,7 @@ bool Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, c if (!o) return false; - ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[l->nameIndex]); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]); return o->put(name, value); } diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 20d640bb6b..c701e981b7 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -508,7 +508,7 @@ bool Object::setLookup(Managed *m, Lookup *l, const Value &value) { Scope scope(static_cast(m)->engine()); ScopedObject o(scope, static_cast(m)); - ScopedString name(scope, scope.engine->current->v4Function->compilationUnit->runtimeStrings[l->nameIndex]); + ScopedString name(scope, scope.engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]); InternalClass *c = o->internalClass(); uint idx = c->find(name); @@ -1219,7 +1219,7 @@ void Heap::ArrayObject::init(const QStringList &list) ReturnedValue ArrayObject::getLookup(const Managed *m, Lookup *l) { Scope scope(static_cast(m)->engine()); - ScopedString name(scope, scope.engine->current->v4Function->compilationUnit->runtimeStrings[l->nameIndex]); + ScopedString name(scope, scope.engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]); if (name->equals(scope.engine->id_length())) { // special case, as the property is on the object itself l->getter = Lookup::arrayLengthGetter; diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index e81ab783cf..81f1efbff0 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -308,7 +308,7 @@ void RuntimeHelpers::numberToString(QString *result, double num, int radix) ReturnedValue Runtime::method_closure(ExecutionEngine *engine, int functionId) { - QV4::Function *clos = static_cast(engine->current->v4Function->compilationUnit)->runtimeFunctions[functionId]; + QV4::Function *clos = static_cast(engine->currentStackFrame->v4Function->compilationUnit)->runtimeFunctions[functionId]; Q_ASSERT(clos); return FunctionObject::createScriptFunction(engine->currentContext, clos)->asReturnedValue(); } @@ -330,7 +330,7 @@ bool Runtime::method_deleteElement(ExecutionEngine *engine, const Value &base, c bool Runtime::method_deleteMember(ExecutionEngine *engine, const Value &base, int nameIndex) { Scope scope(engine); - ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[nameIndex]); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); return method_deleteMemberString(engine, base, name); } @@ -346,7 +346,7 @@ bool Runtime::method_deleteMemberString(ExecutionEngine *engine, const Value &ba bool Runtime::method_deleteName(ExecutionEngine *engine, int nameIndex) { Scope scope(engine); - ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[nameIndex]); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); return engine->currentContext->deleteProperty(name); } @@ -591,7 +591,7 @@ QV4::ReturnedValue Runtime::method_addString(ExecutionEngine *engine, const Valu bool Runtime::method_setProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value) { Scope scope(engine); - ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[nameIndex]); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); ScopedObject o(scope, object.toObject(engine)); if (!o) return false; @@ -741,14 +741,14 @@ ReturnedValue Runtime::method_foreachNextPropertyName(const Value &foreach_itera bool Runtime::method_setActivationProperty(ExecutionEngine *engine, int nameIndex, const Value &value) { Scope scope(engine); - ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[nameIndex]); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); return engine->currentContext->setProperty(name, value); } ReturnedValue Runtime::method_getProperty(ExecutionEngine *engine, const Value &object, int nameIndex) { Scope scope(engine); - ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[nameIndex]); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); ScopedObject o(scope, object); if (o) @@ -768,7 +768,7 @@ ReturnedValue Runtime::method_getProperty(ExecutionEngine *engine, const Value & ReturnedValue Runtime::method_getActivationProperty(ExecutionEngine *engine, int nameIndex) { Scope scope(engine); - ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[nameIndex]); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); return engine->currentContext->getProperty(name); } @@ -1003,12 +1003,12 @@ ReturnedValue Runtime::method_callGlobalLookup(ExecutionEngine *engine, uint ind Scope scope(engine); Q_ASSERT(callData->thisObject.isUndefined()); - Lookup *l = engine->current->v4Function->compilationUnit->runtimeLookups + index; + Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index; ScopedFunctionObject o(scope, l->globalGetter(l, engine)); if (!o) return engine->throwTypeError(); - ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[l->nameIndex]); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]); if (o->d() == scope.engine->evalFunction()->d() && name->equals(scope.engine->id_eval())) return static_cast(o.getPointer())->evalCall(callData, true); @@ -1020,7 +1020,7 @@ ReturnedValue Runtime::method_callActivationProperty(ExecutionEngine *engine, in { Q_ASSERT(callData->thisObject.isUndefined()); Scope scope(engine); - ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[nameIndex]); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); ScopedObject base(scope); ScopedValue func(scope, engine->currentContext->getPropertyAndBase(name, base.getRef())); @@ -1048,7 +1048,7 @@ ReturnedValue Runtime::method_callActivationProperty(ExecutionEngine *engine, in ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) { Scope scope(engine); - ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[nameIndex]); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); ScopedObject baseObject(scope, callData->thisObject); if (!baseObject) { Q_ASSERT(!callData->thisObject.isEmpty()); @@ -1075,7 +1075,7 @@ ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, int nameInde ReturnedValue Runtime::method_callPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData) { - Lookup *l = engine->current->v4Function->compilationUnit->runtimeLookups + index; + Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index; Value v; v = l->getter(l, engine, callData->thisObject); Object *o = v.objectValue(); @@ -1116,7 +1116,7 @@ ReturnedValue Runtime::method_constructGlobalLookup(ExecutionEngine *engine, uin Scope scope(engine); Q_ASSERT(callData->thisObject.isUndefined()); - Lookup *l = engine->current->v4Function->compilationUnit->runtimeLookups + index; + Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index; ScopedObject f(scope, l->globalGetter(l, engine)); if (f) return f->construct(callData); @@ -1128,7 +1128,7 @@ ReturnedValue Runtime::method_constructGlobalLookup(ExecutionEngine *engine, uin ReturnedValue Runtime::method_constructActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) { Scope scope(engine); - ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[nameIndex]); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); ScopedValue func(scope, engine->currentContext->getProperty(name)); if (scope.engine->hasException) return Encode::undefined(); @@ -1153,7 +1153,7 @@ ReturnedValue Runtime::method_constructProperty(ExecutionEngine *engine, int nam { Scope scope(engine); ScopedObject thisObject(scope, callData->thisObject.toObject(engine)); - ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[nameIndex]); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); if (scope.engine->hasException) return Encode::undefined(); @@ -1166,7 +1166,7 @@ ReturnedValue Runtime::method_constructProperty(ExecutionEngine *engine, int nam ReturnedValue Runtime::method_constructPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData) { - Lookup *l = engine->current->v4Function->compilationUnit->runtimeLookups + index; + Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index; Value v; v = l->getter(l, engine, callData->thisObject); Object *o = v.objectValue(); @@ -1215,7 +1215,7 @@ ReturnedValue Runtime::method_typeofValue(ExecutionEngine *engine, const Value & QV4::ReturnedValue Runtime::method_typeofName(ExecutionEngine *engine, int nameIndex) { Scope scope(engine); - ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[nameIndex]); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); ScopedValue prop(scope, engine->currentContext->getProperty(name)); // typeof doesn't throw. clear any possible exception scope.engine->hasException = false; @@ -1247,7 +1247,7 @@ void Runtime::method_pushCatchScope(NoThrowEngine *engine, int exceptionVarNameI { engine->jsAlloca(1); // keep this symmetric with pushWithScope ExecutionContext *c = engine->currentContext; - engine->pushContext(c->newCatchContext(engine->current->v4Function->compilationUnit->runtimeStrings[exceptionVarNameIndex], engine->catchException(0))); + engine->pushContext(c->newCatchContext(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[exceptionVarNameIndex], engine->catchException(0))); Q_ASSERT(engine->jsStackTop == engine->currentContext + 2); } @@ -1261,7 +1261,7 @@ void Runtime::method_popScope(NoThrowEngine *engine) void Runtime::method_declareVar(ExecutionEngine *engine, bool deletable, int nameIndex) { Scope scope(engine); - ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[nameIndex]); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); engine->currentContext->createMutableBinding(name, deletable); } @@ -1273,7 +1273,7 @@ ReturnedValue Runtime::method_arrayLiteral(ExecutionEngine *engine, Value *value ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags) { Scope scope(engine); - QV4::InternalClass *klass = static_cast(engine->current->v4Function->compilationUnit)->runtimeClasses[classId]; + QV4::InternalClass *klass = static_cast(engine->currentStackFrame->v4Function->compilationUnit)->runtimeClasses[classId]; ScopedObject o(scope, engine->newObject(klass, engine->objectPrototype())); { @@ -1369,7 +1369,7 @@ ReturnedValue Runtime::method_getQmlContext(NoThrowEngine *engine) ReturnedValue Runtime::method_regexpLiteral(ExecutionEngine *engine, int id) { - return static_cast(engine->current->v4Function->compilationUnit)->runtimeRegularExpressions[id].asReturnedValue(); + return static_cast(engine->currentStackFrame->v4Function->compilationUnit)->runtimeRegularExpressions[id].asReturnedValue(); } ReturnedValue Runtime::method_getQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired) @@ -1421,7 +1421,7 @@ ReturnedValue Runtime::method_getQmlImportedScripts(NoThrowEngine *engine) QV4::ReturnedValue Runtime::method_getQmlSingleton(QV4::NoThrowEngine *engine, int nameIndex) { Scope scope(engine); - ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[nameIndex]); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); return engine->qmlSingletonWrapper(name); } diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index f6cb6fda5d..5e3e71a30f 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -109,7 +109,7 @@ struct Scope { ~Scope() { #ifndef QT_NO_DEBUG Q_ASSERT(engine->jsStackTop >= mark); - Q_ASSERT(engine->currentContext < mark); +// Q_ASSERT(engine->currentContext < mark); memset(mark, 0, (engine->jsStackTop - mark)*sizeof(Value)); #endif #ifdef V4_USE_VALGRIND diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 6297f42c81..97e9a90b5a 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -455,17 +455,21 @@ QV4::ReturnedValue VME::exec(Function *function, const FunctionObject *jsFunctio const uchar *exceptionHandler = 0; QV4::Scope scope(engine); - int nFormals = function->nFormals; - stack = scope.alloc(function->compiledFunction->nRegisters + nFormals + 2 + sizeof(EngineBase::JSStackFrame)/sizeof(QV4::Value)); - QV4::Value &accumulator = *stack; - ++stack; - memcpy(stack, &engine->current->callData->thisObject, (nFormals + 1)*sizeof(Value)); - stack += nFormals + 1; + if (!function->canUseSimpleFunction()) { + int nFormals = function->nFormals; + stack = scope.alloc(nFormals + 1 + function->compiledFunction->nRegisters + sizeof(EngineBase::JSStackFrame)/sizeof(QV4::Value)); + memcpy(stack, &engine->current->callData->thisObject, (nFormals + 1)*sizeof(Value)); + stack += nFormals + 1; + } else { + stack = scope.alloc(function->compiledFunction->nRegisters + sizeof(EngineBase::JSStackFrame)/sizeof(QV4::Value)); + } frame.jsFrame = reinterpret_cast(stack); frame.jsFrame->context = engine->current; if (jsFunction) frame.jsFrame->jsFunction = *jsFunction; + QV4::Value &accumulator = frame.jsFrame->accumulator; + if (QV4::Debugging::Debugger *debugger = engine->debugger()) debugger->enteringFunction(); diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index e00c8d30be..231708da70 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -217,10 +217,11 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine()); QV4::Scope scope(v4); + QV4::ScopedValue value(scope); QV4::ScopedValue result(scope, QV4::Primitive::undefinedValue()); callData->thisObject = v4->globalObject; if (scopeObject()) { - QV4::ScopedValue value(scope, QV4::QObjectWrapper::wrap(v4, scopeObject())); + value = QV4::QObjectWrapper::wrap(v4, scopeObject()); if (value->isObject()) callData->thisObject = value; } diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index ebf8918d31..a3874e4e65 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -1908,10 +1908,10 @@ ReturnedValue GlobalExtensions::method_qsTr(const BuiltinFunction *b, CallData * int length = lastDot - (lastSlash + 1); context = (lastSlash > -1) ? path.mid(lastSlash + 1, (length > -1) ? length : -1) : QString(); } else { - ExecutionContext *parentCtx = scope.engine->currentContext; + ExecutionEngine::StackFrame *frame = scope.engine->currentStackFrame; // The first non-empty source URL in the call stack determines the translation context. - while (!!parentCtx && context.isEmpty()) { - if (CompiledData::CompilationUnit *unit = parentCtx->d()->v4Function->compilationUnit) { + while (frame && context.isEmpty()) { + if (CompiledData::CompilationUnit *unit = frame->v4Function->compilationUnit) { QString fileName = unit->fileName(); QUrl url(unit->fileName()); if (url.isValid() && url.isRelative()) { @@ -1923,7 +1923,7 @@ ReturnedValue GlobalExtensions::method_qsTr(const BuiltinFunction *b, CallData * } context = QFileInfo(context).baseName(); } - parentCtx = scope.engine->parentContext(parentCtx); + frame = frame->parent; } } -- cgit v1.2.3