зеркало из https://github.com/mozilla/gecko-dev.git
IonMonkey read/write barrier support. (Bug 701990, r=cdleary)
This commit is contained in:
Родитель
64d322aef2
Коммит
5e2a053a46
|
@ -424,6 +424,7 @@ class ReadBarriered
|
|||
T *value;
|
||||
|
||||
public:
|
||||
ReadBarriered() : value(NULL) {}
|
||||
ReadBarriered(T *value) : value(value) {}
|
||||
|
||||
T *get() const {
|
||||
|
|
|
@ -173,15 +173,15 @@ IonCompartment::mark(JSTracer *trc, JSCompartment *compartment)
|
|||
|
||||
// These must be available if we could be running JIT code.
|
||||
if (enterJIT_)
|
||||
MarkIonCode(trc, enterJIT_, "enterJIT");
|
||||
MarkRoot(trc, enterJIT_, "enterJIT");
|
||||
|
||||
// These need to be here until we can figure out how to make the GC
|
||||
// scan these references inside the code generator itself.
|
||||
if (bailoutHandler_)
|
||||
MarkIonCode(trc, bailoutHandler_, "bailoutHandler");
|
||||
MarkRoot(trc, bailoutHandler_, "bailoutHandler");
|
||||
for (size_t i = 0; i < bailoutTables_.length(); i++) {
|
||||
if (bailoutTables_[i])
|
||||
MarkIonCode(trc, bailoutTables_[i], "bailoutTable");
|
||||
MarkRoot(trc, bailoutTables_[i], "bailoutTable");
|
||||
}
|
||||
|
||||
// functionWrappers_ are not marked because this is a WeakCache of VM
|
||||
|
@ -321,6 +321,40 @@ IonCode::finalize(JSContext *cx)
|
|||
pool_->release();
|
||||
}
|
||||
|
||||
void
|
||||
IonCode::readBarrier(IonCode *code)
|
||||
{
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
if (!code)
|
||||
return;
|
||||
|
||||
JSCompartment *comp = code->compartment();
|
||||
if (comp->needsBarrier())
|
||||
MarkIonCodeUnbarriered(comp->barrierTracer(), code, "ioncode read barrier");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
IonCode::writeBarrierPre(IonCode *code)
|
||||
{
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
if (!code)
|
||||
return;
|
||||
|
||||
JSCompartment *comp = code->compartment();
|
||||
if (comp->needsBarrier())
|
||||
MarkIonCodeUnbarriered(comp->barrierTracer(), code, "ioncode write barrier");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
IonCode::writeBarrierPost(IonCode *code, void *addr)
|
||||
{
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
// Nothing to do.
|
||||
#endif
|
||||
}
|
||||
|
||||
IonScript::IonScript()
|
||||
: method_(NULL),
|
||||
deoptTable_(NULL),
|
||||
|
|
|
@ -2156,6 +2156,14 @@ IonBuilder::jsop_setgname(JSAtom *atom)
|
|||
MStoreSlot *store = MStoreSlot::New(slots, shape->slot - globalObj->numFixedSlots(), value);
|
||||
current->add(store);
|
||||
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
// Determine whether write barrier is required.
|
||||
if (cx->compartment->needsBarrier() &&
|
||||
(!propertyTypes || propertyTypes->needsBarrier(cx))) {
|
||||
store->setNeedsBarrier(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!resumeAfter(store))
|
||||
return false;
|
||||
|
||||
|
|
|
@ -128,6 +128,11 @@ class IonCode : public gc::Cell
|
|||
// object can be allocated, NULL is returned. On failure, |pool| is
|
||||
// automatically released, so the code may be freed.
|
||||
static IonCode *New(JSContext *cx, uint8 *code, uint32 bufferSize, JSC::ExecutablePool *pool);
|
||||
|
||||
public:
|
||||
static void readBarrier(IonCode *code);
|
||||
static void writeBarrierPre(IonCode *code);
|
||||
static void writeBarrierPost(IonCode *code, void *addr);
|
||||
};
|
||||
|
||||
#define ION_DISABLED_SCRIPT ((IonScript *)0x1)
|
||||
|
@ -138,10 +143,10 @@ class SnapshotWriter;
|
|||
struct IonScript
|
||||
{
|
||||
// Code pointer containing the actual method.
|
||||
IonCode *method_;
|
||||
HeapPtr<IonCode> method_;
|
||||
|
||||
// Deoptimization table used by this method.
|
||||
IonCode *deoptTable_;
|
||||
HeapPtr<IonCode> deoptTable_;
|
||||
|
||||
// Offset from the start of the code buffer to its snapshot buffer.
|
||||
uint32 snapshots_;
|
||||
|
|
|
@ -61,7 +61,7 @@ struct VMFunction;
|
|||
|
||||
class IonCompartment
|
||||
{
|
||||
typedef WeakCache<const VMFunction *, IonCode *> VMWrapperMap;
|
||||
typedef WeakCache<const VMFunction *, ReadBarriered<IonCode> > VMWrapperMap;
|
||||
|
||||
friend class IonActivation;
|
||||
|
||||
|
@ -71,17 +71,17 @@ class IonCompartment
|
|||
IonActivation *active_;
|
||||
|
||||
// Trampoline for entering JIT code.
|
||||
IonCode *enterJIT_;
|
||||
ReadBarriered<IonCode> enterJIT_;
|
||||
|
||||
// Vector mapping frame class sizes to bailout tables.
|
||||
js::Vector<IonCode *, 4, SystemAllocPolicy> bailoutTables_;
|
||||
js::Vector<ReadBarriered<IonCode>, 4, SystemAllocPolicy> bailoutTables_;
|
||||
|
||||
// Generic bailout table; used if the bailout table overflows.
|
||||
IonCode *bailoutHandler_;
|
||||
ReadBarriered<IonCode> bailoutHandler_;
|
||||
|
||||
// Argument-rectifying thunk, in the case of insufficient arguments passed
|
||||
// to a function call site. Pads with |undefined|.
|
||||
IonCode *argumentsRectifier_;
|
||||
ReadBarriered<IonCode> argumentsRectifier_;
|
||||
|
||||
// Map VMFunction addresses to the IonCode of the wrapper.
|
||||
VMWrapperMap *functionWrappers_;
|
||||
|
@ -137,7 +137,7 @@ class IonCompartment
|
|||
if (!enterJIT_)
|
||||
return NULL;
|
||||
}
|
||||
return enterJIT_->as<EnterIonCode>();
|
||||
return enterJIT_.get()->as<EnterIonCode>();
|
||||
}
|
||||
|
||||
IonActivation *activation() const {
|
||||
|
|
|
@ -753,6 +753,33 @@ class LStoreSlotT : public LInstructionHelper<0, 2, 0>
|
|||
}
|
||||
};
|
||||
|
||||
// Mark a Value if it is a GCThing.
|
||||
class LWriteBarrierV : public LInstructionHelper<0, BOX_PIECES, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(WriteBarrierV);
|
||||
|
||||
LWriteBarrierV()
|
||||
{ }
|
||||
|
||||
static const size_t Input = 0;
|
||||
};
|
||||
|
||||
// Mark a GCThing.
|
||||
class LWriteBarrierT : public LInstructionHelper<0, 1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(WriteBarrierT);
|
||||
|
||||
LWriteBarrierT(const LAllocation &value) {
|
||||
setOperand(0, value);
|
||||
}
|
||||
|
||||
const LAllocation *value() {
|
||||
return getOperand(0);
|
||||
}
|
||||
};
|
||||
|
||||
// Guard that a value is in a TypeSet.
|
||||
class LTypeBarrier : public LInstructionHelper<BOX_PIECES, BOX_PIECES, 1>
|
||||
{
|
||||
|
|
|
@ -80,6 +80,8 @@
|
|||
_(StoreSlotV) \
|
||||
_(StoreSlotT) \
|
||||
_(GuardShape) \
|
||||
_(WriteBarrierV) \
|
||||
_(WriteBarrierT) \
|
||||
_(TypeBarrier)
|
||||
|
||||
#if defined(JS_CPU_X86)
|
||||
|
|
|
@ -557,11 +557,54 @@ LIRGenerator::visitLoadSlot(MLoadSlot *ins)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::emitWriteBarrier(MInstruction *ins, MDefinition *input)
|
||||
{
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
JS_ASSERT(GetIonContext()->cx->compartment->needsBarrier());
|
||||
LInstruction *barrier;
|
||||
|
||||
switch (input->type()) {
|
||||
// Possible GCThings.
|
||||
case MIRType_Value:
|
||||
barrier = new LWriteBarrierV;
|
||||
if (!useBox(barrier, LWriteBarrierV::Input, input))
|
||||
return false;
|
||||
add(barrier, ins);
|
||||
break;
|
||||
|
||||
// Known GCThings.
|
||||
case MIRType_String:
|
||||
case MIRType_Object:
|
||||
add(new LWriteBarrierT(useRegisterOrConstant(input)), ins);
|
||||
break;
|
||||
|
||||
// Known non-GCThings.
|
||||
case MIRType_Undefined:
|
||||
case MIRType_Null:
|
||||
case MIRType_Boolean:
|
||||
case MIRType_Int32:
|
||||
case MIRType_Double:
|
||||
break;
|
||||
|
||||
// Nonsensical input.
|
||||
default:
|
||||
JS_NOT_REACHED("Unexpected MIRType.");
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitStoreSlot(MStoreSlot *ins)
|
||||
{
|
||||
LInstruction *lir;
|
||||
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
if (ins->needsBarrier() && !emitWriteBarrier(ins, ins->value()))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
switch (ins->value()->type()) {
|
||||
case MIRType_Value:
|
||||
lir = new LStoreSlotV(useRegister(ins->slots()));
|
||||
|
|
|
@ -95,6 +95,9 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||
// Free argument slots following a function call.
|
||||
void freeArguments(uint32 argc);
|
||||
|
||||
// Emit an LWriteBarrierV or LWriteBarrierT if required, based on MIRType.
|
||||
bool emitWriteBarrier(MInstruction *ins, MDefinition *input);
|
||||
|
||||
public:
|
||||
bool visitInstruction(MInstruction *ins);
|
||||
bool visitBlock(MBasicBlock *block);
|
||||
|
|
|
@ -1643,11 +1643,13 @@ class MStoreSlot
|
|||
{
|
||||
uint32 slot_;
|
||||
MIRType slotType_;
|
||||
bool needsBarrier_;
|
||||
|
||||
MStoreSlot(MDefinition *slots, uint32 slot, MDefinition *value)
|
||||
: MBinaryInstruction(slots, value),
|
||||
slot_(slot),
|
||||
slotType_(MIRType_None)
|
||||
slotType_(MIRType_None),
|
||||
needsBarrier_(false)
|
||||
{
|
||||
JS_ASSERT(slots->type() == MIRType_Slots);
|
||||
}
|
||||
|
@ -1681,6 +1683,12 @@ class MStoreSlot
|
|||
bool congruentTo(MDefinition * const &ins) const {
|
||||
return false;
|
||||
}
|
||||
bool needsBarrier() const {
|
||||
return needsBarrier_;
|
||||
}
|
||||
void setNeedsBarrier(bool needsBarrier) {
|
||||
needsBarrier_ = needsBarrier;
|
||||
}
|
||||
};
|
||||
|
||||
// Given a value, guard that the value is in a particular TypeSet, then returns
|
||||
|
|
|
@ -211,7 +211,7 @@ Assembler::TraceJumpRelocations(JSTracer *trc, IonCode *code, CompactBufferReade
|
|||
RelocationIterator iter(reader);
|
||||
while (iter.read()) {
|
||||
IonCode *child = CodeFromJump(code->raw() + iter.offset());
|
||||
MarkIonCode(trc, child, "rel32");
|
||||
MarkIonCodeUnbarriered(trc, child, "rel32");
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ Assembler::trace(JSTracer *trc)
|
|||
for (size_t i = 0; i < jumps_.length(); i++) {
|
||||
RelativePatch &rp = jumps_[i];
|
||||
if (rp.kind == Relocation::CODE)
|
||||
MarkIonCode(trc, IonCode::FromExecutable((uint8 *)rp.target), "masmrel32");
|
||||
MarkIonCodeUnbarriered(trc, IonCode::FromExecutable((uint8 *)rp.target), "masmrel32");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ AssemblerX86Shared::trace(JSTracer *trc)
|
|||
for (size_t i = 0; i < jumps_.length(); i++) {
|
||||
RelativePatch &rp = jumps_[i];
|
||||
if (rp.kind == Relocation::CODE)
|
||||
MarkIonCode(trc, IonCode::FromExecutable((uint8 *)rp.target), "masmrel32");
|
||||
MarkIonCodeUnbarriered(trc, IonCode::FromExecutable((uint8 *)rp.target), "masmrel32");
|
||||
}
|
||||
if (dataRelocations_.length()) {
|
||||
CompactBufferReader reader(dataRelocations_);
|
||||
|
|
|
@ -173,7 +173,7 @@ Assembler::TraceJumpRelocations(JSTracer *trc, IonCode *code, CompactBufferReade
|
|||
RelocationIterator iter(reader);
|
||||
while (iter.read()) {
|
||||
IonCode *child = CodeFromJump(code, code->raw() + iter.offset());
|
||||
MarkIonCode(trc, child, "rel32");
|
||||
MarkIonCodeUnbarriered(trc, child, "rel32");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -296,6 +296,35 @@ CodeGeneratorX64::visitStackArg(LStackArg *arg)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorX64::visitWriteBarrierV(LWriteBarrierV *barrier)
|
||||
{
|
||||
// TODO: Perform C++ call to some WriteBarrier stub.
|
||||
// For now, we just guard and breakpoint on failure.
|
||||
|
||||
const ValueOperand value = ToValue(barrier, LWriteBarrierV::Input);
|
||||
|
||||
Label skipBarrier;
|
||||
masm.branchTestGCThing(Assembler::NotEqual, value, &skipBarrier);
|
||||
{
|
||||
masm.breakpoint();
|
||||
masm.breakpoint();
|
||||
}
|
||||
masm.bind(&skipBarrier);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorX64::visitWriteBarrierT(LWriteBarrierT *barrier)
|
||||
{
|
||||
// TODO: Perform C++ call to some WriteBarrier stub.
|
||||
// For now, we just breakpoint.
|
||||
masm.breakpoint();
|
||||
masm.breakpoint();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorX64::visitGuardShape(LGuardShape *guard)
|
||||
{
|
||||
|
|
|
@ -74,6 +74,8 @@ class CodeGeneratorX64 : public CodeGeneratorX86Shared
|
|||
bool visitLoadSlotT(LLoadSlotT *load);
|
||||
bool visitStoreSlotV(LStoreSlotV *store);
|
||||
bool visitStoreSlotT(LStoreSlotT *store);
|
||||
bool visitWriteBarrierV(LWriteBarrierV *barrier);
|
||||
bool visitWriteBarrierT(LWriteBarrierT *barrier);
|
||||
bool visitGuardShape(LGuardShape *guard);
|
||||
};
|
||||
|
||||
|
|
|
@ -167,6 +167,12 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
|||
cmpl(tag, Imm32(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET));
|
||||
return cond == Equal ? BelowOrEqual : Above;
|
||||
}
|
||||
Condition testGCThing(Condition cond, Register tag) {
|
||||
JS_ASSERT(cond == Equal || cond == NotEqual);
|
||||
cmpl(tag, Imm32(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
|
||||
return cond == Equal ? AboveOrEqual : Below;
|
||||
}
|
||||
|
||||
Condition testUndefined(Condition cond, const ValueOperand &src) {
|
||||
splitTag(src, ScratchReg);
|
||||
return testUndefined(cond, ScratchReg);
|
||||
|
@ -197,6 +203,10 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
|||
splitTag(src, ScratchReg);
|
||||
return testObject(cond, ScratchReg);
|
||||
}
|
||||
Condition testGCThing(Condition cond, const ValueOperand &src) {
|
||||
splitTag(src, ScratchReg);
|
||||
return testGCThing(cond, ScratchReg);
|
||||
}
|
||||
|
||||
void cmpPtr(const Register &lhs, const ImmWord rhs) {
|
||||
JS_ASSERT(lhs != ScratchReg);
|
||||
|
@ -338,6 +348,10 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
|||
cond = testObject(cond, src);
|
||||
j(cond, label);
|
||||
}
|
||||
void branchTestGCThing(Condition cond, const ValueOperand &src, Label *label) {
|
||||
cond = testGCThing(cond, src);
|
||||
j(cond, label);
|
||||
}
|
||||
Condition testError(Condition cond, const ValueOperand &src) {
|
||||
splitTag(src, ScratchReg);
|
||||
return testError(cond, ScratchReg);
|
||||
|
|
|
@ -91,7 +91,7 @@ Assembler::TraceJumpRelocations(JSTracer *trc, IonCode *code, CompactBufferReade
|
|||
RelocationIterator iter(reader);
|
||||
while (iter.read()) {
|
||||
IonCode *child = CodeFromJump(code->raw() + iter.offset());
|
||||
MarkIonCode(trc, child, "rel32");
|
||||
MarkIonCodeUnbarriered(trc, child, "rel32");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -322,6 +322,35 @@ CodeGeneratorX86::visitStoreSlotT(LStoreSlotT *store)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorX86::visitWriteBarrierV(LWriteBarrierV *barrier)
|
||||
{
|
||||
// TODO: Perform C++ call to some WriteBarrier stub.
|
||||
// For now, we just guard and breakpoint on failure.
|
||||
|
||||
const ValueOperand value = ToValue(barrier, LWriteBarrierV::Input);
|
||||
|
||||
Label skipBarrier;
|
||||
masm.branchTestGCThing(Assembler::NotEqual, value, &skipBarrier);
|
||||
{
|
||||
masm.breakpoint();
|
||||
masm.breakpoint();
|
||||
}
|
||||
masm.bind(&skipBarrier);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorX86::visitWriteBarrierT(LWriteBarrierT *barrier)
|
||||
{
|
||||
// TODO: Perform C++ call to some WriteBarrier stub.
|
||||
// For now, we just breakpoint.
|
||||
masm.breakpoint();
|
||||
masm.breakpoint();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorX86::visitGuardShape(LGuardShape *guard)
|
||||
{
|
||||
|
|
|
@ -99,13 +99,15 @@ class CodeGeneratorX86 : public CodeGeneratorX86Shared
|
|||
bool visitLoadSlotT(LLoadSlotT *load);
|
||||
bool visitStoreSlotV(LStoreSlotV *store);
|
||||
bool visitStoreSlotT(LStoreSlotT *store);
|
||||
bool visitWriteBarrierV(LWriteBarrierV *barrier);
|
||||
bool visitWriteBarrierT(LWriteBarrierT *barrier);
|
||||
bool visitGuardShape(LGuardShape *guard);
|
||||
};
|
||||
|
||||
typedef CodeGeneratorX86 CodeGeneratorSpecific;
|
||||
|
||||
} // ion
|
||||
} // js
|
||||
} // namespace ion
|
||||
} // namespace js
|
||||
|
||||
#endif // jsion_codegen_x86_h__
|
||||
|
||||
|
|
|
@ -203,6 +203,11 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
|
|||
cmpl(tag, ImmTag(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET));
|
||||
return cond == Equal ? BelowOrEqual : Above;
|
||||
}
|
||||
Condition testGCThing(Condition cond, const Register &tag) {
|
||||
JS_ASSERT(cond == Equal || cond == NotEqual);
|
||||
cmpl(tag, ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
|
||||
return cond == Equal ? AboveOrEqual : Below;
|
||||
}
|
||||
Condition testError(Condition cond, const Register &tag) {
|
||||
JS_ASSERT(cond == Equal || cond == NotEqual);
|
||||
cmpl(tag, ImmType(JSVAL_TYPE_MAGIC));
|
||||
|
@ -235,6 +240,9 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
|
|||
Condition testNumber(Condition cond, const ValueOperand &value) {
|
||||
return testNumber(cond, value.typeReg());
|
||||
}
|
||||
Condition testGCThing(Condition cond, const ValueOperand &value) {
|
||||
return testGCThing(cond, value.typeReg());
|
||||
}
|
||||
|
||||
void cmpPtr(const Register &lhs, const ImmWord rhs) {
|
||||
cmpl(lhs, Imm32(rhs.value));
|
||||
|
@ -325,6 +333,11 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
|
|||
cond = testNumber(cond, t);
|
||||
j(cond, label);
|
||||
}
|
||||
template <typename T>
|
||||
void branchTestGCThing(Condition cond, const T &t, Label *label) {
|
||||
cond = testGCThing(cond, t);
|
||||
j(cond, label);
|
||||
}
|
||||
|
||||
void unboxInt32(const ValueOperand &operand, const Register &dest) {
|
||||
movl(operand.payloadReg(), dest);
|
||||
|
|
|
@ -232,7 +232,7 @@ MarkShape(JSTracer *trc, const MarkablePtr<const Shape> &shape, const char *name
|
|||
}
|
||||
|
||||
void
|
||||
MarkIonCode(JSTracer *trc, ion::IonCode *code, const char *name)
|
||||
MarkIonCodeUnbarriered(JSTracer *trc, ion::IonCode *code, const char *name)
|
||||
{
|
||||
JS_ASSERT(trc);
|
||||
JS_ASSERT(code);
|
||||
|
@ -240,6 +240,12 @@ MarkIonCode(JSTracer *trc, ion::IonCode *code, const char *name)
|
|||
Mark(trc, code);
|
||||
}
|
||||
|
||||
void
|
||||
MarkIonCode(JSTracer *trc, const MarkablePtr<ion::IonCode> &code, const char *name)
|
||||
{
|
||||
MarkIonCodeUnbarriered(trc, code.value, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkTypeObjectUnbarriered(JSTracer *trc, types::TypeObject *type, const char *name)
|
||||
{
|
||||
|
@ -610,7 +616,7 @@ MarkRoot(JSTracer *trc, JSXML *thing, const char *name)
|
|||
void
|
||||
MarkRoot(JSTracer *trc, ion::IonCode *code, const char *name)
|
||||
{
|
||||
MarkIonCode(trc, code, name);
|
||||
MarkIonCodeUnbarriered(trc, code, name);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -64,9 +64,6 @@ MarkAtom(JSTracer *trc, JSAtom *str, const char *name);
|
|||
void
|
||||
MarkObjectUnbarriered(JSTracer *trc, JSObject *obj, const char *name);
|
||||
|
||||
void
|
||||
MarkIonCode(JSTracer *trc, ion::IonCode *code, const char *name);
|
||||
|
||||
void
|
||||
MarkObject(JSTracer *trc, const MarkablePtr<JSObject> &obj, const char *name);
|
||||
|
||||
|
@ -88,6 +85,12 @@ MarkShapeUnbarriered(JSTracer *trc, const Shape *shape, const char *name);
|
|||
void
|
||||
MarkShape(JSTracer *trc, const MarkablePtr<const Shape> &shape, const char *name);
|
||||
|
||||
void
|
||||
MarkIonCodeUnbarriered(JSTracer *trc, ion::IonCode *code, const char *name);
|
||||
|
||||
void
|
||||
MarkIonCode(JSTracer *trc, const MarkablePtr<ion::IonCode> &code, const char *name);
|
||||
|
||||
void
|
||||
MarkTypeObjectUnbarriered(JSTracer *trc, types::TypeObject *type, const char *name);
|
||||
|
||||
|
@ -224,7 +227,7 @@ Mark(JSTracer *trc, const MarkablePtr<JSObject> &o, const char *name)
|
|||
}
|
||||
|
||||
inline void
|
||||
Mark(JSTracer *trc, ion::IonCode *code, const char *name)
|
||||
Mark(JSTracer *trc, const MarkablePtr<ion::IonCode> &code, const char *name)
|
||||
{
|
||||
MarkIonCode(trc, code, name);
|
||||
}
|
||||
|
|
|
@ -281,14 +281,17 @@ typedef uint64 JSValueShiftedTag;
|
|||
#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_MAX_DOUBLE | (type)))
|
||||
#define JSVAL_TYPE_TO_SHIFTED_TAG(type) (((uint64)JSVAL_TYPE_TO_TAG(type)) << JSVAL_TAG_SHIFT)
|
||||
|
||||
#define JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET JSVAL_TAG_NULL
|
||||
#define JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET JSVAL_TAG_OBJECT
|
||||
#define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET JSVAL_TAG_INT32
|
||||
#define JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET JSVAL_TAG_STRING
|
||||
|
||||
#define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET JSVAL_SHIFTED_TAG_NULL
|
||||
#define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET JSVAL_SHIFTED_TAG_OBJECT
|
||||
#define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET JSVAL_SHIFTED_TAG_UNDEFINED
|
||||
#define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_PTR_PAYLOAD_SET JSVAL_SHIFTED_TAG_MAGIC
|
||||
#define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET JSVAL_SHIFTED_TAG_STRING
|
||||
|
||||
#define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET JSVAL_TAG_INT32
|
||||
|
||||
#endif /* JS_BITS_PER_WORD */
|
||||
|
||||
typedef enum JSWhyMagic
|
||||
|
|
Загрузка…
Ссылка в новой задаче