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 <simon.hausmann@digia.com>
This commit is contained in:
parent
51e7447481
commit
3cfc7e0c02
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)";
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -78,7 +78,7 @@ protected:
|
|||
struct ArgumentsObject: Object {
|
||||
CallContext *context;
|
||||
QVector<Value> mappedArguments;
|
||||
ArgumentsObject(CallContext *context, int formalParameterCount, int actualParameterCount);
|
||||
ArgumentsObject(CallContext *context);
|
||||
~ArgumentsObject() {}
|
||||
|
||||
enum {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -157,6 +157,7 @@ struct SimpleCallContext : public ExecutionContext
|
|||
void initSimpleCallContext(ExecutionEngine *engine);
|
||||
FunctionObject *function;
|
||||
Value *arguments;
|
||||
unsigned int realArgumentCount;
|
||||
unsigned int argumentCount;
|
||||
};
|
||||
|
||||
|
|
|
@ -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<CallContext *>(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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue