mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge backout.
This commit is contained in:
commit
674cddc8c2
@ -1,23 +0,0 @@
|
||||
// |jit-test| error: TypeError
|
||||
// vim: set ts=4 sw=4 tw=99 et:
|
||||
g = undefined;
|
||||
function L() { }
|
||||
|
||||
function h() {
|
||||
with (h) { }
|
||||
for (var i = 0; i < 10; i++)
|
||||
g();
|
||||
}
|
||||
|
||||
function f(x) {
|
||||
g = x;
|
||||
}
|
||||
|
||||
f(L);
|
||||
h();
|
||||
f(L);
|
||||
f(2);
|
||||
h();
|
||||
|
||||
/* Don't assert/crash. */
|
||||
|
@ -500,33 +500,24 @@ mjit::Compiler::finishThisUp(JITScript **jitp)
|
||||
if (ic::MICInfo *scriptMICs = jit->mics) {
|
||||
for (size_t i = 0; i < mics.length(); i++) {
|
||||
scriptMICs[i].kind = mics[i].kind;
|
||||
scriptMICs[i].fastPathStart = fullCode.locationOf(mics[i].fastPathStart);
|
||||
scriptMICs[i].slowPathStart = stubCode.locationOf(mics[i].slowPathStart);
|
||||
if (mics[i].kind == ic::MICInfo::GET)
|
||||
scriptMICs[i].load = fullCode.locationOf(mics[i].load);
|
||||
else
|
||||
scriptMICs[i].load = fullCode.locationOf(mics[i].store).labelAtOffset(0);
|
||||
scriptMICs[i].shape = fullCode.locationOf(mics[i].shape);
|
||||
scriptMICs[i].stubCall = stubCode.locationOf(mics[i].call);
|
||||
scriptMICs[i].usePropertyCache = mics[i].usePropertyCache;
|
||||
scriptMICs[i].extraShapeGuard = 0;
|
||||
scriptMICs[i].objConst = mics[i].objConst;
|
||||
scriptMICs[i].shapeReg = mics[i].shapeReg;
|
||||
scriptMICs[i].objReg = mics[i].objReg;
|
||||
scriptMICs[i].vr = mics[i].vr;
|
||||
|
||||
if (mics[i].kind == ic::MICInfo::SET) {
|
||||
int offset = fullCode.locationOf(mics[i].shapeGuardJump) -
|
||||
scriptMICs[i].fastPathStart;
|
||||
scriptMICs[i].inlineShapeJump = offset;
|
||||
JS_ASSERT(scriptMICs[i].inlineShapeJump == offset);
|
||||
|
||||
offset = fullCode.locationOf(mics[i].fastPathRejoin) -
|
||||
scriptMICs[i].fastPathStart;
|
||||
scriptMICs[i].fastRejoinOffset = offset;
|
||||
JS_ASSERT(scriptMICs[i].fastRejoinOffset == offset);
|
||||
scriptMICs[i].entry = fullCode.locationOf(mics[i].entry);
|
||||
switch (mics[i].kind) {
|
||||
case ic::MICInfo::GET:
|
||||
case ic::MICInfo::SET:
|
||||
if (mics[i].kind == ic::MICInfo::GET)
|
||||
scriptMICs[i].load = fullCode.locationOf(mics[i].load);
|
||||
else
|
||||
scriptMICs[i].load = fullCode.locationOf(mics[i].store).labelAtOffset(0);
|
||||
scriptMICs[i].shape = fullCode.locationOf(mics[i].shape);
|
||||
scriptMICs[i].stubCall = stubCode.locationOf(mics[i].call);
|
||||
scriptMICs[i].stubEntry = stubCode.locationOf(mics[i].stubEntry);
|
||||
scriptMICs[i].u.name.typeConst = mics[i].u.name.typeConst;
|
||||
scriptMICs[i].u.name.dataConst = mics[i].u.name.dataConst;
|
||||
scriptMICs[i].u.name.usePropertyCache = mics[i].u.name.usePropertyCache;
|
||||
break;
|
||||
default:
|
||||
JS_NOT_REACHED("Bad MIC kind");
|
||||
}
|
||||
|
||||
stubCode.patch(mics[i].addrLabel, &scriptMICs[i]);
|
||||
}
|
||||
}
|
||||
@ -4317,7 +4308,7 @@ mjit::Compiler::jsop_getgname(uint32 index)
|
||||
RegisterID objReg;
|
||||
Jump shapeGuard;
|
||||
|
||||
mic.fastPathStart = masm.label();
|
||||
mic.entry = masm.label();
|
||||
if (fe->isConstant()) {
|
||||
JSObject *obj = &fe->getValue().toObject();
|
||||
frame.pop();
|
||||
@ -4339,10 +4330,11 @@ mjit::Compiler::jsop_getgname(uint32 index)
|
||||
Imm32(int32(JSObjectMap::INVALID_SHAPE)), mic.shape);
|
||||
frame.freeReg(reg);
|
||||
}
|
||||
mic.slowPathStart = stubcc.linkExit(shapeGuard, Uses(0));
|
||||
stubcc.linkExit(shapeGuard, Uses(0));
|
||||
|
||||
stubcc.leave();
|
||||
passMICAddress(mic);
|
||||
mic.stubEntry = stubcc.masm.label();
|
||||
mic.call = OOL_STUBCALL(ic::GetGlobalName);
|
||||
|
||||
/* Garbage value. */
|
||||
@ -4361,8 +4353,6 @@ mjit::Compiler::jsop_getgname(uint32 index)
|
||||
frame.pushRegs(treg, dreg);
|
||||
|
||||
stubcc.rejoin(Changes(1));
|
||||
|
||||
mic.fastPathRejoin = masm.label();
|
||||
mics.append(mic);
|
||||
|
||||
#else
|
||||
@ -4388,71 +4378,91 @@ mjit::Compiler::jsop_setgname(JSAtom *atom, bool usePropertyCache)
|
||||
{
|
||||
#if defined JS_MONOIC
|
||||
FrameEntry *objFe = frame.peek(-2);
|
||||
FrameEntry *fe = frame.peek(-1);
|
||||
JS_ASSERT_IF(objFe->isTypeKnown(), objFe->getKnownType() == JSVAL_TYPE_OBJECT);
|
||||
|
||||
MICGenInfo mic(ic::MICInfo::SET);
|
||||
frame.pinEntry(fe, mic.vr);
|
||||
|
||||
RESERVE_IC_SPACE(masm);
|
||||
RegisterID objReg;
|
||||
Jump shapeGuard;
|
||||
|
||||
mic.fastPathStart = masm.label();
|
||||
mic.entry = masm.label();
|
||||
if (objFe->isConstant()) {
|
||||
JSObject *obj = &objFe->getValue().toObject();
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
mic.objReg = frame.allocReg();
|
||||
mic.shapeReg = mic.objReg;
|
||||
mic.objConst = true;
|
||||
objReg = frame.allocReg();
|
||||
|
||||
masm.load32FromImm(&obj->objShape, mic.shapeReg);
|
||||
shapeGuard = masm.branch32WithPatch(Assembler::NotEqual, mic.shapeReg,
|
||||
masm.load32FromImm(&obj->objShape, objReg);
|
||||
shapeGuard = masm.branch32WithPatch(Assembler::NotEqual, objReg,
|
||||
Imm32(int32(JSObjectMap::INVALID_SHAPE)),
|
||||
mic.shape);
|
||||
masm.move(ImmPtr(obj), mic.objReg);
|
||||
masm.move(ImmPtr(obj), objReg);
|
||||
} else {
|
||||
mic.objReg = frame.copyDataIntoReg(objFe);
|
||||
mic.shapeReg = frame.allocReg();
|
||||
mic.objConst = false;
|
||||
objReg = frame.copyDataIntoReg(objFe);
|
||||
RegisterID reg = frame.allocReg();
|
||||
|
||||
masm.loadShape(mic.objReg, mic.shapeReg);
|
||||
shapeGuard = masm.branch32WithPatch(Assembler::NotEqual, mic.shapeReg,
|
||||
masm.loadShape(objReg, reg);
|
||||
shapeGuard = masm.branch32WithPatch(Assembler::NotEqual, reg,
|
||||
Imm32(int32(JSObjectMap::INVALID_SHAPE)),
|
||||
mic.shape);
|
||||
frame.freeReg(mic.shapeReg);
|
||||
frame.freeReg(reg);
|
||||
}
|
||||
mic.shapeGuardJump = shapeGuard;
|
||||
mic.slowPathStart = stubcc.linkExit(shapeGuard, Uses(2));
|
||||
stubcc.linkExit(shapeGuard, Uses(2));
|
||||
|
||||
stubcc.leave();
|
||||
passMICAddress(mic);
|
||||
mic.stubEntry = stubcc.masm.label();
|
||||
mic.call = OOL_STUBCALL(ic::SetGlobalName);
|
||||
|
||||
/* Garbage value. */
|
||||
uint32 slot = 1 << 24;
|
||||
|
||||
mic.usePropertyCache = usePropertyCache;
|
||||
/* Get both type and reg into registers. */
|
||||
FrameEntry *fe = frame.peek(-1);
|
||||
|
||||
masm.loadPtr(Address(mic.objReg, offsetof(JSObject, slots)), mic.objReg);
|
||||
Address address(mic.objReg, slot);
|
||||
Value v;
|
||||
RegisterID typeReg = Registers::ReturnReg;
|
||||
RegisterID dataReg = Registers::ReturnReg;
|
||||
JSValueType typeTag = JSVAL_TYPE_INT32;
|
||||
|
||||
if (mic.vr.isConstant()) {
|
||||
mic.store = masm.storeValueWithAddressOffsetPatch(mic.vr.value(), address);
|
||||
} else if (mic.vr.isTypeKnown()) {
|
||||
mic.store = masm.storeValueWithAddressOffsetPatch(ImmType(mic.vr.knownType()),
|
||||
mic.vr.dataReg(), address);
|
||||
mic.u.name.typeConst = fe->isTypeKnown();
|
||||
mic.u.name.dataConst = fe->isConstant();
|
||||
mic.u.name.usePropertyCache = usePropertyCache;
|
||||
|
||||
if (!mic.u.name.dataConst) {
|
||||
dataReg = frame.ownRegForData(fe);
|
||||
if (!mic.u.name.typeConst)
|
||||
typeReg = frame.ownRegForType(fe);
|
||||
else
|
||||
typeTag = fe->getKnownType();
|
||||
} else {
|
||||
mic.store = masm.storeValueWithAddressOffsetPatch(mic.vr.typeReg(), mic.vr.dataReg(), address);
|
||||
v = fe->getValue();
|
||||
}
|
||||
|
||||
frame.freeReg(mic.objReg);
|
||||
frame.unpinEntry(mic.vr);
|
||||
frame.shimmy(1);
|
||||
masm.loadPtr(Address(objReg, offsetof(JSObject, slots)), objReg);
|
||||
Address address(objReg, slot);
|
||||
|
||||
if (mic.u.name.dataConst) {
|
||||
mic.store = masm.storeValueWithAddressOffsetPatch(v, address);
|
||||
} else if (mic.u.name.typeConst) {
|
||||
mic.store = masm.storeValueWithAddressOffsetPatch(ImmType(typeTag), dataReg, address);
|
||||
} else {
|
||||
mic.store = masm.storeValueWithAddressOffsetPatch(typeReg, dataReg, address);
|
||||
}
|
||||
|
||||
frame.freeReg(objReg);
|
||||
frame.popn(2);
|
||||
if (mic.u.name.dataConst) {
|
||||
frame.push(v);
|
||||
} else {
|
||||
if (mic.u.name.typeConst)
|
||||
frame.pushTypedPayload(typeTag, dataReg);
|
||||
else
|
||||
frame.pushRegs(typeReg, dataReg);
|
||||
}
|
||||
|
||||
stubcc.rejoin(Changes(1));
|
||||
|
||||
mic.fastPathRejoin = masm.label();
|
||||
mics.append(mic);
|
||||
#else
|
||||
jsop_setgname_slow(atom, usePropertyCache);
|
||||
|
@ -70,21 +70,27 @@ class Compiler : public BaseCompiler
|
||||
struct MICGenInfo {
|
||||
MICGenInfo(ic::MICInfo::Kind kind) : kind(kind)
|
||||
{ }
|
||||
Label fastPathStart;
|
||||
Label slowPathStart;
|
||||
Label fastPathRejoin;
|
||||
Label load;
|
||||
Label entry;
|
||||
Label stubEntry;
|
||||
DataLabel32 shape;
|
||||
DataLabelPtr addrLabel;
|
||||
Label load;
|
||||
DataLabel32 store;
|
||||
Call call;
|
||||
ic::MICInfo::Kind kind;
|
||||
Jump shapeGuardJump;
|
||||
ValueRemat vr;
|
||||
RegisterID objReg;
|
||||
RegisterID shapeReg;
|
||||
bool objConst;
|
||||
bool usePropertyCache;
|
||||
jsbytecode *jumpTarget;
|
||||
Jump traceHint;
|
||||
MaybeJump slowTraceHint;
|
||||
union {
|
||||
struct {
|
||||
bool typeConst;
|
||||
bool dataConst;
|
||||
bool usePropertyCache;
|
||||
} name;
|
||||
struct {
|
||||
uint32 pcOffs;
|
||||
} tracer;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct EqualityGenInfo {
|
||||
|
@ -48,7 +48,6 @@
|
||||
#include "methodjit/CodeGenIncludes.h"
|
||||
#include "methodjit/Compiler.h"
|
||||
#include "methodjit/ICRepatcher.h"
|
||||
#include "methodjit/PolyIC.h"
|
||||
#include "InlineFrameAssembler.h"
|
||||
#include "jsobj.h"
|
||||
|
||||
@ -67,8 +66,6 @@ typedef JSC::MacroAssembler::Jump Jump;
|
||||
typedef JSC::MacroAssembler::Imm32 Imm32;
|
||||
typedef JSC::MacroAssembler::ImmPtr ImmPtr;
|
||||
typedef JSC::MacroAssembler::Call Call;
|
||||
typedef JSC::MacroAssembler::Label Label;
|
||||
typedef JSC::MacroAssembler::DataLabel32 DataLabel32;
|
||||
|
||||
#if defined JS_MONOIC
|
||||
|
||||
@ -101,6 +98,8 @@ ic::GetGlobalName(VMFrame &f, ic::MICInfo *ic)
|
||||
}
|
||||
uint32 slot = shape->slot;
|
||||
|
||||
ic->u.name.touched = true;
|
||||
|
||||
/* Patch shape guard. */
|
||||
Repatcher repatcher(f.jit());
|
||||
repatcher.repatch(ic->shape, obj->shape());
|
||||
@ -142,174 +141,51 @@ PatchSetFallback(VMFrame &f, ic::MICInfo *ic)
|
||||
JSScript *script = f.fp()->script();
|
||||
|
||||
Repatcher repatch(f.jit());
|
||||
VoidStubMIC stub = ic->usePropertyCache
|
||||
VoidStubMIC stub = ic->u.name.usePropertyCache
|
||||
? STRICT_VARIANT(DisabledSetGlobal)
|
||||
: STRICT_VARIANT(DisabledSetGlobalNoCache);
|
||||
JSC::FunctionPtr fptr(JS_FUNC_TO_DATA_PTR(void *, stub));
|
||||
repatch.relink(ic->stubCall, fptr);
|
||||
}
|
||||
|
||||
static LookupStatus
|
||||
UpdateSetGlobalNameStub(VMFrame &f, ic::MICInfo *ic, JSObject *obj, const Shape *shape)
|
||||
{
|
||||
Repatcher repatcher(ic->extraStub);
|
||||
|
||||
JSC::CodeLocationLabel label(JSC::MacroAssemblerCodePtr(ic->extraStub.start()));
|
||||
repatcher.repatch(label.dataLabel32AtOffset(ic->extraShapeGuard), obj->shape());
|
||||
|
||||
label = label.labelAtOffset(ic->extraStoreOffset);
|
||||
repatcher.patchAddressOffsetForValueStore(label, shape->slot * sizeof(Value),
|
||||
ic->vr.isTypeKnown());
|
||||
|
||||
return Lookup_Cacheable;
|
||||
}
|
||||
|
||||
static LookupStatus
|
||||
AttachSetGlobalNameStub(VMFrame &f, ic::MICInfo *ic, JSObject *obj, const Shape *shape)
|
||||
{
|
||||
Assembler masm;
|
||||
|
||||
Label start = masm.label();
|
||||
|
||||
DataLabel32 shapeLabel;
|
||||
Jump guard = masm.branch32WithPatch(Assembler::NotEqual, ic->shapeReg, Imm32(obj->shape()),
|
||||
shapeLabel);
|
||||
|
||||
/* A constant object needs rematerialization. */
|
||||
if (ic->objConst)
|
||||
masm.move(ImmPtr(obj), ic->objReg);
|
||||
|
||||
JS_ASSERT(obj->branded());
|
||||
|
||||
/*
|
||||
* Load obj->slots. If ic->objConst, then this clobbers objReg, because
|
||||
* ic->objReg == ic->shapeReg.
|
||||
*/
|
||||
masm.loadPtr(Address(ic->objReg, offsetof(JSObject, slots)), ic->shapeReg);
|
||||
|
||||
/* Test if overwriting a function-tagged slot. */
|
||||
Address slot(ic->shapeReg, sizeof(Value) * shape->slot);
|
||||
Jump isNotObject = masm.testObject(Assembler::NotEqual, slot);
|
||||
|
||||
/* Now, test if the object is a function object. */
|
||||
masm.loadPayload(slot, ic->shapeReg);
|
||||
Jump isFun = masm.testFunction(Assembler::Equal, ic->shapeReg);
|
||||
|
||||
/* Restore shapeReg to obj->slots, since we clobbered it. */
|
||||
if (ic->objConst) {
|
||||
masm.move(ImmPtr(obj), ic->objReg);
|
||||
masm.loadPtr(Address(ic->objReg, offsetof(JSObject, slots)), ic->shapeReg);
|
||||
}
|
||||
|
||||
/* If the object test fails, shapeReg is still obj->slots. */
|
||||
isNotObject.linkTo(masm.label(), &masm);
|
||||
DataLabel32 store = masm.storeValueWithAddressOffsetPatch(ic->vr, slot);
|
||||
|
||||
Jump done = masm.jump();
|
||||
|
||||
JITScript *jit = f.jit();
|
||||
LinkerHelper linker(masm);
|
||||
JSC::ExecutablePool *ep = linker.init(f.cx);
|
||||
if (!ep)
|
||||
return Lookup_Error;
|
||||
if (!jit->execPools.append(ep)) {
|
||||
ep->release();
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
return Lookup_Error;
|
||||
}
|
||||
|
||||
if (!linker.verifyRange(jit)) {
|
||||
ep->release();
|
||||
return Lookup_Uncacheable;
|
||||
}
|
||||
|
||||
linker.link(done, ic->fastPathStart.labelAtOffset(ic->fastRejoinOffset));
|
||||
linker.link(guard, ic->slowPathStart);
|
||||
linker.link(isFun, ic->slowPathStart);
|
||||
|
||||
JSC::CodeLocationLabel cs = linker.finalize();
|
||||
JaegerSpew(JSpew_PICs, "generated setgname stub at %p\n", cs.executableAddress());
|
||||
|
||||
Repatcher repatcher(f.jit());
|
||||
repatcher.relink(ic->fastPathStart.jumpAtOffset(ic->inlineShapeJump), cs);
|
||||
|
||||
int offset = linker.locationOf(shapeLabel) - linker.locationOf(start);
|
||||
ic->extraShapeGuard = offset;
|
||||
JS_ASSERT(ic->extraShapeGuard == offset);
|
||||
JS_ASSERT(offset);
|
||||
|
||||
ic->extraStub = JSC::JITCode(cs.executableAddress(), linker.size());
|
||||
offset = linker.locationOf(store) - linker.locationOf(start);
|
||||
ic->extraStoreOffset = offset;
|
||||
JS_ASSERT(ic->extraStoreOffset == offset);
|
||||
|
||||
return Lookup_Cacheable;
|
||||
}
|
||||
|
||||
static LookupStatus
|
||||
UpdateGlobalName(VMFrame &f, ic::MICInfo *ic, JSObject *obj, const Shape *shape)
|
||||
{
|
||||
/* Give globals a chance to appear. */
|
||||
if (!shape)
|
||||
return Lookup_Uncacheable;
|
||||
|
||||
if (shape->isMethod() ||
|
||||
!shape->hasDefaultSetter() ||
|
||||
!shape->writable() ||
|
||||
!shape->hasSlot())
|
||||
{
|
||||
/* Disable the IC for weird shape attributes. */
|
||||
PatchSetFallback(f, ic);
|
||||
return Lookup_Uncacheable;
|
||||
}
|
||||
|
||||
/* Branded sets must guard that they don't overwrite method-valued properties. */
|
||||
if (obj->branded()) {
|
||||
/*
|
||||
* If this slot has a function valued property, the tail of this opcode
|
||||
* could change the shape. Even if it doesn't, the IC is probably
|
||||
* pointless, because it will always hit the function-test path and
|
||||
* bail out. In these cases, don't bother building or updating the IC.
|
||||
*/
|
||||
const Value &v = obj->getSlot(shape->slot);
|
||||
if (v.isObject() && v.toObject().isFunction()) {
|
||||
/*
|
||||
* If we're going to rebrand, the object may unbrand, allowing this
|
||||
* IC to come back to life. In that case, we don't disable the IC.
|
||||
*/
|
||||
if (!ChangesMethodValue(v, f.regs.sp[-1]))
|
||||
PatchSetFallback(f, ic);
|
||||
return Lookup_Uncacheable;
|
||||
}
|
||||
|
||||
if (ic->extraShapeGuard)
|
||||
return UpdateSetGlobalNameStub(f, ic, obj, shape);
|
||||
|
||||
return AttachSetGlobalNameStub(f, ic, obj, shape);
|
||||
}
|
||||
|
||||
/* Object is not branded, so we can use the inline path. */
|
||||
Repatcher repatcher(f.jit());
|
||||
repatcher.repatch(ic->shape, obj->shape());
|
||||
repatcher.patchAddressOffsetForValueStore(ic->load, shape->slot * sizeof(Value),
|
||||
ic->vr.isTypeKnown());
|
||||
|
||||
return Lookup_Cacheable;
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
ic::SetGlobalName(VMFrame &f, ic::MICInfo *ic)
|
||||
{
|
||||
JSObject *obj = f.fp()->scopeChain().getGlobal();
|
||||
JSScript *script = f.fp()->script();
|
||||
JSAtom *atom = script->getAtom(GET_INDEX(f.regs.pc));
|
||||
const Shape *shape = obj->nativeLookup(ATOM_TO_JSID(atom));
|
||||
jsid id = ATOM_TO_JSID(atom);
|
||||
|
||||
LookupStatus status = UpdateGlobalName(f, ic, obj, shape);
|
||||
if (status == Lookup_Error)
|
||||
THROW();
|
||||
JS_ASSERT(ic->kind == ic::MICInfo::SET);
|
||||
|
||||
if (ic->usePropertyCache)
|
||||
const Shape *shape = obj->nativeLookup(id);
|
||||
if (!shape ||
|
||||
shape->isMethod() ||
|
||||
!shape->hasDefaultSetter() ||
|
||||
!shape->writable() ||
|
||||
!shape->hasSlot())
|
||||
{
|
||||
if (shape)
|
||||
PatchSetFallback(f, ic);
|
||||
if (ic->u.name.usePropertyCache)
|
||||
STRICT_VARIANT(stubs::SetGlobalName)(f, atom);
|
||||
else
|
||||
STRICT_VARIANT(stubs::SetGlobalNameNoCache)(f, atom);
|
||||
return;
|
||||
}
|
||||
uint32 slot = shape->slot;
|
||||
|
||||
ic->u.name.touched = true;
|
||||
|
||||
/* Patch shape guard. */
|
||||
Repatcher repatcher(f.jit());
|
||||
repatcher.repatch(ic->shape, obj->shape());
|
||||
|
||||
/* Patch loads. */
|
||||
repatcher.patchAddressOffsetForValueStore(ic->load, slot * sizeof(Value),
|
||||
ic->u.name.typeConst);
|
||||
|
||||
if (ic->u.name.usePropertyCache)
|
||||
STRICT_VARIANT(stubs::SetGlobalName)(f, atom);
|
||||
else
|
||||
STRICT_VARIANT(stubs::SetGlobalNameNoCache)(f, atom);
|
||||
@ -1281,16 +1157,6 @@ JITScript::sweepCallICs(JSContext *cx, bool purgeAll)
|
||||
released++;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < nMICs; i ++) {
|
||||
ic::MICInfo &ic = mics[i];
|
||||
if (!ic.extraShapeGuard)
|
||||
continue;
|
||||
JS_ASSERT(ic.kind == ic::MICInfo::SET);
|
||||
repatcher.relink(ic.fastPathStart.jumpAtOffset(ic.inlineShapeJump), ic.slowPathStart);
|
||||
ic.extraShapeGuard = 0;
|
||||
released++;
|
||||
}
|
||||
|
||||
JS_ASSERT(released == execPools.length());
|
||||
for (uint32 i = 0; i < released; i++)
|
||||
execPools[i]->release();
|
||||
|
@ -43,7 +43,6 @@
|
||||
|
||||
#include "assembler/assembler/MacroAssembler.h"
|
||||
#include "assembler/assembler/CodeLocation.h"
|
||||
#include "assembler/moco/MocoStubs.h"
|
||||
#include "methodjit/MethodJIT.h"
|
||||
#include "CodeGenIncludes.h"
|
||||
|
||||
@ -101,10 +100,9 @@ struct MICInfo {
|
||||
SET
|
||||
};
|
||||
|
||||
typedef JSC::MacroAssembler::RegisterID RegisterID;
|
||||
|
||||
JSC::CodeLocationLabel fastPathStart;
|
||||
JSC::CodeLocationLabel slowPathStart;
|
||||
/* Used by multiple MICs. */
|
||||
JSC::CodeLocationLabel entry;
|
||||
JSC::CodeLocationLabel stubEntry;
|
||||
|
||||
/*
|
||||
* - ARM and x64 always emit exactly one instruction which needs to be
|
||||
@ -119,21 +117,17 @@ struct MICInfo {
|
||||
JSC::CodeLocationDataLabel32 shape;
|
||||
JSC::CodeLocationCall stubCall;
|
||||
|
||||
/* SET only, if we had to generate an out-of-line path. */
|
||||
Kind kind : 2;
|
||||
bool usePropertyCache : 1;
|
||||
int inlineShapeJump : 10; /* Offset into inline path for shape jump. */
|
||||
int extraShapeGuard : 6; /* Offset into stub for shape guard. */
|
||||
bool objConst : 1; /* True if the object is constant. */
|
||||
RegisterID objReg : 5; /* Register for object, if objConst is false. */
|
||||
RegisterID shapeReg : 5; /* Register for shape; volatile. */
|
||||
JSC::JITCode extraStub; /* Out-of-line generated stub. */
|
||||
|
||||
int fastRejoinOffset : 16; /* Offset from fastPathStart to rejoin. */
|
||||
int extraStoreOffset : 16; /* Offset into store code. */
|
||||
|
||||
/* SET only. */
|
||||
ValueRemat vr; /* RHS value. */
|
||||
/* Used by all MICs. */
|
||||
Kind kind : 3;
|
||||
union {
|
||||
/* Used by GET/SET. */
|
||||
struct {
|
||||
bool touched : 1;
|
||||
bool typeConst : 1;
|
||||
bool dataConst : 1;
|
||||
bool usePropertyCache : 1;
|
||||
} name;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct TraceICInfo {
|
||||
|
Loading…
Reference in New Issue
Block a user