diff options
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 199 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 6 | ||||
-rw-r--r-- | src/qml/compiler/qv4compiler.cpp | 8 | ||||
-rw-r--r-- | src/qml/compiler/qv4compiler_p.h | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 19 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_moth.cpp | 103 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_moth_p.h | 4 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_p.cpp | 53 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_p.h | 6 | ||||
-rw-r--r-- | src/qml/compiler/qv4jsir.cpp | 4 | ||||
-rw-r--r-- | src/qml/compiler/qv4jsir_p.h | 2 | ||||
-rw-r--r-- | src/qml/jit/qv4isel_masm.cpp | 83 | ||||
-rw-r--r-- | src/qml/jit/qv4isel_masm_p.h | 4 | ||||
-rw-r--r-- | src/qml/jit/qv4regalloc.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 59 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime_p.h | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 10 | ||||
-rw-r--r-- | src/qml/parser/qqmljsast_p.h | 22 |
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 = ¤tArrayEntry; + 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 = ¤tKeyValueEntry; + (*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 *¤t = *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; }; |