From ee12984cba1d77ed1925e7ee5229718628a86272 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 26 Nov 2012 13:57:46 -0800 Subject: [PATCH] Add incremental barriers to addprop ICs (bug 811058, r=billm). --HG-- extra : rebase_source : 518dcb987ddd2967ffd24e79afcee203d9d83820 --- js/src/ion/Ion.cpp | 16 +++++++++++++--- js/src/ion/Ion.h | 3 ++- js/src/ion/IonCaches.cpp | 5 ++++- js/src/ion/IonCompartment.h | 13 +++++++++---- js/src/ion/IonMacroAssembler.h | 9 +++++++-- js/src/ion/IonTypes.h | 21 +++++++++++++++++++++ js/src/ion/TypeOracle.h | 21 --------------------- js/src/ion/arm/Trampoline-arm.cpp | 9 +++++++-- js/src/ion/x64/Trampoline-x64.cpp | 9 +++++++-- js/src/ion/x86/Trampoline-x86.cpp | 10 ++++++++-- 10 files changed, 78 insertions(+), 38 deletions(-) diff --git a/js/src/ion/Ion.cpp b/js/src/ion/Ion.cpp index 8530025e499c..cf4872817932 100644 --- a/js/src/ion/Ion.cpp +++ b/js/src/ion/Ion.cpp @@ -187,8 +187,12 @@ IonRuntime::initialize(JSContext *cx) if (!enterJIT_) return false; - preBarrier_ = generatePreBarrier(cx); - if (!preBarrier_) + valuePreBarrier_ = generatePreBarrier(cx, MIRType_Value); + if (!valuePreBarrier_) + return false; + + shapePreBarrier_ = generatePreBarrier(cx, MIRType_Shape); + if (!shapePreBarrier_) return false; for (VMFunction *fun = VMFunction::functions; fun; fun = fun->next) { @@ -1916,11 +1920,17 @@ ion::FinishInvalidation(FreeOp *fop, JSScript *script) } void -ion::MarkFromIon(JSRuntime *rt, Value *vp) +ion::MarkValueFromIon(JSRuntime *rt, Value *vp) { gc::MarkValueUnbarriered(&rt->gcMarker, vp, "write barrier"); } +void +ion::MarkShapeFromIon(JSRuntime *rt, Shape **shapep) +{ + gc::MarkShapeUnbarriered(&rt->gcMarker, shapep, "write barrier"); +} + void ion::ForbidCompilation(JSContext *cx, JSScript *script) { diff --git a/js/src/ion/Ion.h b/js/src/ion/Ion.h index d8bcd20effc9..c1d70f32f288 100644 --- a/js/src/ion/Ion.h +++ b/js/src/ion/Ion.h @@ -269,7 +269,8 @@ void Invalidate(types::TypeCompartment &types, FreeOp *fop, void Invalidate(JSContext *cx, const Vector &invalid, bool resetUses = true); bool Invalidate(JSContext *cx, JSScript *script, bool resetUses = true); -void MarkFromIon(JSRuntime *rt, Value *vp); +void MarkValueFromIon(JSRuntime *rt, Value *vp); +void MarkShapeFromIon(JSRuntime *rt, Shape **shapep); void ToggleBarriers(JSCompartment *comp, bool needs); diff --git a/js/src/ion/IonCaches.cpp b/js/src/ion/IonCaches.cpp index a8543e7e41db..3ae8b8895ee6 100644 --- a/js/src/ion/IonCaches.cpp +++ b/js/src/ion/IonCaches.cpp @@ -1173,7 +1173,10 @@ IonCacheSetProperty::attachNativeAdding(JSContext *cx, IonScript *ion, JSObject masm.pop(object()); // restore object reg /* Changing object shape. Write the object's new shape. */ - masm.storePtr(ImmGCPtr(newShape), Address(object(), JSObject::offsetOfShape())); + Address shapeAddr(object(), JSObject::offsetOfShape()); + if (cx->compartment->needsBarrier()) + masm.callPreBarrier(shapeAddr, MIRType_Shape); + masm.storePtr(ImmGCPtr(newShape), shapeAddr); /* Set the value on the object. */ if (obj->isFixedSlot(propShape->slot())) { diff --git a/js/src/ion/IonCompartment.h b/js/src/ion/IonCompartment.h index ba23c6d28fc5..1cfd8a01dd23 100644 --- a/js/src/ion/IonCompartment.h +++ b/js/src/ion/IonCompartment.h @@ -51,7 +51,8 @@ class IonRuntime IonCode *invalidator_; // Thunk that calls the GC pre barrier. - IonCode *preBarrier_; + IonCode *valuePreBarrier_; + IonCode *shapePreBarrier_; // Map VMFunction addresses to the IonCode of the wrapper. typedef WeakCache VMWrapperMap; @@ -63,7 +64,7 @@ class IonRuntime IonCode *generateBailoutTable(JSContext *cx, uint32 frameClass); IonCode *generateBailoutHandler(JSContext *cx); IonCode *generateInvalidator(JSContext *cx); - IonCode *generatePreBarrier(JSContext *cx); + IonCode *generatePreBarrier(JSContext *cx, MIRType type); IonCode *generateVMWrapper(JSContext *cx, const VMFunction &f); public: @@ -127,8 +128,12 @@ class IonCompartment return rt->enterJIT_->as(); } - IonCode *preBarrier() { - return rt->preBarrier_; + IonCode *valuePreBarrier() { + return rt->valuePreBarrier_; + } + + IonCode *shapePreBarrier() { + return rt->shapePreBarrier_; } AutoFlushCache *flusher() { diff --git a/js/src/ion/IonMacroAssembler.h b/js/src/ion/IonMacroAssembler.h index 8ad65e15f1e8..b77aca7c030d 100644 --- a/js/src/ion/IonMacroAssembler.h +++ b/js/src/ion/IonMacroAssembler.h @@ -385,7 +385,10 @@ class MacroAssembler : public MacroAssemblerSpecific template void callPreBarrier(const T &address, MIRType type) { - JS_ASSERT(type == MIRType_Value || type == MIRType_String || type == MIRType_Object); + JS_ASSERT(type == MIRType_Value || + type == MIRType_String || + type == MIRType_Object || + type == MIRType_Shape); Label done; if (type == MIRType_Value) @@ -395,7 +398,9 @@ class MacroAssembler : public MacroAssemblerSpecific computeEffectiveAddress(address, PreBarrierReg); JSCompartment *compartment = GetIonContext()->compartment; - IonCode *preBarrier = compartment->ionCompartment()->preBarrier(); + IonCode *preBarrier = (type == MIRType_Shape) + ? compartment->ionCompartment()->shapePreBarrier() + : compartment->ionCompartment()->valuePreBarrier(); call(preBarrier); Pop(PreBarrierReg); diff --git a/js/src/ion/IonTypes.h b/js/src/ion/IonTypes.h index 3beda5b2e14f..192cf4e4084b 100644 --- a/js/src/ion/IonTypes.h +++ b/js/src/ion/IonTypes.h @@ -59,6 +59,27 @@ enum BailoutKind Bailout_CachedShapeGuard }; +// The ordering of this enumeration is important: Anything < Value is a +// specialized type. Furthermore, anything < String has trivial conversion to +// a number. +enum MIRType +{ + MIRType_Undefined, + MIRType_Null, + MIRType_Boolean, + MIRType_Int32, + MIRType_Double, + MIRType_String, + MIRType_Object, + MIRType_Magic, + MIRType_Value, + MIRType_None, // Invalid, used as a placeholder. + MIRType_Slots, // A slots vector + MIRType_Elements, // An elements vector + MIRType_StackFrame, // StackFrame pointer for OSR. + MIRType_Shape // A Shape pointer. +}; + #ifdef DEBUG // Track the pipeline of opcodes which has produced a snapshot. #define TRACK_SNAPSHOTS 1 diff --git a/js/src/ion/TypeOracle.h b/js/src/ion/TypeOracle.h index 97ee0f2a6bbd..9fda19732309 100644 --- a/js/src/ion/TypeOracle.h +++ b/js/src/ion/TypeOracle.h @@ -13,27 +13,6 @@ namespace js { namespace ion { - -// The ordering of this enumeration is important: Anything < Value is a -// specialized type. Furthermore, anything < String has trivial conversion to -// a number. -enum MIRType -{ - MIRType_Undefined, - MIRType_Null, - MIRType_Boolean, - MIRType_Int32, - MIRType_Double, - MIRType_String, - MIRType_Object, - MIRType_Magic, - MIRType_Value, - MIRType_None, // Invalid, used as a placeholder. - MIRType_Slots, // A slots vector - MIRType_Elements, // An elements vector - MIRType_StackFrame // StackFrame pointer for OSR. -}; - enum LazyArgumentsType { MaybeArguments = 0, DefinitelyArguments, diff --git a/js/src/ion/arm/Trampoline-arm.cpp b/js/src/ion/arm/Trampoline-arm.cpp index d7390a0f9925..43a7ddadb412 100644 --- a/js/src/ion/arm/Trampoline-arm.cpp +++ b/js/src/ion/arm/Trampoline-arm.cpp @@ -609,7 +609,7 @@ IonRuntime::generateVMWrapper(JSContext *cx, const VMFunction &f) } IonCode * -IonRuntime::generatePreBarrier(JSContext *cx) +IonRuntime::generatePreBarrier(JSContext *cx, MIRType type) { MacroAssembler masm; @@ -623,7 +623,12 @@ IonRuntime::generatePreBarrier(JSContext *cx) masm.setupUnalignedABICall(2, r2); masm.passABIArg(r0); masm.passABIArg(r1); - masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, MarkFromIon)); + if (type == MIRType_Value) { + masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, MarkValueFromIon)); + } else { + JS_ASSERT(type == MIRType_Shape); + masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, MarkShapeFromIon)); + } masm.PopRegsInMask(save); masm.ret(); diff --git a/js/src/ion/x64/Trampoline-x64.cpp b/js/src/ion/x64/Trampoline-x64.cpp index dc0718d26c45..0300612527be 100644 --- a/js/src/ion/x64/Trampoline-x64.cpp +++ b/js/src/ion/x64/Trampoline-x64.cpp @@ -517,7 +517,7 @@ IonRuntime::generateVMWrapper(JSContext *cx, const VMFunction &f) } IonCode * -IonRuntime::generatePreBarrier(JSContext *cx) +IonRuntime::generatePreBarrier(JSContext *cx, MIRType type) { MacroAssembler masm; @@ -531,7 +531,12 @@ IonRuntime::generatePreBarrier(JSContext *cx) masm.setupUnalignedABICall(2, rax); masm.passABIArg(rcx); masm.passABIArg(rdx); - masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, MarkFromIon)); + if (type == MIRType_Value) { + masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, MarkValueFromIon)); + } else { + JS_ASSERT(type == MIRType_Shape); + masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, MarkShapeFromIon)); + } masm.PopRegsInMask(regs); masm.ret(); diff --git a/js/src/ion/x86/Trampoline-x86.cpp b/js/src/ion/x86/Trampoline-x86.cpp index b7bae586f436..d87f77d89446 100644 --- a/js/src/ion/x86/Trampoline-x86.cpp +++ b/js/src/ion/x86/Trampoline-x86.cpp @@ -544,7 +544,7 @@ IonRuntime::generateVMWrapper(JSContext *cx, const VMFunction &f) } IonCode * -IonRuntime::generatePreBarrier(JSContext *cx) +IonRuntime::generatePreBarrier(JSContext *cx, MIRType type) { MacroAssembler masm; @@ -558,7 +558,13 @@ IonRuntime::generatePreBarrier(JSContext *cx) masm.setupUnalignedABICall(2, eax); masm.passABIArg(ecx); masm.passABIArg(edx); - masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, MarkFromIon)); + + if (type == MIRType_Value) { + masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, MarkValueFromIon)); + } else { + JS_ASSERT(type == MIRType_Shape); + masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, MarkShapeFromIon)); + } masm.PopRegsInMask(save); masm.ret();