aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jit
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@qt.io>2018-11-23 12:34:48 +0100
committerErik Verbruggen <erik.verbruggen@qt.io>2019-01-31 09:19:13 +0000
commit3f2efbd1b904cdc9358ed328235502e338b020bf (patch)
tree38fe2d4e1d00d30fb6ce51944eae3f5d8bd662da /src/qml/jit
parent965f49bb4f83c9eedd56f9ec01f166a4634a05d3 (diff)
V4: Generate labels for backward jumps
When analyzing the bytecode from top-to-bottom in a single pass, we don't know when a jump back to previously seen code occurs. For example, in the baseline JIT we would already have generated code for some bytecode when we see a jump back (like at the end of a loop body), and we can't go back and insert a label to jump to. As JavaScript has no goto's, the only backward jumps are at the end of loops, so there are very few cases where we need to actually generate labels. This was previously handled by analyzing the bytecode twice: once to collect all jump targets, and then second pass over the bytecode to do the actual JITting (which would use the jump targets to insert labels). We can now do that with one single pass. So the trade-off is to store 4 bytes more per function plus 4 bytes for each loop, instead of having to analyze all functions only to find where all jumps are each time that function is JITted. Change-Id: I3abfcb69f65851a397dbd4a9762ea5e9e57495f6 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/jit')
-rw-r--r--src/qml/jit/qv4assemblercommon_p.h3
-rw-r--r--src/qml/jit/qv4baselineassembler.cpp21
-rw-r--r--src/qml/jit/qv4baselineassembler_p.h14
-rw-r--r--src/qml/jit/qv4baselinejit.cpp20
-rw-r--r--src/qml/jit/qv4baselinejit_p.h5
5 files changed, 35 insertions, 28 deletions
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