diff options
-rw-r--r-- | src/qml/compiler/qv4bytecodegenerator.cpp | 16 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth.cpp | 6 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 163 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 2 |
4 files changed, 108 insertions, 79 deletions
diff --git a/src/qml/compiler/qv4bytecodegenerator.cpp b/src/qml/compiler/qv4bytecodegenerator.cpp index 6efeac2a31..7e1f49ee86 100644 --- a/src/qml/compiler/qv4bytecodegenerator.cpp +++ b/src/qml/compiler/qv4bytecodegenerator.cpp @@ -75,8 +75,9 @@ void BytecodeGenerator::packInstruction(I &i) type = Instr::narrowInstructionType(type); int instructionsAsInts[sizeof(Instr)/sizeof(int)] = {}; int nMembers = Moth::InstrInfo::argumentCount[static_cast<int>(i.type)]; + uchar *code = i.packed + Instr::encodedLength(type); for (int j = 0; j < nMembers; ++j) { - instructionsAsInts[j] = qFromLittleEndian<qint32>(i.packed + 1 + j * sizeof(int)); + instructionsAsInts[j] = qFromLittleEndian<qint32>(code + j * sizeof(int)); } enum { Normal, @@ -88,11 +89,10 @@ void BytecodeGenerator::packInstruction(I &i) break; } } - uchar *code = i.packed; + code = i.packed; switch (width) { case Normal: - Instr::pack(code, type); - ++code; + code = Instr::pack(code, type); for (int n = 0; n < nMembers; ++n) { qint8 v = static_cast<qint8>(instructionsAsInts[n]); memcpy(code, &v, 1); @@ -225,12 +225,10 @@ QT_WARNING_POP const int argCount = Moth::InstrInfo::argumentCount[static_cast<int>(type)]; int s = argCount*sizeof(int); if (offsetOfOffset != -1) - offsetOfOffset += 1; - I instr{type, static_cast<short>(s + 1), 0, currentLine, offsetOfOffset, -1, "\0\0" }; + offsetOfOffset += Instr::encodedLength(type); + I instr{type, static_cast<short>(s + Instr::encodedLength(type)), 0, currentLine, offsetOfOffset, -1, "\0\0" }; uchar *code = instr.packed; - Instr::pack(code, Instr::wideInstructionType(type)); - ++code; - Q_ASSERT(static_cast<uint>(Instr::wideInstructionType(type)) < 256); + code = Instr::pack(code, Instr::wideInstructionType(type)); for (int j = 0; j < argCount; ++j) { qToLittleEndian<qint32>(i.argumentsAsInts[j], code); diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp index 6773f97c8b..8e474b3783 100644 --- a/src/qml/compiler/qv4instr_moth.cpp +++ b/src/qml/compiler/qv4instr_moth.cpp @@ -48,7 +48,7 @@ int InstrInfo::size(Instr::Type type) { #define MOTH_RETURN_INSTR_SIZE(I) case Instr::Type::I: case Instr::Type::I##_Wide: return InstrMeta<int(Instr::Type::I)>::Size; switch (type) { - FOR_EACH_MOTH_INSTR(MOTH_RETURN_INSTR_SIZE) + FOR_EACH_MOTH_INSTR_ALL(MOTH_RETURN_INSTR_SIZE) } #undef MOTH_RETURN_INSTR_SIZE Q_UNREACHABLE(); @@ -111,6 +111,8 @@ static QString toString(QV4::ReturnedValue v) QDebug d = qDebug(); \ d.noquote(); \ d.nospace(); \ + if (static_cast<int>(Instr::Type::instr) >= 0x100) \ + --base_ptr; \ d << alignedLineNumber(line) << alignedNumber(codeOffset).constData() << ": " \ << rawBytes(base_ptr, int(code - base_ptr)) << #instr << " "; @@ -123,7 +125,7 @@ namespace QV4 { namespace Moth { const int InstrInfo::argumentCount[] = { - FOR_EACH_MOTH_INSTR(MOTH_COLLECT_NARGS) + FOR_EACH_MOTH_INSTR_ALL(MOTH_COLLECT_NARGS) }; diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 29fc28c128..4e2dd370c4 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -62,6 +62,7 @@ QT_BEGIN_NAMESPACE op##_INSTRUCTION(name, nargs, __VA_ARGS__) /* for all jump instructions, the offset has to come last, to simplify the job of the bytecode generator */ +#define INSTR_Nop(op) INSTRUCTION(op, Nop, 0) #define INSTR_Ret(op) INSTRUCTION(op, Ret, 0) #define INSTR_Debug(op) INSTRUCTION(op, Debug, 0) #define INSTR_LoadConst(op) INSTRUCTION(op, LoadConst, 1, index) @@ -191,10 +192,12 @@ QT_BEGIN_NAMESPACE #define INSTR_LoadQmlContext(op) INSTRUCTION(op, LoadQmlContext, 1, result) #define INSTR_LoadQmlImportedScripts(op) INSTRUCTION(op, LoadQmlImportedScripts, 1, result) +#define FOR_EACH_MOTH_INSTR_ALL(F) \ + F(Nop) \ + FOR_EACH_MOTH_INSTR(F) #define FOR_EACH_MOTH_INSTR(F) \ F(Ret) \ - F(Debug) \ F(LoadConst) \ F(LoadZero) \ F(LoadTrue) \ @@ -202,6 +205,7 @@ QT_BEGIN_NAMESPACE F(LoadNull) \ F(LoadUndefined) \ F(LoadInt) \ + F(LoadRuntimeString) \ F(MoveConst) \ F(LoadReg) \ F(StoreReg) \ @@ -210,7 +214,6 @@ QT_BEGIN_NAMESPACE F(StoreLocal) \ F(LoadScopedLocal) \ F(StoreScopedLocal) \ - F(LoadRuntimeString) \ F(MoveRegExp) \ F(LoadClosure) \ F(LoadName) \ @@ -230,51 +233,7 @@ QT_BEGIN_NAMESPACE F(LoadScopeObjectProperty) \ F(LoadContextObjectProperty) \ F(LoadIdObject) \ - F(Yield) \ - F(Resume) \ - F(CallValue) \ - F(CallProperty) \ - F(CallPropertyLookup) \ - F(CallElement) \ - F(CallName) \ - F(CallPossiblyDirectEval) \ - F(CallGlobalLookup) \ - F(CallScopeObjectProperty) \ - F(CallContextObjectProperty) \ - F(CallWithSpread) \ - F(Construct) \ - F(ConstructWithSpread) \ - F(SetUnwindHandler) \ - F(UnwindDispatch) \ - F(UnwindToLabel) \ - F(ThrowException) \ - F(GetException) \ - F(SetException) \ - F(CreateCallContext) \ - F(PushCatchContext) \ - F(PushWithContext) \ - F(PushBlockContext) \ - F(CloneBlockContext) \ - F(PushScriptContext) \ - F(PopScriptContext) \ - F(PopContext) \ - F(GetIterator) \ - F(IteratorNext) \ - F(IteratorClose) \ - F(DestructureRestElement) \ - F(DeleteProperty) \ - F(DeleteName) \ - F(TypeofName) \ - F(TypeofValue) \ - F(DeclareVar) \ - F(DefineArray) \ - F(DefineObjectLiteral) \ - F(CreateClass) \ - F(CreateMappedArgumentsObject) \ - F(CreateUnmappedArgumentsObject) \ - F(CreateRestParameter) \ F(ConvertThisToObject) \ - F(LoadSuperConstructor) \ F(ToObject) \ F(Jump) \ F(JumpTrue) \ @@ -319,9 +278,55 @@ QT_BEGIN_NAMESPACE F(Div) \ F(Mod) \ F(Sub) \ + F(CallValue) \ + F(CallProperty) \ + F(CallPropertyLookup) \ + F(CallElement) \ + F(CallName) \ + F(CallPossiblyDirectEval) \ + F(CallGlobalLookup) \ + F(CallScopeObjectProperty) \ + F(CallContextObjectProperty) \ + F(CallWithSpread) \ + F(Construct) \ + F(ConstructWithSpread) \ + F(SetUnwindHandler) \ + F(UnwindDispatch) \ + F(UnwindToLabel) \ + F(ThrowException) \ + F(GetException) \ + F(SetException) \ + F(CreateCallContext) \ + F(PushCatchContext) \ + F(PushWithContext) \ + F(PushBlockContext) \ + F(CloneBlockContext) \ + F(PopContext) \ + F(GetIterator) \ + F(IteratorNext) \ + F(IteratorClose) \ + F(DestructureRestElement) \ + F(DeleteProperty) \ + F(DeleteName) \ + F(TypeofName) \ + F(TypeofValue) \ + F(DeclareVar) \ + F(DefineArray) \ + F(DefineObjectLiteral) \ + F(CreateMappedArgumentsObject) \ + F(CreateUnmappedArgumentsObject) \ + F(CreateRestParameter) \ F(LoadQmlContext) \ - F(LoadQmlImportedScripts) -#define MOTH_NUM_INSTRUCTIONS() (static_cast<int>(Moth::Instr::Type::LoadQmlImportedScripts_Wide)) + F(LoadQmlImportedScripts) \ + F(Yield) \ + F(Resume) \ + F(CreateClass) \ + F(LoadSuperConstructor) \ + F(PushScriptContext) \ + F(PopScriptContext) \ + F(Debug) \ + +#define MOTH_NUM_INSTRUCTIONS() (static_cast<int>(Moth::Instr::Type::Debug_Wide) + 1) #if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) // icc before version 1200 doesn't support computed goto, and at least up to version 18.0.0 the @@ -439,27 +444,44 @@ QT_BEGIN_NAMESPACE #define MOTH_JUMP_TABLE \ static const void *jumpTable[] = { \ - FOR_EACH_MOTH_INSTR(COLLECT_LABELS) \ + FOR_EACH_MOTH_INSTR_ALL(COLLECT_LABELS) \ }; -#define MOTH_DISPATCH() \ +#define MOTH_DISPATCH_SINGLE() \ goto *jumpTable[*reinterpret_cast<const uchar *>(code)]; + +#define MOTH_DISPATCH() \ + MOTH_DISPATCH_SINGLE() \ + op_byte_Nop: \ + ++code; \ + MOTH_DISPATCH_SINGLE() \ + op_int_Nop: /* wide prefix */ \ + ++code; \ + goto *jumpTable[0x100 | *reinterpret_cast<const uchar *>(code)]; #else #define MOTH_JUMP_TABLE #define MOTH_INSTR_CASE_AND_JUMP(instr) \ - INSTR_##instr(GET_CASE_AND_JUMP) -#define GET_CASE_AND_JUMP_INSTRUCTION(name, ...) \ - case static_cast<uchar>(Instr::Type::name): goto op_byte_##name; -#define MOTH_INSTR_CASE_AND_JUMP_WIDE(instr) \ + INSTR_##instr(GET_CASE_AND_JUMP) \ INSTR_##instr(GET_CASE_AND_JUMP_WIDE) +#define GET_CASE_AND_JUMP_INSTRUCTION(name, ...) \ + case Instr::Type::name: goto op_byte_##name; #define GET_CASE_AND_JUMP_WIDE_INSTRUCTION(name, ...) \ - case (static_cast<uchar>(Instr::Type::name##_Wide)): goto op_int_##name; + case Instr::Type::name##_Wide: goto op_int_##name; #define MOTH_DISPATCH() \ - switch (static_cast<uchar>(*code)) { \ + Instr::Type type = Instr::Type(static_cast<uchar>(*code)); \ + dispatch: \ + switch (type) { \ + case Instr::Type::Nop: \ + ++code; \ + type = Instr::Type(static_cast<uchar>(*code)); \ + goto dispatch; \ + case Instr::Type::Nop_Wide: /* wide prefix */ \ + ++code; \ + type = Instr::Type(0x100 | static_cast<uchar>(*code)); \ + goto dispatch; \ FOR_EACH_MOTH_INSTR(MOTH_INSTR_CASE_AND_JUMP) \ - FOR_EACH_MOTH_INSTR(MOTH_INSTR_CASE_AND_JUMP_WIDE) \ } #endif @@ -502,20 +524,29 @@ inline void dumpBytecode(const QByteArray &bytecode, int nLocals, int nFormals, union Instr { enum class Type { - FOR_EACH_MOTH_INSTR(MOTH_INSTR_ENUM) + FOR_EACH_MOTH_INSTR_ALL(MOTH_INSTR_ENUM) }; static Type wideInstructionType(Type t) { return Type(int(t) | 1); } static Type narrowInstructionType(Type t) { return Type(int(t) & ~1); } static bool isWide(Type t) { return int(t) & 1; } static bool isNarrow(Type t) { return !(int(t) & 1); } + static int encodedLength(Type t) { return int(t) >= 256 ? 2 : 1; } + + static Type unpack(const uchar *c) { if (c[0] == 0x1) return Type(0x100 + c[1]); return Type(c[0]); } + static uchar *pack(uchar *c, Type t) { + if (uint(t) >= 256) { + c[0] = 0x1; + c[1] = uint(t) &0xff; + return c + 2; + } + c[0] = uchar(uint(t)); + return c + 1; + } - static Type unpack(const uchar *c) { return Type(*c); } - static void pack(uchar *c, Type t) { *c = uchar(uint(t)); } - - FOR_EACH_MOTH_INSTR(MOTH_EMIT_STRUCTS) + FOR_EACH_MOTH_INSTR_ALL(MOTH_EMIT_STRUCTS) - FOR_EACH_MOTH_INSTR(MOTH_EMIT_INSTR_MEMBERS) + FOR_EACH_MOTH_INSTR_ALL(MOTH_EMIT_INSTR_MEMBERS) int argumentsAsInts[4]; }; @@ -526,8 +557,6 @@ struct InstrInfo static int size(Instr::Type type); }; -Q_STATIC_ASSERT(MOTH_NUM_INSTRUCTIONS() <= 256); - template<int N> struct InstrMeta { }; @@ -545,7 +574,7 @@ QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized") reinterpret_cast<const char *>(&v), \ Size); } \ }; -FOR_EACH_MOTH_INSTR(MOTH_INSTR_META_TEMPLATE); +FOR_EACH_MOTH_INSTR_ALL(MOTH_INSTR_META_TEMPLATE); #undef MOTH_INSTR_META_TEMPLATE QT_WARNING_POP @@ -556,7 +585,7 @@ class InstrData : public InstrMeta<InstrType>::DataType struct Instruction { #define MOTH_INSTR_DATA_TYPEDEF(I) typedef InstrData<int(Instr::Type::I)> I; -FOR_EACH_MOTH_INSTR(MOTH_INSTR_DATA_TYPEDEF) +FOR_EACH_MOTH_INSTR_ALL(MOTH_INSTR_DATA_TYPEDEF) #undef MOTH_INSTR_DATA_TYPEDEF private: Instruction(); diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 6c667110a9..53e5632eff 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -328,7 +328,7 @@ static struct InstrCount { #ifdef MOTH_COMPUTED_GOTO #define MOTH_END_INSTR(instr) \ - MOTH_DISPATCH() \ + MOTH_DISPATCH_SINGLE() \ } #else // !MOTH_COMPUTED_GOTO #define MOTH_END_INSTR(instr) \ |