aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qv4codegen.cpp199
-rw-r--r--src/qml/compiler/qv4codegen_p.h6
-rw-r--r--src/qml/compiler/qv4compiler.cpp8
-rw-r--r--src/qml/compiler/qv4compiler_p.h2
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h19
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp103
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h4
-rw-r--r--src/qml/compiler/qv4isel_p.cpp53
-rw-r--r--src/qml/compiler/qv4isel_p.h6
-rw-r--r--src/qml/compiler/qv4jsir.cpp4
-rw-r--r--src/qml/compiler/qv4jsir_p.h2
-rw-r--r--src/qml/jit/qv4isel_masm.cpp83
-rw-r--r--src/qml/jit/qv4isel_masm_p.h4
-rw-r--r--src/qml/jit/qv4regalloc.cpp4
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp59
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h4
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp10
-rw-r--r--src/qml/parser/qqmljsast_p.h22
18 files changed, 285 insertions, 307 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 6685336b5f..f08ebaf6cd 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -261,6 +261,9 @@ bool Codegen::ScanFunctions::visit(ObjectLiteral *ast)
{
int argc = 0;
for (PropertyAssignmentList *it = ast->properties; it; it = it->next) {
+ QString key = it->assignment->name->asString();
+ if (QV4::String::toArrayIndex(key) != UINT_MAX)
+ ++argc;
++argc;
if (AST::cast<AST::PropertyGetterSetter *>(it->assignment))
++argc;
@@ -776,17 +779,6 @@ Codegen::Result Codegen::expression(ExpressionNode *ast)
return r;
}
-QString Codegen::propertyName(PropertyName *ast)
-{
- QString p;
- if (ast) {
- qSwap(_property, p);
- accept(ast);
- qSwap(_property, p);
- }
- return p;
-}
-
Codegen::Result Codegen::sourceElement(SourceElement *ast)
{
Result r(nx);
@@ -1597,8 +1589,8 @@ bool Codegen::visit(ObjectLiteral *ast)
QMap<QString, ObjectPropertyValue> valueMap;
for (PropertyAssignmentList *it = ast->properties; it; it = it->next) {
+ QString name = it->assignment->name->asString();
if (PropertyNameAndValue *nv = AST::cast<AST::PropertyNameAndValue *>(it->assignment)) {
- QString name = propertyName(nv->name);
Result value = expression(nv->value);
ObjectPropertyValue &v = valueMap[name];
if (v.hasGetter() || v.hasSetter() || (_function->isStrict && v.value)) {
@@ -1609,7 +1601,6 @@ bool Codegen::visit(ObjectLiteral *ast)
valueMap[name].value = *value;
} else if (PropertyGetterSetter *gs = AST::cast<AST::PropertyGetterSetter *>(it->assignment)) {
- QString name = propertyName(gs->name);
const int function = defineFunction(name, gs, gs->formals, gs->functionBody ? gs->functionBody->elements : 0);
ObjectPropertyValue &v = valueMap[name];
if (v.value ||
@@ -1628,104 +1619,99 @@ bool Codegen::visit(ObjectLiteral *ast)
}
}
- IR::ExprList *args = 0;
+ // The linked-list arguments to builtin_define_object_literal
+ // begin with a CONST counting the number of key/value pairs, followed by the
+ // key value pairs, followed by the array entries.
+ IR::ExprList *args = _function->New<IR::ExprList>();
- if (!valueMap.isEmpty()) {
- IR::ExprList *current;
- for (QMap<QString, ObjectPropertyValue>::iterator it = valueMap.begin(); it != valueMap.end(); ) {
- if (QV4::String::toArrayIndex(it.key()) != UINT_MAX) {
- ++it;
- continue;
+ IR::Const *entryCountParam = _function->New<IR::Const>();
+ entryCountParam->init(IR::SInt32Type, 0);
+ args->expr = entryCountParam;
+ args->next = 0;
+
+ IR::ExprList *keyValueEntries = 0;
+ IR::ExprList *currentKeyValueEntry = 0;
+ int keyValueEntryCount = 0;
+ IR::ExprList *arrayEntries = 0;
+
+ IR::ExprList *currentArrayEntry = 0;
+
+ for (QMap<QString, ObjectPropertyValue>::iterator it = valueMap.begin(); it != valueMap.end(); ) {
+ IR::ExprList **currentPtr = 0;
+ uint keyAsIndex = QV4::String::toArrayIndex(it.key());
+ if (keyAsIndex != UINT_MAX) {
+ if (!arrayEntries) {
+ arrayEntries = _function->New<IR::ExprList>();
+ currentArrayEntry = arrayEntries;
+ } else {
+ currentArrayEntry->next = _function->New<IR::ExprList>();
+ currentArrayEntry = currentArrayEntry->next;
}
-
- if (!args) {
- args = _function->New<IR::ExprList>();
- current = args;
+ currentPtr = &currentArrayEntry;
+ IR::Const *idx = _function->New<IR::Const>();
+ idx->init(IR::UInt32Type, keyAsIndex);
+ (*currentPtr)->expr = idx;
+ } else {
+ if (!keyValueEntries) {
+ keyValueEntries = _function->New<IR::ExprList>();
+ currentKeyValueEntry = keyValueEntries;
} else {
- current->next = _function->New<IR::ExprList>();
- current = current->next;
+ currentKeyValueEntry->next = _function->New<IR::ExprList>();
+ currentKeyValueEntry = currentKeyValueEntry->next;
}
+ currentPtr = &currentKeyValueEntry;
+ (*currentPtr)->expr = _block->NAME(it.key(), 0, 0);
+ keyValueEntryCount++;
+ }
- current->expr = _block->NAME(it.key(), 0, 0);
-
- if (it->value) {
- current->next = _function->New<IR::ExprList>();
- current = current->next;
- current->expr = _block->CONST(IR::BoolType, true);
-
- unsigned value = _block->newTemp();
- move(_block->TEMP(value), it->value);
+ IR::ExprList *&current = *currentPtr;
+ if (it->value) {
+ current->next = _function->New<IR::ExprList>();
+ current = current->next;
+ current->expr = _block->CONST(IR::BoolType, true);
- current->next = _function->New<IR::ExprList>();
- current = current->next;
- current->expr = _block->TEMP(value);
- } else {
- current->next = _function->New<IR::ExprList>();
- current = current->next;
- current->expr = _block->CONST(IR::BoolType, false);
-
- unsigned getter = _block->newTemp();
- unsigned setter = _block->newTemp();
- move(_block->TEMP(getter), it->hasGetter() ? _block->CLOSURE(it->getter) : _block->CONST(IR::UndefinedType, 0));
- move(_block->TEMP(setter), it->hasSetter() ? _block->CLOSURE(it->setter) : _block->CONST(IR::UndefinedType, 0));
-
- current->next = _function->New<IR::ExprList>();
- current = current->next;
- current->expr = _block->TEMP(getter);
- current->next = _function->New<IR::ExprList>();
- current = current->next;
- current->expr = _block->TEMP(setter);
- }
+ unsigned value = _block->newTemp();
+ move(_block->TEMP(value), it->value);
- it = valueMap.erase(it);
- }
- }
+ current->next = _function->New<IR::ExprList>();
+ current = current->next;
+ current->expr = _block->TEMP(value);
+ } else {
+ current->next = _function->New<IR::ExprList>();
+ current = current->next;
+ current->expr = _block->CONST(IR::BoolType, false);
- const unsigned t = _block->newTemp();
- move(_block->TEMP(t), _block->CALL(_block->NAME(IR::Name::builtin_define_object_literal,
- ast->firstSourceLocation().startLine, ast->firstSourceLocation().startColumn), args));
+ unsigned getter = _block->newTemp();
+ unsigned setter = _block->newTemp();
+ move(_block->TEMP(getter), it->hasGetter() ? _block->CLOSURE(it->getter) : _block->CONST(IR::UndefinedType, 0));
+ move(_block->TEMP(setter), it->hasSetter() ? _block->CLOSURE(it->setter) : _block->CONST(IR::UndefinedType, 0));
- // What's left are array entries
- if (!valueMap.isEmpty()) {
- unsigned value = 0;
- unsigned getter = 0;
- unsigned setter = 0;
- for (QMap<QString, ObjectPropertyValue>::const_iterator it = valueMap.constBegin(); it != valueMap.constEnd(); ++it) {
- IR::ExprList *args = _function->New<IR::ExprList>();
- IR::ExprList *current = args;
- current->expr = _block->TEMP(t);
current->next = _function->New<IR::ExprList>();
current = current->next;
- current->expr = _block->NAME(it.key(), 0, 0);
+ current->expr = _block->TEMP(getter);
current->next = _function->New<IR::ExprList>();
current = current->next;
+ current->expr = _block->TEMP(setter);
+ }
- if (it->value) {
- if (!value)
- value = _block->newTemp();
- move(_block->TEMP(value), it->value);
- // __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_property, 0, 0), args));
- } else {
- if (!getter) {
- getter = _block->newTemp();
- setter = _block->newTemp();
- }
- move(_block->TEMP(getter), it->hasGetter() ? _block->CLOSURE(it->getter) : _block->CONST(IR::UndefinedType, 0));
- move(_block->TEMP(setter), it->hasSetter() ? _block->CLOSURE(it->setter) : _block->CONST(IR::UndefinedType, 0));
+ it = valueMap.erase(it);
+ }
+ entryCountParam->value = keyValueEntryCount;
- // __qmljs_builtin_define_getter_setter(Value object, String *name, Value getter, Value setter, ExecutionContext *ctx);
- current->expr = _block->TEMP(getter);
- current->next = _function->New<IR::ExprList>();
- current = current->next;
- current->expr = _block->TEMP(setter);
- _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_define_getter_setter, 0, 0), args));
- }
- }
+ if (keyValueEntries)
+ args->next = keyValueEntries;
+ if (arrayEntries) {
+ if (currentKeyValueEntry)
+ currentKeyValueEntry->next = arrayEntries;
+ else
+ args->next = arrayEntries;
}
+ const unsigned t = _block->newTemp();
+ move(_block->TEMP(t), _block->CALL(_block->NAME(IR::Name::builtin_define_object_literal,
+ ast->firstSourceLocation().startLine, ast->firstSourceLocation().startColumn), args));
+
_expr.code = _block->TEMP(t);
return false;
}
@@ -2072,33 +2058,6 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
return functionIndex;
}
-bool Codegen::visit(IdentifierPropertyName *ast)
-{
- if (hasError)
- return false;
-
- _property = ast->id.toString();
- return false;
-}
-
-bool Codegen::visit(NumericLiteralPropertyName *ast)
-{
- if (hasError)
- return false;
-
- _property = QString::number(ast->id, 'g', 16);
- return false;
-}
-
-bool Codegen::visit(StringLiteralPropertyName *ast)
-{
- if (hasError)
- return false;
-
- _property = ast->id.toString();
- return false;
-}
-
bool Codegen::visit(FunctionSourceElement *ast)
{
if (hasError)
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index 37055171b1..9c43dc17fe 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -315,7 +315,6 @@ protected:
void statement(AST::ExpressionNode *ast);
void condition(AST::ExpressionNode *ast, QV4::IR::BasicBlock *iftrue, QV4::IR::BasicBlock *iffalse);
Result expression(AST::ExpressionNode *ast);
- QString propertyName(AST::PropertyName *ast);
Result sourceElement(AST::SourceElement *ast);
UiMember uiObjectMember(AST::UiObjectMember *ast);
@@ -397,11 +396,6 @@ protected:
virtual bool visit(AST::VoidExpression *ast);
virtual bool visit(AST::FunctionDeclaration *ast);
- // property names
- virtual bool visit(AST::IdentifierPropertyName *ast);
- virtual bool visit(AST::NumericLiteralPropertyName *ast);
- virtual bool visit(AST::StringLiteralPropertyName *ast);
-
// source elements
virtual bool visit(AST::FunctionSourceElement *ast);
virtual bool visit(AST::StatementSourceElement *ast);
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index 7be902f1c1..b28195960f 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -151,14 +151,14 @@ void QV4::Compiler::JSUnitGenerator::registerLineNumberMapping(QV4::IR::Function
lineNumberMappingsPerFunction.insert(function, mappings);
}
-int QV4::Compiler::JSUnitGenerator::registerJSClass(QV4::IR::ExprList *args)
+int QV4::Compiler::JSUnitGenerator::registerJSClass(int count, IR::ExprList *args)
{
// ### re-use existing class definitions.
QList<CompiledData::JSClassMember> members;
- QV4::IR::ExprList *it = args;
- while (it) {
+ IR::ExprList *it = args;
+ for (int i = 0; i < count; ++i, it = it->next) {
CompiledData::JSClassMember member;
QV4::IR::Name *name = it->expr->asName();
@@ -173,8 +173,6 @@ int QV4::Compiler::JSUnitGenerator::registerJSClass(QV4::IR::ExprList *args)
if (!isData)
it = it->next;
-
- it = it->next;
}
jsClasses << members;
diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h
index 29cf82e2bc..a917ea3d94 100644
--- a/src/qml/compiler/qv4compiler_p.h
+++ b/src/qml/compiler/qv4compiler_p.h
@@ -79,7 +79,7 @@ struct Q_QML_EXPORT JSUnitGenerator {
void registerLineNumberMapping(IR::Function *function, const QVector<uint> &mappings);
- int registerJSClass(IR::ExprList *args);
+ int registerJSClass(int count, IR::ExprList *args);
QV4::CompiledData::Unit *generateUnit(int *totalUnitSize = 0);
// Returns bytes written
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index bca878d648..08c523ce56 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -95,8 +95,6 @@ QT_BEGIN_NAMESPACE
F(CallBuiltinTypeofName, callBuiltinTypeofName) \
F(CallBuiltinTypeofValue, callBuiltinTypeofValue) \
F(CallBuiltinDeclareVar, callBuiltinDeclareVar) \
- F(CallBuiltinDefineGetterSetter, callBuiltinDefineGetterSetter) \
- F(CallBuiltinDefineProperty, callBuiltinDefineProperty) \
F(CallBuiltinDefineArray, callBuiltinDefineArray) \
F(CallBuiltinDefineObjectLiteral, callBuiltinDefineObjectLiteral) \
F(CallBuiltinSetupArgumentsObject, callBuiltinSetupArgumentsObject) \
@@ -481,19 +479,6 @@ union Instr
int varName;
bool isDeletable;
};
- struct instr_callBuiltinDefineGetterSetter {
- MOTH_INSTR_HEADER
- int name;
- Param object;
- Param getter;
- Param setter;
- };
- struct instr_callBuiltinDefineProperty {
- MOTH_INSTR_HEADER
- int name;
- Param object;
- Param value;
- };
struct instr_callBuiltinDefineArray {
MOTH_INSTR_HEADER
quint32 argc;
@@ -503,6 +488,8 @@ union Instr
struct instr_callBuiltinDefineObjectLiteral {
MOTH_INSTR_HEADER
int internalClassId;
+ int arrayValueCount;
+ int arrayGetterSetterCount;
quint32 args;
Param result;
};
@@ -768,8 +755,6 @@ union Instr
instr_callBuiltinTypeofName callBuiltinTypeofName;
instr_callBuiltinTypeofValue callBuiltinTypeofValue;
instr_callBuiltinDeclareVar callBuiltinDeclareVar;
- instr_callBuiltinDefineGetterSetter callBuiltinDefineGetterSetter;
- instr_callBuiltinDefineProperty callBuiltinDefineProperty;
instr_callBuiltinDefineArray callBuiltinDefineArray;
instr_callBuiltinDefineObjectLiteral callBuiltinDefineObjectLiteral;
instr_callBuiltinSetupArgumentsObject callBuiltinSetupArgumentsObject;
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index ba4f2331a1..8045b811ea 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -1252,26 +1252,6 @@ void InstructionSelection::callBuiltinDeclareVar(bool deletable, const QString &
addInstruction(call);
}
-void InstructionSelection::callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter)
-{
- Instruction::CallBuiltinDefineGetterSetter call;
- call.object = getParam(object);
- call.name = registerString(name);
- call.getter = getParam(getter);
- call.setter = getParam(setter);
- addInstruction(call);
-}
-
-void InstructionSelection::callBuiltinDefineProperty(IR::Temp *object, const QString &name,
- IR::Expr *value)
-{
- Instruction::CallBuiltinDefineProperty call;
- call.object = getParam(object);
- call.name = registerString(name);
- call.value = getParam(value);
- addInstruction(call);
-}
-
void InstructionSelection::callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args)
{
Instruction::CallBuiltinDefineArray call;
@@ -1280,13 +1260,16 @@ void InstructionSelection::callBuiltinDefineArray(IR::Temp *result, IR::ExprList
addInstruction(call);
}
-void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, IR::ExprList *args)
+void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries)
{
int argLocation = outgoingArgumentTempStart();
- const int classId = registerJSClass(args);
- IR::ExprList *it = args;
- while (it) {
+ const int classId = registerJSClass(keyValuePairCount, keyValuePairs);
+
+ // Process key/value pairs first
+ IR::ExprList *it = keyValuePairs;
+ for (int i = 0; i < keyValuePairCount; ++i, it = it->next) {
+ // Skip name
it = it->next;
bool isData = it->expr->asConst()->value;
@@ -1314,12 +1297,84 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, IR::
addInstruction(move);
++argLocation;
}
+ }
+
+ // Process array values
+ int arrayValueCount = 0;
+ it = arrayEntries;
+ while (it) {
+ IR::Const *index = it->expr->asConst();
+ it = it->next;
+
+ bool isData = it->expr->asConst()->value;
+ it = it->next;
+
+ if (!isData) {
+ it = it->next; // getter
+ it = it->next; // setter
+ continue;
+ }
+ ++arrayValueCount;
+
+ Instruction::MoveConst indexMove;
+ indexMove.source = convertToValue(index).asReturnedValue();
+ indexMove.result = Param::createTemp(argLocation);
+ addInstruction(indexMove);
+ ++argLocation;
+
+ Instruction::Move move;
+ move.source = getParam(it->expr);
+ move.result = Param::createTemp(argLocation);
+ addInstruction(move);
+ ++argLocation;
+ it = it->next;
+ }
+
+ // Process array getter/setter pairs
+ int arrayGetterSetterCount = 0;
+ it = arrayEntries;
+ while (it) {
+ IR::Const *index = it->expr->asConst();
+ it = it->next;
+
+ bool isData = it->expr->asConst()->value;
+ it = it->next;
+
+ if (isData) {
+ it = it->next; // value
+ continue;
+ }
+
+ ++arrayGetterSetterCount;
+
+ Instruction::MoveConst indexMove;
+ indexMove.source = convertToValue(index).asReturnedValue();
+ indexMove.result = Param::createTemp(argLocation);
+ addInstruction(indexMove);
+ ++argLocation;
+
+ // getter
+ Instruction::Move moveGetter;
+ moveGetter.source = getParam(it->expr);
+ moveGetter.result = Param::createTemp(argLocation);
+ addInstruction(moveGetter);
+ ++argLocation;
+ it = it->next;
+
+ // setter
+ Instruction::Move moveSetter;
+ moveSetter.source = getParam(it->expr);
+ moveSetter.result = Param::createTemp(argLocation);
+ addInstruction(moveSetter);
+ ++argLocation;
it = it->next;
}
Instruction::CallBuiltinDefineObjectLiteral call;
call.internalClassId = classId;
+ call.arrayValueCount = arrayValueCount;
+ call.arrayGetterSetterCount = arrayGetterSetterCount;
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 e2ba971e26..732341c3ca 100644
--- a/src/qml/compiler/qv4isel_moth_p.h
+++ b/src/qml/compiler/qv4isel_moth_p.h
@@ -98,10 +98,8 @@ protected:
virtual void callBuiltinPushWithScope(IR::Temp *arg);
virtual void callBuiltinPopScope();
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::Expr *value);
virtual void callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args);
- virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, IR::ExprList *args);
+ virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries);
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 4c70c1ddd8..2a73b55ed2 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -347,48 +347,29 @@ void IRDecoder::callBuiltin(IR::Call *call, IR::Temp *result)
}
} return;
- case IR::Name::builtin_define_getter_setter: {
- if (!call->args)
- return;
- IR::ExprList *args = call->args;
- IR::Temp *object = args->expr->asTemp();
- assert(object);
- args = args->next;
- assert(args);
- IR::Name *name = args->expr->asName();
- args = args->next;
- assert(args);
- IR::Temp *getter = args->expr->asTemp();
- args = args->next;
- assert(args);
- IR::Temp *setter = args->expr->asTemp();
-
- callBuiltinDefineGetterSetter(object, *name->id, getter, setter);
- } return;
+ case IR::Name::builtin_define_array:
+ callBuiltinDefineArray(result, call->args);
+ return;
- case IR::Name::builtin_define_property: {
- if (!call->args)
- return;
+ case IR::Name::builtin_define_object_literal: {
IR::ExprList *args = call->args;
- IR::Temp *object = args->expr->asTemp();
- assert(object);
- args = args->next;
- assert(args);
- IR::Name *name = args->expr->asName();
+ const int keyValuePairsCount = args->expr->asConst()->value;
args = args->next;
- assert(args);
- IR::Expr *value = args->expr;
- callBuiltinDefineProperty(object, *name->id, value);
- } return;
+ IR::ExprList *keyValuePairs = args;
+ for (int i = 0; i < keyValuePairsCount; ++i) {
+ args = args->next; // name
+ bool isData = args->expr->asConst()->value;
+ args = args->next; // isData flag
+ args = args->next; // value or getter
+ if (!isData)
+ args = args->next; // setter
+ }
- case IR::Name::builtin_define_array:
- callBuiltinDefineArray(result, call->args);
- return;
+ IR::ExprList *arrayEntries = args;
- case IR::Name::builtin_define_object_literal:
- callBuiltinDefineObjectLiteral(result, call->args);
- return;
+ callBuiltinDefineObjectLiteral(result, keyValuePairsCount, keyValuePairs, arrayEntries);
+ } return;
case IR::Name::builtin_setup_argument_object:
callBuiltinSetupArgumentObject(result);
diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h
index bfe0adc431..7137979b66 100644
--- a/src/qml/compiler/qv4isel_p.h
+++ b/src/qml/compiler/qv4isel_p.h
@@ -76,7 +76,7 @@ public:
uint registerSetterLookup(const QString &name) { return jsGenerator->registerSetterLookup(name); }
uint registerGlobalGetterLookup(const QString &name) { return jsGenerator->registerGlobalGetterLookup(name); }
int registerRegExp(IR::RegExp *regexp) { return jsGenerator->registerRegExp(regexp); }
- int registerJSClass(IR::ExprList *args) { return jsGenerator->registerJSClass(args); }
+ int registerJSClass(int count, IR::ExprList *args) { return jsGenerator->registerJSClass(count, args); }
QV4::Compiler::JSUnitGenerator *jsUnitGenerator() const { return jsGenerator; }
protected:
@@ -130,10 +130,8 @@ public: // to implement by subclasses:
virtual void callBuiltinPushWithScope(IR::Temp *arg) = 0;
virtual void callBuiltinPopScope() = 0;
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::Expr *value) = 0;
virtual void callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args) = 0;
- virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, IR::ExprList *args) = 0;
+ virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries) = 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/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index 2683278b12..d9d0742b68 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -427,12 +427,8 @@ static const char *builtin_to_string(Name::Builtin b)
return "builtin_pop_scope";
case IR::Name::builtin_declare_vars:
return "builtin_declare_vars";
- case IR::Name::builtin_define_property:
- return "builtin_define_property";
case IR::Name::builtin_define_array:
return "builtin_define_array";
- case IR::Name::builtin_define_getter_setter:
- return "builtin_define_getter_setter";
case IR::Name::builtin_define_object_literal:
return "builtin_define_object_literal";
case IR::Name::builtin_setup_argument_object:
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 89b6da6278..58a569b862 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -349,9 +349,7 @@ struct Name: Expr {
builtin_push_with_scope,
builtin_pop_scope,
builtin_declare_vars,
- builtin_define_property,
builtin_define_array,
- builtin_define_getter_setter,
builtin_define_object_literal,
builtin_setup_argument_object,
builtin_convert_this_to_object,
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index 706130e995..2d05592f72 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -483,27 +483,6 @@ void InstructionSelection::callBuiltinDeclareVar(bool deletable, const QString &
Assembler::TrustedImm32(deletable), Assembler::PointerToString(name));
}
-void InstructionSelection::callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter)
-{
- Q_ASSERT(object);
- Q_ASSERT(getter);
- Q_ASSERT(setter);
- generateFunctionCall(Assembler::Void, __qmljs_builtin_define_getter_setter, Assembler::ContextRegister,
- Assembler::Reference(object), Assembler::PointerToString(name), Assembler::PointerToValue(getter), Assembler::PointerToValue(setter));
-}
-
-void InstructionSelection::callBuiltinDefineProperty(IR::Temp *object, const QString &name,
- IR::Expr *value)
-{
- Q_ASSERT(object);
- Q_ASSERT(value->asTemp() || value->asConst());
-
- generateFunctionCall(Assembler::Void, __qmljs_builtin_define_property,
- Assembler::ContextRegister, Assembler::Reference(object),
- Assembler::PointerToString(name),
- Assembler::PointerToValue(value));
-}
-
void InstructionSelection::callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args)
{
Q_ASSERT(result);
@@ -513,16 +492,16 @@ void InstructionSelection::callBuiltinDefineArray(IR::Temp *result, IR::ExprList
baseAddressForCallArguments(), Assembler::TrustedImm32(length));
}
-void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, IR::ExprList *args)
+void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries)
{
Q_ASSERT(result);
int argc = 0;
- const int classId = registerJSClass(args);
+ const int classId = registerJSClass(keyValuePairCount, keyValuePairs);
- IR::ExprList *it = args;
- while (it) {
+ IR::ExprList *it = keyValuePairs;
+ for (int i = 0; i < keyValuePairCount; ++i, it = it->next) {
it = it->next;
bool isData = it->expr->asConst()->value;
@@ -534,12 +513,64 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, IR::
it = it->next;
_as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr);
}
+ }
+
+ it = arrayEntries;
+ int arrayValueCount = 0;
+ while (it) {
+ uint index = it->expr->asConst()->value;
+ it = it->next;
+
+ bool isData = it->expr->asConst()->value;
+ it = it->next;
+
+ if (!isData) {
+ it = it->next; // getter
+ it = it->next; // setter
+ continue;
+ }
+ ++arrayValueCount;
+
+ // Index
+ _as->storeValue(QV4::Primitive::fromUInt32(index), _as->stackLayout().argumentAddressForCall(argc++));
+
+ // Value
+ _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr);
+ it = it->next;
+ }
+
+ it = arrayEntries;
+ int arrayGetterSetterCount = 0;
+ while (it) {
+ uint index = it->expr->asConst()->value;
+ it = it->next;
+
+ bool isData = it->expr->asConst()->value;
+ it = it->next;
+
+ if (isData) {
+ it = it->next; // value
+ continue;
+ }
+
+ ++arrayGetterSetterCount;
+
+ // Index
+ _as->storeValue(QV4::Primitive::fromUInt32(index), _as->stackLayout().argumentAddressForCall(argc++));
+
+ // Getter
+ _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr);
+ it = it->next;
+
+ // Setter
+ _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr);
it = it->next;
}
generateFunctionCall(result, __qmljs_builtin_define_object_literal, Assembler::ContextRegister,
- baseAddressForCallArguments(), Assembler::TrustedImm32(classId));
+ baseAddressForCallArguments(), Assembler::TrustedImm32(classId),
+ Assembler::TrustedImm32(arrayValueCount), Assembler::TrustedImm32(arrayGetterSetterCount));
}
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 69317cb062..5e4e77318c 100644
--- a/src/qml/jit/qv4isel_masm_p.h
+++ b/src/qml/jit/qv4isel_masm_p.h
@@ -94,10 +94,8 @@ protected:
virtual void callBuiltinPushWithScope(IR::Temp *arg);
virtual void callBuiltinPopScope();
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::Expr *value);
virtual void callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args);
- virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, IR::ExprList *args);
+ virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries);
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 4ff03611fa..76a0734f07 100644
--- a/src/qml/jit/qv4regalloc.cpp
+++ b/src/qml/jit/qv4regalloc.cpp
@@ -213,10 +213,8 @@ protected: // IRDecoder
virtual void callBuiltinPushWithScope(IR::Temp *) {}
virtual void callBuiltinPopScope() {}
virtual void callBuiltinDeclareVar(bool , const QString &) {}
- virtual void callBuiltinDefineGetterSetter(IR::Temp *, const QString &, IR::Temp *, IR::Temp *) {}
- virtual void callBuiltinDefineProperty(IR::Temp *, const QString &, IR::Expr *) {}
virtual void callBuiltinDefineArray(IR::Temp *, IR::ExprList *) {}
- virtual void callBuiltinDefineObjectLiteral(IR::Temp *, IR::ExprList *) {}
+ virtual void callBuiltinDefineObjectLiteral(IR::Temp *, int, IR::ExprList *, IR::ExprList *) {}
virtual void callBuiltinSetupArgumentObject(IR::Temp *) {}
virtual void callBuiltinConvertThisToObject() {}
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index f89a51fd85..7c7ce23bcb 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -1087,23 +1087,6 @@ void __qmljs_builtin_declare_var(ExecutionContext *ctx, bool deletable, const St
ctx->createMutableBinding(name, deletable);
}
-void __qmljs_builtin_define_property(ExecutionContext *ctx, const ValueRef object, const StringRef name, ValueRef val)
-{
- Scope scope(ctx);
- ScopedObject o(scope, object->asObject());
- assert(o);
-
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX) {
- if (idx > 16 && (!o->arrayData || idx > o->arrayData->length() * 2))
- o->initSparseArray();
- o->arraySet(idx, val);
- } else {
- ScopedValue v(scope, val ? *val : Primitive::undefinedValue());
- o->insertMember(name, v);
- }
-}
-
ReturnedValue __qmljs_builtin_define_array(ExecutionContext *ctx, Value *values, uint length)
{
Scope scope(ctx);
@@ -1117,24 +1100,7 @@ ReturnedValue __qmljs_builtin_define_array(ExecutionContext *ctx, Value *values,
return a.asReturnedValue();
}
-void __qmljs_builtin_define_getter_setter(ExecutionContext *ctx, const ValueRef object, const StringRef name, const ValueRef getter, const ValueRef setter)
-{
- Scope scope(ctx);
- ScopedObject o(scope, object->asObject());
- Q_ASSERT(!!o);
-
- uint idx = name->asArrayIndex();
- Property pd;
- pd.value = getter;
- pd.set = setter;
- if (idx != UINT_MAX) {
- o->arraySet(idx, pd, Attr_Accessor);
- } else {
- o->insertMember(name, pd, Attr_Accessor);
- }
-}
-
-ReturnedValue __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, const QV4::Value *args, int classId)
+ReturnedValue __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCount)
{
Scope scope(ctx);
QV4::InternalClass *klass = ctx->compilationUnit->runtimeClasses[classId];
@@ -1151,6 +1117,29 @@ 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 idx = args->toUInt32();
+ if (idx > 16 && (!o->arrayData || idx > o->arrayData->length() * 2))
+ o->initSparseArray();
+ ++args;
+ pd->value = *args;
+ ++args;
+ pd->set = *args;
+ ++args;
+ o->arraySet(idx, pd, Attr_Accessor);
+ }
+
return o.asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index 1c34e554c3..dbe7e030e1 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -141,10 +141,8 @@ QV4::ExecutionContext *__qmljs_builtin_push_catch_scope(QV4::ExecutionContext *c
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);
-void __qmljs_builtin_define_property(QV4::ExecutionContext *ctx, const QV4::ValueRef object, const QV4::StringRef name, QV4::ValueRef val);
QV4::ReturnedValue __qmljs_builtin_define_array(QV4::ExecutionContext *ctx, Value *values, uint length);
-void __qmljs_builtin_define_getter_setter(QV4::ExecutionContext *ctx, const QV4::ValueRef object, const QV4::StringRef name, const QV4::ValueRef getter, const QV4::ValueRef setter);
-QV4::ReturnedValue __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, const QV4::Value *args, int classId);
+QV4::ReturnedValue __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCount);
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 3c44063606..5ae0b3daff 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -473,14 +473,6 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
__qmljs_builtin_declare_var(context, instr.isDeletable, runtimeStrings[instr.varName]);
MOTH_END_INSTR(CallBuiltinDeclareVar)
- MOTH_BEGIN_INSTR(CallBuiltinDefineGetterSetter)
- __qmljs_builtin_define_getter_setter(context, VALUEPTR(instr.object), runtimeStrings[instr.name], VALUEPTR(instr.getter), VALUEPTR(instr.setter));
- MOTH_END_INSTR(CallBuiltinDefineGetterSetter)
-
- MOTH_BEGIN_INSTR(CallBuiltinDefineProperty)
- __qmljs_builtin_define_property(context, VALUEPTR(instr.object), runtimeStrings[instr.name], VALUEPTR(instr.value));
- MOTH_END_INSTR(CallBuiltinDefineProperty)
-
MOTH_BEGIN_INSTR(CallBuiltinDefineArray)
Q_ASSERT(instr.args + instr.argc <= stackSize);
QV4::Value *args = stack + instr.args;
@@ -489,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));
+ STOREVALUE(instr.result, __qmljs_builtin_define_object_literal(context, args, instr.internalClassId, instr.arrayValueCount, instr.arrayGetterSetterCount));
MOTH_END_INSTR(CallBuiltinDefineObjectLiteral)
MOTH_BEGIN_INSTR(CallBuiltinSetupArgumentsObject)
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index 6cc3b7649e..ba782cfe9e 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -603,6 +603,8 @@ public:
virtual SourceLocation lastSourceLocation() const
{ return propertyNameToken; }
+ virtual QString asString() const = 0;
+
// attributes
SourceLocation propertyNameToken;
};
@@ -610,7 +612,11 @@ public:
class QML_PARSER_EXPORT PropertyAssignment: public Node
{
public:
- PropertyAssignment() {}
+ PropertyAssignment(PropertyName *n)
+ : name(n)
+ {}
+// attributes
+ PropertyName *name;
};
class QML_PARSER_EXPORT PropertyAssignmentList: public Node
@@ -658,7 +664,7 @@ public:
QQMLJS_DECLARE_AST_NODE(PropertyNameAndValue)
PropertyNameAndValue(PropertyName *n, ExpressionNode *v)
- : name(n), value(v)
+ : PropertyAssignment(n), value(v)
{ kind = K; }
virtual void accept0(Visitor *visitor);
@@ -670,7 +676,6 @@ public:
{ return value->lastSourceLocation(); }
// attributes
- PropertyName *name;
SourceLocation colonToken;
ExpressionNode *value;
SourceLocation commaToken;
@@ -687,11 +692,11 @@ public:
};
PropertyGetterSetter(PropertyName *n, FunctionBody *b)
- : type(Getter), name(n), formals(0), functionBody (b)
+ : PropertyAssignment(n), type(Getter), formals(0), functionBody (b)
{ kind = K; }
PropertyGetterSetter(PropertyName *n, FormalParameterList *f, FunctionBody *b)
- : type(Setter), name(n), formals(f), functionBody (b)
+ : PropertyAssignment(n), type(Setter), formals(f), functionBody (b)
{ kind = K; }
virtual void accept0(Visitor *visitor);
@@ -705,7 +710,6 @@ public:
// attributes
Type type;
SourceLocation getSetToken;
- PropertyName *name;
SourceLocation lparenToken;
FormalParameterList *formals;
SourceLocation rparenToken;
@@ -724,6 +728,8 @@ public:
virtual void accept0(Visitor *visitor);
+ virtual QString asString() const { return id.toString(); }
+
// attributes
QStringRef id;
};
@@ -738,6 +744,8 @@ public:
virtual void accept0(Visitor *visitor);
+ virtual QString asString() const { return id.toString(); }
+
// attributes
QStringRef id;
};
@@ -752,6 +760,8 @@ public:
virtual void accept0(Visitor *visitor);
+ virtual QString asString() const { return QString::number(id, 'g', 16); }
+
// attributes
double id;
};