Bug 831507 - Add generational-gc post-write barriers to baseline compiler. r=jandem

This commit is contained in:
Kannan Vijayan 2013-05-29 16:02:02 -04:00
parent bdc5222535
commit 4ba3a2af98
6 changed files with 265 additions and 37 deletions

View File

@ -27,6 +27,8 @@ class MinorCollectionTracer;
namespace ion { namespace ion {
class CodeGenerator; class CodeGenerator;
class MacroAssembler; class MacroAssembler;
class ICStubCompiler;
class BaselineCompiler;
} }
class Nursery class Nursery
@ -189,6 +191,8 @@ class Nursery
friend class gc::MinorCollectionTracer; friend class gc::MinorCollectionTracer;
friend class ion::CodeGenerator; friend class ion::CodeGenerator;
friend class ion::MacroAssembler; friend class ion::MacroAssembler;
friend class ion::ICStubCompiler;
friend class ion::BaselineCompiler;
}; };
} /* namespace js */ } /* namespace js */

View File

@ -23,6 +23,9 @@ using namespace js::ion;
BaselineCompiler::BaselineCompiler(JSContext *cx, HandleScript script) BaselineCompiler::BaselineCompiler(JSContext *cx, HandleScript script)
: BaselineCompilerSpecific(cx, script), : BaselineCompilerSpecific(cx, script),
return_(new HeapLabel()) return_(new HeapLabel())
#ifdef JSGC_GENERATIONAL
, postBarrierSlot_(new HeapLabel())
#endif
{ {
} }
@ -90,6 +93,11 @@ BaselineCompiler::compile()
if (!emitEpilogue()) if (!emitEpilogue())
return Method_Error; return Method_Error;
#ifdef JSGC_GENERATIONAL
if (!emitOutOfLinePostBarrierSlot())
return Method_Error;
#endif
if (masm.oom()) if (masm.oom())
return Method_Error; return Method_Error;
@ -264,6 +272,40 @@ BaselineCompiler::emitEpilogue()
return true; return true;
} }
#ifdef JSGC_GENERATIONAL
// On input:
// R2.scratchReg() contains object being written to.
// R1.scratchReg() contains slot index being written to.
// Otherwise, baseline stack will be synced, so all other registers are usable as scratch.
// This calls:
// void PostWriteBarrier(JSRuntime *rt, JSObject *obj);
bool
BaselineCompiler::emitOutOfLinePostBarrierSlot()
{
masm.bind(postBarrierSlot_);
Register objReg = R2.scratchReg();
GeneralRegisterSet regs(GeneralRegisterSet::All());
regs.take(objReg);
regs.take(BaselineFrameReg);
Register scratch = regs.takeAny();
#if defined(JS_CPU_ARM)
// On ARM, save the link register before calling. It contains the return
// address. The |masm.ret()| later will pop this into |pc| to return.
masm.push(lr);
#endif
masm.setupUnalignedABICall(2, scratch);
masm.movePtr(ImmWord(cx->runtime), scratch);
masm.passABIArg(scratch);
masm.passABIArg(objReg);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, PostWriteBarrier));
masm.ret();
return true;
}
#endif // JSGC_GENERATIONAL
bool bool
BaselineCompiler::emitIC(ICStub *stub, bool isForOp) BaselineCompiler::emitIC(ICStub *stub, bool isForOp)
{ {
@ -1676,23 +1718,36 @@ BaselineCompiler::emit_JSOP_DELPROP()
return true; return true;
} }
Address void
BaselineCompiler::getScopeCoordinateAddress(Register reg) BaselineCompiler::getScopeCoordinateObject(Register reg)
{ {
ScopeCoordinate sc(pc); ScopeCoordinate sc(pc);
masm.loadPtr(frame.addressOfScopeChain(), reg); masm.loadPtr(frame.addressOfScopeChain(), reg);
for (unsigned i = sc.hops; i; i--) for (unsigned i = sc.hops; i; i--)
masm.extractObject(Address(reg, ScopeObject::offsetOfEnclosingScope()), reg); masm.extractObject(Address(reg, ScopeObject::offsetOfEnclosingScope()), reg);
}
Address
BaselineCompiler::getScopeCoordinateAddressFromObject(Register objReg, Register reg)
{
ScopeCoordinate sc(pc);
Shape *shape = ScopeCoordinateToStaticScopeShape(cx, script, pc); Shape *shape = ScopeCoordinateToStaticScopeShape(cx, script, pc);
Address addr; Address addr;
if (shape->numFixedSlots() <= sc.slot) { if (shape->numFixedSlots() <= sc.slot) {
masm.loadPtr(Address(reg, JSObject::offsetOfSlots()), reg); masm.loadPtr(Address(objReg, JSObject::offsetOfSlots()), reg);
return Address(reg, (sc.slot - shape->numFixedSlots()) * sizeof(Value)); return Address(reg, (sc.slot - shape->numFixedSlots()) * sizeof(Value));
} }
return Address(reg, JSObject::getFixedSlotOffset(sc.slot)); return Address(objReg, JSObject::getFixedSlotOffset(sc.slot));
}
Address
BaselineCompiler::getScopeCoordinateAddress(Register reg)
{
getScopeCoordinateObject(reg);
return getScopeCoordinateAddressFromObject(reg, reg);
} }
bool bool
@ -1720,13 +1775,34 @@ BaselineCompiler::emit_JSOP_CALLALIASEDVAR()
bool bool
BaselineCompiler::emit_JSOP_SETALIASEDVAR() BaselineCompiler::emit_JSOP_SETALIASEDVAR()
{ {
// Sync everything except the top value, so that we can use R0 as scratch // Keep rvalue in R0.
// (storeValue does not touch it if the top value is in R0). frame.popRegsAndSync(1);
frame.syncStack(1); Register objReg = R2.scratchReg();
Address address = getScopeCoordinateAddress(R2.scratchReg()); getScopeCoordinateObject(objReg);
Address address = getScopeCoordinateAddressFromObject(objReg, R1.scratchReg());
masm.patchableCallPreBarrier(address, MIRType_Value); masm.patchableCallPreBarrier(address, MIRType_Value);
storeValue(frame.peek(-1), address, R0); masm.storeValue(R0, address);
frame.push(R0);
#ifdef JSGC_GENERATIONAL
// Fully sync the stack if post-barrier is needed.
// Scope coordinate object is already in R2.scratchReg().
frame.syncStack(0);
Nursery &nursery = cx->runtime->gcNursery;
Label skipBarrier;
Label isTenured;
masm.branchTestObject(Assembler::NotEqual, R0, &skipBarrier);
masm.branchPtr(Assembler::Below, objReg, ImmWord(nursery.start()), &isTenured);
masm.branchPtr(Assembler::Below, objReg, ImmWord(nursery.end()), &skipBarrier);
masm.bind(&isTenured);
masm.call(postBarrierSlot_);
masm.bind(&skipBarrier);
#endif
return true; return true;
} }

View File

@ -171,6 +171,9 @@ class BaselineCompiler : public BaselineCompilerSpecific
{ {
FixedList<Label> labels_; FixedList<Label> labels_;
HeapLabel * return_; HeapLabel * return_;
#ifdef JSGC_GENERATIONAL
HeapLabel * postBarrierSlot_;
#endif
// Native code offset right before the scope chain is initialized. // Native code offset right before the scope chain is initialized.
CodeOffsetLabel prologueOffset_; CodeOffsetLabel prologueOffset_;
@ -190,6 +193,9 @@ class BaselineCompiler : public BaselineCompilerSpecific
bool emitPrologue(); bool emitPrologue();
bool emitEpilogue(); bool emitEpilogue();
#ifdef JSGC_GENERATIONAL
bool emitOutOfLinePostBarrierSlot();
#endif
bool emitIC(ICStub *stub, bool isForOp); bool emitIC(ICStub *stub, bool isForOp);
bool emitOpIC(ICStub *stub) { bool emitOpIC(ICStub *stub) {
return emitIC(stub, true); return emitIC(stub, true);
@ -238,6 +244,8 @@ class BaselineCompiler : public BaselineCompilerSpecific
bool addPCMappingEntry(bool addIndexEntry); bool addPCMappingEntry(bool addIndexEntry);
void getScopeCoordinateObject(Register reg);
Address getScopeCoordinateAddressFromObject(Register objReg, Register reg);
Address getScopeCoordinateAddress(Register reg); Address getScopeCoordinateAddress(Register reg);
}; };

View File

@ -11,8 +11,10 @@
# include "x86/BaselineHelpers-x86.h" # include "x86/BaselineHelpers-x86.h"
#elif defined(JS_CPU_X64) #elif defined(JS_CPU_X64)
# include "x64/BaselineHelpers-x64.h" # include "x64/BaselineHelpers-x64.h"
#else #elif defined(JS_CPU_ARM)
# include "arm/BaselineHelpers-arm.h" # include "arm/BaselineHelpers-arm.h"
#else
# error "Unknown architecture!"
#endif #endif
namespace js { namespace js {

View File

@ -638,6 +638,36 @@ ICStubCompiler::guardProfilingEnabled(MacroAssembler &masm, Register scratch, La
masm.branch32(Assembler::Equal, AbsoluteAddress(enabledAddr), Imm32(0), skip); masm.branch32(Assembler::Equal, AbsoluteAddress(enabledAddr), Imm32(0), skip);
} }
#ifdef JSGC_GENERATIONAL
inline bool
ICStubCompiler::emitPostWriteBarrierSlot(MacroAssembler &masm, Register obj, Register scratch,
GeneralRegisterSet saveRegs)
{
Nursery &nursery = cx->runtime->gcNursery;
Label skipBarrier;
Label isTenured;
masm.branchPtr(Assembler::Below, obj, ImmWord(nursery.start()), &isTenured);
masm.branchPtr(Assembler::Below, obj, ImmWord(nursery.end()), &skipBarrier);
masm.bind(&isTenured);
// void PostWriteBarrier(JSRuntime *rt, JSObject *obj);
#ifdef JS_CPU_ARM
saveRegs.add(BaselineTailCallReg);
#endif
masm.PushRegsInMask(saveRegs);
masm.setupUnalignedABICall(2, scratch);
masm.movePtr(ImmWord(cx->runtime), scratch);
masm.passABIArg(scratch);
masm.passABIArg(obj);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, PostWriteBarrier));
masm.PopRegsInMask(saveRegs);
masm.bind(&skipBarrier);
return true;
}
#endif // JSGC_GENERATIONAL
// //
// UseCount_Fallback // UseCount_Fallback
// //
@ -4324,12 +4354,13 @@ ICSetElem_Dense::Compiler::generateStubCode(MacroAssembler &masm)
regs = availableGeneralRegs(2); regs = availableGeneralRegs(2);
scratchReg = regs.takeAny(); scratchReg = regs.takeAny();
// Unbox object and key.
obj = masm.extractObject(R0, ExtractTemp0);
Register key = masm.extractInt32(R1, ExtractTemp1);
// Load obj->elements in scratchReg. // Load obj->elements in scratchReg.
masm.loadPtr(Address(obj, JSObject::offsetOfElements()), scratchReg); masm.loadPtr(Address(obj, JSObject::offsetOfElements()), scratchReg);
// Unbox key.
Register key = masm.extractInt32(R1, ExtractTemp1);
// Bounds check. // Bounds check.
Address initLength(scratchReg, ObjectElements::offsetOfInitializedLength()); Address initLength(scratchReg, ObjectElements::offsetOfInitializedLength());
masm.branch32(Assembler::BelowOrEqual, initLength, key, &failure); masm.branch32(Assembler::BelowOrEqual, initLength, key, &failure);
@ -4338,6 +4369,12 @@ ICSetElem_Dense::Compiler::generateStubCode(MacroAssembler &masm)
BaseIndex element(scratchReg, key, TimesEight); BaseIndex element(scratchReg, key, TimesEight);
masm.branchTestMagic(Assembler::Equal, element, &failure); masm.branchTestMagic(Assembler::Equal, element, &failure);
// Failure is not possible now. Free up registers.
regs.add(R0);
regs.add(R1);
regs.takeUnchecked(obj);
regs.takeUnchecked(key);
// Convert int32 values to double if convertDoubleElements is set. In this // Convert int32 values to double if convertDoubleElements is set. In this
// case the heap typeset is guaranteed to contain both int32 and double, so // case the heap typeset is guaranteed to contain both int32 and double, so
// it's okay to store a double. // it's okay to store a double.
@ -4347,12 +4384,28 @@ ICSetElem_Dense::Compiler::generateStubCode(MacroAssembler &masm)
Imm32(ObjectElements::CONVERT_DOUBLE_ELEMENTS), Imm32(ObjectElements::CONVERT_DOUBLE_ELEMENTS),
&convertDoubles); &convertDoubles);
masm.bind(&convertDoublesDone); masm.bind(&convertDoublesDone);
// No longer need key.
// It's safe to overwrite R0 now. // Don't overwrite R0 becuase |obj| might overlap with it, and it's needed
// for post-write barrier later.
Address valueAddr(BaselineStackReg, ICStackValueOffset); Address valueAddr(BaselineStackReg, ICStackValueOffset);
masm.loadValue(valueAddr, R0); ValueOperand tmpVal = regs.takeAnyValue();
masm.loadValue(valueAddr, tmpVal);
EmitPreBarrier(masm, element, MIRType_Value); EmitPreBarrier(masm, element, MIRType_Value);
masm.storeValue(R0, element); masm.storeValue(tmpVal, element);
#ifdef JSGC_GENERATIONAL
Label skipBarrier;
masm.branchTestObject(Assembler::NotEqual, tmpVal, &skipBarrier);
regs.add(key);
regs.add(tmpVal);
{
Register r = regs.takeAny();
GeneralRegisterSet saveRegs;
emitPostWriteBarrierSlot(masm, obj, r, saveRegs);
regs.add(r);
}
masm.bind(&skipBarrier);
#endif
EmitReturnFromIC(masm); EmitReturnFromIC(masm);
// Convert to double and jump back. Note that double arrays are only // Convert to double and jump back. Note that double arrays are only
@ -4360,7 +4413,7 @@ ICSetElem_Dense::Compiler::generateStubCode(MacroAssembler &masm)
// Ion is disabled and there should be no double arrays. // Ion is disabled and there should be no double arrays.
masm.bind(&convertDoubles); masm.bind(&convertDoubles);
if (cx->runtime->jitSupportsFloatingPoint) if (cx->runtime->jitSupportsFloatingPoint)
masm.convertInt32ValueToDouble(valueAddr, R0.scratchReg(), &convertDoublesDone); masm.convertInt32ValueToDouble(valueAddr, regs.getAny(), &convertDoublesDone);
else else
masm.breakpoint(); masm.breakpoint();
masm.jump(&convertDoublesDone); masm.jump(&convertDoublesDone);
@ -4481,12 +4534,13 @@ ICSetElemDenseAddCompiler::generateStubCode(MacroAssembler &masm)
regs = availableGeneralRegs(2); regs = availableGeneralRegs(2);
scratchReg = regs.takeAny(); scratchReg = regs.takeAny();
// Unbox obj and key.
obj = masm.extractObject(R0, ExtractTemp0);
Register key = masm.extractInt32(R1, ExtractTemp1);
// Load obj->elements in scratchReg. // Load obj->elements in scratchReg.
masm.loadPtr(Address(obj, JSObject::offsetOfElements()), scratchReg); masm.loadPtr(Address(obj, JSObject::offsetOfElements()), scratchReg);
// Unbox key.
Register key = masm.extractInt32(R1, ExtractTemp1);
// Bounds check (key == initLength) // Bounds check (key == initLength)
Address initLength(scratchReg, ObjectElements::offsetOfInitializedLength()); Address initLength(scratchReg, ObjectElements::offsetOfInitializedLength());
masm.branch32(Assembler::NotEqual, initLength, key, &failure); masm.branch32(Assembler::NotEqual, initLength, key, &failure);
@ -4495,6 +4549,12 @@ ICSetElemDenseAddCompiler::generateStubCode(MacroAssembler &masm)
Address capacity(scratchReg, ObjectElements::offsetOfCapacity()); Address capacity(scratchReg, ObjectElements::offsetOfCapacity());
masm.branch32(Assembler::BelowOrEqual, capacity, key, &failure); masm.branch32(Assembler::BelowOrEqual, capacity, key, &failure);
// Failure is not possible now. Free up registers.
regs.add(R0);
regs.add(R1);
regs.takeUnchecked(obj);
regs.takeUnchecked(key);
// Increment initLength before write. // Increment initLength before write.
masm.add32(Imm32(1), initLength); masm.add32(Imm32(1), initLength);
@ -4515,12 +4575,26 @@ ICSetElemDenseAddCompiler::generateStubCode(MacroAssembler &masm)
&convertDoubles); &convertDoubles);
masm.bind(&convertDoublesDone); masm.bind(&convertDoublesDone);
// Write the value. No need for write barrier since we're not overwriting an old value.
// It's safe to overwrite R0 now.
BaseIndex element(scratchReg, key, TimesEight);
Address valueAddr(BaselineStackReg, ICStackValueOffset); Address valueAddr(BaselineStackReg, ICStackValueOffset);
masm.loadValue(valueAddr, R0);
masm.storeValue(R0, element); // Write the value. No need for pre-barrier since we're not overwriting an old value.
ValueOperand tmpVal = regs.takeAnyValue();
BaseIndex element(scratchReg, key, TimesEight);
masm.loadValue(valueAddr, tmpVal);
masm.storeValue(tmpVal, element);
#ifdef JSGC_GENERATIONAL
Label skipBarrier;
masm.branchTestObject(Assembler::NotEqual, tmpVal, &skipBarrier);
regs.add(key);
regs.add(tmpVal);
{
Register r = regs.takeAny();
GeneralRegisterSet saveRegs;
emitPostWriteBarrierSlot(masm, obj, r, saveRegs);
regs.add(r);
}
masm.bind(&skipBarrier);
#endif
EmitReturnFromIC(masm); EmitReturnFromIC(masm);
// Convert to double and jump back. Note that double arrays are only // Convert to double and jump back. Note that double arrays are only
@ -4528,7 +4602,7 @@ ICSetElemDenseAddCompiler::generateStubCode(MacroAssembler &masm)
// Ion is disabled and there should be no double arrays. // Ion is disabled and there should be no double arrays.
masm.bind(&convertDoubles); masm.bind(&convertDoubles);
if (cx->runtime->jitSupportsFloatingPoint) if (cx->runtime->jitSupportsFloatingPoint)
masm.convertInt32ValueToDouble(valueAddr, R0.scratchReg(), &convertDoublesDone); masm.convertInt32ValueToDouble(valueAddr, regs.getAny(), &convertDoublesDone);
else else
masm.breakpoint(); masm.breakpoint();
masm.jump(&convertDoublesDone); masm.jump(&convertDoublesDone);
@ -6299,13 +6373,35 @@ ICSetProp_Native::Compiler::generateStubCode(MacroAssembler &masm)
// Unstow R0 and R1 (object and key) // Unstow R0 and R1 (object and key)
EmitUnstowICValues(masm, 2); EmitUnstowICValues(masm, 2);
if (!isFixedSlot_) regs.add(R0);
masm.loadPtr(Address(objReg, JSObject::offsetOfSlots()), objReg); regs.takeUnchecked(objReg);
Register holderReg;
if (isFixedSlot_) {
holderReg = objReg;
} else {
holderReg = regs.takeAny();
masm.loadPtr(Address(objReg, JSObject::offsetOfSlots()), holderReg);
}
// Perform the store. // Perform the store.
masm.load32(Address(BaselineStubReg, ICSetProp_Native::offsetOfOffset()), scratch); masm.load32(Address(BaselineStubReg, ICSetProp_Native::offsetOfOffset()), scratch);
EmitPreBarrier(masm, BaseIndex(objReg, scratch, TimesOne), MIRType_Value); EmitPreBarrier(masm, BaseIndex(holderReg, scratch, TimesOne), MIRType_Value);
masm.storeValue(R1, BaseIndex(objReg, scratch, TimesOne)); masm.storeValue(R1, BaseIndex(holderReg, scratch, TimesOne));
if (holderReg != objReg)
regs.add(holderReg);
#ifdef JSGC_GENERATIONAL
Label skipBarrier;
masm.branchTestObject(Assembler::NotEqual, R1, &skipBarrier);
{
Register scr = regs.takeAny();
GeneralRegisterSet saveRegs;
saveRegs.add(R1);
emitPostWriteBarrierSlot(masm, objReg, scr, saveRegs);
regs.add(scr);
}
masm.bind(&skipBarrier);
#endif
// The RHS has to be in R0. // The RHS has to be in R0.
masm.moveValue(R1, R0); masm.moveValue(R1, R0);
@ -6400,13 +6496,35 @@ ICSetPropNativeAddCompiler::generateStubCode(MacroAssembler &masm)
masm.loadPtr(Address(BaselineStubReg, ICSetProp_NativeAdd::offsetOfNewShape()), scratch); masm.loadPtr(Address(BaselineStubReg, ICSetProp_NativeAdd::offsetOfNewShape()), scratch);
masm.storePtr(scratch, shapeAddr); masm.storePtr(scratch, shapeAddr);
if (!isFixedSlot_) Register holderReg;
masm.loadPtr(Address(objReg, JSObject::offsetOfSlots()), objReg); regs.add(R0);
regs.takeUnchecked(objReg);
if (isFixedSlot_) {
holderReg = objReg;
} else {
holderReg = regs.takeAny();
masm.loadPtr(Address(objReg, JSObject::offsetOfSlots()), holderReg);
}
// Perform the store. No write barrier required since this is a new // Perform the store. No write barrier required since this is a new
// initialization. // initialization.
masm.load32(Address(BaselineStubReg, ICSetProp_NativeAdd::offsetOfOffset()), scratch); masm.load32(Address(BaselineStubReg, ICSetProp_NativeAdd::offsetOfOffset()), scratch);
masm.storeValue(R1, BaseIndex(objReg, scratch, TimesOne)); masm.storeValue(R1, BaseIndex(holderReg, scratch, TimesOne));
if (holderReg != objReg)
regs.add(holderReg);
#ifdef JSGC_GENERATIONAL
Label skipBarrier;
masm.branchTestObject(Assembler::NotEqual, R1, &skipBarrier);
{
Register scr = regs.takeAny();
GeneralRegisterSet saveRegs;
saveRegs.add(R1);
emitPostWriteBarrierSlot(masm, objReg, scr, saveRegs);
}
masm.bind(&skipBarrier);
#endif
// The RHS has to be in R0. // The RHS has to be in R0.
masm.moveValue(R1, R0); masm.moveValue(R1, R0);
@ -8219,7 +8337,8 @@ ICSetProp_Native::Compiler::getStub(ICStubSpace *space)
ICSetProp_NativeAdd::ICSetProp_NativeAdd(IonCode *stubCode, HandleTypeObject type, ICSetProp_NativeAdd::ICSetProp_NativeAdd(IonCode *stubCode, HandleTypeObject type,
size_t protoChainDepth, size_t protoChainDepth,
HandleShape newShape, uint32_t offset) HandleShape newShape,
uint32_t offset)
: ICUpdatedStub(SetProp_NativeAdd, stubCode), : ICUpdatedStub(SetProp_NativeAdd, stubCode),
type_(type), type_(type),
newShape_(newShape), newShape_(newShape),
@ -8244,7 +8363,8 @@ ICSetProp_NativeAddImpl<ProtoChainDepth>::ICSetProp_NativeAddImpl(IonCode *stubC
ICSetPropNativeAddCompiler::ICSetPropNativeAddCompiler(JSContext *cx, HandleObject obj, ICSetPropNativeAddCompiler::ICSetPropNativeAddCompiler(JSContext *cx, HandleObject obj,
HandleShape oldShape, HandleShape oldShape,
size_t protoChainDepth, bool isFixedSlot, size_t protoChainDepth,
bool isFixedSlot,
uint32_t offset) uint32_t offset)
: ICStubCompiler(cx, ICStub::SetProp_NativeAdd), : ICStubCompiler(cx, ICStub::SetProp_NativeAdd),
obj_(cx, obj), obj_(cx, obj),

View File

@ -744,6 +744,19 @@ class ICStub
} }
} }
static bool NeedsPostBarrier(ICStub::Kind kind) {
JS_ASSERT(IsValidKind(kind));
switch (kind) {
case SetProp_Native:
case SetProp_NativeAdd:
case SetElem_Dense:
case SetElem_DenseAdd:
return true;
default:
return false;
}
}
// Optimized stubs get purged on GC. But some stubs can be active on the // Optimized stubs get purged on GC. But some stubs can be active on the
// stack during GC - specifically the ones that can make calls. To ensure // stack during GC - specifically the ones that can make calls. To ensure
// that these do not get purged, all stubs that can make calls are allocated // that these do not get purged, all stubs that can make calls are allocated
@ -1046,6 +1059,11 @@ class ICStubCompiler
return regs; return regs;
} }
#ifdef JSGC_GENERATIONAL
inline bool emitPostWriteBarrierSlot(MacroAssembler &masm, Register obj, Register scratch,
GeneralRegisterSet saveRegs);
#endif
public: public:
virtual ICStub *getStub(ICStubSpace *space) = 0; virtual ICStub *getStub(ICStubSpace *space) = 0;
@ -4552,7 +4570,7 @@ class ICSetProp_Native : public ICUpdatedStub
} }
class Compiler : public ICStubCompiler { class Compiler : public ICStubCompiler {
HandleObject obj_; RootedObject obj_;
bool isFixedSlot_; bool isFixedSlot_;
uint32_t offset_; uint32_t offset_;
@ -4566,7 +4584,7 @@ class ICSetProp_Native : public ICUpdatedStub
public: public:
Compiler(JSContext *cx, HandleObject obj, bool isFixedSlot, uint32_t offset) Compiler(JSContext *cx, HandleObject obj, bool isFixedSlot, uint32_t offset)
: ICStubCompiler(cx, ICStub::SetProp_Native), : ICStubCompiler(cx, ICStub::SetProp_Native),
obj_(obj), obj_(cx, obj),
isFixedSlot_(isFixedSlot), isFixedSlot_(isFixedSlot),
offset_(offset) offset_(offset)
{} {}