diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2014-02-15 04:39:33 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-02-24 20:41:48 +0100 |
commit | 90a7249e70b37f97907a28ccc6016064231eb861 (patch) | |
tree | 96cb93cc7c4357c7c526063948a49a52e4654df9 | |
parent | c78d1052c2509646c8cf13b460a8d098de836ad0 (diff) |
Determine whether or not an object literal requires a sparse array at compile time
Change-Id: Ieb7f6ee97a4f251f1e2369850ebb9e2931f84ac1
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 4 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_moth.cpp | 8 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_moth_p.h | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_p.cpp | 15 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_p.h | 2 | ||||
-rw-r--r-- | src/qml/jit/qv4isel_masm.cpp | 8 | ||||
-rw-r--r-- | src/qml/jit/qv4isel_masm_p.h | 2 | ||||
-rw-r--r-- | src/qml/jit/qv4regalloc.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 15 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 2 |
11 files changed, 39 insertions, 23 deletions
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 08c523ce56..c424407e2c 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -488,8 +488,8 @@ union Instr struct instr_callBuiltinDefineObjectLiteral { MOTH_INSTR_HEADER int internalClassId; - int arrayValueCount; - int arrayGetterSetterCount; + uint arrayValueCount; + uint arrayGetterSetterCountAndFlags; // 30 bits for count, 1 bit for needsSparseArray boolean quint32 args; Param result; }; diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp index 8045b811ea..0dac3dbdf2 100644 --- a/src/qml/compiler/qv4isel_moth.cpp +++ b/src/qml/compiler/qv4isel_moth.cpp @@ -1260,7 +1260,7 @@ void InstructionSelection::callBuiltinDefineArray(IR::Temp *result, IR::ExprList addInstruction(call); } -void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries) +void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray) { int argLocation = outgoingArgumentTempStart(); @@ -1300,7 +1300,7 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int } // Process array values - int arrayValueCount = 0; + uint arrayValueCount = 0; it = arrayEntries; while (it) { IR::Const *index = it->expr->asConst(); @@ -1332,7 +1332,7 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int } // Process array getter/setter pairs - int arrayGetterSetterCount = 0; + uint arrayGetterSetterCount = 0; it = arrayEntries; while (it) { IR::Const *index = it->expr->asConst(); @@ -1374,7 +1374,7 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int Instruction::CallBuiltinDefineObjectLiteral call; call.internalClassId = classId; call.arrayValueCount = arrayValueCount; - call.arrayGetterSetterCount = arrayGetterSetterCount; + call.arrayGetterSetterCountAndFlags = arrayGetterSetterCount | (needSparseArray << 30); call.args = outgoingArgumentTempStart(); call.result = getResultParam(result); addInstruction(call); diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h index 732341c3ca..000ff634e7 100644 --- a/src/qml/compiler/qv4isel_moth_p.h +++ b/src/qml/compiler/qv4isel_moth_p.h @@ -99,7 +99,7 @@ protected: virtual void callBuiltinPopScope(); virtual void callBuiltinDeclareVar(bool deletable, const QString &name); virtual void callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args); - virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries); + virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray); virtual void callBuiltinSetupArgumentObject(IR::Temp *result); virtual void callBuiltinConvertThisToObject(); virtual void callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result); diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp index 2a73b55ed2..f0092b70fc 100644 --- a/src/qml/compiler/qv4isel_p.cpp +++ b/src/qml/compiler/qv4isel_p.cpp @@ -367,8 +367,21 @@ void IRDecoder::callBuiltin(IR::Call *call, IR::Temp *result) } IR::ExprList *arrayEntries = args; + bool needSparseArray = false; + for (IR::ExprList *it = arrayEntries; it; it = it->next) { + uint index = it->expr->asConst()->value; + if (index > 16) { + needSparseArray = true; + break; + } + it = it->next; + bool isData = it->expr->asConst()->value; + it = it->next; + if (!isData) + it = it->next; + } - callBuiltinDefineObjectLiteral(result, keyValuePairsCount, keyValuePairs, arrayEntries); + callBuiltinDefineObjectLiteral(result, keyValuePairsCount, keyValuePairs, arrayEntries, needSparseArray); } return; case IR::Name::builtin_setup_argument_object: diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h index 7137979b66..f4aab412df 100644 --- a/src/qml/compiler/qv4isel_p.h +++ b/src/qml/compiler/qv4isel_p.h @@ -131,7 +131,7 @@ public: // to implement by subclasses: virtual void callBuiltinPopScope() = 0; virtual void callBuiltinDeclareVar(bool deletable, const QString &name) = 0; virtual void callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args) = 0; - virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries) = 0; + virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray) = 0; virtual void callBuiltinSetupArgumentObject(IR::Temp *result) = 0; virtual void callBuiltinConvertThisToObject() = 0; virtual void callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result) = 0; diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index 2d05592f72..80f22551cd 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -492,7 +492,7 @@ void InstructionSelection::callBuiltinDefineArray(IR::Temp *result, IR::ExprList baseAddressForCallArguments(), Assembler::TrustedImm32(length)); } -void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries) +void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray) { Q_ASSERT(result); @@ -516,7 +516,7 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int } it = arrayEntries; - int arrayValueCount = 0; + uint arrayValueCount = 0; while (it) { uint index = it->expr->asConst()->value; it = it->next; @@ -541,7 +541,7 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int } it = arrayEntries; - int arrayGetterSetterCount = 0; + uint arrayGetterSetterCount = 0; while (it) { uint index = it->expr->asConst()->value; it = it->next; @@ -570,7 +570,7 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int generateFunctionCall(result, __qmljs_builtin_define_object_literal, Assembler::ContextRegister, baseAddressForCallArguments(), Assembler::TrustedImm32(classId), - Assembler::TrustedImm32(arrayValueCount), Assembler::TrustedImm32(arrayGetterSetterCount)); + Assembler::TrustedImm32(arrayValueCount), Assembler::TrustedImm32(arrayGetterSetterCount | (needSparseArray << 30))); } void InstructionSelection::callBuiltinSetupArgumentObject(IR::Temp *result) diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h index 5e4e77318c..62891e4273 100644 --- a/src/qml/jit/qv4isel_masm_p.h +++ b/src/qml/jit/qv4isel_masm_p.h @@ -95,7 +95,7 @@ protected: virtual void callBuiltinPopScope(); virtual void callBuiltinDeclareVar(bool deletable, const QString &name); virtual void callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args); - virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries); + virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray); virtual void callBuiltinSetupArgumentObject(IR::Temp *result); virtual void callBuiltinConvertThisToObject(); virtual void callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result); diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp index 76a0734f07..72ec66d1c2 100644 --- a/src/qml/jit/qv4regalloc.cpp +++ b/src/qml/jit/qv4regalloc.cpp @@ -214,7 +214,7 @@ protected: // IRDecoder virtual void callBuiltinPopScope() {} virtual void callBuiltinDeclareVar(bool , const QString &) {} virtual void callBuiltinDefineArray(IR::Temp *, IR::ExprList *) {} - virtual void callBuiltinDefineObjectLiteral(IR::Temp *, int, IR::ExprList *, IR::ExprList *) {} + virtual void callBuiltinDefineObjectLiteral(IR::Temp *, int, IR::ExprList *, IR::ExprList *, bool) {} virtual void callBuiltinSetupArgumentObject(IR::Temp *) {} virtual void callBuiltinConvertThisToObject() {} diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 7c7ce23bcb..a3ba4b0d75 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1100,12 +1100,18 @@ ReturnedValue __qmljs_builtin_define_array(ExecutionContext *ctx, Value *values, return a.asReturnedValue(); } -ReturnedValue __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCount) +ReturnedValue __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags) { Scope scope(ctx); QV4::InternalClass *klass = ctx->compilationUnit->runtimeClasses[classId]; Scoped<Object> o(scope, ctx->engine->newObject(klass)); + { + bool needSparseArray = arrayGetterSetterCountAndFlags >> 30; + if (needSparseArray) + o->initSparseArray(); + } + for (uint i = 0; i < klass->size; ++i) { if (klass->propertyData[i].isData()) o->memberData[i].value = *args++; @@ -1120,18 +1126,15 @@ ReturnedValue __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, ScopedValue entry(scope); for (int i = 0; i < arrayValueCount; ++i) { uint idx = args->toUInt32(); - if (idx > 16 && (!o->arrayData || idx > o->arrayData->length() * 2)) - o->initSparseArray(); ++args; entry = *args++; o->arraySet(idx, entry); } ScopedProperty pd(scope); - for (int i = 0; i < arrayGetterSetterCount; ++i) { + uint arrayGetterSetterCount = arrayGetterSetterCountAndFlags & ((1 << 30) - 1); + for (uint i = 0; i < arrayGetterSetterCount; ++i) { uint idx = args->toUInt32(); - if (idx > 16 && (!o->arrayData || idx > o->arrayData->length() * 2)) - o->initSparseArray(); ++args; pd->value = *args; ++args; diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h index dbe7e030e1..dbdb891328 100644 --- a/src/qml/jsruntime/qv4runtime_p.h +++ b/src/qml/jsruntime/qv4runtime_p.h @@ -142,7 +142,7 @@ QV4::ExecutionContext *__qmljs_builtin_pop_scope(QV4::ExecutionContext *ctx); ReturnedValue __qmljs_builtin_unwind_exception(ExecutionContext *ctx); void __qmljs_builtin_declare_var(QV4::ExecutionContext *ctx, bool deletable, const QV4::StringRef name); QV4::ReturnedValue __qmljs_builtin_define_array(QV4::ExecutionContext *ctx, Value *values, uint length); -QV4::ReturnedValue __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCount); +QV4::ReturnedValue __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags); QV4::ReturnedValue __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx); void __qmljs_builtin_convert_this_to_object(ExecutionContext *ctx); diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 5ae0b3daff..a657b34be5 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -481,7 +481,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code MOTH_BEGIN_INSTR(CallBuiltinDefineObjectLiteral) QV4::Value *args = stack + instr.args; - STOREVALUE(instr.result, __qmljs_builtin_define_object_literal(context, args, instr.internalClassId, instr.arrayValueCount, instr.arrayGetterSetterCount)); + STOREVALUE(instr.result, __qmljs_builtin_define_object_literal(context, args, instr.internalClassId, instr.arrayValueCount, instr.arrayGetterSetterCountAndFlags)); MOTH_END_INSTR(CallBuiltinDefineObjectLiteral) MOTH_BEGIN_INSTR(CallBuiltinSetupArgumentsObject) |