diff options
author | Erik Verbruggen <erik.verbruggen@qt.io> | 2017-07-18 15:48:21 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2017-08-02 13:56:35 +0000 |
commit | 3181e3dae0f01077ff209c4e8d9c83e901f20b0e (patch) | |
tree | 500b027e8f636916cbdad275dddf4f59eb290a9e /src/qml/compiler | |
parent | 49946ef87478fb34dc017a0ff7592ef9a0336d31 (diff) |
Introduce an accumulator in the interpreter, and change instructions
This reduces the number of stores to the stack (for which we need a
write-barrier in the future) by keeping the last calculated value in the
accumulator register (which is a local variable).
In the future we might want to collapse certain common instruction
patterns into a super-sized instruction.
Change-Id: I02ebed2db957765e994c8f939bf7585894881deb
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r-- | src/qml/compiler/qqmlirbuilder.cpp | 14 | ||||
-rw-r--r-- | src/qml/compiler/qv4bytecodegenerator_p.h | 12 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 819 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 80 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilercontrolflow_p.h | 38 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth.cpp | 186 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 168 |
7 files changed, 572 insertions, 745 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index cd85482cb3..27e9d3f417 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -2053,7 +2053,7 @@ void JSCodeGen::beginFunctionBodyHook() #ifndef V4_BOOTSTRAP Instruction::LoadQmlContext load; - load.result = Reference::fromTemp(this, _qmlContextTemp).asLValue(); + load.result = Reference::fromTemp(this, _qmlContextTemp).temp(); bytecodeGenerator->addInstruction(load); #if 0 @@ -2065,7 +2065,7 @@ void JSCodeGen::beginFunctionBodyHook() #endif Instruction::LoadQmlImportedScripts loadScripts; - loadScripts.result = Reference::fromTemp(this, _importedScriptsTemp).asLValue(); + loadScripts.result = Reference::fromTemp(this, _importedScriptsTemp).temp(); bytecodeGenerator->addInstruction(loadScripts); #endif } @@ -2093,11 +2093,11 @@ QV4::Compiler::Codegen::Reference JSCodeGen::fallbackNameLookup(const QString &n if (_context->compilationMode == QV4::Compiler::QmlBinding) _context->idObjectDependencies.insert(mapping.idIndex); - Reference result = Reference::fromTemp(this); Instruction::LoadIdObject load; - load.base = Reference::fromTemp(this, _qmlContextTemp).asRValue(); + load.base = Reference::fromTemp(this, _qmlContextTemp).temp(); load.index = mapping.idIndex; - load.result = result.asLValue(); + + Reference result = Reference::fromAccumulator(this); bytecodeGenerator->addInstruction(load); result.isReadonly = true; return result; @@ -2112,12 +2112,10 @@ QV4::Compiler::Codegen::Reference JSCodeGen::fallbackNameLookup(const QString &n return Reference::fromSubscript(imports, Reference::fromConst(this, QV4::Encode(r.scriptIndex))); } else if (r.type) { if (r.type->isCompositeSingleton()) { - Reference result = Reference::fromTemp(this); Instruction::LoadQmlSingleton load; - load.result = result.asRValue(); load.name = registerString(name); bytecodeGenerator->addInstruction(load); - return result; + return Reference::fromAccumulator(this); } return Reference::fromName(this, name); } else { diff --git a/src/qml/compiler/qv4bytecodegenerator_p.h b/src/qml/compiler/qv4bytecodegenerator_p.h index a2c4c20716..d66377fb34 100644 --- a/src/qml/compiler/qv4bytecodegenerator_p.h +++ b/src/qml/compiler/qv4bytecodegenerator_p.h @@ -150,33 +150,29 @@ public: return addJumpInstruction(data); } - Q_REQUIRED_RESULT Jump jumpEq(const Temp &cond) + Q_REQUIRED_RESULT Jump jumpEq() { Instruction::JumpEq data; - data.condition = cond; return addJumpInstruction(data); } - Q_REQUIRED_RESULT Jump jumpNe(const Temp &cond) + Q_REQUIRED_RESULT Jump jumpNe() { Instruction::JumpNe data; - data.condition = cond; return addJumpInstruction(data); } - Q_REQUIRED_RESULT Jump jumpStrictEqual(const Temp &lhs, const Temp &rhs) + Q_REQUIRED_RESULT Jump jumpStrictEqual(const Temp &lhs) { Instruction::JumpStrictEqual data; data.lhs = lhs; - data.rhs = rhs; return addJumpInstruction(data); } - Q_REQUIRED_RESULT Jump jumpStrictNotEqual(const Temp &lhs, const Temp &rhs) + Q_REQUIRED_RESULT Jump jumpStrictNotEqual(const Temp &lhs) { Instruction::JumpStrictNotEqual data; data.lhs = lhs; - data.rhs = rhs; return addJumpInstruction(data); } diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index d0cb692473..95d895ad28 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -170,7 +170,7 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr) return _expr.result(); #ifndef V4_BOOTSTRAP - if (expr.type == Reference::Const) { + if (expr.isConst()) { auto v = Value::fromReturnedValue(expr.constant); if (v.isNumber()) { switch (op) { @@ -189,66 +189,80 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr) } #endif // V4_BOOTSTRAP - auto dest = Reference::fromTemp(this); - switch (op) { case UMinus: { + expr.loadInAccumulator(); Instruction::UMinus uminus; - uminus.source = expr.asRValue(); - uminus.result = dest.asLValue(); bytecodeGenerator->addInstruction(uminus); - } break; + return Reference::fromAccumulator(this); + } case UPlus: { + expr.loadInAccumulator(); Instruction::UPlus uplus; - uplus.source = expr.asRValue(); - uplus.result = dest.asLValue(); bytecodeGenerator->addInstruction(uplus); - } break; + return Reference::fromAccumulator(this); + } case Not: { + expr.loadInAccumulator(); Instruction::UNot unot; - unot.source = expr.asRValue(); - unot.result = dest.asLValue(); bytecodeGenerator->addInstruction(unot); - } break; + return Reference::fromAccumulator(this); + } case Compl: { + expr.loadInAccumulator(); Instruction::UCompl ucompl; - ucompl.source = expr.asRValue(); - ucompl.result = dest.asLValue(); bytecodeGenerator->addInstruction(ucompl); - } break; + return Reference::fromAccumulator(this); + } + case PostIncrement: + if (!_expr.accept(nx)) { + expr.loadInAccumulator(); + Instruction::UPlus uplus; + bytecodeGenerator->addInstruction(uplus); + Reference originalValue = Reference::fromTemp(this).storeRetainAccumulator(); + Instruction::Increment inc; + bytecodeGenerator->addInstruction(inc); + expr.storeConsumeAccumulator(); + return originalValue; + } else { + // intentionally fall-through: the result is never used, so it's equivalent to + // "expr += 1", which is what a pre-increment does as well. + } case PreIncrement: { - Instruction::PreIncrement inc; - inc.source = expr.asRValue(); - inc.result = dest.asLValue(); + expr.loadInAccumulator(); + Instruction::Increment inc; bytecodeGenerator->addInstruction(inc); - expr.store(dest); - } break; + if (_expr.accept(nx)) + return expr.storeConsumeAccumulator(); + else + return expr.storeRetainAccumulator(); + } + case PostDecrement: + if (!_expr.accept(nx)) { + expr.loadInAccumulator(); + Instruction::UPlus uplus; + bytecodeGenerator->addInstruction(uplus); + Reference originalValue = Reference::fromTemp(this).storeRetainAccumulator(); + Instruction::Decrement dec; + bytecodeGenerator->addInstruction(dec); + expr.storeConsumeAccumulator(); + return originalValue; + } else { + // intentionally fall-through: the result is never used, so it's equivalent to + // "expr -= 1", which is what a pre-decrement does as well. + } case PreDecrement: { - Instruction::PreDecrement dec; - dec.source = expr.asRValue(); - dec.result = dest.asLValue(); - bytecodeGenerator->addInstruction(dec); - expr.store(dest); - } break; - case PostIncrement: { - Instruction::PostIncrement inc; - inc.source = expr.asRValue(); - inc.result = dest.asLValue(); - bytecodeGenerator->addInstruction(inc); - expr.asLValue(); // mark expr as needsWriteBack - expr.writeBack(); - } break; - case PostDecrement: { - Instruction::PostDecrement dec; - dec.source = expr.asRValue(); - dec.result = dest.asLValue(); + expr.loadInAccumulator(); + Instruction::Decrement dec; bytecodeGenerator->addInstruction(dec); - expr.asLValue(); // mark expr as needsWriteBack - expr.writeBack(); - } break; + if (_expr.accept(nx)) + return expr.storeConsumeAccumulator(); + else + return expr.storeRetainAccumulator(); + } } - return dest; + Q_UNREACHABLE(); } void Codegen::accept(Node *node) @@ -281,19 +295,8 @@ void Codegen::statement(ExpressionNode *ast) if (hasError) return; qSwap(_expr, r); -// if (r.format == ex) { -// if (r->asCall()) { -// _block->EXP(*r); // the nest nx representation for calls is EXP(CALL(c..)) -// } else if (r->asTemp() || r->asArgLocal()) { -// // there is nothing to do -// } else { -// unsigned t = bytecodeGenerator->newTemp(); -// move(_block->TEMP(t), *r); -// } -// } - - if (r.result().isValid() && !r.result().isTempLocalArg()) - r.result().asRValue(); // triggers side effects + if (r.result().loadTriggersSideEffect()) + r.result().loadInAccumulator(); // triggers side effects } } @@ -309,11 +312,11 @@ void Codegen::condition(ExpressionNode *ast, const BytecodeGenerator::Label *ift Q_ASSERT(iftrue == r.iftrue()); Q_ASSERT(iffalse == r.iffalse()); bytecodeGenerator->setLocation(ast->firstSourceLocation()); - auto cond = r.result().asRValue(); + r.result().loadInAccumulator(); if (r.trueBlockFollowsCondition()) - bytecodeGenerator->jumpNe(cond).link(*r.iffalse()); + bytecodeGenerator->jumpNe().link(*r.iffalse()); else - bytecodeGenerator->jumpEq(cond).link(*r.iftrue()); + bytecodeGenerator->jumpEq().link(*r.iftrue()); } } } @@ -371,8 +374,10 @@ void Codegen::variableDeclaration(VariableDeclaration *ast) Reference rhs = expression(ast->expression); if (hasError) return; + Reference lhs = referenceForName(ast->name.toString(), true); - lhs.storeConsume(rhs); + rhs.loadInAccumulator(); + lhs.storeConsumeAccumulator(); } void Codegen::variableDeclarationList(VariableDeclarationList *ast) @@ -572,7 +577,6 @@ bool Codegen::visit(ArrayLiteral *ast) if (hasError) return false; - auto result = Reference::fromTemp(this); TempScope scope(this); int argc = 0; @@ -582,10 +586,11 @@ bool Codegen::visit(ArrayLiteral *ast) if (args == -1) args = temp; if (!arg) { - Reference::fromTemp(this, temp).store(Reference::fromConst(this, Primitive::emptyValue().asReturnedValue())); + auto c = Reference::fromConst(this, Primitive::emptyValue().asReturnedValue()); + (void) c.storeInTemp(temp); } else { TempScope scope(this); - Reference::fromTemp(this, temp).store(expression(arg)); + (void) expression(arg).storeInTemp(temp); } ++argc; }; @@ -610,9 +615,8 @@ bool Codegen::visit(ArrayLiteral *ast) Instruction::CallBuiltinDefineArray call; call.argc = argc; call.args = Moth::Temp::create(args); - call.result = result.asLValue(); bytecodeGenerator->addInstruction(call); - _expr.setResult(result); + _expr.setResult(Reference::fromAccumulator(this)); return false; } @@ -625,6 +629,7 @@ bool Codegen::visit(ArrayMemberExpression *ast) Reference base = expression(ast->base); if (hasError) return false; + base = base.storeInTemp(); Reference index = expression(ast->expression); _expr.setResult(Reference::fromSubscript(base, index)); return false; @@ -663,26 +668,23 @@ bool Codegen::visit(BinaryExpression *ast) auto iftrue = bytecodeGenerator->newLabel(); auto endif = bytecodeGenerator->newLabel(); - auto r = Reference::fromTemp(this); - - Reference lhs = expression(ast->left); + Reference left = expression(ast->left); if (hasError) return false; - - r.store(lhs); + left.loadInAccumulator(); bytecodeGenerator->setLocation(ast->operatorToken); - bytecodeGenerator->jumpNe(r.asRValue()).link(endif); + bytecodeGenerator->jumpNe().link(endif); iftrue.link(); - Reference rhs = expression(ast->right); + Reference right = expression(ast->right); if (hasError) return false; + right.loadInAccumulator(); - r.store(rhs); endif.link(); - _expr.setResult(r); + _expr.setResult(Reference::fromAccumulator(this)); } return false; } else if (ast->op == QSOperator::Or) { @@ -695,26 +697,23 @@ bool Codegen::visit(BinaryExpression *ast) auto iffalse = bytecodeGenerator->newLabel(); auto endif = bytecodeGenerator->newLabel(); - auto r = Reference::fromTemp(this); - - Reference lhs = expression(ast->left); + Reference left = expression(ast->left); if (hasError) return false; - - r.store(lhs); + left.loadInAccumulator(); bytecodeGenerator->setLocation(ast->operatorToken); - bytecodeGenerator->jumpEq(r.asRValue()).link(endif); + bytecodeGenerator->jumpEq().link(endif); iffalse.link(); - Reference rhs = expression(ast->right); + Reference right = expression(ast->right); if (hasError) return false; + right.loadInAccumulator(); - r.store(rhs); endif.link(); - _expr.setResult(r); + _expr.setResult(Reference::fromAccumulator(this)); } return false; } @@ -732,7 +731,7 @@ bool Codegen::visit(BinaryExpression *ast) case QSOperator::Assign: { if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(left, ast->left->lastSourceLocation())) return false; - Reference right = expression(ast->right); + expression(ast->right).loadInAccumulator(); if (hasError) return false; if (!left.isLValue()) { @@ -740,8 +739,7 @@ bool Codegen::visit(BinaryExpression *ast) return false; } - left.storeConsume(right); - _expr.setResult(left); + _expr.setResult(left.storeRetainAccumulator()); break; } @@ -764,18 +762,29 @@ bool Codegen::visit(BinaryExpression *ast) return false; } + Reference tempLeft = left.storeInTemp(); Reference right = expression(ast->right); if (hasError) return false; - _expr.setResult(Reference::fromTemp(this)); - binopHelper(baseOp(ast->op), left, right, _expr.result()); - left.store(_expr.result()); + binopHelper(baseOp(ast->op), tempLeft, right).loadInAccumulator(); + _expr.setResult(left.storeRetainAccumulator()); break; } + case QSOperator::BitAnd: + case QSOperator::BitOr: + case QSOperator::BitXor: + if (left.isConst()) { + Reference right = expression(ast->right); + if (hasError) + return false; + _expr.setResult(binopHelper(static_cast<QSOperator::Op>(ast->op), right, left)); + break; + } + // intentional fall-through! case QSOperator::In: case QSOperator::InstanceOf: case QSOperator::Equal: @@ -787,28 +796,20 @@ bool Codegen::visit(BinaryExpression *ast) case QSOperator::StrictEqual: case QSOperator::StrictNotEqual: case QSOperator::Add: - case QSOperator::BitAnd: - case QSOperator::BitOr: - case QSOperator::BitXor: case QSOperator::Div: - case QSOperator::LShift: case QSOperator::Mod: case QSOperator::Mul: - case QSOperator::RShift: case QSOperator::Sub: + case QSOperator::LShift: + case QSOperator::RShift: case QSOperator::URShift: { - if (left.isConst()) { - //### TODO: try constant folding? - } - - left.asRValue(); // force any loads of the lhs, so the rhs won't clobber it + auto tempLeft = left.storeInTemp(); // force any loads of the lhs, so the rhs won't clobber it Reference right = expression(ast->right); if (hasError) return false; - _expr.setResult(Reference::fromTemp(this)); - binopHelper(static_cast<QSOperator::Op>(ast->op), left, right, _expr.result()); + _expr.setResult(binopHelper(static_cast<QSOperator::Op>(ast->op), tempLeft, right)); break; } @@ -818,153 +819,121 @@ bool Codegen::visit(BinaryExpression *ast) return false; } -QV4::Moth::Temp Codegen::binopHelper(QSOperator::Op oper, Reference &left, Reference &right, - const Reference &dest) +Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Reference &right) { - if (oper == QSOperator::Add) { + switch (oper) { + case QSOperator::Add: { + right.loadInAccumulator(); Instruction::Add add; - add.lhs = left.asRValue(); - add.rhs = right.asRValue(); - add.result = dest.asLValue(); + add.lhs = left.temp(); bytecodeGenerator->addInstruction(add); - return add.result; + break; } - if (oper == QSOperator::Sub) { + case QSOperator::Sub: { + right.loadInAccumulator(); Instruction::Sub sub; - sub.lhs = left.asRValue(); - sub.rhs = right.asRValue(); - sub.result = dest.asLValue(); + sub.lhs = left.temp(); bytecodeGenerator->addInstruction(sub); - return sub.result; + break; } - if (oper == QSOperator::Mul) { + case QSOperator::Mul: { + right.loadInAccumulator(); Instruction::Mul mul; - mul.lhs = left.asRValue(); - mul.rhs = right.asRValue(); - mul.result = dest.asLValue(); + mul.lhs = left.temp(); bytecodeGenerator->addInstruction(mul); - return mul.result; - } - if (oper == QSOperator::BitAnd) { - Reference *l = &left; - Reference *r = &right; - if (l->type == Reference::Const) - std::swap(l, r); - if (r->type == Reference::Const) { + break; + } + case QSOperator::BitAnd: + if (right.isConst()) { + left.loadInAccumulator(); Instruction::BitAndConst bitAnd; - bitAnd.lhs = l->asRValue(); - bitAnd.rhs = Primitive::fromReturnedValue(r->constant).toInt32(); - bitAnd.result = dest.asLValue(); + bitAnd.rhs = Primitive::fromReturnedValue(right.constant).toInt32(); + bytecodeGenerator->addInstruction(bitAnd); + } else { + right.loadInAccumulator(); + Instruction::BitAnd bitAnd; + bitAnd.lhs = left.temp(); bytecodeGenerator->addInstruction(bitAnd); - return bitAnd.result; } - Instruction::BitAnd bitAnd; - bitAnd.lhs = left.asRValue(); - bitAnd.rhs = right.asRValue(); - bitAnd.result = dest.asLValue(); - bytecodeGenerator->addInstruction(bitAnd); - return bitAnd.result; - } - if (oper == QSOperator::BitOr) { - Reference *l = &left; - Reference *r = &right; - if (l->type == Reference::Const) - std::swap(l, r); - if (r->type == Reference::Const) { + break; + case QSOperator::BitOr: + if (right.isConst()) { + left.loadInAccumulator(); Instruction::BitOrConst bitOr; - bitOr.lhs = l->asRValue(); - bitOr.rhs = Primitive::fromReturnedValue(r->constant).toInt32(); - bitOr.result = dest.asLValue(); + bitOr.rhs = Primitive::fromReturnedValue(right.constant).toInt32(); + bytecodeGenerator->addInstruction(bitOr); + } else { + right.loadInAccumulator(); + Instruction::BitOr bitOr; + bitOr.lhs = left.temp(); bytecodeGenerator->addInstruction(bitOr); - return bitOr.result; } - Instruction::BitOr bitOr; - bitOr.lhs = left.asRValue(); - bitOr.rhs = right.asRValue(); - bitOr.result = dest.asLValue(); - bytecodeGenerator->addInstruction(bitOr); - return bitOr.result; - } - if (oper == QSOperator::BitXor) { - Reference *l = &left; - Reference *r = &right; - if (l->type == Reference::Const) - std::swap(l, r); - if (r->type == Reference::Const) { + break; + case QSOperator::BitXor: + if (right.isConst()) { + left.loadInAccumulator(); Instruction::BitXorConst bitXor; - bitXor.lhs = l->asRValue(); - bitXor.rhs = Primitive::fromReturnedValue(r->constant).toInt32(); - bitXor.result = dest.asLValue(); + bitXor.rhs = Primitive::fromReturnedValue(right.constant).toInt32(); + bytecodeGenerator->addInstruction(bitXor); + } else { + right.loadInAccumulator(); + Instruction::BitXor bitXor; + bitXor.lhs = left.temp(); bytecodeGenerator->addInstruction(bitXor); - return bitXor.result; } - Instruction::BitXor bitXor; - bitXor.lhs = left.asRValue(); - bitXor.rhs = right.asRValue(); - bitXor.result = dest.asLValue(); - bytecodeGenerator->addInstruction(bitXor); - return bitXor.result; - } - if (oper == QSOperator::RShift) { - if (right.type == Reference::Const) { + break; + case QSOperator::RShift: + if (right.isConst()) { + left.loadInAccumulator(); Instruction::ShrConst shr; - shr.lhs = left.asRValue(); shr.rhs = Primitive::fromReturnedValue(right.constant).toInt32() & 0x1f; - shr.result = dest.asLValue(); bytecodeGenerator->addInstruction(shr); - return shr.result; + } else { + right.loadInAccumulator(); + Instruction::Shr shr; + shr.lhs = left.temp(); + bytecodeGenerator->addInstruction(shr); } - Instruction::Shr shr; - shr.lhs = left.asRValue(); - shr.rhs = right.asRValue(); - shr.result = dest.asLValue(); - bytecodeGenerator->addInstruction(shr); - return shr.result; - } - if (oper == QSOperator::LShift) { - if (right.type == Reference::Const) { + break; + case QSOperator::LShift: + if (right.isConst()) { + left.loadInAccumulator(); Instruction::ShlConst shl; - shl.lhs = left.asRValue(); shl.rhs = Primitive::fromReturnedValue(right.constant).toInt32() & 0x1f; - shl.result = dest.asLValue(); bytecodeGenerator->addInstruction(shl); - return shl.result; + } else { + right.loadInAccumulator(); + Instruction::Shl shl; + shl.lhs = left.temp(); + bytecodeGenerator->addInstruction(shl); } - Instruction::Shl shl; - shl.lhs = left.asRValue(); - shl.rhs = right.asRValue(); - shl.result = dest.asLValue(); - bytecodeGenerator->addInstruction(shl); - return shl.result; - } - - if (oper == QSOperator::InstanceOf || oper == QSOperator::In || oper == QSOperator::Add) { + break; + case QSOperator::InstanceOf: + case QSOperator::In: { Instruction::BinopContext binop; if (oper == QSOperator::InstanceOf) binop.alu = QV4::Runtime::instanceof; - else if (oper == QSOperator::In) - binop.alu = QV4::Runtime::in; else - binop.alu = QV4::Runtime::add; - binop.lhs = left.asRValue(); - binop.rhs = right.asRValue(); - binop.result = dest.asLValue(); + binop.alu = QV4::Runtime::in; Q_ASSERT(binop.alu != QV4::Runtime::InvalidRuntimeMethod); + right.loadInAccumulator(); + binop.lhs = left.temp(); bytecodeGenerator->addInstruction(binop); - return binop.result; - } else { + break; + } + default: { auto binopFunc = aluOpFunction(oper); Q_ASSERT(binopFunc != QV4::Runtime::InvalidRuntimeMethod); + right.loadInAccumulator(); Instruction::Binop binop; binop.alu = binopFunc; - binop.lhs = left.asRValue(); - binop.rhs = right.asRValue(); - binop.result = dest.asLValue(); + binop.lhs = left.temp(); bytecodeGenerator->addInstruction(binop); - return binop.result; + break; + } } - Q_UNIMPLEMENTED(); + return Reference::fromAccumulator(this); } bool Codegen::visit(CallExpression *ast) @@ -972,54 +941,51 @@ bool Codegen::visit(CallExpression *ast) if (hasError) return false; - Reference r = Reference::fromTemp(this); - TempScope scope(this); Reference base = expression(ast->base); if (hasError) return false; + if (base.type != Reference::Member && base.type != Reference::Subscript && + base.type != Reference::Name) + base = base.storeInTemp(); auto calldata = pushArgs(ast->arguments); if (hasError) return false; + //### Do we really need all these call instructions? can's we load the callee in a temp? if (base.type == Reference::Member) { Instruction::CallProperty call; - call.base = base.base; - call.name = base.nameIndex; + call.base = base.propertyBase; + call.name = base.propertyNameIndex; call.callData = calldata; - call.result = r.asLValue(); bytecodeGenerator->addInstruction(call); } else if (base.type == Reference::Subscript) { Instruction::CallElement call; - call.base = base.base; - call.index = base.subscript; + call.base = base.elementBase; + call.index = base.elementSubscript; call.callData = calldata; - call.result = r.asLValue(); bytecodeGenerator->addInstruction(call); } else if (base.type == Reference::Name) { if (useFastLookups && base.global) { Instruction::CallGlobalLookup call; - call.index = registerGlobalGetterLookup(base.nameIndex); + call.index = registerGlobalGetterLookup(base.unqualifiedNameIndex); call.callData = calldata; - call.result = r.asLValue(); bytecodeGenerator->addInstruction(call); } else { Instruction::CallActivationProperty call; - call.name = base.nameIndex; + call.name = base.unqualifiedNameIndex; call.callData = calldata; - call.result = r.asLValue(); bytecodeGenerator->addInstruction(call); } } else { Instruction::CallValue call; - call.dest = base.asRValue(); + call.dest = base.temp(); call.callData = calldata; - call.result = r.asLValue(); bytecodeGenerator->addInstruction(call); } - _expr.setResult(r); + _expr.setResult(Reference::fromAccumulator(this)); return false; } @@ -1030,13 +996,16 @@ Moth::Temp Codegen::pushArgs(ArgumentList *args) ++argc; int calldata = bytecodeGenerator->newTempArray(argc + 2); // 2 additional values for CallData - Reference::fromTemp(this, calldata).store(Reference::fromConst(this, QV4::Encode(argc))); - Reference::fromTemp(this, calldata + 1).store(Reference::fromConst(this, QV4::Encode::undefined())); + (void) Reference::fromConst(this, QV4::Encode(argc)).storeInTemp(calldata); + (void) Reference::fromConst(this, QV4::Encode::undefined()).storeInTemp(calldata + 1); argc = 0; for (ArgumentList *it = args; it; it = it->next) { TempScope scope(this); - Reference::fromTemp(this, calldata + 2 + argc).store(expression(it->expression)); + Reference e = expression(it->expression); + if (hasError) + break; + (void) e.storeInTemp(calldata + 2 + argc); ++argc; } @@ -1048,9 +1017,6 @@ bool Codegen::visit(ConditionalExpression *ast) if (hasError) return true; - const unsigned t = bytecodeGenerator->newTemp(); - _expr.setResult(Reference::fromTemp(this, t)); - TempScope scope(this); BytecodeGenerator::Label iftrue = bytecodeGenerator->newLabel(); @@ -1058,13 +1024,20 @@ bool Codegen::visit(ConditionalExpression *ast) condition(ast->expression, &iftrue, &iffalse, true); iftrue.link(); - _expr.result().store(expression(ast->ok)); + Reference ok = expression(ast->ok); + if (hasError) + return false; + ok.loadInAccumulator(); BytecodeGenerator::Jump jump_endif = bytecodeGenerator->jump(); iffalse.link(); - _expr.result().store(expression(ast->ko)); + Reference ko = expression(ast->ko); + if (hasError) + return false; + ko.loadInAccumulator(); jump_endif.link(); + _expr.setResult(Reference::fromAccumulator(this)); return false; } @@ -1097,29 +1070,26 @@ bool Codegen::visit(DeleteExpression *ast) throwSyntaxError(ast->deleteToken, QStringLiteral("Delete of an unqualified identifier in strict mode.")); return false; } - _expr.setResult(Reference::fromTemp(this)); Instruction::CallBuiltinDeleteName del; - del.name = expr.nameIndex; - del.result = _expr.result().asLValue(); + del.name = expr.unqualifiedNameIndex; bytecodeGenerator->addInstruction(del); + _expr.setResult(Reference::fromAccumulator(this)); return false; } case Reference::Member: { - _expr.setResult(Reference::fromTemp(this)); Instruction::CallBuiltinDeleteMember del; - del.base = expr.base; - del.member = expr.nameIndex; - del.result = _expr.result().asLValue(); + del.base = expr.propertyBase; + del.member = expr.propertyNameIndex; bytecodeGenerator->addInstruction(del); + _expr.setResult(Reference::fromAccumulator(this)); return false; } case Reference::Subscript: { - _expr.setResult(Reference::fromTemp(this)); Instruction::CallBuiltinDeleteSubscript del; - del.base = expr.base; - del.index = expr.subscript; - del.result = _expr.result().asLValue(); + del.base = expr.elementBase; + del.index = expr.elementSubscript; bytecodeGenerator->addInstruction(del); + _expr.setResult(Reference::fromAccumulator(this)); return false; } default: @@ -1241,21 +1211,21 @@ bool Codegen::visit(NewExpression *ast) if (hasError) return false; - Reference r = Reference::fromTemp(this); TempScope scope(this); Reference base = expression(ast->expression); if (hasError) return false; + //### Maybe create a CreateValueA that takes an accumulator? + base = base.storeInTemp(); auto calldata = pushArgs(0); Instruction::CreateValue create; - create.func = base.asRValue(); + create.func = base.temp(); create.callData = calldata; - create.result = r.asLValue(); bytecodeGenerator->addInstruction(create); - _expr.setResult(r); + _expr.setResult(Reference::fromAccumulator(this)); return false; } @@ -1264,23 +1234,22 @@ bool Codegen::visit(NewMemberExpression *ast) if (hasError) return false; - Reference r = Reference::fromTemp(this); TempScope scope(this); Reference base = expression(ast->base); if (hasError) return false; + base = base.storeInTemp(); auto calldata = pushArgs(ast->arguments); if (hasError) return false; Instruction::CreateValue create; - create.func = base.asRValue(); + create.func = base.temp(); create.callData = calldata; - create.result = r.asRValue(); bytecodeGenerator->addInstruction(create); - _expr.setResult(r); + _expr.setResult(Reference::fromAccumulator(this)); return false; } @@ -1322,7 +1291,6 @@ bool Codegen::visit(ObjectLiteral *ast) QMap<QString, ObjectPropertyValue> valueMap; - auto result = Reference::fromTemp(this); TempScope scope(this); for (PropertyAssignmentList *it = ast->properties; it; it = it->next) { @@ -1339,9 +1307,7 @@ bool Codegen::visit(ObjectLiteral *ast) return false; } - v.rvalue = value; - if (v.rvalue.type != Reference::Const) - v.rvalue.asRValue(); + v.rvalue = value.storeInTemp(); } else if (PropertyGetterSetter *gs = AST::cast<AST::PropertyGetterSetter *>(it->assignment)) { const int function = defineFunction(name, gs, gs->formals, gs->functionBody ? gs->functionBody->elements : 0); ObjectPropertyValue &v = valueMap[name]; @@ -1386,7 +1352,7 @@ bool Codegen::visit(ObjectLiteral *ast) int temp = bytecodeGenerator->newTemp(); if (args == -1) args = temp; - Reference::fromTemp(this, temp).store(arg); + (void) arg.storeInTemp(temp); }; auto undefined = [this](){ return Reference::fromConst(this, Encode::undefined()); }; @@ -1438,10 +1404,9 @@ bool Codegen::visit(ObjectLiteral *ast) call.arrayValueCount = arrayKeyWithValue.size(); call.arrayGetterSetterCountAndFlags = arrayGetterSetterCountAndFlags; call.args = Moth::Temp::create(args); - call.result = result.asLValue(); bytecodeGenerator->addInstruction(call); - _expr.setResult(result); + _expr.setResult(Reference::fromAccumulator(this)); return false; } @@ -1526,12 +1491,11 @@ bool Codegen::visit(RegExpLiteral *ast) if (hasError) return false; - auto r = Reference::fromTemp(this); + auto r = Reference::fromAccumulator(this); r.isReadonly = true; _expr.setResult(r); Instruction::LoadRegExp instr; - instr.result = r.asLValue(); instr.regExpId = jsUnitGenerator->registerRegExp(ast); bytecodeGenerator->addInstruction(instr); return false; @@ -1542,12 +1506,11 @@ bool Codegen::visit(StringLiteral *ast) if (hasError) return false; - auto r = Reference::fromTemp(this); + auto r = Reference::fromAccumulator(this); r.isReadonly = true; _expr.setResult(r); Instruction::LoadRuntimeString instr; - instr.result = r.asLValue(); instr.stringId = registerString(ast->value.toString()); bytecodeGenerator->addInstruction(instr); return false; @@ -1585,8 +1548,6 @@ bool Codegen::visit(TypeOfExpression *ast) if (hasError) return false; - _expr.setResult(Reference::fromTemp(this)); - TempScope scope(this); Reference expr = expression(ast->expression); @@ -1596,15 +1557,14 @@ bool Codegen::visit(TypeOfExpression *ast) if (expr.type == Reference::Name) { // special handling as typeof doesn't throw here Instruction::CallBuiltinTypeofName instr; - instr.name = expr.nameIndex; - instr.result = _expr.result().asLValue(); + instr.name = expr.unqualifiedNameIndex; bytecodeGenerator->addInstruction(instr); } else { + expr.loadInAccumulator(); Instruction::CallBuiltinTypeofValue instr; - instr.value = expr.asRValue(); - instr.result = _expr.result().asLValue(); bytecodeGenerator->addInstruction(instr); } + _expr.setResult(Reference::fromAccumulator(this)); return false; } @@ -1647,9 +1607,8 @@ bool Codegen::visit(FunctionDeclaration * ast) TempScope scope(this); if (_context->compilationMode == QmlBinding) { - Reference source = Reference::fromName(this, ast->name.toString()); - Reference target = Reference::fromTemp(this, _returnAddress); - target.store(source); + Reference::fromName(this, ast->name.toString()).loadInAccumulator(); + Reference::fromTemp(this, _returnAddress).storeConsumeAccumulator(); } _expr.accept(nx); return false; @@ -1722,22 +1681,20 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, if (member.function) { const int function = defineFunction(member.function->name.toString(), member.function, member.function->formals, member.function->body ? member.function->body->elements : 0); - auto func = Reference::fromClosure(this, function); + Reference::fromClosure(this, function).loadInAccumulator(); if (! _context->parent) { - Reference name = Reference::fromName(this, member.function->name.toString()); - name.store(func); + Reference::fromName(this, member.function->name.toString()).storeConsumeAccumulator(); } else { Q_ASSERT(member.index >= 0); Reference local = member.canEscape ? Reference::fromLocal(this, member.index, 0) : Reference::fromTemp(this, member.index, true); - local.store(func); + local.storeConsumeAccumulator(); } } } if (_context->usesArgumentsObject == Context::ArgumentsObjectUsed) { - auto args = referenceForName(QStringLiteral("arguments"), false); Instruction::CallBuiltinSetupArgumentsObject setup; - setup.result = args.asLValue(); bytecodeGenerator->addInstruction(setup); + referenceForName(QStringLiteral("arguments"), false).storeConsumeAccumulator(); } if (_context->usesThis && !_context->isStrict) { // make sure we convert this to an object @@ -1754,7 +1711,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, { Instruction::Ret ret; - ret.result = Reference::fromTemp(this, _returnAddress).base; + ret.result = Reference::fromTemp(this, _returnAddress).temporary; bytecodeGenerator->addInstruction(ret); } @@ -1903,8 +1860,8 @@ bool Codegen::visit(ExpressionStatement *ast) Reference e = expression(ast->expression); if (hasError) return false; - Reference retVal = Reference::fromTemp(this, _returnAddress); - retVal.store(e); + e.loadInAccumulator(); + Reference::fromTemp(this, _returnAddress).storeConsumeAccumulator(); } else { statement(ast->expression); } @@ -1923,10 +1880,10 @@ bool Codegen::visit(ForEachStatement *ast) if (hasError) return true; + expr.loadInAccumulator(); Instruction::CallBuiltinForeachIteratorObject iteratorObjInstr; - iteratorObjInstr.result = obj.asLValue(); - iteratorObjInstr.arg = expr.asRValue(); bytecodeGenerator->addInstruction(iteratorObjInstr); + obj.storeConsumeAccumulator(); BytecodeGenerator::Label in = bytecodeGenerator->newLabel(); BytecodeGenerator::Label end = bytecodeGenerator->newLabel(); @@ -1943,15 +1900,13 @@ bool Codegen::visit(ForEachStatement *ast) Reference lhs = expression(ast->initialiser); + obj.loadInAccumulator(); Instruction::CallBuiltinForeachNextPropertyName nextPropInstr; - nextPropInstr.result = lhs.asLValue(); - nextPropInstr.arg = obj.asRValue(); bytecodeGenerator->addInstruction(nextPropInstr); + lhs = lhs.storeRetainAccumulator().storeInTemp(); - lhs.writeBack(); - - Reference null = Reference::fromConst(this, QV4::Encode::null()); - bytecodeGenerator->jumpStrictNotEqual(lhs.asRValue(), null.asRValue()).link(body); + Reference::fromConst(this, QV4::Encode::null()).loadInAccumulator(); + bytecodeGenerator->jumpStrictNotEqual(lhs.temp()).link(body); end.link(); @@ -2064,10 +2019,10 @@ bool Codegen::visit(LocalForEachStatement *ast) variableDeclaration(ast->declaration); + expr.loadInAccumulator(); Instruction::CallBuiltinForeachIteratorObject iteratorObjInstr; - iteratorObjInstr.result = obj.asLValue(); - iteratorObjInstr.arg = expr.asRValue(); bytecodeGenerator->addInstruction(iteratorObjInstr); + obj.storeConsumeAccumulator(); BytecodeGenerator::Label in = bytecodeGenerator->newLabel(); BytecodeGenerator::Label end = bytecodeGenerator->newLabel(); @@ -2082,15 +2037,13 @@ bool Codegen::visit(LocalForEachStatement *ast) in.link(); + obj.loadInAccumulator(); Instruction::CallBuiltinForeachNextPropertyName nextPropInstr; - nextPropInstr.result = it.asLValue(); - nextPropInstr.arg = obj.asRValue(); bytecodeGenerator->addInstruction(nextPropInstr); + auto lhs = it.storeRetainAccumulator().storeInTemp(); - it.writeBack(); - - Reference null = Reference::fromConst(this, QV4::Encode::null()); - bytecodeGenerator->jumpStrictNotEqual(it.asRValue(), null.asRValue()).link(body); + Reference::fromConst(this, QV4::Encode::null()).loadInAccumulator(); + bytecodeGenerator->jumpStrictNotEqual(lhs.temp()).link(body); end.link(); @@ -2137,7 +2090,10 @@ bool Codegen::visit(ReturnStatement *ast) } if (ast->expression) { Reference expr = expression(ast->expression); - Reference::fromTemp(this, _returnAddress).storeConsume(expr); + if (hasError) + return false; + expr.loadInAccumulator(); + Reference::fromTemp(this, _returnAddress).storeConsumeAccumulator(); } if (_context->controlFlow) { @@ -2160,6 +2116,9 @@ bool Codegen::visit(SwitchStatement *ast) BytecodeGenerator::Label switchEnd = bytecodeGenerator->newLabel(); Reference lhs = expression(ast->expression); + if (hasError) + return false; + lhs = lhs.storeInTemp(); // set up labels for all clauses QHash<Node *, BytecodeGenerator::Label> blockMap; @@ -2174,13 +2133,19 @@ bool Codegen::visit(SwitchStatement *ast) for (CaseClauses *it = ast->block->clauses; it; it = it->next) { CaseClause *clause = it->clause; Reference rhs = expression(clause->expression); - bytecodeGenerator->jumpStrictEqual(lhs.asRValue(), rhs.asRValue()).link(blockMap.value(clause)); + if (hasError) + return false; + rhs.loadInAccumulator(); + bytecodeGenerator->jumpStrictEqual(lhs.temp()).link(blockMap.value(clause)); } for (CaseClauses *it = ast->block->moreClauses; it; it = it->next) { CaseClause *clause = it->clause; Reference rhs = expression(clause->expression); - bytecodeGenerator->jumpStrictEqual(lhs.asRValue(), rhs.asRValue()).link(blockMap.value(clause)); + if (hasError) + return false; + rhs.loadInAccumulator(); + bytecodeGenerator->jumpStrictEqual(lhs.temp()).link(blockMap.value(clause)); } if (DefaultClause *defaultClause = ast->block->defaultClause) @@ -2224,17 +2189,19 @@ bool Codegen::visit(SwitchStatement *ast) bool Codegen::visit(ThrowStatement *ast) { if (hasError) - return true; + return false; TempScope scope(this); Reference expr = expression(ast->expression); + if (hasError) + return false; if (_context->controlFlow) { _context->controlFlow->handleThrow(expr); } else { + expr.loadInAccumulator(); Instruction::CallBuiltinThrow instr; - instr.arg = expr.asRValue(); bytecodeGenerator->addInstruction(instr); } return false; @@ -2333,12 +2300,12 @@ bool Codegen::visit(WithStatement *ast) Reference src = expression(ast->expression); if (hasError) return false; - src.asRValue(); // trigger load before we setup the exception handler, so exceptions here go to the right place + src = src.storeInTemp(); // trigger load before we setup the exception handler, so exceptions here go to the right place ControlFlowWith flow(this); + src.loadInAccumulator(); Instruction::CallBuiltinPushScope pushScope; - pushScope.arg = src.asRValue(); bytecodeGenerator->addInstruction(pushScope); statement(ast->statement); @@ -2388,7 +2355,7 @@ bool Codegen::throwSyntaxErrorOnEvalOrArgumentsInStrictMode(const Reference &r, return false; bool isArgOrEval = false; if (r.type == Reference::Name) { - QString str = jsUnitGenerator->stringForIndex(r.nameIndex); + QString str = jsUnitGenerator->stringForIndex(r.unqualifiedNameIndex); if (str == QLatin1String("eval") || str == QLatin1String("arguments")) { isArgOrEval = true; } @@ -2487,15 +2454,14 @@ Codegen::Reference::Reference(const Codegen::Reference &other) Codegen::Reference &Codegen::Reference::operator =(const Reference &other) { - other.writeBack(); - type = other.type; - base = other.base; switch (type) { case Invalid: + case Accumulator: break; case Temporary: + temporary = other.temporary; break; case Local: case Argument: @@ -2503,11 +2469,15 @@ Codegen::Reference &Codegen::Reference::operator =(const Reference &other) scope = other.scope; break; case Name: + unqualifiedNameIndex = other.unqualifiedNameIndex; + break; case Member: - nameIndex = other.nameIndex; + propertyBase = other.propertyBase; + propertyNameIndex = other.propertyNameIndex; break; case Subscript: - subscript = other.subscript; + elementBase = other.elementBase; + elementSubscript = other.elementSubscript; break; case Const: constant = other.constant; @@ -2517,6 +2487,7 @@ Codegen::Reference &Codegen::Reference::operator =(const Reference &other) break; case QmlScopeObject: case QmlContextObject: + qmlBase = other.qmlBase; qmlCoreIndex = other.qmlCoreIndex; qmlNotifyIndex = other.qmlNotifyIndex; captureRequired = other.captureRequired; @@ -2526,8 +2497,6 @@ Codegen::Reference &Codegen::Reference::operator =(const Reference &other) } // keep loaded reference - temp = other.temp; - needsWriteBack = false; isArgOrEval = other.isArgOrEval; codegen = other.codegen; isReadonly = other.isReadonly; @@ -2536,28 +2505,25 @@ Codegen::Reference &Codegen::Reference::operator =(const Reference &other) return *this; } -Codegen::Reference::~Reference() -{ - writeBack(); -} - bool Codegen::Reference::operator==(const Codegen::Reference &other) const { if (type != other.type) return false; switch (type) { case Invalid: + case Accumulator: break; case Temporary: + return temporary == other.temporary; case Local: case Argument: - return base == other.base; + return index == other.index && scope == other.scope; case Name: - return nameIndex == other.nameIndex; + return unqualifiedNameIndex == other.unqualifiedNameIndex; case Member: - return base == other.base && nameIndex == other.nameIndex; + return propertyBase == other.propertyBase && propertyNameIndex == other.propertyNameIndex; case Subscript: - return base == other.base && subscript == other.subscript; + return elementBase == other.elementBase && elementSubscript == other.elementSubscript; case Const: return constant == other.constant; case Closure: @@ -2572,108 +2538,94 @@ bool Codegen::Reference::operator==(const Codegen::Reference &other) const return true; } -void Codegen::Reference::storeConsume(Reference &source) const +Codegen::Reference Codegen::Reference::storeConsumeAccumulator() const { - if (!isTemp() && !source.isTemp()) { - source.asRValue(); // trigger load - - Q_ASSERT(source.temp.index >= 0); - temp = source.temp; - source.temp.index = -1; - needsWriteBack = true; - return; - } - - store(source); + storeAccumulator(); // it doesn't matter what happens here, just do it. + return Reference::fromAccumulator(codegen); } -void Codegen::Reference::store(const Reference &source) const +Codegen::Reference Codegen::Reference::storeInTemp(int tempIndex) const { - Q_ASSERT(type != Const); - Q_ASSERT(!needsWriteBack); - - if (*this == source) - return; - + if (isTemp() && tempIndex == -1) + return *this; - if (isTemp()) { - if (source.temp.index != -1) { - Instruction::Move move; - move.source = source.asRValue(); - move.result = asLValue(); - codegen->bytecodeGenerator->addInstruction(move); - return; - } else { - source.load(base); - } - return; + if (isTemp()) { // temp-to-temp move + Reference dest = Reference::fromTemp(codegen, tempIndex); + Instruction::MoveReg move; + move.srcReg = temp(); + move.destReg = dest.temp(); + codegen->bytecodeGenerator->addInstruction(move); + return dest; } - if (temp.index < 0) - temp.index = codegen->bytecodeGenerator->newTemp(); - if (!source.isTemp() && source.temp.index == -1) { - source.load(temp); - needsWriteBack = true; - return; + Reference temp = Reference::fromTemp(codegen, tempIndex); + if (isConst()) { + Instruction::MoveConst move; + move.constIndex = codegen->registerConstant(constant); + move.destTemp = temp.temp(); + codegen->bytecodeGenerator->addInstruction(move); + } else { + loadInAccumulator(); + temp.storeConsumeAccumulator(); } - needsWriteBack = true; - - Moth::Temp x = source.asRValue(); - Q_ASSERT(temp != x); - Instruction::Move move; - move.source = x; - move.result = temp; - codegen->bytecodeGenerator->addInstruction(move); + return temp; } -Moth::Temp Codegen::Reference::asRValue() const +Codegen::Reference Codegen::Reference::storeRetainAccumulator() const { - Q_ASSERT(!needsWriteBack); - - Q_ASSERT(type != Invalid); - if (isTemp()) - return base; - - // need a temp to hold the value - if (temp.index == -1) { - temp.index = codegen->bytecodeGenerator->newTemp(); - load(temp); + if (storeWipesAccumulator()) { + // a store will + auto tmp = Reference::fromTemp(codegen); + tmp.storeAccumulator(); // this is safe, and won't destory the accumulator + storeAccumulator(); + return tmp; + } else { + // ok, this is safe, just do the store. + storeAccumulator(); + return *this; } - return temp; } -Moth::Temp Codegen::Reference::asLValue() const +bool Codegen::Reference::storeWipesAccumulator() const { - Q_ASSERT(type <= LastLValue); - - if (isTemp()) - return base; - - if (temp.index == -1) - temp.index = codegen->bytecodeGenerator->newTemp(); - needsWriteBack = true; - return temp; + switch (type) { + default: + case Invalid: + case This: + case Const: + case Accumulator: + Q_UNREACHABLE(); + return false; + case Temporary: + case Local: + case Argument: + return false; + case Name: + case Member: + case Subscript: + case Closure: + case QmlScopeObject: + case QmlContextObject: + return true; + } } -void Codegen::Reference::writeBack() const +void Codegen::Reference::storeAccumulator() const { - if (!needsWriteBack) - return; - - Q_ASSERT(!isTemp()); - Q_ASSERT(temp.index >= 0); - needsWriteBack = false; - switch (type) { + case Temporary: { + Instruction::StoreReg store; + store.reg = temporary; + codegen->bytecodeGenerator->addInstruction(store); + return; + } case Local: if (scope == 0) { Instruction::StoreLocal store; - store.source = temp; store.index = index; codegen->bytecodeGenerator->addInstruction(store); } else { Instruction::StoreScopedLocal store; - store.source = temp; store.index = index; store.scope = scope; codegen->bytecodeGenerator->addInstruction(store); @@ -2682,12 +2634,10 @@ void Codegen::Reference::writeBack() const case Argument: if (scope == 0) { Instruction::StoreArg store; - store.source = temp; store.index = index; codegen->bytecodeGenerator->addInstruction(store); } else { Instruction::StoreScopedArg store; - store.source = temp; store.index = index; store.scope = scope; codegen->bytecodeGenerator->addInstruction(store); @@ -2695,48 +2645,42 @@ void Codegen::Reference::writeBack() const return; case Name: { Instruction::StoreName store; - store.source = temp; - store.name = nameIndex; + store.name = unqualifiedNameIndex; codegen->bytecodeGenerator->addInstruction(store); } return; case Member: if (codegen->useFastLookups) { Instruction::SetLookup store; - store.base = base; - store.index = codegen->registerSetterLookup(nameIndex); - store.source = temp; + store.base = propertyBase; + store.index = codegen->registerSetterLookup(propertyNameIndex); codegen->bytecodeGenerator->addInstruction(store); } else { Instruction::StoreProperty store; - store.base = base; - store.name = nameIndex; - store.source = temp; + store.base = propertyBase; + store.name = propertyNameIndex; codegen->bytecodeGenerator->addInstruction(store); } return; case Subscript: { Instruction::StoreElement store; - store.base = base; - store.index = subscript; - store.source = temp; + store.base = elementBase; + store.index = elementSubscript; codegen->bytecodeGenerator->addInstruction(store); } return; case QmlScopeObject: { Instruction::StoreScopeObjectProperty store; - store.base = base; + store.base = qmlBase; store.propertyIndex = qmlCoreIndex; - store.source = temp; codegen->bytecodeGenerator->addInstruction(store); } return; case QmlContextObject: { Instruction::StoreContextObjectProperty store; - store.base = base; + store.base = qmlBase; store.propertyIndex = qmlCoreIndex; - store.source = temp; codegen->bytecodeGenerator->addInstruction(store); } return; case Invalid: - case Temporary: + case Accumulator: case Closure: case Const: case This: @@ -2747,26 +2691,30 @@ void Codegen::Reference::writeBack() const Q_UNREACHABLE(); } -void Codegen::Reference::load(Moth::Temp dest) const +void Codegen::Reference::loadInAccumulator() const { switch (type) { + case Accumulator: + return; case Const: { Instruction::LoadConst load; load.index = codegen->registerConstant(constant); - load.result = dest; + codegen->bytecodeGenerator->addInstruction(load); + } return; + case Temporary: { + Instruction::LoadReg load; + load.reg = temp(); codegen->bytecodeGenerator->addInstruction(load); } return; case Local: if (scope == 0) { Instruction::LoadLocal load; load.index = index; - load.result = dest; codegen->bytecodeGenerator->addInstruction(load); } else { Instruction::LoadScopedLocal load; load.index = index; load.scope = scope; - load.result = dest; codegen->bytecodeGenerator->addInstruction(load); } return; @@ -2774,62 +2722,53 @@ void Codegen::Reference::load(Moth::Temp dest) const if (scope == 0) { Instruction::LoadArg load; load.index = index; - load.result = dest; codegen->bytecodeGenerator->addInstruction(load); } else { Instruction::LoadScopedArg load; load.index = index; load.scope = scope; - load.result = dest; codegen->bytecodeGenerator->addInstruction(load); } return; case Name: if (codegen->useFastLookups && global) { Instruction::GetGlobalLookup load; - load.index = codegen->registerGlobalGetterLookup(nameIndex); - load.result = dest; + load.index = codegen->registerGlobalGetterLookup(unqualifiedNameIndex); codegen->bytecodeGenerator->addInstruction(load); } else { Instruction::LoadName load; - load.name = nameIndex; - load.result = dest; + load.name = unqualifiedNameIndex; codegen->bytecodeGenerator->addInstruction(load); } return; case Member: if (codegen->useFastLookups) { Instruction::GetLookup load; - load.base = base; - load.index = codegen->registerGetterLookup(nameIndex); - load.result = dest; + load.base = propertyBase; + load.index = codegen->registerGetterLookup(propertyNameIndex); codegen->bytecodeGenerator->addInstruction(load); } else { Instruction::LoadProperty load; - load.base = base; - load.name = nameIndex; - load.result = dest; + load.base = propertyBase; + load.name = propertyNameIndex; codegen->bytecodeGenerator->addInstruction(load); } return; case Subscript: { Instruction::LoadElement load; - load.base = base; - load.index = subscript; - load.result = dest; + load.base = elementBase; + load.index = elementSubscript; codegen->bytecodeGenerator->addInstruction(load); } return; case Closure: { Instruction::LoadClosure load; load.value = closureId; - load.result = dest; codegen->bytecodeGenerator->addInstruction(load); } return; case QmlScopeObject: { Instruction::LoadScopeObjectProperty load; - load.base = base; + load.base = qmlBase; load.propertyIndex = qmlCoreIndex; - load.result = dest; load.captureRequired = captureRequired; codegen->bytecodeGenerator->addInstruction(load); if (!captureRequired) @@ -2837,9 +2776,8 @@ void Codegen::Reference::load(Moth::Temp dest) const } return; case QmlContextObject: { Instruction::LoadContextObjectProperty load; - load.base = base; + load.base = qmlBase; load.propertyIndex = qmlCoreIndex; - load.result = dest; load.captureRequired = captureRequired; codegen->bytecodeGenerator->addInstruction(load); if (!captureRequired) @@ -2847,15 +2785,8 @@ void Codegen::Reference::load(Moth::Temp dest) const } return; case This: { Instruction::LoadThis load; - load.result = dest; codegen->bytecodeGenerator->addInstruction(load); } return; - case Temporary: { - Instruction::Move move; - move.source = base; - move.result = dest; - codegen->bytecodeGenerator->addInstruction(move); - } return; case Invalid: break; } diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index a5eb4d35f1..198a5e1ac8 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -106,6 +106,7 @@ public: struct Reference { enum Type { Invalid, + Accumulator, Temporary, Local, Argument, @@ -128,21 +129,34 @@ public: , codegen(nullptr) {} Reference(const Reference &other); - ~Reference(); Reference &operator =(const Reference &other); bool operator==(const Reference &other) const; bool isValid() const { return type != Invalid; } - bool isTempLocalArg() const { return isValid() && type < Argument; } + bool loadTriggersSideEffect() const { + switch (type) { + case Name: + case Member: + case Subscript: + return true; + default: + return false; + } + } bool isConst() const { return type == Const; } + bool isAccumulator() const { return type == Accumulator; } + bool isTemp() const { return type == Temporary; } + static Reference fromAccumulator(Codegen *cg) { + return Reference(cg, Accumulator); + } static Reference fromTemp(Codegen *cg, int tempIndex = -1, bool isLocal = false) { Reference r(cg, Temporary); if (tempIndex == -1) tempIndex = cg->bytecodeGenerator->newTemp(); - r.base = Moth::Temp::create(tempIndex); + r.temporary = Moth::Temp::create(tempIndex); r.tempIsLocal = isLocal; return r; } @@ -160,19 +174,22 @@ public: } static Reference fromName(Codegen *cg, const QString &name) { Reference r(cg, Name); - r.nameIndex = cg->registerString(name); + r.unqualifiedNameIndex = cg->registerString(name); return r; } static Reference fromMember(const Reference &baseRef, const QString &name) { Reference r(baseRef.codegen, Member); - r.base = baseRef.asRValue(); - r.nameIndex = r.codegen->registerString(name); + //### Add a case where the base can be in the accumulator? + r.propertyBase = baseRef.storeInTemp().temp(); + r.propertyNameIndex = r.codegen->registerString(name); return r; } static Reference fromSubscript(const Reference &baseRef, const Reference &subscript) { + Q_ASSERT(baseRef.isTemp()); Reference r(baseRef.codegen, Subscript); - r.base = baseRef.asRValue(); - r.subscript = subscript.asRValue(); + r.elementBase = baseRef.temp(); + //### Add a case where the subscript can be in the accumulator? + r.elementSubscript = subscript.storeInTemp().temp(); return r; } static Reference fromConst(Codegen *cg, QV4::ReturnedValue constant) { @@ -188,7 +205,7 @@ public: } static Reference fromQmlScopeObject(const Reference &base, qint16 coreIndex, qint16 notifyIndex, bool captureRequired) { Reference r(base.codegen, QmlScopeObject); - r.base = base.asRValue(); + r.qmlBase = base.storeInTemp().temp(); r.qmlCoreIndex = coreIndex; r.qmlNotifyIndex = notifyIndex; r.captureRequired = captureRequired; @@ -196,7 +213,7 @@ public: } static Reference fromQmlContextObject(const Reference &base, qint16 coreIndex, qint16 notifyIndex, bool captureRequired) { Reference r(base.codegen, QmlContextObject); - r.base = base.asRValue(); + r.qmlBase = base.storeInTemp().temp(); r.qmlCoreIndex = coreIndex; r.qmlNotifyIndex = notifyIndex; r.captureRequired = captureRequired; @@ -220,43 +237,53 @@ public: } } - bool isTemp() const { - return type == Temporary; - } - - void store(const Reference &source) const; - void storeConsume(Reference &source) const; + static Reference storeConstInTemp(Codegen *cg, QV4::ReturnedValue constant, int tempIndex) + { return Reference::fromConst(cg, constant).storeInTemp(tempIndex); } + Q_REQUIRED_RESULT Reference storeInTemp(int tempIndex = -1) const; + Q_REQUIRED_RESULT Reference storeRetainAccumulator() const; + Reference storeConsumeAccumulator() const; - Moth::Temp asRValue() const; - Moth::Temp asLValue() const; + bool storeWipesAccumulator() const; + void loadInAccumulator() const; - void writeBack() const; - void load(Moth::Temp dest) const; + Moth::Temp temp() const { + if (Q_UNLIKELY(!isTemp())) + Q_UNREACHABLE(); + return temporary; + } - Moth::Temp base; union { + Moth::Temp temporary; QV4::ReturnedValue constant; + int unqualifiedNameIndex; struct { // Argument/Local int index; int scope; }; - uint nameIndex; - Moth::Temp subscript; + struct { + Moth::Temp propertyBase; + int propertyNameIndex; + }; + struct { + Moth::Temp elementBase; + Moth::Temp elementSubscript; + }; int closureId; struct { // QML scope/context object case + Moth::Temp qmlBase; qint16 qmlCoreIndex; qint16 qmlNotifyIndex; bool captureRequired; }; }; - mutable Moth::Temp temp = Moth::Temp::create(-1); - mutable bool needsWriteBack = false; mutable bool isArgOrEval = false; bool isReadonly = false; bool tempIsLocal = false; bool global = false; Codegen *codegen; + private: + void storeAccumulator() const; }; struct TempScope { @@ -524,8 +551,7 @@ public: QList<QQmlError> qmlErrors() const; #endif - Moth::Temp binopHelper(QSOperator::Op oper, Reference &left, Reference &right, - const Reference &dest); + Reference binopHelper(QSOperator::Op oper, Reference &left, Reference &right); Moth::Temp pushArgs(AST::ArgumentList *args); void setUseFastLookups(bool b) { useFastLookups = b; } diff --git a/src/qml/compiler/qv4compilercontrolflow_p.h b/src/qml/compiler/qv4compilercontrolflow_p.h index ba0c4751c9..76063bc214 100644 --- a/src/qml/compiler/qv4compilercontrolflow_p.h +++ b/src/qml/compiler/qv4compilercontrolflow_p.h @@ -104,11 +104,8 @@ struct ControlFlow { } void jumpToHandler(const Handler &h) { - if (h.tempIndex >= 0) { - Reference val = Reference::fromConst(cg, QV4::Encode(h.value)); - Reference temp = Reference::fromTemp(cg, h.tempIndex); - temp.store(val); - } + if (h.tempIndex >= 0) + Reference::storeConstInTemp(cg, QV4::Encode(h.value), h.tempIndex); cg->bytecodeGenerator->jump().link(h.linkLabel); } @@ -147,14 +144,14 @@ struct ControlFlow { } virtual void handleThrow(const Reference &expr) { + Reference e = expr; Handler h = getHandler(ControlFlow::Throw); if (h.tempIndex >= 0) { - Reference val = Reference::fromConst(cg, QV4::Encode(h.value)); - Reference temp = Reference::fromTemp(cg, h.tempIndex); - temp.store(val); + e = e.storeInTemp(); + Reference::storeConstInTemp(cg, QV4::Encode(h.value), h.tempIndex); } + e.loadInAccumulator(); Instruction::CallBuiltinThrow instr; - instr.arg = expr.asRValue(); generator()->addInstruction(instr); } @@ -218,7 +215,7 @@ struct ControlFlowUnwind : public ControlFlow { Q_ASSERT(type != Loop); controlFlowTemp = static_cast<int>(generator()->newTemp()); - Reference::fromTemp(cg, controlFlowTemp).store(Reference::fromConst(cg, QV4::Encode::undefined())); + Reference::storeConstInTemp(cg, QV4::Encode::undefined(), controlFlowTemp); // we'll need at least a handler for throw getHandler(Throw); } @@ -232,20 +229,18 @@ struct ControlFlowUnwind : public ControlFlow Codegen::TempScope tempScope(cg); Handler parentHandler = getParentHandler(h.type, h.label); - if (h.type == Throw || parentHandler.tempIndex >= 0) { BytecodeGenerator::Label skip = generator()->newLabel(); - generator()->jumpStrictNotEqual(temp.asRValue(), Reference::fromConst(cg, QV4::Encode(h.value)).asRValue()) - .link(skip); + Reference::fromConst(cg, QV4::Encode(h.value)).loadInAccumulator(); + generator()->jumpStrictNotEqual(temp.temp()).link(skip); if (h.type == Throw) emitForThrowHandling(); - Reference parentTemp = Reference::fromTemp(cg, parentHandler.tempIndex); - parentTemp.store(Reference::fromConst(cg, QV4::Encode(parentHandler.value))); + Reference::storeConstInTemp(cg, QV4::Encode(parentHandler.value), parentHandler.tempIndex); generator()->jump().link(parentHandler.linkLabel); skip.link(); } else { - generator()->jumpStrictEqual(temp.asRValue(), Reference::fromConst(cg, QV4::Encode(h.value)).asRValue()) - .link(parentHandler.linkLabel); + Reference::fromConst(cg, QV4::Encode(h.value)).loadInAccumulator(); + generator()->jumpStrictEqual(temp.temp()).link(parentHandler.linkLabel); } } } @@ -339,10 +334,10 @@ struct ControlFlowCatch : public ControlFlowUnwind exceptionLabel.link(); Reference name = Reference::fromName(cg, catchExpression->name.toString()); Instruction::CallBuiltinPushCatchScope pushCatchScope; - pushCatchScope.name = name.nameIndex; + pushCatchScope.name = name.unqualifiedNameIndex; generator()->addInstruction(pushCatchScope); // clear the unwind temp for exceptions, we want to resume normal code flow afterwards - Reference::fromTemp(cg, controlFlowTemp).store(Reference::fromConst(cg, QV4::Encode::undefined())); + Reference::storeConstInTemp(cg, QV4::Encode::undefined(), controlFlowTemp); generator()->setExceptionHandler(&catchUnwindLabel); cg->statement(catchExpression->statement); @@ -396,10 +391,9 @@ struct ControlFlowFinally : public ControlFlowUnwind insideFinally = true; exceptionTemp = generator()->newTemp(); - Reference exception = Reference::fromTemp(cg, exceptionTemp); Instruction::GetException instr; - instr.result = exception.asLValue(); generator()->addInstruction(instr); + Reference::fromTemp(cg, exceptionTemp).storeConsumeAccumulator(); generator()->setExceptionHandler(parentExceptionHandler()); cg->statement(finally->statement); @@ -410,9 +404,9 @@ struct ControlFlowFinally : public ControlFlowUnwind virtual void emitForThrowHandling() { // reset the exception flag, that got cleared before executing the statements in finally + Reference::fromTemp(cg, exceptionTemp).loadInAccumulator(); Instruction::SetException setException; Q_ASSERT(exceptionTemp != -1); - setException.exception = Reference::fromTemp(cg, exceptionTemp).asRValue(); generator()->addInstruction(setException); } }; diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp index 3d1470da76..6a7fce577b 100644 --- a/src/qml/compiler/qv4instr_moth.cpp +++ b/src/qml/compiler/qv4instr_moth.cpp @@ -122,120 +122,132 @@ void dumpBytecode(const char *code, int len) const Instr *genericInstr = reinterpret_cast<const Instr *>(code); switch (genericInstr->common.instructionType) { + MOTH_BEGIN_INSTR(LoadReg) + d << instr.reg; + MOTH_END_INSTR(LoadReg) + + MOTH_BEGIN_INSTR(StoreReg) + d << instr.reg; + MOTH_END_INSTR(StoreReg) + + MOTH_BEGIN_INSTR(MoveReg) + d << instr.destReg << ", " << instr.srcReg; + MOTH_END_INSTR(MoveReg) + MOTH_BEGIN_INSTR(LoadConst) - d << instr.result << ", " << "C" << instr.index; + d << "C" << instr.index; MOTH_END_INSTR(LoadConst) + MOTH_BEGIN_INSTR(MoveConst) + d << instr.destTemp << ", C" << instr.constIndex; + MOTH_END_INSTR(MoveConst) + MOTH_BEGIN_INSTR(LoadLocal) - d << instr.result << ", " << "$" << instr.index; + d << "$" << instr.index; MOTH_END_INSTR(LoadLocal) MOTH_BEGIN_INSTR(StoreLocal) - d << "$" << instr.index << ", " << instr.source; + d << "$" << instr.index; MOTH_END_INSTR(StoreLocal) MOTH_BEGIN_INSTR(LoadArg) - d << instr.result << ", " << "#" << instr.index; + d << "#" << instr.index; MOTH_END_INSTR(LoadArg) MOTH_BEGIN_INSTR(StoreArg) - d << "#" << instr.index << ", " << instr.source; + d << "#" << instr.index; MOTH_END_INSTR(StoreArg) MOTH_BEGIN_INSTR(LoadScopedLocal) - d << instr.result << ", " << "$" << instr.index << "@" << instr.scope; + d << "$" << instr.index << "@" << instr.scope; MOTH_END_INSTR(LoadScopedLocal) MOTH_BEGIN_INSTR(StoreScopedLocal) - d << ", " << "$" << instr.index << "@" << instr.scope << ", " << instr.source; + d << ", " << "$" << instr.index << "@" << instr.scope; MOTH_END_INSTR(StoreScopedLocal) MOTH_BEGIN_INSTR(LoadScopedArg) - d << instr.result << ", " << "#" << instr.index << "@" << instr.scope; + d << "#" << instr.index << "@" << instr.scope; MOTH_END_INSTR(LoadScopedArg) MOTH_BEGIN_INSTR(StoreScopedArg) - d << "#" << instr.index << "@" << instr.scope << ", " << instr.source; + d << "#" << instr.index << "@" << instr.scope; MOTH_END_INSTR(StoreScopedArg) - MOTH_BEGIN_INSTR(Move) - d << instr.result << ", " << instr.source; - MOTH_END_INSTR(Move) - MOTH_BEGIN_INSTR(LoadRuntimeString) - d << instr.result << ", " << instr.stringId; + d << instr.stringId; MOTH_END_INSTR(LoadRuntimeString) MOTH_BEGIN_INSTR(LoadRegExp) - d << instr.result << ", " << instr.regExpId; + d << instr.regExpId; MOTH_END_INSTR(LoadRegExp) MOTH_BEGIN_INSTR(LoadClosure) - d << instr.result << ", " << instr.value; + d << instr.value; MOTH_END_INSTR(LoadClosure) MOTH_BEGIN_INSTR(LoadName) - d << instr.result << ", " << instr.name; + d << instr.name; MOTH_END_INSTR(LoadName) MOTH_BEGIN_INSTR(GetGlobalLookup) - d << instr.result << ", " << instr.index; + d << instr.index; MOTH_END_INSTR(GetGlobalLookup) MOTH_BEGIN_INSTR(StoreName) - d << instr.name << ", " << instr.source; + d << instr.name; MOTH_END_INSTR(StoreName) MOTH_BEGIN_INSTR(LoadElement) - d << instr.result << ", " << instr.base << "[" << instr.index << "]"; + d << instr.base << "[" << instr.index << "]"; MOTH_END_INSTR(LoadElement) MOTH_BEGIN_INSTR(LoadElementLookup) - d << instr.result << ", " << instr.base << "[" << instr.index << "]"; + d << instr.base << "[" << instr.index << "]"; MOTH_END_INSTR(LoadElementLookup) MOTH_BEGIN_INSTR(StoreElement) - d << instr.base << "[" << instr.index << "]" << ", " << instr.source; + d << instr.base << "[" << instr.index << "]"; MOTH_END_INSTR(StoreElement) MOTH_BEGIN_INSTR(StoreElementLookup) - d << instr.base << "[" << instr.index << "]" << ", " << instr.source; + d << instr.base << "[" << instr.index << "]"; MOTH_END_INSTR(StoreElementLookup) MOTH_BEGIN_INSTR(LoadProperty) - d << instr.result << ", " << instr.base << "[" << instr.name << "]"; + d << instr.base << "[" << instr.name << "]"; MOTH_END_INSTR(LoadProperty) MOTH_BEGIN_INSTR(GetLookup) - d << instr.result << ", " << instr.base << "(" << instr.index << ")"; + d << instr.base << "(" << instr.index << ")"; MOTH_END_INSTR(GetLookup) MOTH_BEGIN_INSTR(StoreProperty) - d << instr.base << "[" << instr.name<< "]" << ", " << instr.source; + d << instr.base << "[" << instr.name<< "]"; MOTH_END_INSTR(StoreProperty) MOTH_BEGIN_INSTR(SetLookup) - d << instr.base << ", " << instr.source; + d << instr.base; MOTH_END_INSTR(SetLookup) MOTH_BEGIN_INSTR(StoreScopeObjectProperty) - d << instr.base << "[" << instr.propertyIndex << "]" << ", " << instr.source; + d << instr.base << "[" << instr.propertyIndex << "]"; MOTH_END_INSTR(StoreScopeObjectProperty) MOTH_BEGIN_INSTR(LoadScopeObjectProperty) - d << instr.result << ", " << instr.base << "[" << instr.propertyIndex << "]"; + d << instr.base << "[" << instr.propertyIndex << "]"; MOTH_END_INSTR(LoadScopeObjectProperty) MOTH_BEGIN_INSTR(StoreContextObjectProperty) - d << instr.base << "[" << instr.propertyIndex << "]" << ", " << instr.source; + d << instr.base << "[" << instr.propertyIndex << "]"; MOTH_END_INSTR(StoreContextObjectProperty) MOTH_BEGIN_INSTR(LoadContextObjectProperty) - d << instr.result << ", " << instr.base << "[" << instr.propertyIndex << "]"; + d << instr.base << "[" << instr.propertyIndex << "]"; MOTH_END_INSTR(LoadContextObjectProperty) MOTH_BEGIN_INSTR(LoadIdObject) - d << instr.result << ", " << instr.base << "[" << instr.index << "]"; + d << instr.base << "[" << instr.index << "]"; MOTH_END_INSTR(LoadIdObject) MOTH_BEGIN_INSTR(InitStackFrame) @@ -243,27 +255,27 @@ void dumpBytecode(const char *code, int len) MOTH_END_INSTR(InitStackFrame) MOTH_BEGIN_INSTR(CallValue) - d << instr.result << ", " << instr.dest << "(" << instr.callData << ")"; + d << instr.dest << "(" << instr.callData << ")"; MOTH_END_INSTR(CallValue) MOTH_BEGIN_INSTR(CallProperty) - d << instr.result << ", " << instr.base<<"."<<instr.name << "(" << instr.callData << ")"; + d << instr.base<<"."<<instr.name << "(" << instr.callData << ")"; MOTH_END_INSTR(CallProperty) MOTH_BEGIN_INSTR(CallPropertyLookup) - d << instr.result << ", " << instr.lookupIndex << "(" << instr.callData << ")"; + d << instr.lookupIndex << "(" << instr.callData << ")"; MOTH_END_INSTR(CallPropertyLookup) MOTH_BEGIN_INSTR(CallElement) - d << instr.result << ", " << instr.base << "[" << instr.index << "]" << "(" << instr.callData << ")"; + d << instr.base << "[" << instr.index << "]" << "(" << instr.callData << ")"; MOTH_END_INSTR(CallElement) MOTH_BEGIN_INSTR(CallActivationProperty) - d << instr.result << ", " << instr.name << "(" << instr.callData << ")"; + d << instr.name << "(" << instr.callData << ")"; MOTH_END_INSTR(CallActivationProperty) MOTH_BEGIN_INSTR(CallGlobalLookup) - d << instr.result << ", " << instr.index << "(" << instr.callData << ")"; + d << instr.index << "(" << instr.callData << ")"; MOTH_END_INSTR(CallGlobalLookup) MOTH_BEGIN_INSTR(SetExceptionHandler) @@ -274,19 +286,15 @@ void dumpBytecode(const char *code, int len) MOTH_END_INSTR(SetExceptionHandler) MOTH_BEGIN_INSTR(CallBuiltinThrow) - d << instr.arg; MOTH_END_INSTR(CallBuiltinThrow) MOTH_BEGIN_INSTR(GetException) - d << instr.result; MOTH_END_INSTR(HasException) MOTH_BEGIN_INSTR(SetException) - d << instr.exception; MOTH_END_INSTR(SetExceptionFlag) MOTH_BEGIN_INSTR(CallBuiltinUnwindException) - d << instr.result; MOTH_END_INSTR(CallBuiltinUnwindException) MOTH_BEGIN_INSTR(CallBuiltinPushCatchScope) @@ -294,38 +302,34 @@ void dumpBytecode(const char *code, int len) MOTH_END_INSTR(CallBuiltinPushCatchScope) MOTH_BEGIN_INSTR(CallBuiltinPushScope) - d << instr.arg; MOTH_END_INSTR(CallBuiltinPushScope) MOTH_BEGIN_INSTR(CallBuiltinPopScope) MOTH_END_INSTR(CallBuiltinPopScope) MOTH_BEGIN_INSTR(CallBuiltinForeachIteratorObject) - d << instr.result; MOTH_END_INSTR(CallBuiltinForeachIteratorObject) MOTH_BEGIN_INSTR(CallBuiltinForeachNextPropertyName) - d << instr.result << ", " << instr.arg; MOTH_END_INSTR(CallBuiltinForeachNextPropertyName) MOTH_BEGIN_INSTR(CallBuiltinDeleteMember) - d << instr.result << ", " << instr.base << "[" << instr.member << "]"; + d << instr.base << "[" << instr.member << "]"; MOTH_END_INSTR(CallBuiltinDeleteMember) MOTH_BEGIN_INSTR(CallBuiltinDeleteSubscript) - d << instr.result << ", " << instr.base << "[" << instr.index << "]"; + d << instr.base << "[" << instr.index << "]"; MOTH_END_INSTR(CallBuiltinDeleteSubscript) MOTH_BEGIN_INSTR(CallBuiltinDeleteName) - d << instr.result << ", " << instr.name; + d << instr.name; MOTH_END_INSTR(CallBuiltinDeleteName) MOTH_BEGIN_INSTR(CallBuiltinTypeofName) - d << instr.result << ", " << instr.name; + d << instr.name; MOTH_END_INSTR(CallBuiltinTypeofName) MOTH_BEGIN_INSTR(CallBuiltinTypeofValue) - d << instr.result << ", " << instr.value; MOTH_END_INSTR(CallBuiltinTypeofValue) MOTH_BEGIN_INSTR(CallBuiltinDeclareVar) @@ -333,41 +337,40 @@ void dumpBytecode(const char *code, int len) MOTH_END_INSTR(CallBuiltinDeclareVar) MOTH_BEGIN_INSTR(CallBuiltinDefineArray) - d << instr.result << ", " << instr.args << ", " << instr.argc; + d << instr.args << ", " << instr.argc; MOTH_END_INSTR(CallBuiltinDefineArray) MOTH_BEGIN_INSTR(CallBuiltinDefineObjectLiteral) - d << instr.result << ", " << instr.args + d << instr.args << ", " << instr.internalClassId << ", " << instr.arrayValueCount << ", " << instr.arrayGetterSetterCountAndFlags; MOTH_END_INSTR(CallBuiltinDefineObjectLiteral) MOTH_BEGIN_INSTR(CallBuiltinSetupArgumentsObject) - d << instr.result; MOTH_END_INSTR(CallBuiltinSetupArgumentsObject) MOTH_BEGIN_INSTR(CallBuiltinConvertThisToObject) MOTH_END_INSTR(CallBuiltinConvertThisToObject) MOTH_BEGIN_INSTR(CreateValue) - d << instr.result << ", new" << instr.func << "(" << instr.callData << ")"; + d << "new" << instr.func << "(" << instr.callData << ")"; MOTH_END_INSTR(CreateValue) MOTH_BEGIN_INSTR(CreateProperty) - d << instr.result << ", new" << instr.name << "(" << instr.callData << instr.argc << ")"; + d << "new" << instr.name << "(" << instr.callData << instr.argc << ")"; MOTH_END_INSTR(CreateProperty) MOTH_BEGIN_INSTR(ConstructPropertyLookup) - d << instr.result << ", new" << instr.index << "(" << instr.callData << instr.argc << ")"; + d << "new" << instr.index << "(" << instr.callData << instr.argc << ")"; MOTH_END_INSTR(ConstructPropertyLookup) MOTH_BEGIN_INSTR(CreateActivationProperty) - d << instr.result << ", new" << instr.name << "(" << instr.callData << instr.argc << ")"; + d << "new" << instr.name << "(" << instr.callData << instr.argc << ")"; MOTH_END_INSTR(CreateActivationProperty) MOTH_BEGIN_INSTR(ConstructGlobalLookup) - d << instr.result << ", new" << instr.index << "(" << instr.callData << instr.argc << ")"; + d << "new" << instr.index << "(" << instr.callData << instr.argc << ")"; MOTH_END_INSTR(ConstructGlobalLookup) MOTH_BEGIN_INSTR(Jump) @@ -375,119 +378,103 @@ void dumpBytecode(const char *code, int len) MOTH_END_INSTR(Jump) MOTH_BEGIN_INSTR(JumpEq) - d << instr.condition << " " << absoluteInstructionOffset(start, instr); + d << "acc " << absoluteInstructionOffset(start, instr); MOTH_END_INSTR(JumpEq) MOTH_BEGIN_INSTR(JumpNe) - d << instr.condition << " " << absoluteInstructionOffset(start, instr); + d << "acc " << absoluteInstructionOffset(start, instr); MOTH_END_INSTR(JumpNe) MOTH_BEGIN_INSTR(JumpStrictEqual) - d << instr.lhs<< ", " << instr.rhs << " " << absoluteInstructionOffset(start, instr); + d << instr.lhs << " " << absoluteInstructionOffset(start, instr); MOTH_END_INSTR(JumpStrictEqual) MOTH_BEGIN_INSTR(JumpStrictNotEqual) - d << instr.lhs<< ", " << instr.rhs << " " << absoluteInstructionOffset(start, instr); + d << instr.lhs << " " << absoluteInstructionOffset(start, instr); MOTH_END_INSTR(JumpStrictNotEqual) MOTH_BEGIN_INSTR(UNot) - d << instr.result << ", " << instr.source; MOTH_END_INSTR(UNot) MOTH_BEGIN_INSTR(UNotBool) - d << instr.result << ", " << instr.source; MOTH_END_INSTR(UNotBool) MOTH_BEGIN_INSTR(UPlus) - d << instr.result << ", " << instr.source; MOTH_END_INSTR(UPlus) MOTH_BEGIN_INSTR(UMinus) - d << instr.result << ", " << instr.source; MOTH_END_INSTR(UMinus) MOTH_BEGIN_INSTR(UCompl) - d << instr.result << ", " << instr.source; MOTH_END_INSTR(UCompl) MOTH_BEGIN_INSTR(UComplInt) - d << instr.result << ", " << instr.source; MOTH_END_INSTR(UComplInt) - MOTH_BEGIN_INSTR(PreIncrement) - d << instr.result << ", " << instr.source; + MOTH_BEGIN_INSTR(Increment) MOTH_END_INSTR(PreIncrement) - MOTH_BEGIN_INSTR(PreDecrement) - d << instr.result << ", " << instr.source; + MOTH_BEGIN_INSTR(Decrement) MOTH_END_INSTR(PreDecrement) - MOTH_BEGIN_INSTR(PostIncrement) - d << instr.result << ", " << instr.source; - MOTH_END_INSTR(PostIncrement) - - MOTH_BEGIN_INSTR(PostDecrement) - d << instr.result << ", " << instr.source; - MOTH_END_INSTR(PostDecrement) - MOTH_BEGIN_INSTR(Binop) - d << instr.alu << ", " << instr.result << ", " << instr.lhs << ", " << instr.rhs; + d << instr.alu << ", " << instr.lhs << ", acc"; MOTH_END_INSTR(Binop) MOTH_BEGIN_INSTR(Add) - d << instr.result << ", " << instr.lhs << ", " << instr.rhs; + d << instr.lhs; MOTH_END_INSTR(Add) MOTH_BEGIN_INSTR(BitAnd) - d << instr.result << ", " << instr.lhs << ", " << instr.rhs; + d << instr.lhs << ", acc"; MOTH_END_INSTR(BitAnd) MOTH_BEGIN_INSTR(BitOr) - d << instr.result << ", " << instr.lhs << ", " << instr.rhs; + d << instr.lhs << ", acc"; MOTH_END_INSTR(BitOr) MOTH_BEGIN_INSTR(BitXor) - d << instr.result << ", " << instr.lhs << ", " << instr.rhs; + d << instr.lhs << ", acc"; MOTH_END_INSTR(BitXor) MOTH_BEGIN_INSTR(Shr) - d << instr.result << ", " << instr.lhs << ", " << instr.rhs; + d << instr.lhs << ", acc"; MOTH_END_INSTR(Shr) MOTH_BEGIN_INSTR(Shl) - d << instr.result << ", " << instr.lhs << ", " << instr.rhs; + d << instr.lhs << ", acc"; MOTH_END_INSTR(Shl) MOTH_BEGIN_INSTR(BitAndConst) - d << instr.result << ", " << instr.lhs << ", " << instr.rhs; - MOTH_END_INSTR(BitAnd) + d << "acc, " << instr.rhs; + MOTH_END_INSTR(BitAndConst) MOTH_BEGIN_INSTR(BitOrConst) - d << instr.result << ", " << instr.lhs << ", " << instr.rhs; + d << "acc, " << instr.rhs; MOTH_END_INSTR(BitOr) MOTH_BEGIN_INSTR(BitXorConst) - d << instr.result << ", " << instr.lhs << ", " << instr.rhs; + d << "acc, " << instr.rhs; MOTH_END_INSTR(BitXor) MOTH_BEGIN_INSTR(ShrConst) - d << instr.result << ", " << instr.lhs << ", " << instr.rhs; + d << "acc, " << instr.rhs; MOTH_END_INSTR(ShrConst) MOTH_BEGIN_INSTR(ShlConst) - d << instr.result << ", " << instr.lhs << ", " << instr.rhs; + d << "acc, " << instr.rhs; MOTH_END_INSTR(ShlConst) MOTH_BEGIN_INSTR(Mul) - d << instr.result << ", " << instr.lhs << ", " << instr.rhs; + d << instr.lhs << ", acc"; MOTH_END_INSTR(Mul) MOTH_BEGIN_INSTR(Sub) - d << instr.result << ", " << instr.lhs << ", " << instr.rhs; + d << instr.lhs << ", acc"; MOTH_END_INSTR(Sub) MOTH_BEGIN_INSTR(BinopContext) - d << instr.alu << instr.result << ", " << instr.lhs << ", " << instr.rhs; + d << instr.alu << " " << instr.lhs << ", acc"; MOTH_END_INSTR(BinopContext) MOTH_BEGIN_INSTR(Ret) @@ -504,19 +491,18 @@ void dumpBytecode(const char *code, int len) #endif // QT_NO_QML_DEBUGGER MOTH_BEGIN_INSTR(LoadThis) - d << instr.result; MOTH_END_INSTR(LoadThis) MOTH_BEGIN_INSTR(LoadQmlContext) - d << instr.result; + d << instr.result; MOTH_END_INSTR(LoadQmlContext) MOTH_BEGIN_INSTR(LoadQmlImportedScripts) - d << instr.result; + d << instr.result; MOTH_END_INSTR(LoadQmlImportedScripts) MOTH_BEGIN_INSTR(LoadQmlSingleton) - d << instr.result << instr.name; + d << instr.name; MOTH_END_INSTR(LoadQmlSingleton) default: diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 82ba1d2ff0..b0bcb41de7 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -72,6 +72,10 @@ QT_BEGIN_NAMESPACE F(Ret, ret) \ MOTH_DEBUG_INSTR(F) \ F(LoadConst, loadConst) \ + F(MoveConst, moveConst) \ + F(LoadReg, loadReg) \ + F(StoreReg, storeReg) \ + F(MoveReg, moveReg) \ F(LoadLocal, loadLocal) \ F(StoreLocal, storeLocal) \ F(LoadArg, loadArg) \ @@ -83,7 +87,6 @@ QT_BEGIN_NAMESPACE F(LoadRuntimeString, loadRuntimeString) \ F(LoadRegExp, loadRegExp) \ F(LoadClosure, loadClosure) \ - F(Move, move) \ F(LoadName, loadName) \ F(GetGlobalLookup, getGlobalLookup) \ F(StoreName, storeName) \ @@ -143,10 +146,8 @@ QT_BEGIN_NAMESPACE F(UMinus, uminus) \ F(UCompl, ucompl) \ F(UComplInt, ucomplInt) \ - F(PreIncrement, preIncrement) \ - F(PreDecrement, preDecrement) \ - F(PostIncrement, postIncrement) \ - F(PostDecrement, postDecrement) \ + F(Increment, increment) \ + F(Decrement, decrement) \ F(Binop, binop) \ F(Add, add) \ F(BitAnd, bitAnd) \ @@ -232,168 +233,153 @@ union Instr struct instr_loadConst { MOTH_INSTR_HEADER int index; - Temp result; + }; + struct instr_moveConst { + MOTH_INSTR_HEADER + int constIndex; + Temp destTemp; + }; + struct instr_loadReg { + MOTH_INSTR_HEADER + Temp reg; + }; + struct instr_storeReg { + MOTH_INSTR_HEADER + Temp reg; + }; + struct instr_moveReg { + MOTH_INSTR_HEADER + Temp srcReg; + Temp destReg; }; struct instr_loadLocal { MOTH_INSTR_HEADER int index; - Temp result; }; struct instr_storeLocal { MOTH_INSTR_HEADER int index; - Temp source; }; struct instr_loadArg { MOTH_INSTR_HEADER int index; - Temp result; }; struct instr_storeArg { MOTH_INSTR_HEADER int index; - Temp source; }; struct instr_loadScopedLocal { MOTH_INSTR_HEADER unsigned scope : 12; unsigned index : 20; - Temp result; }; struct instr_storeScopedLocal { MOTH_INSTR_HEADER unsigned scope : 12; unsigned index : 20; - Temp source; }; struct instr_loadScopedArg { MOTH_INSTR_HEADER unsigned scope : 12; unsigned index : 20; - Temp result; }; struct instr_storeScopedArg { MOTH_INSTR_HEADER unsigned scope : 12; unsigned index : 20; - Temp source; }; struct instr_loadRuntimeString { MOTH_INSTR_HEADER int stringId; - Temp result; }; struct instr_loadRegExp { MOTH_INSTR_HEADER int regExpId; - Temp result; - }; - struct instr_move { - MOTH_INSTR_HEADER - Temp source; - Temp result; }; struct instr_loadClosure { MOTH_INSTR_HEADER int value; - Temp result; }; struct instr_loadName { MOTH_INSTR_HEADER int name; - Temp result; }; struct instr_getGlobalLookup { MOTH_INSTR_HEADER int index; - Temp result; }; struct instr_storeName { MOTH_INSTR_HEADER int name; - Temp source; }; struct instr_loadProperty { MOTH_INSTR_HEADER int name; Temp base; - Temp result; }; struct instr_getLookup { MOTH_INSTR_HEADER int index; Temp base; - Temp result; }; struct instr_loadScopeObjectProperty { MOTH_INSTR_HEADER int propertyIndex; Temp base; - Temp result; bool captureRequired; }; struct instr_loadContextObjectProperty { MOTH_INSTR_HEADER int propertyIndex; Temp base; - Temp result; bool captureRequired; }; struct instr_loadIdObject { MOTH_INSTR_HEADER int index; Temp base; - Temp result; }; struct instr_storeProperty { MOTH_INSTR_HEADER int name; Temp base; - Temp source; }; struct instr_setLookup { MOTH_INSTR_HEADER int index; Temp base; - Temp source; }; struct instr_storeScopeObjectProperty { MOTH_INSTR_HEADER Temp base; int propertyIndex; - Temp source; }; struct instr_storeContextObjectProperty { MOTH_INSTR_HEADER Temp base; int propertyIndex; - Temp source; }; struct instr_loadElement { MOTH_INSTR_HEADER Temp base; Temp index; - Temp result; }; struct instr_loadElementLookup { MOTH_INSTR_HEADER uint lookup; Temp base; Temp index; - Temp result; }; struct instr_storeElement { MOTH_INSTR_HEADER Temp base; Temp index; - Temp source; }; struct instr_storeElementLookup { MOTH_INSTR_HEADER uint lookup; Temp base; Temp index; - Temp source; }; struct instr_initStackFrame { MOTH_INSTR_HEADER @@ -403,14 +389,12 @@ union Instr MOTH_INSTR_HEADER Temp callData; Temp dest; - Temp result; }; struct instr_callProperty { MOTH_INSTR_HEADER int name; Temp callData; Temp base; - Temp result; }; struct instr_callPropertyLookup { MOTH_INSTR_HEADER @@ -418,26 +402,22 @@ union Instr int argc; Temp callData; Temp base; - Temp result; }; struct instr_callElement { MOTH_INSTR_HEADER Temp base; Temp index; Temp callData; - Temp result; }; struct instr_callActivationProperty { MOTH_INSTR_HEADER int name; Temp callData; - Temp result; }; struct instr_callGlobalLookup { MOTH_INSTR_HEADER int index; Temp callData; - Temp result; }; struct instr_setExceptionHandler { MOTH_INSTR_HEADER @@ -445,19 +425,15 @@ union Instr }; struct instr_callBuiltinThrow { MOTH_INSTR_HEADER - Temp arg; }; struct instr_getException { MOTH_INSTR_HEADER - Temp result; }; struct instr_setException { MOTH_INSTR_HEADER - Temp exception; }; struct instr_callBuiltinUnwindException { MOTH_INSTR_HEADER - Temp result; }; struct instr_callBuiltinPushCatchScope { MOTH_INSTR_HEADER @@ -465,47 +441,36 @@ union Instr }; struct instr_callBuiltinPushScope { MOTH_INSTR_HEADER - Temp arg; }; struct instr_callBuiltinPopScope { MOTH_INSTR_HEADER }; struct instr_callBuiltinForeachIteratorObject { MOTH_INSTR_HEADER - Temp arg; - Temp result; }; struct instr_callBuiltinForeachNextPropertyName { MOTH_INSTR_HEADER - Temp arg; - Temp result; }; struct instr_callBuiltinDeleteMember { MOTH_INSTR_HEADER int member; Temp base; - Temp result; }; struct instr_callBuiltinDeleteSubscript { MOTH_INSTR_HEADER Temp base; Temp index; - Temp result; }; struct instr_callBuiltinDeleteName { MOTH_INSTR_HEADER int name; - Temp result; }; struct instr_callBuiltinTypeofName { MOTH_INSTR_HEADER int name; - Temp result; }; struct instr_callBuiltinTypeofValue { MOTH_INSTR_HEADER - Temp value; - Temp result; }; struct instr_callBuiltinDeclareVar { MOTH_INSTR_HEADER @@ -516,7 +481,6 @@ union Instr MOTH_INSTR_HEADER uint argc; Temp args; - Temp result; }; struct instr_callBuiltinDefineObjectLiteral { MOTH_INSTR_HEADER @@ -524,11 +488,9 @@ union Instr int arrayValueCount; int arrayGetterSetterCountAndFlags; // 30 bits for count, 1 bit for needsSparseArray boolean Temp args; - Temp result; }; struct instr_callBuiltinSetupArgumentsObject { MOTH_INSTR_HEADER - Temp result; }; struct instr_callBuiltinConvertThisToObject { MOTH_INSTR_HEADER @@ -537,7 +499,6 @@ union Instr MOTH_INSTR_HEADER Temp callData; Temp func; - Temp result; }; struct instr_createProperty { MOTH_INSTR_HEADER @@ -545,7 +506,6 @@ union Instr int argc; Temp callData; Temp base; - Temp result; }; struct instr_constructPropertyLookup { MOTH_INSTR_HEADER @@ -553,21 +513,18 @@ union Instr int argc; Temp callData; Temp base; - Temp result; }; struct instr_createActivationProperty { MOTH_INSTR_HEADER int name; int argc; Temp callData; - Temp result; }; struct instr_constructGlobalLookup { MOTH_INSTR_HEADER int index; int argc; Temp callData; - Temp result; }; struct instr_jump { MOTH_INSTR_HEADER @@ -576,170 +533,109 @@ union Instr struct instr_jumpEq { MOTH_INSTR_HEADER ptrdiff_t offset; - Temp condition; }; struct instr_jumpNe { MOTH_INSTR_HEADER ptrdiff_t offset; - Temp condition; }; struct instr_jumpStrictEqual { MOTH_INSTR_HEADER ptrdiff_t offset; Temp lhs; - Temp rhs; }; struct instr_jumpStrictNotEqual { MOTH_INSTR_HEADER ptrdiff_t offset; Temp lhs; - Temp rhs; }; struct instr_unot { MOTH_INSTR_HEADER - Temp source; - Temp result; }; struct instr_unotBool { MOTH_INSTR_HEADER - Temp source; - Temp result; }; struct instr_uplus { MOTH_INSTR_HEADER - Temp source; - Temp result; }; struct instr_uminus { MOTH_INSTR_HEADER - Temp source; - Temp result; }; struct instr_ucompl { MOTH_INSTR_HEADER - Temp source; - Temp result; }; struct instr_ucomplInt { MOTH_INSTR_HEADER - Temp source; - Temp result; }; - struct instr_preIncrement { + struct instr_increment { MOTH_INSTR_HEADER - Temp source; - Temp result; }; - struct instr_preDecrement { + struct instr_decrement { MOTH_INSTR_HEADER - Temp source; - Temp result; - }; - struct instr_postIncrement { - MOTH_INSTR_HEADER - Temp source; - Temp result; - }; - struct instr_postDecrement { - MOTH_INSTR_HEADER - Temp source; - Temp result; }; struct instr_binop { MOTH_INSTR_HEADER int alu; // QV4::Runtime::RuntimeMethods enum value Temp lhs; - Temp rhs; - Temp result; }; struct instr_add { MOTH_INSTR_HEADER Temp lhs; - Temp rhs; - Temp result; }; struct instr_bitAnd { MOTH_INSTR_HEADER Temp lhs; - Temp rhs; - Temp result; }; struct instr_bitOr { MOTH_INSTR_HEADER Temp lhs; - Temp rhs; - Temp result; }; struct instr_bitXor { MOTH_INSTR_HEADER Temp lhs; - Temp rhs; - Temp result; }; struct instr_shr { MOTH_INSTR_HEADER Temp lhs; - Temp rhs; - Temp result; }; struct instr_shl { MOTH_INSTR_HEADER Temp lhs; - Temp rhs; - Temp result; }; struct instr_bitAndConst { MOTH_INSTR_HEADER - Temp lhs; int rhs; - Temp result; }; struct instr_bitOrConst { MOTH_INSTR_HEADER - Temp lhs; int rhs; - Temp result; }; struct instr_bitXorConst { MOTH_INSTR_HEADER - Temp lhs; int rhs; - Temp result; }; struct instr_shrConst { MOTH_INSTR_HEADER - Temp lhs; int rhs; - Temp result; }; struct instr_shlConst { MOTH_INSTR_HEADER - Temp lhs; int rhs; - Temp result; }; struct instr_mul { MOTH_INSTR_HEADER Temp lhs; - Temp rhs; - Temp result; }; struct instr_sub { MOTH_INSTR_HEADER Temp lhs; - Temp rhs; - Temp result; }; struct instr_binopContext { MOTH_INSTR_HEADER uint alu; // offset inside the runtime methods Temp lhs; - Temp rhs; - Temp result; }; struct instr_loadThis { MOTH_INSTR_HEADER - Temp result; }; struct instr_loadQmlContext { MOTH_INSTR_HEADER @@ -751,7 +647,6 @@ union Instr }; struct instr_loadQmlSingleton { MOTH_INSTR_HEADER - Temp result; int name; }; @@ -760,6 +655,10 @@ union Instr instr_line line; instr_debug debug; instr_loadConst loadConst; + instr_moveConst moveConst; + instr_loadReg loadReg; + instr_storeReg storeReg; + instr_moveReg moveReg; instr_loadLocal loadLocal; instr_storeLocal storeLocal; instr_loadArg loadArg; @@ -770,7 +669,6 @@ union Instr instr_storeScopedArg storeScopedArg; instr_loadRuntimeString loadRuntimeString; instr_loadRegExp loadRegExp; - instr_move move; instr_loadClosure loadClosure; instr_loadName loadName; instr_getGlobalLookup getGlobalLookup; @@ -831,10 +729,8 @@ union Instr instr_uminus uminus; instr_ucompl ucompl; instr_ucomplInt ucomplInt; - instr_preIncrement preIncrement; - instr_preDecrement preDecrement; - instr_postIncrement postIncrement; - instr_postDecrement postDecrement; + instr_increment increment; + instr_decrement decrement; instr_binop binop; instr_add add; instr_bitAnd bitAnd; |