зеркало из https://github.com/mozilla/gecko-dev.git
Bug 906091 - Post-barrier globals, but only add to the store buffer on first write r=terrence
This commit is contained in:
Родитель
38b17c9cb2
Коммит
ff95dc15cd
|
@ -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)
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче