From 4e4fb0ced23391c4ffb1b59845d94e6c658d3deb Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 24 Jan 2013 12:53:47 +0100 Subject: [PATCH] Fix properties of literal array initialisers Array entries defined in such a way need to be own properties. To avoid calling builtin_define_property with the integer index converted to a string for each property, this patch also introduces a builtin_define_array_property that takes an integer index instead. Change-Id: Ib21f99a555b3237753a7930a7edc70bfcd49ac18 Reviewed-by: Lars Knoll --- moth/qv4instr_moth_p.h | 8 ++++++++ moth/qv4isel_moth.cpp | 9 +++++++++ moth/qv4isel_moth_p.h | 1 + moth/qv4vme_moth.cpp | 4 ++++ qmljs_runtime.cpp | 14 ++++++++++++++ qmljs_runtime.h | 1 + qv4codegen.cpp | 19 ++++++++++++++++++- qv4ir.cpp | 2 ++ qv4ir_p.h | 1 + qv4isel_masm.cpp | 6 ++++++ qv4isel_masm_p.h | 1 + qv4isel_p.cpp | 16 ++++++++++++++++ qv4isel_p.h | 1 + tests/TestExpectations | 16 +--------------- 14 files changed, 83 insertions(+), 16 deletions(-) diff --git a/moth/qv4instr_moth_p.h b/moth/qv4instr_moth_p.h index a2863ef..28d72cb 100644 --- a/moth/qv4instr_moth_p.h +++ b/moth/qv4instr_moth_p.h @@ -32,6 +32,7 @@ F(CallBuiltinDeclareVar, callBuiltinDeclareVar) \ F(CallBuiltinDefineGetterSetter, callBuiltinDefineGetterSetter) \ F(CallBuiltinDefineProperty, callBuiltinDefineProperty) \ + F(CallBuiltinDefineArrayProperty, callBuiltinDefineArrayProperty) \ F(CreateValue, createValue) \ F(CreateProperty, createProperty) \ F(CreateActivationProperty, createActivationProperty) \ @@ -240,6 +241,12 @@ union Instr VM::String *name; int valueTemp; }; + struct instr_callBuiltinDefineArrayProperty { + MOTH_INSTR_HEADER + int objectTemp; + int index; + int valueTemp; + }; struct instr_createValue { MOTH_INSTR_HEADER int func; @@ -342,6 +349,7 @@ union Instr instr_callBuiltinDeclareVar callBuiltinDeclareVar; instr_callBuiltinDefineGetterSetter callBuiltinDefineGetterSetter; instr_callBuiltinDefineProperty callBuiltinDefineProperty; + instr_callBuiltinDefineArrayProperty callBuiltinDefineArrayProperty; instr_createValue createValue; instr_createProperty createProperty; instr_createActivationProperty createActivationProperty; diff --git a/moth/qv4isel_moth.cpp b/moth/qv4isel_moth.cpp index 2246442..eab1e63 100644 --- a/moth/qv4isel_moth.cpp +++ b/moth/qv4isel_moth.cpp @@ -847,6 +847,15 @@ void InstructionSelection::callBuiltinDefineProperty(IR::Temp *object, const QSt addInstruction(call); } +void InstructionSelection::callBuiltinDefineArrayProperty(IR::Temp *object, int index, IR::Temp *value) +{ + Instruction::CallBuiltinDefineArrayProperty call; + call.objectTemp = object->index; + call.index = index; + call.valueTemp = value->index; + addInstruction(call); +} + ptrdiff_t InstructionSelection::addInstructionHelper(Instr::Type type, Instr &instr) { #ifdef MOTH_THREADED_INTERPRETER diff --git a/moth/qv4isel_moth_p.h b/moth/qv4isel_moth_p.h index 10cb33a..3874adf 100644 --- a/moth/qv4isel_moth_p.h +++ b/moth/qv4isel_moth_p.h @@ -44,6 +44,7 @@ protected: virtual void callBuiltinDeclareVar(bool deletable, const QString &name); virtual void callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter); virtual void callBuiltinDefineProperty(IR::Temp *object, const QString &name, IR::Temp *value); + virtual void callBuiltinDefineArrayProperty(IR::Temp *object, int index, IR::Temp *value); virtual void callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result); virtual void callProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result); virtual void constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Temp *result); diff --git a/moth/qv4vme_moth.cpp b/moth/qv4vme_moth.cpp index fbfa47d..5052d82 100644 --- a/moth/qv4vme_moth.cpp +++ b/moth/qv4vme_moth.cpp @@ -339,6 +339,10 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co __qmljs_builtin_define_property(TEMP(instr.objectTemp), instr.name, TEMP(instr.valueTemp), context); MOTH_END_INSTR(CallBuiltinDefineProperty) + MOTH_BEGIN_INSTR(CallBuiltinDefineArrayProperty) + __qmljs_builtin_define_array_property(TEMP(instr.objectTemp), instr.index, TEMP(instr.valueTemp), context); + MOTH_END_INSTR(CallBuiltinDefineArrayProperty) + MOTH_BEGIN_INSTR(CreateValue) int argStart = instr.args - context->variableCount(); VM::Value *args = stack + argStart; diff --git a/qmljs_runtime.cpp b/qmljs_runtime.cpp index 114a7b9..e297dab 100644 --- a/qmljs_runtime.cpp +++ b/qmljs_runtime.cpp @@ -924,6 +924,20 @@ void __qmljs_builtin_define_property(Value object, String *name, Value val, Exec o->__defineOwnProperty__(ctx, name, &pd); } +void __qmljs_builtin_define_array_property(Value object, int index, Value val, ExecutionContext *ctx) +{ + Object *o = object.asObject(); + assert(o); + + PropertyDescriptor pd; + pd.value = val; + pd.type = PropertyDescriptor::Data; + pd.writable = PropertyDescriptor::Enabled; + pd.enumberable = PropertyDescriptor::Enabled; + pd.configurable = PropertyDescriptor::Enabled; + o->__defineOwnProperty__(ctx, index, &pd); +} + void __qmljs_builtin_define_getter_setter(Value object, String *name, Value getter, Value setter, ExecutionContext *ctx) { Object *o = object.asObject(); diff --git a/qmljs_runtime.h b/qmljs_runtime.h index e1c6d5a..08ba85a 100644 --- a/qmljs_runtime.h +++ b/qmljs_runtime.h @@ -105,6 +105,7 @@ ExecutionContext *__qmljs_builtin_push_with_scope(Value o, ExecutionContext *ctx ExecutionContext *__qmljs_builtin_pop_scope(ExecutionContext *ctx); void __qmljs_builtin_declare_var(ExecutionContext *ctx, bool deletable, String *name); void __qmljs_builtin_define_property(Value object, String *name, Value val, ExecutionContext *ctx); +void __qmljs_builtin_define_array_property(Value object, int index, Value val, ExecutionContext *ctx); void __qmljs_builtin_define_getter_setter(Value object, String *name, Value getter, Value setter, ExecutionContext *ctx); // constructors diff --git a/qv4codegen.cpp b/qv4codegen.cpp index 5ee7159..5678373 100644 --- a/qv4codegen.cpp +++ b/qv4codegen.cpp @@ -1025,11 +1025,28 @@ bool Codegen::visit(ArrayLiteral *ast) const unsigned t = _block->newTemp(); move(_block->TEMP(t), _block->NEW(_block->NAME(QStringLiteral("Array"), ast->firstSourceLocation().startLine, ast->firstSourceLocation().startColumn))); int index = 0; + unsigned value = 0; for (ElementList *it = ast->elements; it; it = it->next) { for (Elision *elision = it->elision; elision; elision = elision->next) ++index; Result expr = expression(it->expression); - move(subscript(_block->TEMP(t), _block->CONST(IR::NumberType, index)), *expr); + + IR::ExprList *args = _function->New(); + IR::ExprList *current = args; + current->expr = _block->TEMP(t); + current->next = _function->New(); + current = current->next; + current->expr = _block->CONST(IR::NumberType, index); + current->next = _function->New(); + current = current->next; + + if (!value) + value = _block->newTemp(); + move(_block->TEMP(value), *expr); + // __qmljs_builtin_define_property(Value object, String *name, Value val, ExecutionContext *ctx) + current->expr = _block->TEMP(value); + _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_define_array_property, 0, 0), args)); + ++index; } if (ast->elision) { diff --git a/qv4ir.cpp b/qv4ir.cpp index 969d07a..a34a294 100644 --- a/qv4ir.cpp +++ b/qv4ir.cpp @@ -244,6 +244,8 @@ static const char *builtin_to_string(Name::Builtin b) return "builtin_declare_vars"; case IR::Name::builtin_define_property: return "builtin_define_property"; + case IR::Name::builtin_define_array_property: + return "builtin_define_array_property"; case IR::Name::builtin_define_getter_setter: return "builtin_define_getter_setter"; } diff --git a/qv4ir_p.h b/qv4ir_p.h index 6905978..f77cb58 100644 --- a/qv4ir_p.h +++ b/qv4ir_p.h @@ -285,6 +285,7 @@ struct Name: Expr { builtin_pop_scope, builtin_declare_vars, builtin_define_property, + builtin_define_array_property, builtin_define_getter_setter }; diff --git a/qv4isel_masm.cpp b/qv4isel_masm.cpp index 5f34c02..15cf5fc 100644 --- a/qv4isel_masm.cpp +++ b/qv4isel_masm.cpp @@ -541,6 +541,12 @@ void InstructionSelection::callBuiltinDefineProperty(IR::Temp *object, const QSt object, identifier(name), value, Assembler::ContextRegister); } +void InstructionSelection::callBuiltinDefineArrayProperty(IR::Temp *object, int index, IR::Temp *value) +{ + generateFunctionCall(Assembler::Void, __qmljs_builtin_define_array_property, + object, Assembler::TrustedImm32(index), value, Assembler::ContextRegister); +} + void InstructionSelection::callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result) { int argc = prepareVariableArguments(args); diff --git a/qv4isel_masm_p.h b/qv4isel_masm_p.h index e45ed51..35f4852 100644 --- a/qv4isel_masm_p.h +++ b/qv4isel_masm_p.h @@ -672,6 +672,7 @@ protected: virtual void callBuiltinDeclareVar(bool deletable, const QString &name); virtual void callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter); virtual void callBuiltinDefineProperty(IR::Temp *object, const QString &name, IR::Temp *value); + virtual void callBuiltinDefineArrayProperty(IR::Temp *object, int index, IR::Temp *value); virtual void callProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result); virtual void callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result); virtual void loadThisObject(IR::Temp *temp); diff --git a/qv4isel_p.cpp b/qv4isel_p.cpp index 17f8466..03600fd 100644 --- a/qv4isel_p.cpp +++ b/qv4isel_p.cpp @@ -348,6 +348,22 @@ void InstructionSelection::callBuiltin(IR::Call *call, IR::Temp *result) callBuiltinDefineProperty(object, *name->id, value); } return; + case IR::Name::builtin_define_array_property: { + if (!call->args) + return; + IR::ExprList *args = call->args; + IR::Temp *object = args->expr->asTemp(); + assert(object); + args = args->next; + assert(args); + IR::Const *index = args->expr->asConst(); + args = args->next; + assert(args); + IR::Temp *value = args->expr->asTemp(); + + callBuiltinDefineArrayProperty(object, int(index->value), value); + } return; + default: break; } diff --git a/qv4isel_p.h b/qv4isel_p.h index fc14552..8b932ae 100644 --- a/qv4isel_p.h +++ b/qv4isel_p.h @@ -100,6 +100,7 @@ public: // to implement by subclasses: virtual void callBuiltinDeclareVar(bool deletable, const QString &name) = 0; virtual void callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter) = 0; virtual void callBuiltinDefineProperty(IR::Temp *object, const QString &name, IR::Temp *value) = 0; + virtual void callBuiltinDefineArrayProperty(IR::Temp *object, int index, IR::Temp *value) = 0; virtual void callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result) = 0; virtual void callProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result) = 0; virtual void constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Temp *result) = 0; diff --git a/tests/TestExpectations b/tests/TestExpectations index 4193992..e6a473f 100644 --- a/tests/TestExpectations +++ b/tests/TestExpectations @@ -13,8 +13,6 @@ S15.1.3.2_A2.5_T1 10.4.3-1-17-s failing 10.4.3-1-63-s failing 10.4.3-1-82-s failing -11.1.4_4-5-1 failing -11.1.4_5-6-1 failing S11.11.1_A2.1_T1 failing S11.11.1_A3_T2 failing S11.11.1_A3_T3 failing @@ -110,21 +108,9 @@ S15.12.2_A1 failing 15.4.4.14-9-a-17 failing 15.4.4.14-9-a-7 failing 15.4.4.14-9-a-9 failing -15.4.4.14-9-b-i-5 failing -15.4.4.15-8-b-i-5 failing -15.4.4.16-7-c-i-6 failing -15.4.4.17-7-c-i-6 failing -15.4.4.18-7-c-i-6 failing 15.4.4.19-5-1 failing -15.4.4.19-8-c-i-6 failing -15.4.4.20-9-c-i-6 failing -15.4.4.21-8-b-iii-1-6 failing -15.4.4.21-9-c-i-6 failing -15.4.4.22-8-b-iii-1-6 failing -15.4.4.22-9-c-i-6 failing S15.4.4.3_A1_T1 failing S15.4.4.3_A3_T1 failing -15.4.4.4-5-b-iii-3-b-1 failing 15.4.4.4-5-c-i-1 failing S15.4.4.4_A1_T2 failing S15.4.4.4_A2_T1 failing @@ -156,4 +142,4 @@ S12.9_A1_T6 failing S12.9_A1_T7 failing S12.9_A1_T8 failing S12.9_A1_T9 failing -S15.2.4.4_A14 failing \ No newline at end of file +S15.2.4.4_A14 failing -- 2.7.4