Bug 1033873 - "Differential Testing: Different output message involving __proto__". r=jandem, a=sledru
authorEric Faust <efaustbmo@gmail.com>
Tue, 16 Sep 2014 09:23:00 -0400
changeset 216768 2dbe6d8a5c30
parent 216767 11e34dc2f591
child 216769 75eddbd6dc80
push id3906
push userryanvm@gmail.com
push date2014-09-17 15:11 +0000
treeherdermozilla-beta@62d020eff891 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem, sledru
bugs1033873
milestone33.0
Bug 1033873 - "Differential Testing: Different output message involving __proto__". r=jandem, a=sledru
js/src/jit/IonCaches.cpp
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -843,32 +843,32 @@ GenerateReadSlot(JSContext *cx, IonScrip
 
 }
 
 static bool
 EmitGetterCall(JSContext *cx, MacroAssembler &masm,
                IonCache::StubAttacher &attacher, JSObject *obj,
                JSObject *holder, HandleShape shape,
                RegisterSet liveRegs, Register object,
-               Register scratchReg, TypedOrValueRegister output,
+               TypedOrValueRegister output,
                void *returnAddr)
 {
     JS_ASSERT(output.hasValue());
     MacroAssembler::AfterICSaveLive aic = masm.icSaveLive(liveRegs);
 
     // Remaining registers should basically be free, but we need to use |object| still
     // so leave it alone.
     RegisterSet 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
     // we're done with it.
-    scratchReg               = regSet.takeGeneral();
+    Register scratchReg      = regSet.takeGeneral();
     Register argJSContextReg = regSet.takeGeneral();
     Register argUintNReg     = regSet.takeGeneral();
     Register argVpReg        = regSet.takeGeneral();
 
     // Shape has a getter function.
     bool callNative = IsCacheableGetPropCallNative(obj, holder, shape);
     JS_ASSERT_IF(!callNative, IsCacheableGetPropCallPropertyOp(obj, holder, shape));
 
@@ -985,38 +985,54 @@ GenerateCallGetter(JSContext *cx, IonScr
     Label stubFailure;
     failures = failures ? failures : &stubFailure;
 
     // Initial shape check.
     masm.branchPtr(Assembler::NotEqual, Address(object, JSObject::offsetOfShape()),
                    ImmGCPtr(obj->lastProperty()), failures);
 
     Register scratchReg = output.valueReg().scratchReg();
+    bool spillObjReg = scratchReg == object;
+    Label pop1AndFail;
+    Label *maybePopAndFail = failures;
+
+    // Save off the object register if it aliases the scratchReg
+    if (spillObjReg) {
+        masm.push(object);
+        maybePopAndFail = &pop1AndFail;
+    }
 
     // Note: this may clobber the object register if it's used as scratch.
     if (obj != holder)
         GeneratePrototypeGuards(cx, ion, masm, obj, holder, object, scratchReg, failures);
 
     // Guard on the holder's shape.
     Register holderReg = scratchReg;
     masm.moveNurseryPtr(ImmMaybeNurseryPtr(holder), holderReg);
     masm.branchPtr(Assembler::NotEqual,
                    Address(holderReg, JSObject::offsetOfShape()),
                    ImmGCPtr(holder->lastProperty()),
-                   failures);
+                   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,
-                        scratchReg, output, returnAddr))
+                        output, returnAddr))
         return false;
 
     // Rejoin jump.
     attacher.jumpRejoin(masm);
 
     // Jump to next stub.
+    if (spillObjReg) {
+        masm.bind(&pop1AndFail);
+        masm.pop(object);
+    }
     masm.bind(failures);
     attacher.jumpNextStub(masm);
 
     return true;
 }
 
 static bool
 GenerateArrayLength(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &attacher,
@@ -1474,17 +1490,17 @@ GetPropertyIC::tryAttachDOMProxyUnshadow
             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.
             JS_ASSERT(canCache == CanAttachCallGetter);
             JS_ASSERT(!idempotent());
             if (!EmitGetterCall(cx, masm, attacher, checkObj, holder, shape, liveRegs_,
-                                object(), scratchReg, output(), returnAddr))
+                                object(), output(), returnAddr))
             {
                 return false;
             }
         }
     } else {
         // Property was not found on the prototype chain. Deoptimize down to
         // proxy get call
         JS_ASSERT(!idempotent());