Bug 906091 - Post-barrier globals, but only add to the store buffer on first write r=terrence

This commit is contained in:
Jon Coppeard 2013-09-24 10:08:35 +01:00
parent 7ad032bc1e
commit fee1aeb3b7
7 changed files with 31 additions and 32 deletions

View File

@ -619,30 +619,6 @@ JSPropertyDescriptor::trace(JSTracer *trc)
}
}
static inline void
MarkGlobalForMinorGC(JSTracer *trc, JSCompartment *compartment)
{
#ifdef JS_ION
/*
* Named properties of globals which have had Ion activity are treated as
* roots during minor GCs. This allows writes to globals to occur without
* needing a write barrier.
*/
JS_ASSERT(trc->runtime->isHeapMinorCollecting());
if (!compartment->ionCompartment())
return;
GlobalObject *global = compartment->maybeGlobal();
if (!global)
return;
/* Global reserved slots never hold nursery things. */
for (size_t i = JSCLASS_RESERVED_SLOTS(global->getClass()); i < global->slotSpan(); ++i)
MarkValueRoot(trc, global->nativeGetSlotRef(i).unsafeGet(), "MinorGlobalRoot");
#endif /* JS_ION */
}
void
js::gc::MarkRuntime(JSTracer *trc, bool useSavedRoots)
{
@ -726,12 +702,12 @@ js::gc::MarkRuntime(JSTracer *trc, bool useSavedRoots)
/* We can't use GCCompartmentsIter if we're called from TraceRuntime. */
for (CompartmentsIter c(rt); !c.done(); c.next()) {
if (trc->runtime->isHeapMinorCollecting())
c->globalWriteBarriered = false;
if (IS_GC_MARKING_TRACER(trc) && !c->zone()->isCollecting())
continue;
if (trc->runtime->isHeapMinorCollecting())
MarkGlobalForMinorGC(trc, c);
/* During a GC, these are treated as weak pointers. */
if (!IS_GC_MARKING_TRACER(trc)) {
if (c->watchpointMap)

View File

@ -1440,9 +1440,12 @@ CodeGenerator::visitOutOfLineCallPostWriteBarrier(OutOfLineCallPostWriteBarrier
regs.add(CallTempReg2);
Register objreg;
bool isGlobal = false;
if (obj->isConstant()) {
JSObject *object = &obj->toConstant()->toObject();
isGlobal = object->is<GlobalObject>();
objreg = regs.takeAny();
masm.movePtr(ImmGCPtr(&obj->toConstant()->toObject()), objreg);
masm.movePtr(ImmGCPtr(object), objreg);
} else {
objreg = ToRegister(obj);
regs.takeUnchecked(objreg);
@ -1451,10 +1454,11 @@ CodeGenerator::visitOutOfLineCallPostWriteBarrier(OutOfLineCallPostWriteBarrier
Register runtimereg = regs.takeAny();
masm.mov(ImmPtr(GetIonContext()->runtime), runtimereg);
void (*fun)(JSRuntime*, JSObject*) = isGlobal ? PostGlobalWriteBarrier : PostWriteBarrier;
masm.setupUnalignedABICall(2, regs.takeAny());
masm.passABIArg(runtimereg);
masm.passABIArg(objreg);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, PostWriteBarrier));
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, fun));
restoreLive(ool->lir());

View File

@ -6423,9 +6423,7 @@ IonBuilder::setStaticName(JSObject *staticObject, PropertyName *name)
if (!propertyTypes)
obj = addShapeGuard(obj, staticObject->lastProperty(), Bailout_ShapeGuard);
// Note: we do not use a post barrier when writing to the global object.
// Slots in the global object will be treated as roots during a minor GC.
if (!staticObject->is<GlobalObject>() && NeedsPostBarrier(info(), value))
if (NeedsPostBarrier(info(), value))
current->add(MPostWriteBarrier::New(obj, value));
// If the property has a known type, we may be able to optimize typed stores by not

View File

@ -631,6 +631,16 @@ PostWriteBarrier(JSRuntime *rt, JSObject *obj)
JS_ASSERT(!IsInsideNursery(rt, obj));
rt->gcStoreBuffer.putWholeCell(obj);
}
void
PostGlobalWriteBarrier(JSRuntime *rt, JSObject *obj)
{
JS_ASSERT(obj->is<GlobalObject>());
if (!obj->compartment()->globalWriteBarriered) {
PostWriteBarrier(rt, obj);
obj->compartment()->globalWriteBarriered = true;
}
}
#endif
uint32_t

View File

@ -641,6 +641,7 @@ bool FilterArguments(JSContext *cx, JSString *str);
#ifdef JSGC_GENERATIONAL
void PostWriteBarrier(JSRuntime *rt, JSObject *obj);
void PostGlobalWriteBarrier(JSRuntime *rt, JSObject *obj);
#endif
uint32_t GetIndexFromString(JSString *str);

View File

@ -52,6 +52,7 @@ JSCompartment::JSCompartment(Zone *zone, const JS::CompartmentOptions &options =
lastAnimationTime(0),
regExps(runtime_),
typeReprs(runtime_),
globalWriteBarriered(false),
propertyTree(thisForCtor()),
gcIncomingGrayPointers(NULL),
gcLiveArrayBuffers(NULL),

View File

@ -206,6 +206,15 @@ struct JSCompartment
/* Set of all currently living type representations. */
js::TypeRepresentationHash typeReprs;
/*
* For generational GC, record whether a write barrier has added this
* compartment's global to the store buffer since the last minor GC.
*
* This is used to avoid adding it to the store buffer on every write, which
* can quickly fill the buffer and also cause performance problems.
*/
bool globalWriteBarriered;
private:
void sizeOfTypeInferenceData(JS::TypeInferenceSizes *stats, mozilla::MallocSizeOf mallocSizeOf);