[JAEGER] Added monomorphic inline cache for reads of unbound globals.

This commit is contained in:
David Anderson
2010-06-12 19:00:30 -07:00
parent 4aedd979ee
commit ca2cc38c06
14 changed files with 364 additions and 21 deletions

View File

@@ -44,7 +44,9 @@
#include "jslibmath.h"
#include "Compiler.h"
#include "StubCalls.h"
#include "MonoIC.h"
#include "assembler/jit/ExecutableAllocator.h"
#include "assembler/assembler/LinkBuffer.h"
#include "FrameState-inl.h"
#include "jsscriptinlines.h"
@@ -70,7 +72,7 @@ NotCheckedSSE2;
mjit::Compiler::Compiler(JSContext *cx, JSScript *script, JSFunction *fun, JSObject *scopeChain)
: cx(cx), script(script), scopeChain(scopeChain), globalObj(scopeChain->getGlobal()), fun(fun),
analysis(cx, script), jumpMap(NULL), frame(cx, script, masm),
branchPatches(ContextAllocPolicy(cx)), stubcc(cx, *this, frame, script)
branchPatches(ContextAllocPolicy(cx)), mics(ContextAllocPolicy(cx)), stubcc(cx, *this, frame, script)
{
}
@@ -227,6 +229,24 @@ mjit::Compiler::finishThisUp()
}
}
if (mics.length()) {
script->mics = (ic::MICInfo *)cx->calloc(sizeof(ic::MICInfo) * mics.length());
if (!script->mics) {
execPool->release();
return Compile_Error;
}
}
JSC::LinkBuffer fullCode(result, masm.size() + stubcc.size());
JSC::LinkBuffer stubCode(result + masm.size(), stubcc.size());
for (size_t i = 0; i < mics.length(); i++) {
script->mics[i].entry = fullCode.locationOf(mics[i].entry);
script->mics[i].load = fullCode.locationOf(mics[i].load);
script->mics[i].shape = fullCode.locationOf(mics[i].shapeVal);
script->mics[i].stubCall = stubCode.locationOf(mics[i].call);
script->mics[i].stubEntry = stubCode.locationOf(mics[i].stubEntry);
}
/* Link fast and slow paths together. */
stubcc.fixCrossJumps(result, masm.size(), masm.size() + stubcc.size());
@@ -838,12 +858,7 @@ mjit::Compiler::generateMethod()
END_CASE(JSOP_GETARG)
BEGIN_CASE(JSOP_BINDGNAME)
{
if (script->compileAndGo && globalObj)
frame.push(NonFunObjTag(*globalObj));
else
jsop_bindname(fullAtomIndex(PC));
}
jsop_bindgname();
END_CASE(JSOP_BINDGNAME)
BEGIN_CASE(JSOP_SETARG)
@@ -1078,9 +1093,7 @@ mjit::Compiler::generateMethod()
BEGIN_CASE(JSOP_GETGNAME)
BEGIN_CASE(JSOP_CALLGNAME)
prepareStubCall();
stubCall(stubs::GetGlobalName, Uses(0), Defs(1));
frame.pushSynced();
jsop_getgname(fullAtomIndex(PC));
if (op == JSOP_CALLGNAME)
frame.push(NullTag());
END_CASE(JSOP_GETGNAME)
@@ -1774,3 +1787,92 @@ mjit::Compiler::jsop_eleminc(JSOp op, VoidStub stub)
frame.pushSynced();
}
void
mjit::Compiler::jsop_getgname_slow(uint32 index)
{
prepareStubCall();
stubCall(stubs::GetGlobalName, Uses(0), Defs(1));
frame.pushSynced();
}
void
mjit::Compiler::jsop_bindgname()
{
if (script->compileAndGo && globalObj) {
frame.push(NonFunObjTag(*globalObj));
return;
}
/* :TODO: this is slower than it needs to be. */
prepareStubCall();
stubCall(stubs::BindGlobalName, Uses(0), Defs(1));
frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_MASK32_NONFUNOBJ, Registers::ReturnReg);
}
void
mjit::Compiler::jsop_getgname(uint32 index)
{
#if ENABLE_MIC
jsop_bindgname();
FrameEntry *fe = frame.peek(-1);
JS_ASSERT(fe->isTypeKnown() && fe->getTypeTag() == JSVAL_MASK32_NONFUNOBJ);
MICGenInfo mic;
RegisterID objReg;
Jump shapeGuard;
mic.entry = masm.label();
if (fe->isConstant()) {
JSObject *obj = &fe->getValue().asObject();
frame.pop();
JS_ASSERT(obj->isNative());
JSObjectMap *map = obj->map;
objReg = frame.allocReg();
masm.load32FromImm(&map->shape, objReg);
shapeGuard = masm.branchPtrWithPatch(Assembler::NotEqual, objReg, mic.shapeVal);
masm.move(ImmPtr(obj), objReg);
} else {
objReg = frame.ownRegForData(fe);
frame.pop();
RegisterID reg = frame.allocReg();
masm.loadPtr(Address(objReg, offsetof(JSObject, map)), reg);
masm.load32(Address(reg, offsetof(JSObjectMap, shape)), reg);
shapeGuard = masm.branchPtrWithPatch(Assembler::NotEqual, reg, mic.shapeVal);
frame.freeReg(reg);
}
stubcc.linkExit(shapeGuard);
stubcc.leave();
stubcc.masm.move(Imm32(mics.length()), Registers::ArgReg1);
mic.stubEntry = stubcc.masm.label();
mic.call = stubcc.call(ic::GetGlobalName);
/* Garbage value. */
uint32 slot = 1 << 24;
/*
* Ensure at least one register is available.
* This is necessary so the implicit push below does not change the
* expected instruction ordering. :FIXME: this is stupid
*/
frame.freeReg(frame.allocReg());
mic.load = masm.label();
masm.loadPtr(Address(objReg, offsetof(JSObject, dslots)), objReg);
Address address(objReg, slot);
frame.freeReg(objReg);
frame.push(address);
stubcc.rejoin(1);
mics.append(mic);
#else
jsop_getgname_slow(index);
#endif
}