From 3cfc7e0c026faf70eff8e180a2df3a01b34491c0 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 16 Aug 2013 12:54:30 +0200 Subject: [PATCH] Move arguments object creation into the generated code So far we've been creating the arguments object at runtime in initCallContext(). It's much more efficient to simply add arguments as a local variable in qv4codegen if it's being used and initialize it through a builtin method. Change-Id: I6913f3565adf3aa1917adae8dceef9f50ecf1722 Reviewed-by: Simon Hausmann --- src/qml/compiler/qv4codegen.cpp | 10 +++++++++- src/qml/compiler/qv4instr_moth_p.h | 6 ++++++ src/qml/compiler/qv4isel_masm.cpp | 6 ++++++ src/qml/compiler/qv4isel_masm_p.h | 1 + src/qml/compiler/qv4isel_moth.cpp | 7 +++++++ src/qml/compiler/qv4isel_moth_p.h | 1 + src/qml/compiler/qv4isel_p.cpp | 4 ++++ src/qml/compiler/qv4isel_p.h | 1 + src/qml/compiler/qv4jsir.cpp | 2 ++ src/qml/compiler/qv4jsir_p.h | 3 ++- src/qml/jsruntime/qv4argumentsobject.cpp | 8 ++++---- src/qml/jsruntime/qv4argumentsobject_p.h | 2 +- src/qml/jsruntime/qv4context.cpp | 9 +-------- src/qml/jsruntime/qv4context_p.h | 1 + src/qml/jsruntime/qv4runtime.cpp | 11 +++++++++++ src/qml/jsruntime/qv4runtime_p.h | 2 +- src/qml/jsruntime/qv4vme_moth.cpp | 4 ++++ 17 files changed, 62 insertions(+), 16 deletions(-) diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index e0c77cf..8c75124 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -1820,11 +1820,14 @@ V4IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast, V4IR::BasicBlock *exitBlock = function->newBasicBlock(groupStartBlock(), V4IR::Function::DontInsertBlock); V4IR::BasicBlock *throwBlock = function->newBasicBlock(groupStartBlock()); function->hasDirectEval = _env->hasDirectEval; - function->usesArgumentsObject = (_env->usesArgumentsObject == Environment::ArgumentsObjectUsed); + function->usesArgumentsObject = _env->parent && (_env->usesArgumentsObject == Environment::ArgumentsObjectUsed); function->maxNumberOfArguments = _env->maxNumberOfArguments; function->isStrict = _env->isStrict; function->isNamedExpression = _env->isNamedFunctionExpression; + if (function->usesArgumentsObject) + _env->enter("arguments", Environment::VariableDeclaration); + // variables in global code are properties of the global context object, not locals as with other functions. if (_mode == FunctionCode) { unsigned t = 0; @@ -1897,6 +1900,11 @@ V4IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast, } } } + if (_function->usesArgumentsObject) { + move(_block->NAME("arguments", ast->firstSourceLocation().startLine, ast->firstSourceLocation().startColumn), + _block->CALL(_block->NAME(V4IR::Name::builtin_setup_argument_object, + ast->firstSourceLocation().startLine, ast->firstSourceLocation().startColumn), 0)); + } sourceElements(body); diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 8ddecd0..5e1fb6f 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -92,6 +92,7 @@ QT_BEGIN_NAMESPACE F(CallBuiltinDefineProperty, callBuiltinDefineProperty) \ F(CallBuiltinDefineArray, callBuiltinDefineArray) \ F(CallBuiltinDefineObjectLiteral, callBuiltinDefineObjectLiteral) \ + F(CallBuiltinSetupArgumentsObject, callBuiltinSetupArgumentsObject) \ F(CreateValue, createValue) \ F(CreateProperty, createProperty) \ F(CreateActivationProperty, createActivationProperty) \ @@ -440,6 +441,10 @@ union Instr quint32 args; Param result; }; + struct instr_callBuiltinSetupArgumentsObject { + MOTH_INSTR_HEADER + Param result; + }; struct instr_createValue { MOTH_INSTR_HEADER quint32 argc; @@ -577,6 +582,7 @@ union Instr instr_callBuiltinDefineProperty callBuiltinDefineProperty; instr_callBuiltinDefineArray callBuiltinDefineArray; instr_callBuiltinDefineObjectLiteral callBuiltinDefineObjectLiteral; + instr_callBuiltinSetupArgumentsObject callBuiltinSetupArgumentsObject; instr_createValue createValue; instr_createProperty createProperty; instr_createActivationProperty createActivationProperty; diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp index 861ffbf..b1418e5 100644 --- a/src/qml/compiler/qv4isel_masm.cpp +++ b/src/qml/compiler/qv4isel_masm.cpp @@ -977,6 +977,12 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4 Assembler::TrustedImmPtr(klass)); } +void InstructionSelection::callBuiltinSetupArgumentObject(V4IR::Temp *result) +{ + generateFunctionCall(Assembler::Void, __qmljs_builtin_setup_arguments_object, Assembler::ContextRegister, + Assembler::PointerToValue(result)); +} + void InstructionSelection::callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result) { int argc = prepareVariableArguments(args); diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/compiler/qv4isel_masm_p.h index c2f6604..9c91bfb 100644 --- a/src/qml/compiler/qv4isel_masm_p.h +++ b/src/qml/compiler/qv4isel_masm_p.h @@ -815,6 +815,7 @@ protected: virtual void callBuiltinDefineProperty(V4IR::Temp *object, const QString &name, V4IR::Temp *value); virtual void callBuiltinDefineArray(V4IR::Temp *result, V4IR::ExprList *args); virtual void callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4IR::ExprList *args); + virtual void callBuiltinSetupArgumentObject(V4IR::Temp *result); virtual void callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result); virtual void callProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result); virtual void callSubscript(V4IR::Temp *base, V4IR::Temp *index, V4IR::ExprList *args, V4IR::Temp *result); diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp index 6edb2e4..813acde 100644 --- a/src/qml/compiler/qv4isel_moth.cpp +++ b/src/qml/compiler/qv4isel_moth.cpp @@ -1003,6 +1003,13 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4 addInstruction(call); } +void InstructionSelection::callBuiltinSetupArgumentObject(V4IR::Temp *result) +{ + Instruction::CallBuiltinSetupArgumentsObject call; + call.result = getResultParam(result); + addInstruction(call); +} + ptrdiff_t InstructionSelection::addInstructionHelper(Instr::Type type, Instr &instr) { #ifdef MOTH_THREADED_INTERPRETER diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h index f5fffe7..b6e4b43 100644 --- a/src/qml/compiler/qv4isel_moth_p.h +++ b/src/qml/compiler/qv4isel_moth_p.h @@ -100,6 +100,7 @@ protected: virtual void callBuiltinDefineProperty(V4IR::Temp *object, const QString &name, V4IR::Temp *value); virtual void callBuiltinDefineArray(V4IR::Temp *result, V4IR::ExprList *args); virtual void callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4IR::ExprList *args); + virtual void callBuiltinSetupArgumentObject(V4IR::Temp *result); virtual void callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result); virtual void callProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result); virtual void callSubscript(V4IR::Temp *base, V4IR::Temp *index, V4IR::ExprList *args, V4IR::Temp *result); diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp index c864378..7194473 100644 --- a/src/qml/compiler/qv4isel_p.cpp +++ b/src/qml/compiler/qv4isel_p.cpp @@ -428,6 +428,10 @@ void IRDecoder::callBuiltin(V4IR::Call *call, V4IR::Temp *result) callBuiltinDefineObjectLiteral(result, call->args); return; + case V4IR::Name::builtin_setup_argument_object: + callBuiltinSetupArgumentObject(result); + return; + default: break; } diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h index 965caf2..2de7ba6 100644 --- a/src/qml/compiler/qv4isel_p.h +++ b/src/qml/compiler/qv4isel_p.h @@ -128,6 +128,7 @@ public: // to implement by subclasses: virtual void callBuiltinDefineProperty(V4IR::Temp *object, const QString &name, V4IR::Temp *value) = 0; virtual void callBuiltinDefineArray(V4IR::Temp *result, V4IR::ExprList *args) = 0; virtual void callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4IR::ExprList *args) = 0; + virtual void callBuiltinSetupArgumentObject(V4IR::Temp *result) = 0; virtual void callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result) = 0; virtual void callProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result) = 0; virtual void callSubscript(V4IR::Temp *base, V4IR::Temp *index, V4IR::ExprList *args, V4IR::Temp *result) = 0; diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp index f10c869..3c5ba72 100644 --- a/src/qml/compiler/qv4jsir.cpp +++ b/src/qml/compiler/qv4jsir.cpp @@ -413,6 +413,8 @@ static const char *builtin_to_string(Name::Builtin b) return "builtin_define_getter_setter"; case V4IR::Name::builtin_define_object_literal: return "builtin_define_object_literal"; + case V4IR::Name::builtin_setup_argument_object: + return "builtin_setup_argument_object"; } return "builtin_(###FIXME)"; }; diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h index 30e9074..82dc098 100644 --- a/src/qml/compiler/qv4jsir_p.h +++ b/src/qml/compiler/qv4jsir_p.h @@ -314,7 +314,8 @@ struct Name: Expr { builtin_define_property, builtin_define_array, builtin_define_getter_setter, - builtin_define_object_literal + builtin_define_object_literal, + builtin_setup_argument_object }; const QString *id; diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index 07374a0..1670f69 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -50,7 +50,7 @@ static Value throwTypeError(SimpleCallContext *ctx) DEFINE_MANAGED_VTABLE(ArgumentsObject); -ArgumentsObject::ArgumentsObject(CallContext *context, int formalParameterCount, int actualParameterCount) +ArgumentsObject::ArgumentsObject(CallContext *context) : Object(context->engine), context(context) { vtbl = &static_vtbl; @@ -76,8 +76,8 @@ ArgumentsObject::ArgumentsObject(CallContext *context, int formalParameterCount, memberData[CalleePropertyIndex].value = Value::fromObject(context->function); isNonStrictArgumentsObject = true; - uint numAccessors = qMin(formalParameterCount, actualParameterCount); - uint argCount = qMin((uint)actualParameterCount, context->argumentCount); + uint numAccessors = qMin(context->function->formalParameterCount, context->realArgumentCount); + uint argCount = qMin((uint)context->realArgumentCount, context->argumentCount); arrayReserve(argCount); ensureArrayAttributes(); context->engine->requireArgumentsAccessors(numAccessors); @@ -94,7 +94,7 @@ ArgumentsObject::ArgumentsObject(CallContext *context, int formalParameterCount, } assert(LengthPropertyIndex == internalClass->find(context->engine->id_length)); Property *lp = memberData + ArrayObject::LengthPropertyIndex; - lp->value = Value::fromInt32(actualParameterCount); + lp->value = Value::fromInt32(context->realArgumentCount); } void ArgumentsObject::destroy(Managed *that) diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h index 05016cc..097bc4c 100644 --- a/src/qml/jsruntime/qv4argumentsobject_p.h +++ b/src/qml/jsruntime/qv4argumentsobject_p.h @@ -78,7 +78,7 @@ protected: struct ArgumentsObject: Object { CallContext *context; QVector mappedArguments; - ArgumentsObject(CallContext *context, int formalParameterCount, int actualParameterCount); + ArgumentsObject(CallContext *context); ~ArgumentsObject() {} enum { diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index ce947e5..c67b105 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -160,6 +160,7 @@ void CallContext::initCallContext(ExecutionContext *parentContext, FunctionObjec this->function = function; this->arguments = _arguments; + this->realArgumentCount = _argumentCount; this->argumentCount = _argumentCount; this->thisObject = _thisObject; @@ -191,14 +192,6 @@ void CallContext::initCallContext(ExecutionContext *parentContext, FunctionObjec std::fill(arguments + argc, arguments + function->formalParameterCount, Value::undefinedValue()); } - - if (function->usesArgumentsObject) { - ArgumentsObject *args = new (engine->memoryManager) ArgumentsObject(this, function->formalParameterCount, argc); - args->prototype = engine->objectPrototype; - activation = engine->newObject(); - Property desc = Property::fromValue(Value::fromObject(args)); - activation->__defineOwnProperty__(this, engine->id_arguments, desc, Attr_NotConfigurable); - } } void CallContext::initQmlContext(ExecutionContext *parentContext, Object *qml, FunctionObject *function) diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index dfe02bd..79d43c6 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -157,6 +157,7 @@ struct SimpleCallContext : public ExecutionContext void initSimpleCallContext(ExecutionEngine *engine); FunctionObject *function; Value *arguments; + unsigned int realArgumentCount; unsigned int argumentCount; }; diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 76e908c..79bbbf6 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -46,6 +46,7 @@ #include "qv4objectproto_p.h" #include "qv4globalobject_p.h" #include "qv4stringobject_p.h" +#include "qv4argumentsobject_p.h" #include "qv4lookup_p.h" #include "qv4function_p.h" #include "qv4exception_p.h" @@ -1221,6 +1222,15 @@ void __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, QV4::Valu *result = Value::fromObject(o); } +void __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx, Value *result) +{ + assert(ctx->type >= ExecutionContext::Type_CallContext); + CallContext *c = static_cast(ctx); + ArgumentsObject *args = new (c->engine->memoryManager) ArgumentsObject(c); + args->prototype = c->engine->objectPrototype; + *result = Value::fromObject(args); +} + void __qmljs_increment(Value *result, const Value &value) { TRACE1(value); @@ -1264,6 +1274,7 @@ unsigned __qmljs_double_to_uint32(double d) { return Value::toUInt32(d); } + } // namespace QV4 QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h index dd75e6f..bce9508 100644 --- a/src/qml/jsruntime/qv4runtime_p.h +++ b/src/qml/jsruntime/qv4runtime_p.h @@ -125,7 +125,7 @@ void __qmljs_builtin_define_property(QV4::ExecutionContext *ctx, const QV4::Valu void __qmljs_builtin_define_array(QV4::ExecutionContext *ctx, QV4::Value *array, QV4::Value *values, uint length); void __qmljs_builtin_define_getter_setter(QV4::ExecutionContext *ctx, const QV4::Value &object, QV4::String *name, const QV4::Value *getter, const QV4::Value *setter); void __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value *args, QV4::InternalClass *klass); - +void __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx, QV4::Value *result); // constructors void __qmljs_init_closure(QV4::ExecutionContext *ctx, QV4::Value *result, QV4::Function *clos); QV4::Function *__qmljs_register_function(QV4::ExecutionContext *ctx, QV4::String *name, diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 32313c3..7fc52ff 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -467,6 +467,10 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code, __qmljs_builtin_define_object_literal(context, VALUEPTR(instr.result), args, instr.internalClass); MOTH_END_INSTR(CallBuiltinDefineObjectLiteral) + MOTH_BEGIN_INSTR(CallBuiltinSetupArgumentsObject) + __qmljs_builtin_setup_arguments_object(context, VALUEPTR(instr.result)); + MOTH_END_INSTR(CallBuiltinSetupArgumentsObject) + MOTH_BEGIN_INSTR(CreateValue) Q_ASSERT(instr.args + instr.argc <= stackSize); QV4::Value *args = stack + instr.args; -- 2.7.4