mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-26 12:20:56 +00:00
Enable chunked compilation on x64, bug 728372. r=dvander
This commit is contained in:
parent
26067b2024
commit
46a70d99b9
@ -100,6 +100,20 @@ class BaseCompiler : public MacroAssemblerTypedefs
|
||||
{ }
|
||||
};
|
||||
|
||||
#ifdef JS_CPU_X64
|
||||
inline bool
|
||||
VerifyRange(void *start1, size_t size1, void *start2, size_t size2)
|
||||
{
|
||||
uintptr_t end1 = uintptr_t(start1) + size1;
|
||||
uintptr_t end2 = uintptr_t(start2) + size2;
|
||||
|
||||
uintptr_t lowest = JS_MIN(uintptr_t(start1), uintptr_t(start2));
|
||||
uintptr_t highest = JS_MAX(end1, end2);
|
||||
|
||||
return (highest - lowest < INT_MAX);
|
||||
}
|
||||
#endif
|
||||
|
||||
// This class wraps JSC::LinkBuffer for Mozilla-specific memory handling.
|
||||
// Every return |false| guarantees an OOM that has been correctly propagated,
|
||||
// and should continue to propagate.
|
||||
@ -128,13 +142,7 @@ class LinkerHelper : public JSC::LinkBuffer
|
||||
verifiedRange = true;
|
||||
#endif
|
||||
#ifdef JS_CPU_X64
|
||||
uintptr_t lowest = JS_MIN(uintptr_t(m_code), uintptr_t(other.start()));
|
||||
|
||||
uintptr_t myEnd = uintptr_t(m_code) + m_size;
|
||||
uintptr_t otherEnd = uintptr_t(other.start()) + other.size();
|
||||
uintptr_t highest = JS_MAX(myEnd, otherEnd);
|
||||
|
||||
return (highest - lowest < INT_MAX);
|
||||
return VerifyRange(m_code, m_size, other.start(), other.size());
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
@ -666,19 +666,12 @@ MakeJITScript(JSContext *cx, JSScript *script, bool construct)
|
||||
Vector<ChunkDescriptor> chunks(cx);
|
||||
Vector<CrossChunkEdge> edges(cx);
|
||||
|
||||
/*
|
||||
* Chunk compilation is not supported on x64, since there is no guarantee
|
||||
* that cross chunk jumps will be patchable even to go to the default shim.
|
||||
*/
|
||||
#ifndef JS_CPU_X64
|
||||
if (script->length < CHUNK_LIMIT || !cx->typeInferenceEnabled()) {
|
||||
#endif
|
||||
ChunkDescriptor desc;
|
||||
desc.begin = 0;
|
||||
desc.end = script->length;
|
||||
if (!chunks.append(desc))
|
||||
return NULL;
|
||||
#ifndef JS_CPU_X64
|
||||
} else {
|
||||
if (!script->ensureRanInference(cx))
|
||||
return NULL;
|
||||
@ -871,7 +864,6 @@ MakeJITScript(JSContext *cx, JSScript *script, bool construct)
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif /* !JS_CPU_X64 */
|
||||
|
||||
size_t dataSize = sizeof(JITScript)
|
||||
+ (chunks.length() * sizeof(ChunkDescriptor))
|
||||
@ -1259,6 +1251,15 @@ mjit::Compiler::generateEpilogue()
|
||||
CompileStatus
|
||||
mjit::Compiler::finishThisUp()
|
||||
{
|
||||
#ifdef JS_CPU_X64
|
||||
/* Generate trampolines to ensure that cross chunk edges are patchable. */
|
||||
for (unsigned i = 0; i < chunkEdges.length(); i++) {
|
||||
chunkEdges[i].sourceTrampoline = stubcc.masm.label();
|
||||
stubcc.masm.move(ImmPtr(NULL), Registers::ScratchReg);
|
||||
stubcc.masm.jump(Registers::ScratchReg);
|
||||
}
|
||||
#endif
|
||||
|
||||
RETURN_IF_OOM(Compile_Error);
|
||||
|
||||
/*
|
||||
@ -1789,8 +1790,6 @@ mjit::Compiler::finishThisUp()
|
||||
|
||||
outerChunk.chunk = chunk;
|
||||
|
||||
Repatcher repatch(chunk);
|
||||
|
||||
/* Patch all incoming and outgoing cross-chunk jumps. */
|
||||
CrossChunkEdge *crossEdges = jit->edges();
|
||||
for (unsigned i = 0; i < jit->nedges; i++) {
|
||||
@ -1837,12 +1836,15 @@ mjit::Compiler::finishThisUp()
|
||||
* jump is never taken.
|
||||
*/
|
||||
edge.sourceJump1 = fullCode.locationOf(oedge.fastJump).executableAddress();
|
||||
repatch.relink(CodeLocationJump(edge.sourceJump1), targetLabel);
|
||||
if (oedge.slowJump.isSet()) {
|
||||
edge.sourceJump2 =
|
||||
stubCode.locationOf(oedge.slowJump.get()).executableAddress();
|
||||
repatch.relink(CodeLocationJump(edge.sourceJump2), targetLabel);
|
||||
}
|
||||
#ifdef JS_CPU_X64
|
||||
edge.sourceTrampoline =
|
||||
stubCode.locationOf(oedge.sourceTrampoline).executableAddress();
|
||||
#endif
|
||||
jit->patchEdge(edge, label);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -380,6 +380,10 @@ class Compiler : public BaseCompiler
|
||||
uint32_t source;
|
||||
uint32_t target;
|
||||
|
||||
#ifdef JS_CPU_X64
|
||||
Label sourceTrampoline;
|
||||
#endif
|
||||
|
||||
Jump fastJump;
|
||||
MaybeJump slowJump;
|
||||
};
|
||||
|
@ -1230,13 +1230,34 @@ JITScript::patchEdge(const CrossChunkEdge &edge, void *label)
|
||||
{
|
||||
if (edge.sourceJump1 || edge.sourceJump2) {
|
||||
JITChunk *sourceChunk = chunk(script->code + edge.source);
|
||||
JSC::CodeLocationLabel targetLabel(label);
|
||||
ic::Repatcher repatch(sourceChunk);
|
||||
|
||||
#ifdef JS_CPU_X64
|
||||
JS_ASSERT(edge.sourceTrampoline);
|
||||
|
||||
static const uint32_t JUMP_LENGTH = 10;
|
||||
|
||||
if (edge.sourceJump1) {
|
||||
JSC::CodeLocationLabel targetLabel(VerifyRange(edge.sourceJump1, JUMP_LENGTH, label, 0)
|
||||
? label
|
||||
: edge.sourceTrampoline);
|
||||
repatch.relink(JSC::CodeLocationJump(edge.sourceJump1), targetLabel);
|
||||
}
|
||||
if (edge.sourceJump2) {
|
||||
JSC::CodeLocationLabel targetLabel(VerifyRange(edge.sourceJump2, JUMP_LENGTH, label, 0)
|
||||
? label
|
||||
: edge.sourceTrampoline);
|
||||
repatch.relink(JSC::CodeLocationJump(edge.sourceJump2), targetLabel);
|
||||
}
|
||||
JSC::CodeLocationDataLabelPtr sourcePatch((char*)edge.sourceTrampoline + JUMP_LENGTH);
|
||||
repatch.repatch(sourcePatch, label);
|
||||
#else
|
||||
JSC::CodeLocationLabel targetLabel(label);
|
||||
if (edge.sourceJump1)
|
||||
repatch.relink(JSC::CodeLocationJump(edge.sourceJump1), targetLabel);
|
||||
if (edge.sourceJump2)
|
||||
repatch.relink(JSC::CodeLocationJump(edge.sourceJump2), targetLabel);
|
||||
#endif
|
||||
}
|
||||
if (edge.jumpTableEntries) {
|
||||
for (unsigned i = 0; i < edge.jumpTableEntries->length(); i++)
|
||||
@ -1317,6 +1338,9 @@ JITScript::destroyChunk(JSContext *cx, unsigned chunkIndex, bool resetUses)
|
||||
CrossChunkEdge &edge = edges[i];
|
||||
if (edge.source >= desc.begin && edge.source < desc.end) {
|
||||
edge.sourceJump1 = edge.sourceJump2 = NULL;
|
||||
#ifdef JS_CPU_X64
|
||||
edge.sourceTrampoline = NULL;
|
||||
#endif
|
||||
if (edge.jumpTableEntries) {
|
||||
cx->delete_(edge.jumpTableEntries);
|
||||
edge.jumpTableEntries = NULL;
|
||||
|
@ -761,6 +761,14 @@ struct CrossChunkEdge
|
||||
void *sourceJump1;
|
||||
void *sourceJump2;
|
||||
|
||||
#ifdef JS_CPU_X64
|
||||
/*
|
||||
* Location of a trampoline for the edge to perform an indirect jump if
|
||||
* out of range, NULL if the source is not compiled.
|
||||
*/
|
||||
void *sourceTrampoline;
|
||||
#endif
|
||||
|
||||
/* Any jump table entries along this edge. */
|
||||
typedef Vector<void**,4,SystemAllocPolicy> JumpTableEntryVector;
|
||||
JumpTableEntryVector *jumpTableEntries;
|
||||
|
Loading…
x
Reference in New Issue
Block a user