diff options
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/compiler/qv4bytecodegenerator.cpp | 4 | ||||
-rw-r--r-- | src/qml/compiler/qv4bytecodegenerator_p.h | 10 | ||||
-rw-r--r-- | src/qml/compiler/qv4bytecodehandler.cpp | 482 | ||||
-rw-r--r-- | src/qml/compiler/qv4bytecodehandler_p.h | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 58 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata_p.h | 15 | ||||
-rw-r--r-- | src/qml/compiler/qv4compiler.cpp | 13 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilercontext_p.h | 1 | ||||
-rw-r--r-- | src/qml/jit/qv4assemblercommon_p.h | 3 | ||||
-rw-r--r-- | src/qml/jit/qv4baselineassembler.cpp | 21 | ||||
-rw-r--r-- | src/qml/jit/qv4baselineassembler_p.h | 14 | ||||
-rw-r--r-- | src/qml/jit/qv4baselinejit.cpp | 20 | ||||
-rw-r--r-- | src/qml/jit/qv4baselinejit_p.h | 5 |
13 files changed, 104 insertions, 544 deletions
diff --git a/src/qml/compiler/qv4bytecodegenerator.cpp b/src/qml/compiler/qv4bytecodegenerator.cpp index d0bca69b56..ea252a6013 100644 --- a/src/qml/compiler/qv4bytecodegenerator.cpp +++ b/src/qml/compiler/qv4bytecodegenerator.cpp @@ -180,6 +180,10 @@ void BytecodeGenerator::finalize(Compiler::Context *context) context->code = code; context->lineNumberMapping = lineNumbers; + + for (const auto &li : _labelInfos) { + context->labelInfo.push_back(instructions.at(labels.at(li.labelIndex)).position); + } } int BytecodeGenerator::addInstructionHelper(Instr::Type type, const Instr &i, int offsetOfOffset) { diff --git a/src/qml/compiler/qv4bytecodegenerator_p.h b/src/qml/compiler/qv4bytecodegenerator_p.h index 5a27d3948c..1d0a57c536 100644 --- a/src/qml/compiler/qv4bytecodegenerator_p.h +++ b/src/qml/compiler/qv4bytecodegenerator_p.h @@ -306,6 +306,11 @@ QT_WARNING_POP return nTraceInfos; } + void addLoopStart(const Label &start) + { + _labelInfos.push_back({ start.index }); + } + private: friend struct Jump; friend struct Label; @@ -342,6 +347,11 @@ private: Moth::Instr lastInstr; TraceInfoCount nTraceInfos = TraceInfoCount(0); + + struct LabelInfo { + int labelIndex; + }; + std::vector<LabelInfo> _labelInfos; }; } diff --git a/src/qml/compiler/qv4bytecodehandler.cpp b/src/qml/compiler/qv4bytecodehandler.cpp index 1508790926..92b112c2fa 100644 --- a/src/qml/compiler/qv4bytecodehandler.cpp +++ b/src/qml/compiler/qv4bytecodehandler.cpp @@ -79,485 +79,3 @@ void ByteCodeHandler::decode(const char *code, uint len) #undef DECODE_AND_DISPATCH #undef DISPATCH_INSTRUCTION - -#define MOTH_UNUSED_ARGS0() -#define MOTH_UNUSED_ARGS1(arg) \ - Q_UNUSED(arg); -#define MOTH_UNUSED_ARGS2(arg1, arg2) \ - Q_UNUSED(arg1); \ - Q_UNUSED(arg2); -#define MOTH_UNUSED_ARGS3(arg1, arg2, arg3) \ - Q_UNUSED(arg1); \ - Q_UNUSED(arg2); \ - Q_UNUSED(arg3); -#define MOTH_UNUSED_ARGS4(arg1, arg2, arg3, arg4) \ - Q_UNUSED(arg1); \ - Q_UNUSED(arg2); \ - Q_UNUSED(arg3); \ - Q_UNUSED(arg4); -#define MOTH_UNUSED_ARGS5(arg1, arg2, arg3, arg4, arg5) \ - Q_UNUSED(arg1); \ - Q_UNUSED(arg2); \ - Q_UNUSED(arg3); \ - Q_UNUSED(arg4); \ - Q_UNUSED(arg5); - -#define MOTH_MARK_ARGS_UNUSED_PLEASE(nargs, ...) \ - MOTH_EXPAND_FOR_MSVC(MOTH_UNUSED_ARGS##nargs(__VA_ARGS__)) - -#define MOTH_MARK_ARGS_UNUSED_INSTRUCTION(name, nargs, ...) \ - MOTH_MARK_ARGS_UNUSED_PLEASE(nargs, __VA_ARGS__) - -#define COLLECTOR_BEGIN_INSTR(instr) \ - { \ - INSTR_##instr(MOTH_DECODE_WITH_BASE) \ - INSTR_##instr(MOTH_MARK_ARGS_UNUSED) \ - Q_UNUSED(base_ptr); - -#define COLLECTOR_END_INSTR(instr) \ - continue; \ - } - -std::vector<int> ByteCodeHandler::collectLabelsInBytecode(const char *code, uint len) -{ - MOTH_JUMP_TABLE; - - std::vector<int> labels; - - const auto addLabel = [&labels,len](int offset) { - Q_ASSERT(offset >= 0 && offset < static_cast<int>(len)); - labels.push_back(offset); - }; - - const char *start = code; - const char *end = code + len; - while (code < end) { - MOTH_DISPATCH() - Q_UNREACHABLE(); - - COLLECTOR_BEGIN_INSTR(LoadReg) - COLLECTOR_END_INSTR(LoadReg) - - COLLECTOR_BEGIN_INSTR(StoreReg) - COLLECTOR_END_INSTR(StoreReg) - - COLLECTOR_BEGIN_INSTR(MoveReg) - COLLECTOR_END_INSTR(MoveReg) - - COLLECTOR_BEGIN_INSTR(LoadConst) - COLLECTOR_END_INSTR(LoadConst) - - COLLECTOR_BEGIN_INSTR(LoadNull) - COLLECTOR_END_INSTR(LoadNull) - - COLLECTOR_BEGIN_INSTR(LoadZero) - COLLECTOR_END_INSTR(LoadZero) - - COLLECTOR_BEGIN_INSTR(LoadTrue) - COLLECTOR_END_INSTR(LoadTrue) - - COLLECTOR_BEGIN_INSTR(LoadFalse) - COLLECTOR_END_INSTR(LoadFalse) - - COLLECTOR_BEGIN_INSTR(LoadUndefined) - COLLECTOR_END_INSTR(LoadUndefined) - - COLLECTOR_BEGIN_INSTR(LoadInt) - COLLECTOR_END_INSTR(LoadInt) - - COLLECTOR_BEGIN_INSTR(MoveConst) - COLLECTOR_END_INSTR(MoveConst) - - COLLECTOR_BEGIN_INSTR(LoadImport) - COLLECTOR_END_INSTR(LoadImport) - - COLLECTOR_BEGIN_INSTR(LoadLocal) - COLLECTOR_END_INSTR(LoadLocal) - - COLLECTOR_BEGIN_INSTR(StoreLocal) - COLLECTOR_END_INSTR(StoreLocal) - - COLLECTOR_BEGIN_INSTR(LoadScopedLocal) - COLLECTOR_END_INSTR(LoadScopedLocal) - - COLLECTOR_BEGIN_INSTR(StoreScopedLocal) - COLLECTOR_END_INSTR(StoreScopedLocal) - - COLLECTOR_BEGIN_INSTR(LoadRuntimeString) - COLLECTOR_END_INSTR(LoadRuntimeString) - - COLLECTOR_BEGIN_INSTR(MoveRegExp) - COLLECTOR_END_INSTR(MoveRegExp) - - COLLECTOR_BEGIN_INSTR(LoadClosure) - COLLECTOR_END_INSTR(LoadClosure) - - COLLECTOR_BEGIN_INSTR(LoadName) - COLLECTOR_END_INSTR(LoadName) - - COLLECTOR_BEGIN_INSTR(LoadGlobalLookup) - COLLECTOR_END_INSTR(LoadGlobalLookup) - - COLLECTOR_BEGIN_INSTR(StoreNameSloppy) - COLLECTOR_END_INSTR(StoreNameSloppy) - - COLLECTOR_BEGIN_INSTR(StoreNameStrict) - COLLECTOR_END_INSTR(StoreNameStrict) - - COLLECTOR_BEGIN_INSTR(LoadElement) - COLLECTOR_END_INSTR(LoadElement) - - COLLECTOR_BEGIN_INSTR(StoreElement) - COLLECTOR_END_INSTR(StoreElement) - - COLLECTOR_BEGIN_INSTR(LoadProperty) - COLLECTOR_END_INSTR(LoadProperty) - - COLLECTOR_BEGIN_INSTR(GetLookup) - COLLECTOR_END_INSTR(GetLookup) - - COLLECTOR_BEGIN_INSTR(StoreProperty) - COLLECTOR_END_INSTR(StoreProperty) - - COLLECTOR_BEGIN_INSTR(SetLookup) - COLLECTOR_END_INSTR(SetLookup) - - COLLECTOR_BEGIN_INSTR(LoadSuperProperty) - COLLECTOR_END_INSTR(LoadSuperProperty) - - COLLECTOR_BEGIN_INSTR(StoreSuperProperty) - COLLECTOR_END_INSTR(StoreSuperProperty) - - COLLECTOR_BEGIN_INSTR(StoreScopeObjectProperty) - COLLECTOR_END_INSTR(StoreScopeObjectProperty) - - COLLECTOR_BEGIN_INSTR(LoadScopeObjectProperty) - COLLECTOR_END_INSTR(LoadScopeObjectProperty) - - COLLECTOR_BEGIN_INSTR(StoreContextObjectProperty) - COLLECTOR_END_INSTR(StoreContextObjectProperty) - - COLLECTOR_BEGIN_INSTR(LoadContextObjectProperty) - COLLECTOR_END_INSTR(LoadContextObjectProperty) - - COLLECTOR_BEGIN_INSTR(LoadIdObject) - COLLECTOR_END_INSTR(LoadIdObject) - - COLLECTOR_BEGIN_INSTR(Yield) - COLLECTOR_END_INSTR(Yield) - - COLLECTOR_BEGIN_INSTR(YieldStar) - COLLECTOR_END_INSTR(YieldStar) - - COLLECTOR_BEGIN_INSTR(Resume) - COLLECTOR_END_INSTR(Resume) - - COLLECTOR_BEGIN_INSTR(CallValue) - COLLECTOR_END_INSTR(CallValue) - - COLLECTOR_BEGIN_INSTR(CallWithReceiver) - COLLECTOR_END_INSTR(CallWithReceiver) - - COLLECTOR_BEGIN_INSTR(CallProperty) - COLLECTOR_END_INSTR(CallProperty) - - COLLECTOR_BEGIN_INSTR(CallPropertyLookup) - COLLECTOR_END_INSTR(CallPropertyLookup) - - COLLECTOR_BEGIN_INSTR(CallElement) - COLLECTOR_END_INSTR(CallElement) - - COLLECTOR_BEGIN_INSTR(CallName) - COLLECTOR_END_INSTR(CallName) - - COLLECTOR_BEGIN_INSTR(CallPossiblyDirectEval) - COLLECTOR_END_INSTR(CallPossiblyDirectEval) - - COLLECTOR_BEGIN_INSTR(CallGlobalLookup) - COLLECTOR_END_INSTR(CallGlobalLookup) - - COLLECTOR_BEGIN_INSTR(CallScopeObjectProperty) - COLLECTOR_END_INSTR(CallScopeObjectProperty) - - COLLECTOR_BEGIN_INSTR(CallContextObjectProperty) - COLLECTOR_END_INSTR(CallContextObjectProperty) - - COLLECTOR_BEGIN_INSTR(CallWithSpread) - COLLECTOR_END_INSTR(CallWithSpread) - - COLLECTOR_BEGIN_INSTR(Construct) - COLLECTOR_END_INSTR(Construct) - - COLLECTOR_BEGIN_INSTR(ConstructWithSpread) - COLLECTOR_END_INSTR(ConstructWithSpread) - - COLLECTOR_BEGIN_INSTR(SetUnwindHandler) - addLabel(code - start + offset); - COLLECTOR_END_INSTR(SetUnwindHandler) - - COLLECTOR_BEGIN_INSTR(UnwindDispatch) - COLLECTOR_END_INSTR(UnwindDispatch) - - COLLECTOR_BEGIN_INSTR(UnwindToLabel) - addLabel(code - start + offset); - COLLECTOR_END_INSTR(UnwindToLabel) - - COLLECTOR_BEGIN_INSTR(DeadTemporalZoneCheck) - COLLECTOR_END_INSTR(DeadTemporalZoneCheck) - - COLLECTOR_BEGIN_INSTR(ThrowException) - COLLECTOR_END_INSTR(ThrowException) - - COLLECTOR_BEGIN_INSTR(GetException) - COLLECTOR_END_INSTR(HasException) - - COLLECTOR_BEGIN_INSTR(SetException) - COLLECTOR_END_INSTR(SetExceptionFlag) - - COLLECTOR_BEGIN_INSTR(CreateCallContext) - COLLECTOR_END_INSTR(CreateCallContext) - - COLLECTOR_BEGIN_INSTR(PushCatchContext) - COLLECTOR_END_INSTR(PushCatchContext) - - COLLECTOR_BEGIN_INSTR(PushWithContext) - COLLECTOR_END_INSTR(PushWithContext) - - COLLECTOR_BEGIN_INSTR(PushBlockContext) - COLLECTOR_END_INSTR(PushBlockContext) - - COLLECTOR_BEGIN_INSTR(CloneBlockContext) - COLLECTOR_END_INSTR(CloneBlockContext) - - COLLECTOR_BEGIN_INSTR(PushScriptContext) - COLLECTOR_END_INSTR(PushScriptContext) - - COLLECTOR_BEGIN_INSTR(PopScriptContext) - COLLECTOR_END_INSTR(PopScriptContext) - - COLLECTOR_BEGIN_INSTR(PopContext) - COLLECTOR_END_INSTR(PopContext) - - COLLECTOR_BEGIN_INSTR(GetIterator) - COLLECTOR_END_INSTR(GetIterator) - - COLLECTOR_BEGIN_INSTR(IteratorNext) - COLLECTOR_END_INSTR(IteratorNext) - - COLLECTOR_BEGIN_INSTR(IteratorNextForYieldStar) - COLLECTOR_END_INSTR(IteratorNextForYieldStar) - - COLLECTOR_BEGIN_INSTR(IteratorClose) - COLLECTOR_END_INSTR(IteratorClose) - - COLLECTOR_BEGIN_INSTR(DestructureRestElement) - COLLECTOR_END_INSTR(DestructureRestElement) - - COLLECTOR_BEGIN_INSTR(DeleteProperty) - COLLECTOR_END_INSTR(DeleteProperty) - - COLLECTOR_BEGIN_INSTR(DeleteName) - COLLECTOR_END_INSTR(DeleteName) - - COLLECTOR_BEGIN_INSTR(TypeofName) - COLLECTOR_END_INSTR(TypeofName) - - COLLECTOR_BEGIN_INSTR(TypeofValue) - COLLECTOR_END_INSTR(TypeofValue) - - COLLECTOR_BEGIN_INSTR(DeclareVar) - COLLECTOR_END_INSTR(DeclareVar) - - COLLECTOR_BEGIN_INSTR(DefineArray) - COLLECTOR_END_INSTR(DefineArray) - - COLLECTOR_BEGIN_INSTR(DefineObjectLiteral) - COLLECTOR_END_INSTR(DefineObjectLiteral) - - COLLECTOR_BEGIN_INSTR(CreateClass) - COLLECTOR_END_INSTR(CreateClass) - - COLLECTOR_BEGIN_INSTR(CreateMappedArgumentsObject) - COLLECTOR_END_INSTR(CreateMappedArgumentsObject) - - COLLECTOR_BEGIN_INSTR(CreateUnmappedArgumentsObject) - COLLECTOR_END_INSTR(CreateUnmappedArgumentsObject) - - COLLECTOR_BEGIN_INSTR(CreateRestParameter) - COLLECTOR_END_INSTR(CreateRestParameter) - - COLLECTOR_BEGIN_INSTR(ConvertThisToObject) - COLLECTOR_END_INSTR(ConvertThisToObject) - - COLLECTOR_BEGIN_INSTR(LoadSuperConstructor) - COLLECTOR_END_INSTR(LoadSuperConstructor) - - COLLECTOR_BEGIN_INSTR(ToObject) - COLLECTOR_END_INSTR(ToObject) - - COLLECTOR_BEGIN_INSTR(Jump) - addLabel(code - start + offset); - COLLECTOR_END_INSTR(Jump) - - COLLECTOR_BEGIN_INSTR(JumpTrue) - addLabel(code - start + offset); - COLLECTOR_END_INSTR(JumpTrue) - - COLLECTOR_BEGIN_INSTR(JumpFalse) - addLabel(code - start + offset); - COLLECTOR_END_INSTR(JumpFalse) - - COLLECTOR_BEGIN_INSTR(JumpNoException) - addLabel(code - start + offset); - COLLECTOR_END_INSTR(JumpNoException) - - COLLECTOR_BEGIN_INSTR(JumpNotUndefined) - addLabel(code - start + offset); - COLLECTOR_END_INSTR(JumpNotUndefined) - - COLLECTOR_BEGIN_INSTR(CmpEqNull) - COLLECTOR_END_INSTR(CmpEqNull) - - COLLECTOR_BEGIN_INSTR(CmpNeNull) - COLLECTOR_END_INSTR(CmpNeNull) - - COLLECTOR_BEGIN_INSTR(CmpEqInt) - COLLECTOR_END_INSTR(CmpEq) - - COLLECTOR_BEGIN_INSTR(CmpNeInt) - COLLECTOR_END_INSTR(CmpNeInt) - - COLLECTOR_BEGIN_INSTR(CmpEq) - COLLECTOR_END_INSTR(CmpEq) - - COLLECTOR_BEGIN_INSTR(CmpNe) - COLLECTOR_END_INSTR(CmpNe) - - COLLECTOR_BEGIN_INSTR(CmpGt) - COLLECTOR_END_INSTR(CmpGt) - - COLLECTOR_BEGIN_INSTR(CmpGe) - COLLECTOR_END_INSTR(CmpGe) - - COLLECTOR_BEGIN_INSTR(CmpLt) - COLLECTOR_END_INSTR(CmpLt) - - COLLECTOR_BEGIN_INSTR(CmpLe) - COLLECTOR_END_INSTR(CmpLe) - - COLLECTOR_BEGIN_INSTR(CmpStrictEqual) - COLLECTOR_END_INSTR(CmpStrictEqual) - - COLLECTOR_BEGIN_INSTR(CmpStrictNotEqual) - COLLECTOR_END_INSTR(CmpStrictNotEqual) - - COLLECTOR_BEGIN_INSTR(CmpIn) - COLLECTOR_END_INSTR(CmpIn) - - COLLECTOR_BEGIN_INSTR(CmpInstanceOf) - COLLECTOR_END_INSTR(CmpInstanceOf) - - COLLECTOR_BEGIN_INSTR(UNot) - COLLECTOR_END_INSTR(UNot) - - COLLECTOR_BEGIN_INSTR(UPlus) - COLLECTOR_END_INSTR(UPlus) - - COLLECTOR_BEGIN_INSTR(UMinus) - COLLECTOR_END_INSTR(UMinus) - - COLLECTOR_BEGIN_INSTR(UCompl) - COLLECTOR_END_INSTR(UCompl) - - COLLECTOR_BEGIN_INSTR(Increment) - COLLECTOR_END_INSTR(PreIncrement) - - COLLECTOR_BEGIN_INSTR(Decrement) - COLLECTOR_END_INSTR(PreDecrement) - - COLLECTOR_BEGIN_INSTR(Add) - COLLECTOR_END_INSTR(Add) - - COLLECTOR_BEGIN_INSTR(BitAnd) - COLLECTOR_END_INSTR(BitAnd) - - COLLECTOR_BEGIN_INSTR(BitOr) - COLLECTOR_END_INSTR(BitOr) - - COLLECTOR_BEGIN_INSTR(BitXor) - COLLECTOR_END_INSTR(BitXor) - - COLLECTOR_BEGIN_INSTR(UShr) - COLLECTOR_END_INSTR(UShr) - - COLLECTOR_BEGIN_INSTR(Shr) - COLLECTOR_END_INSTR(Shr) - - COLLECTOR_BEGIN_INSTR(Shl) - COLLECTOR_END_INSTR(Shl) - - COLLECTOR_BEGIN_INSTR(BitAndConst) - COLLECTOR_END_INSTR(BitAndConst) - - COLLECTOR_BEGIN_INSTR(BitOrConst) - COLLECTOR_END_INSTR(BitOr) - - COLLECTOR_BEGIN_INSTR(BitXorConst) - COLLECTOR_END_INSTR(BitXor) - - COLLECTOR_BEGIN_INSTR(UShrConst) - COLLECTOR_END_INSTR(UShrConst) - - COLLECTOR_BEGIN_INSTR(ShrConst) - COLLECTOR_END_INSTR(ShrConst) - - COLLECTOR_BEGIN_INSTR(ShlConst) - COLLECTOR_END_INSTR(ShlConst) - - COLLECTOR_BEGIN_INSTR(Exp) - COLLECTOR_END_INSTR(Exp) - - COLLECTOR_BEGIN_INSTR(Mul) - COLLECTOR_END_INSTR(Mul) - - COLLECTOR_BEGIN_INSTR(Div) - COLLECTOR_END_INSTR(Div) - - COLLECTOR_BEGIN_INSTR(Mod) - COLLECTOR_END_INSTR(Mod) - - COLLECTOR_BEGIN_INSTR(Sub) - COLLECTOR_END_INSTR(Sub) - - COLLECTOR_BEGIN_INSTR(Ret) - COLLECTOR_END_INSTR(Ret) - -#ifndef QT_NO_QML_DEBUGGER - COLLECTOR_BEGIN_INSTR(Debug) - COLLECTOR_END_INSTR(Debug) -#endif // QT_NO_QML_DEBUGGER - - COLLECTOR_BEGIN_INSTR(InitializeBlockDeadTemporalZone) - COLLECTOR_END_INSTR(InitializeBlockDeadTemporalZone) - - COLLECTOR_BEGIN_INSTR(ThrowOnNullOrUndefined) - COLLECTOR_END_INSTR(ThrowOnNullOrUndefined) - - COLLECTOR_BEGIN_INSTR(GetTemplateObject) - COLLECTOR_END_INSTR(GetTemplateObject) - - COLLECTOR_BEGIN_INSTR(LoadQmlContext) - COLLECTOR_END_INSTR(LoadQmlContext) - - COLLECTOR_BEGIN_INSTR(LoadQmlImportedScripts) - COLLECTOR_END_INSTR(LoadQmlImportedScripts) - - COLLECTOR_BEGIN_INSTR(TailCall) - COLLECTOR_END_INSTR(TailCall) - } - - return labels; -} - -#undef COLLECTOR_BEGIN_INSTR -#undef COLLECTOR_END_INSTR diff --git a/src/qml/compiler/qv4bytecodehandler_p.h b/src/qml/compiler/qv4bytecodehandler_p.h index b37c8810bd..10626ddb74 100644 --- a/src/qml/compiler/qv4bytecodehandler_p.h +++ b/src/qml/compiler/qv4bytecodehandler_p.h @@ -100,8 +100,6 @@ public: int currentInstructionOffset() const { return _currentOffset; } int nextInstructionOffset() const { return _nextOffset; } - static std::vector<int> collectLabelsInBytecode(const char *code, uint len); - protected: FOR_EACH_MOTH_INSTR(BYTECODE_HANDLER_DEFINE_VIRTUAL_BYTECODE_HANDLER) diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 6ad26c41dd..7aa848f6e9 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -3260,25 +3260,28 @@ bool Codegen::visit(DoWhileStatement *ast) RegisterScope scope(this); - BytecodeGenerator::Label body = bytecodeGenerator->label(); + BytecodeGenerator::Label body = bytecodeGenerator->newLabel(); BytecodeGenerator::Label cond = bytecodeGenerator->newLabel(); BytecodeGenerator::Label end = bytecodeGenerator->newLabel(); ControlFlowLoop flow(this, &end, &cond); - - statement(ast->statement); - setJumpOutLocation(bytecodeGenerator, ast->statement, ast->semicolonToken); + bytecodeGenerator->jump().link(body); cond.link(); + bytecodeGenerator->addLoopStart(cond); - TailCallBlocker blockTailCalls(this); - if (!AST::cast<FalseLiteral *>(ast->expression)) { - if (AST::cast<TrueLiteral *>(ast->expression)) - bytecodeGenerator->jump().link(body); - else - condition(ast->expression, &body, &end, false); + if (!AST::cast<TrueLiteral *>(ast->expression)) { + TailCallBlocker blockTailCalls(this); + condition(ast->expression, &body, &end, true); } + body.link(); + statement(ast->statement); + setJumpOutLocation(bytecodeGenerator, ast->statement, ast->semicolonToken); + + if (!AST::cast<FalseLiteral *>(ast->expression)) + bytecodeGenerator->jump().link(cond); + end.link(); return false; @@ -3350,9 +3353,14 @@ bool Codegen::visit(ForEachStatement *ast) } }; ControlFlowLoop flow(this, &end, &in, cleanup); - bytecodeGenerator->jump().link(in); - - BytecodeGenerator::Label body = bytecodeGenerator->label(); + bytecodeGenerator->addLoopStart(in); + in.link(); + iterator.loadInAccumulator(); + Instruction::IteratorNext next; + next.value = lhsValue.stackSlot(); + next.done = iteratorDone.stackSlot(); + bytecodeGenerator->addInstruction(next); + bytecodeGenerator->addTracingJumpInstruction(Instruction::JumpTrue()).link(done); // each iteration gets it's own context, as per spec { @@ -3383,22 +3391,17 @@ bool Codegen::visit(ForEachStatement *ast) Q_UNREACHABLE(); } + blockTailCalls.unblock(); statement(ast->statement); setJumpOutLocation(bytecodeGenerator, ast->statement, ast->forToken); - } - error: - in.link(); - iterator.loadInAccumulator(); - Instruction::IteratorNext next; - next.value = lhsValue.stackSlot(); - next.done = iteratorDone.stackSlot(); - bytecodeGenerator->addInstruction(next); - bytecodeGenerator->addTracingJumpInstruction(Instruction::JumpFalse()).link(body); - bytecodeGenerator->jump().link(done); + bytecodeGenerator->jump().link(in); + error: end.link(); + + // ~ControlFlowLoop will be called here, which will generate unwind code when needed } done.link(); @@ -3427,7 +3430,7 @@ bool Codegen::visit(ForStatement *ast) BytecodeGenerator::Label end = bytecodeGenerator->newLabel(); ControlFlowLoop flow(this, &end, &step); - + bytecodeGenerator->addLoopStart(cond); condition(ast->condition, &body, &end, true); body.link(); @@ -3720,16 +3723,17 @@ bool Codegen::visit(WhileStatement *ast) return false; RegisterScope scope(this); - TailCallBlocker blockTailCalls(this); BytecodeGenerator::Label start = bytecodeGenerator->newLabel(); BytecodeGenerator::Label end = bytecodeGenerator->newLabel(); BytecodeGenerator::Label cond = bytecodeGenerator->label(); ControlFlowLoop flow(this, &end, &cond); + bytecodeGenerator->addLoopStart(cond); - if (!AST::cast<TrueLiteral *>(ast->expression)) + if (!AST::cast<TrueLiteral *>(ast->expression)) { + TailCallBlocker blockTailCalls(this); condition(ast->expression, &start, &end, true); - blockTailCalls.unblock(); + } start.link(); statement(ast->statement); diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 52c8e9f651..7197b4cde8 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE // Bump this whenever the compiler data structures change in an incompatible way. -#define QV4_DATA_STRUCTURE_VERSION 0x1a +#define QV4_DATA_STRUCTURE_VERSION 0x1b class QIODevice; class QQmlPropertyCache; @@ -302,9 +302,14 @@ struct Function typedef quint16_le TraceInfoCount; TraceInfoCount nTraceInfos; static constexpr TraceInfoCount NoTracing() { return TraceInfoCount::max(); } + + quint32_le nLabelInfos; + size_t labelInfosOffset() const { return dependingScopePropertiesOffset() + nDependingScopeProperties; } + // Keep all unaligned data at the end quint8 flags; quint8 padding1; + quint16 padding2; // quint32 formalsIndex[nFormals] // quint32 localsIndex[nLocals] @@ -321,12 +326,14 @@ struct Function const quint32_le *formalsEnd() const { return formalsTable() + nFormals; } // --- + const quint32_le *labelInfoTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + labelInfosOffset()); } + const char *code() const { return reinterpret_cast<const char *>(this) + codeOffset; } inline bool hasQmlDependencies() const { return nDependingIdObjects > 0 || nDependingContextProperties > 0 || nDependingScopeProperties > 0; } - static int calculateSize(int nFormals, int nLocals, int nLines, int nInnerfunctions, int nIdObjectDependencies, int nPropertyDependencies, int codeSize) { - int trailingData = (nFormals + nLocals + nInnerfunctions + nIdObjectDependencies + + static int calculateSize(int nFormals, int nLocals, int nLines, int nInnerfunctions, int nIdObjectDependencies, int nPropertyDependencies, int labelInfoSize, int codeSize) { + int trailingData = (nFormals + nLocals + nInnerfunctions + nIdObjectDependencies + labelInfoSize + 2 * nPropertyDependencies)*sizeof (quint32) + nLines*sizeof(CodeOffsetToLine); size_t size = align(align(sizeof(Function)) + size_t(trailingData)) + align(codeSize); Q_ASSERT(size < INT_MAX); @@ -337,7 +344,7 @@ struct Function return (a + 7) & ~size_t(7); } }; -static_assert(sizeof(Function) == 56, "Function structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); +static_assert(sizeof(Function) == 60, "Function structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct Method { enum Type { diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index 8735cc074b..0833f552e6 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -445,6 +445,12 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte currentOffset += function->nDependingScopeProperties * sizeof(quint32) * 2; } + if (!irFunction->labelInfo.empty()) { + function->nLabelInfos = quint32(irFunction->labelInfo.size()); + Q_ASSERT(function->labelInfosOffset() == currentOffset); + currentOffset += function->nLabelInfos * sizeof(quint32); + } + function->location.line = irFunction->line; function->location.column = irFunction->column; @@ -483,6 +489,11 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte *writtenDeps++ = property.value(); // notify index } + quint32_le *labels = (quint32_le *)(f + function->labelInfosOffset()); + for (unsigned u : irFunction->labelInfo) { + *labels++ = u; + } + // write byte code memcpy(f + function->codeOffset, irFunction->code.constData(), irFunction->code.size()); } @@ -682,7 +693,7 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp const int qmlIdDepsCount = f->idObjectDependencies.count(); const int qmlPropertyDepsCount = f->scopeObjectPropertyDependencies.count() + f->contextObjectPropertyDependencies.count(); quint32 size = QV4::CompiledData::Function::calculateSize(f->arguments.size(), f->locals.size(), f->lineNumberMapping.size(), f->nestedContexts.size(), - qmlIdDepsCount, qmlPropertyDepsCount, f->code.size()); + qmlIdDepsCount, qmlPropertyDepsCount, int(f->labelInfo.size()), f->code.size()); functionSize += size - f->code.size(); nextOffset += size; } diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h index 0fa1074580..5b91b93346 100644 --- a/src/qml/compiler/qv4compilercontext_p.h +++ b/src/qml/compiler/qv4compilercontext_p.h @@ -201,6 +201,7 @@ struct Context { ControlFlow *controlFlow = nullptr; QByteArray code; QVector<CompiledData::CodeOffsetToLine> lineNumberMapping; + std::vector<unsigned> labelInfo; int nRegisters = 0; int registerOffset = -1; diff --git a/src/qml/jit/qv4assemblercommon_p.h b/src/qml/jit/qv4assemblercommon_p.h index 8f4d3238c4..3e70457bd8 100644 --- a/src/qml/jit/qv4assemblercommon_p.h +++ b/src/qml/jit/qv4assemblercommon_p.h @@ -670,7 +670,8 @@ public: void addLabelForOffset(int offset) { - labelForOffset.insert(offset, label()); + if (!labelForOffset.contains(offset)) + labelForOffset.insert(offset, label()); } void addJumpToOffset(const Jump &jump, int offset) diff --git a/src/qml/jit/qv4baselineassembler.cpp b/src/qml/jit/qv4baselineassembler.cpp index 9663754cbf..987f366256 100644 --- a/src/qml/jit/qv4baselineassembler.cpp +++ b/src/qml/jit/qv4baselineassembler.cpp @@ -1382,28 +1382,31 @@ void BaselineAssembler::cmpStrictNotEqual(int lhs) pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean); } -void BaselineAssembler::jump(int offset) +int BaselineAssembler::jump(int offset) { pasm()->addJumpToOffset(pasm()->jump(), offset); + return offset; } -void BaselineAssembler::jumpTrue(int offset) +int BaselineAssembler::jumpTrue(int offset) { pasm()->toBoolean([this, offset](PlatformAssembler::RegisterID resultReg) { auto jump = pasm()->branch32(PlatformAssembler::NotEqual, TrustedImm32(0), resultReg); pasm()->addJumpToOffset(jump, offset); }); + return offset; } -void BaselineAssembler::jumpFalse(int offset) +int BaselineAssembler::jumpFalse(int offset) { pasm()->toBoolean([this, offset](PlatformAssembler::RegisterID resultReg) { auto jump = pasm()->branch32(PlatformAssembler::Equal, TrustedImm32(0), resultReg); pasm()->addJumpToOffset(jump, offset); }); + return offset; } -void BaselineAssembler::jumpNoException(int offset) +int BaselineAssembler::jumpNoException(int offset) { auto jump = pasm()->branch32( PlatformAssembler::Equal, @@ -1411,11 +1414,13 @@ void BaselineAssembler::jumpNoException(int offset) offsetof(EngineBase, hasException)), TrustedImm32(0)); pasm()->addJumpToOffset(jump, offset); + return offset; } -void BaselineAssembler::jumpNotUndefined(int offset) +int BaselineAssembler::jumpNotUndefined(int offset) { pasm()->jumpNotUndefined(offset); + return offset; } void BaselineAssembler::prepareCallWithArgCount(int argc) @@ -1539,10 +1544,11 @@ void BaselineAssembler::setException() noException.link(pasm()); } -void BaselineAssembler::setUnwindHandler(int offset) +int BaselineAssembler::setUnwindHandler(int offset) { auto l = pasm()->storePtrWithPatch(TrustedImmPtr(nullptr), pasm()->exceptionHandlerAddress()); pasm()->addEHTarget(l, offset); + return offset; } @@ -1568,12 +1574,13 @@ void JIT::BaselineAssembler::unwindDispatch() noUnwind.link(pasm()); } -void JIT::BaselineAssembler::unwindToLabel(int level, int offset) +int JIT::BaselineAssembler::unwindToLabel(int level, int offset) { auto l = pasm()->storePtrWithPatch(TrustedImmPtr(nullptr), Address(PlatformAssembler::CppStackFrameRegister, offsetof(CppStackFrame, unwindLabel))); pasm()->addEHTarget(l, offset); pasm()->store32(TrustedImm32(level), Address(PlatformAssembler::CppStackFrameRegister, offsetof(CppStackFrame, unwindLevel))); gotoCatchException(); + return offset; } void BaselineAssembler::pushCatchContext(int index, int name) diff --git a/src/qml/jit/qv4baselineassembler_p.h b/src/qml/jit/qv4baselineassembler_p.h index dbefa42784..c39d002bf9 100644 --- a/src/qml/jit/qv4baselineassembler_p.h +++ b/src/qml/jit/qv4baselineassembler_p.h @@ -135,11 +135,11 @@ public: void cmpStrictNotEqual(int lhs); // jumps - void jump(int offset); - void jumpTrue(int offset); - void jumpFalse(int offset); - void jumpNoException(int offset); - void jumpNotUndefined(int offset); + Q_REQUIRED_RESULT int jump(int offset); + Q_REQUIRED_RESULT int jumpTrue(int offset); + Q_REQUIRED_RESULT int jumpFalse(int offset); + Q_REQUIRED_RESULT int jumpNoException(int offset); + Q_REQUIRED_RESULT int jumpNotUndefined(int offset); // stuff for runtime calls void prepareCallWithArgCount(int argc); @@ -160,10 +160,10 @@ public: void gotoCatchException(); void getException(); void setException(); - void setUnwindHandler(int offset); + Q_REQUIRED_RESULT int setUnwindHandler(int offset); void clearUnwindHandler(); void unwindDispatch(); - void unwindToLabel(int level, int offset); + Q_REQUIRED_RESULT int unwindToLabel(int level, int offset); void pushCatchContext(int index, int name); void popContext(); void deadTemporalZoneCheck(int offsetForSavedIP, int variableName); diff --git a/src/qml/jit/qv4baselinejit.cpp b/src/qml/jit/qv4baselinejit.cpp index ed4cdabd26..df3af1fce3 100644 --- a/src/qml/jit/qv4baselinejit.cpp +++ b/src/qml/jit/qv4baselinejit.cpp @@ -63,7 +63,9 @@ void BaselineJIT::generate() // qDebug()<<"jitting" << function->name()->toQString(); const char *code = function->codeData; uint len = function->compiledFunction->codeSize; - labels = collectLabelsInBytecode(code, len); + + for (unsigned i = 0, ei = function->compiledFunction->nLabelInfos; i != ei; ++i) + labels.insert(int(function->compiledFunction->labelInfoTable()[i])); as->generatePrologue(); decode(code, len); @@ -591,7 +593,7 @@ void BaselineJIT::generate_ConstructWithSpread(int func, int argc, int argv) void BaselineJIT::generate_SetUnwindHandler(int offset) { if (offset) - as->setUnwindHandler(absoluteOffsetForJump(offset)); + labels.insert(as->setUnwindHandler(absoluteOffsetForJump(offset))); else as->clearUnwindHandler(); } @@ -603,7 +605,7 @@ void BaselineJIT::generate_UnwindDispatch() void BaselineJIT::generate_UnwindToLabel(int level, int offset) { - as->unwindToLabel(level, absoluteOffsetForJump(offset)); + labels.insert(as->unwindToLabel(level, absoluteOffsetForJump(offset))); } void BaselineJIT::generate_DeadTemporalZoneCheck(int name) @@ -870,11 +872,11 @@ void BaselineJIT::generate_ToObject() } -void BaselineJIT::generate_Jump(int offset) { as->jump(absoluteOffsetForJump(offset)); } -void BaselineJIT::generate_JumpTrue(int /*traceSlot*/, int offset) { as->jumpTrue(absoluteOffsetForJump(offset)); } -void BaselineJIT::generate_JumpFalse(int /*traceSlot*/, int offset) { as->jumpFalse(absoluteOffsetForJump(offset)); } -void BaselineJIT::generate_JumpNoException(int offset) { as->jumpNoException(absoluteOffsetForJump(offset)); } -void BaselineJIT::generate_JumpNotUndefined(int offset) { as->jumpNotUndefined(absoluteOffsetForJump(offset)); } +void BaselineJIT::generate_Jump(int offset) { labels.insert(as->jump(absoluteOffsetForJump(offset))); } +void BaselineJIT::generate_JumpTrue(int /*traceSlot*/, int offset) { labels.insert(as->jumpTrue(absoluteOffsetForJump(offset))); } +void BaselineJIT::generate_JumpFalse(int /*traceSlot*/, int offset) { labels.insert(as->jumpFalse(absoluteOffsetForJump(offset))); } +void BaselineJIT::generate_JumpNoException(int offset) { labels.insert(as->jumpNoException(absoluteOffsetForJump(offset))); } +void BaselineJIT::generate_JumpNotUndefined(int offset) { labels.insert(as->jumpNotUndefined(absoluteOffsetForJump(offset))); } void BaselineJIT::generate_CmpEqNull() { as->cmpeqNull(); } void BaselineJIT::generate_CmpNeNull() { as->cmpneNull(); } @@ -1004,7 +1006,7 @@ void BaselineJIT::generate_GetTemplateObject(int index) void BaselineJIT::startInstruction(Instr::Type /*instr*/) { - if (hasLabel()) + if (labels.contains(currentInstructionOffset())) as->addLabel(currentInstructionOffset()); } diff --git a/src/qml/jit/qv4baselinejit_p.h b/src/qml/jit/qv4baselinejit_p.h index 9e7dd8f2ca..385fbf72f3 100644 --- a/src/qml/jit/qv4baselinejit_p.h +++ b/src/qml/jit/qv4baselinejit_p.h @@ -221,16 +221,13 @@ public: void endInstruction(Moth::Instr::Type instr) override; protected: - bool hasLabel() const - { return std::find(labels.cbegin(), labels.cend(), currentInstructionOffset()) != labels.cend(); } - int absoluteOffsetForJump(int relativeOffset) const { return nextInstructionOffset() + relativeOffset; } private: QV4::Function *function; QScopedPointer<BaselineAssembler> as; - std::vector<int> labels; + QSet<int> labels; }; #endif // V4_ENABLE_JIT |