aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-02-15 04:39:33 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-02-24 20:41:48 +0100
commit90a7249e70b37f97907a28ccc6016064231eb861 (patch)
tree96cb93cc7c4357c7c526063948a49a52e4654df9
parentc78d1052c2509646c8cf13b460a8d098de836ad0 (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.h4
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp8
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h2
-rw-r--r--src/qml/compiler/qv4isel_p.cpp15
-rw-r--r--src/qml/compiler/qv4isel_p.h2
-rw-r--r--src/qml/jit/qv4isel_masm.cpp8
-rw-r--r--src/qml/jit/qv4isel_masm_p.h2
-rw-r--r--src/qml/jit/qv4regalloc.cpp2
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp15
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h2
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp2
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)