Enable chunked compilation on x64, bug 728372. r=dvander

This commit is contained in:
Brian Hackett 2012-02-18 08:52:04 -08:00
Родитель 26067b2024
Коммит 46a70d99b9
5 изменённых файлов: 66 добавлений и 20 удалений

Просмотреть файл

@ -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;