Bug 1221421 - Fix Ion JSPropertyOp getter stub. r=bz, a=lizzard
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 17 Nov 2015 09:48:38 +0100
changeset 305561 5d43918469c6f66d73b567ffaca1df7998c15f4c
parent 305560 f0282ad221a3bf1aa2d137daa4650ec3ee0e6c1b
child 305562 460116fc714afc60a5d05f95858d46fa6e849c23
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, lizzard
bugs1221421
milestone44.0a2
Bug 1221421 - Fix Ion JSPropertyOp getter stub. r=bz, a=lizzard
js/src/jit/IonCaches.cpp
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -889,24 +889,26 @@ GenerateReadUnboxed(JSContext* cx, IonSc
         masm.bind(failures);
         attacher.jumpNextStub(masm);
     }
 }
 
 static bool
 EmitGetterCall(JSContext* cx, MacroAssembler& masm,
                IonCache::StubAttacher& attacher, JSObject* obj,
-               JSObject* holder, HandleShape shape,
+               JSObject* holder, HandleShape shape, bool holderIsReceiver,
                LiveRegisterSet liveRegs, Register object,
                TypedOrValueRegister output,
                void* returnAddr)
 {
     MOZ_ASSERT(output.hasValue());
     MacroAssembler::AfterICSaveLive aic = masm.icSaveLive(liveRegs);
 
+    MOZ_ASSERT_IF(obj != holder, !holderIsReceiver);
+
     // Remaining registers should basically be free, but we need to use |object| still
     // so leave it alone.
     AllocatableRegisterSet regSet(RegisterSet::All());
     regSet.take(AnyRegister(object));
 
     // This is a slower stub path, and we're going to be doing a call anyway.  Don't need
     // to try so hard to not use the stack.  Scratch regs are just taken from the register
     // set not including the input, current value saved on the stack, and restored when
@@ -981,17 +983,17 @@ EmitGetterCall(JSContext* cx, MacroAssem
         masm.Push(UndefinedValue());
         masm.moveStackPtrTo(argVpReg);
 
         // Push canonical jsid from shape instead of propertyname.
         masm.Push(shape->propid(), scratchReg);
         masm.moveStackPtrTo(argIdReg);
 
         // Push the holder.
-        if (obj == holder) {
+        if (holderIsReceiver) {
             // When the holder is also the current receiver, we just have a shape guard,
             // so we might end up with a random object which is also guaranteed to have
             // this JSGetterOp.
             masm.Push(object);
         } else {
             // If the holder is on the prototype chain, the prototype-guarding
             // only allows objects with the same holder.
             masm.movePtr(ImmGCPtr(holder), scratchReg);
@@ -1114,17 +1116,18 @@ GenerateCallGetter(JSContext* cx, IonScr
                    Address(holderReg, JSObject::offsetOfShape()),
                    ImmGCPtr(holder->as<NativeObject>().lastProperty()),
                    maybePopAndFail);
 
     if (spillObjReg)
         masm.pop(object);
 
     // Now we're good to go to invoke the native call.
-    if (!EmitGetterCall(cx, masm, attacher, obj, holder, shape, liveRegs, object,
+    bool holderIsReceiver = (obj == holder);
+    if (!EmitGetterCall(cx, masm, attacher, obj, holder, shape, holderIsReceiver, liveRegs, object,
                         output, returnAddr))
         return false;
 
     // Rejoin jump.
     attacher.jumpRejoin(masm);
 
     // Jump to next stub.
     if (spillObjReg) {
@@ -1870,20 +1873,22 @@ GetPropertyIC::tryAttachDOMProxyUnshadow
                     &failures);
 
         if (canCache == CanAttachReadSlot) {
             EmitLoadSlot(masm, holder, shape, holderReg, output(), scratchReg);
         } else {
             // EmitGetterCall() expects |obj| to be the object the property is
             // on to do some checks. Since we actually looked at checkObj, and
             // no extra guards will be generated, we can just pass that instead.
+            // The holderIsReceiver check needs to use |obj| though.
             MOZ_ASSERT(canCache == CanAttachCallGetter);
             MOZ_ASSERT(!idempotent());
-            if (!EmitGetterCall(cx, masm, attacher, checkObj, holder, shape, liveRegs_,
-                                object(), output(), returnAddr))
+            bool holderIsReceiver = (obj == holder);
+            if (!EmitGetterCall(cx, masm, attacher, checkObj, holder, shape, holderIsReceiver,
+                                liveRegs_, object(), output(), returnAddr))
             {
                 return false;
             }
         }
     } else {
         // Property was not found on the prototype chain. Deoptimize down to
         // proxy get call
         MOZ_ASSERT(!idempotent());