Backed out changeset 9e282f0c00b8 (bug 906805) for suspicion of causing intermittent mochitest-bc crashes on a CLOSED TREE.
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 04 Sep 2013 16:01:31 -0400
changeset 145481 dffedf20a02dce00267ba25ad39d3aab371e54b3
parent 145480 4dceda951fba9ce5e9cf546449493177ca682fc5
child 145482 a895979d4c8ba4aaa51f6be40e37df076b6646a2
child 145564 99bd249e5a2063029f1527cc9a68e9fac09e107e
push id33293
push userryanvm@gmail.com
push dateWed, 04 Sep 2013 20:01:39 +0000
treeherdermozilla-inbound@dffedf20a02d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs906805
milestone26.0a1
backs out9e282f0c00b862f8ffc9778fabff5a7da92d5a74
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 9e282f0c00b8 (bug 906805) for suspicion of causing intermittent mochitest-bc crashes on a CLOSED TREE.
js/src/jit/BaselineIC.cpp
js/src/jit/BaselineIC.h
js/src/jit/arm/MacroAssembler-arm.cpp
js/src/jit/x86/MacroAssembler-x86.h
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -179,41 +179,30 @@ ICStub::trace(JSTracer *trc)
         MarkScript(trc, &callStub->calleeScript(), "baseline-callscripted-callee");
         break;
       }
       case ICStub::Call_Native: {
         ICCall_Native *callStub = toCall_Native();
         MarkObject(trc, &callStub->callee(), "baseline-callnative-callee");
         break;
       }
-      case ICStub::GetElem_NativeSlot: {
-        ICGetElem_NativeSlot *getElemStub = toGetElem_NativeSlot();
+      case ICStub::GetElem_Native: {
+        ICGetElem_Native *getElemStub = toGetElem_Native();
         MarkShape(trc, &getElemStub->shape(), "baseline-getelem-native-shape");
-        MarkString(trc, &getElemStub->name(), "baseline-getelem-native-name");
+        gc::MarkValue(trc, &getElemStub->idval(), "baseline-getelem-native-idval");
         break;
       }
-      case ICStub::GetElem_NativePrototypeSlot: {
-        ICGetElem_NativePrototypeSlot *getElemStub = toGetElem_NativePrototypeSlot();
+      case ICStub::GetElem_NativePrototype: {
+        ICGetElem_NativePrototype *getElemStub = toGetElem_NativePrototype();
         MarkShape(trc, &getElemStub->shape(), "baseline-getelem-nativeproto-shape");
-        MarkString(trc, &getElemStub->name(), "baseline-getelem-nativeproto-name");
+        gc::MarkValue(trc, &getElemStub->idval(), "baseline-getelem-nativeproto-idval");
         MarkObject(trc, &getElemStub->holder(), "baseline-getelem-nativeproto-holder");
         MarkShape(trc, &getElemStub->holderShape(), "baseline-getelem-nativeproto-holdershape");
         break;
       }
-      case ICStub::GetElem_NativePrototypeCallNative:
-      case ICStub::GetElem_NativePrototypeCallScripted: {
-        ICGetElemNativePrototypeCallStub *callStub =
-            reinterpret_cast<ICGetElemNativePrototypeCallStub *>(this);
-        MarkShape(trc, &callStub->shape(), "baseline-getelem-nativeprotocall-shape");
-        MarkString(trc, &callStub->name(), "baseline-getelem-nativeprotocall-name");
-        MarkObject(trc, &callStub->getter(), "baseline-getelem-nativeprotocall-getter");
-        MarkObject(trc, &callStub->holder(), "baseline-getelem-nativeprotocall-holder");
-        MarkShape(trc, &callStub->holderShape(), "baseline-getelem-nativeprotocall-holdershape");
-        break;
-      }
       case ICStub::GetElem_Dense: {
         ICGetElem_Dense *getElemStub = toGetElem_Dense();
         MarkShape(trc, &getElemStub->shape(), "baseline-getelem-dense-shape");
         break;
       }
       case ICStub::GetElem_TypedArray: {
         ICGetElem_TypedArray *getElemStub = toGetElem_TypedArray();
         MarkShape(trc, &getElemStub->shape(), "baseline-getelem-typedarray-shape");
@@ -629,30 +618,24 @@ ICStubCompiler::leaveStubFrame(MacroAsse
     JS_ASSERT(entersStubFrame_);
     EmitLeaveStubFrame(masm, calledIntoIon);
 }
 
 void
 ICStubCompiler::guardProfilingEnabled(MacroAssembler &masm, Register scratch, Label *skip)
 {
     // This should only be called from the following stubs.
-    JS_ASSERT(kind == ICStub::Call_Scripted                             ||
-              kind == ICStub::Call_AnyScripted                          ||
-              kind == ICStub::Call_Native                               ||
-              kind == ICStub::Call_ScriptedApplyArray                   ||
-              kind == ICStub::Call_ScriptedApplyArguments               ||
-              kind == ICStub::GetProp_CallScripted                      ||
-              kind == ICStub::GetProp_CallNative                        ||
-              kind == ICStub::GetProp_CallDOMProxyNative                ||
-              kind == ICStub::GetElem_NativePrototypeCallNative         ||
-              kind == ICStub::GetElem_NativePrototypeCallScripted       ||
-              kind == ICStub::GetProp_CallDOMProxyWithGenerationNative  ||
-              kind == ICStub::GetProp_DOMProxyShadowed                  ||
-              kind == ICStub::SetProp_CallScripted                      ||
-              kind == ICStub::SetProp_CallNative);
+    JS_ASSERT(kind == ICStub::Call_Scripted      || kind == ICStub::Call_AnyScripted     ||
+              kind == ICStub::Call_Native        || kind == ICStub::GetProp_CallScripted ||
+              kind == ICStub::GetProp_CallNative || kind == ICStub::GetProp_CallDOMProxyNative ||
+              kind == ICStub::Call_ScriptedApplyArray ||
+              kind == ICStub::Call_ScriptedApplyArguments ||
+              kind == ICStub::GetProp_CallDOMProxyWithGenerationNative ||
+              kind == ICStub::GetProp_DOMProxyShadowed ||
+              kind == ICStub::SetProp_CallScripted || kind == ICStub::SetProp_CallNative);
 
     // Guard on bit in frame that indicates if the SPS frame was pushed in the first
     // place.  This code is expected to be called from within a stub that has already
     // entered a stub frame.
     JS_ASSERT(entersStubFrame_);
     masm.loadPtr(Address(BaselineFrameReg, 0), scratch);
     masm.branchTest32(Assembler::Zero,
                       Address(scratch, BaselineFrame::reverseOffsetOfFlags()),
@@ -1562,41 +1545,16 @@ ICTypeUpdate_TypeObject::Compiler::gener
     EmitReturnFromIC(masm);
 
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
     return true;
 }
 
 //
-// VM function to help call native getters.
-//
-
-static bool
-DoCallNativeGetter(JSContext *cx, HandleFunction callee, HandleObject obj,
-                   MutableHandleValue result)
-{
-    JS_ASSERT(callee->isNative());
-    JSNative natfun = callee->native();
-
-    Value vp[2] = { ObjectValue(*callee.get()), ObjectValue(*obj.get()) };
-    AutoValueArray rootVp(cx, vp, 2);
-
-    if (!natfun(cx, 0, vp))
-        return false;
-
-    result.set(vp[0]);
-    return true;
-}
-
-typedef bool (*DoCallNativeGetterFn)(JSContext *, HandleFunction, HandleObject, MutableHandleValue);
-static const VMFunction DoCallNativeGetterInfo =
-    FunctionInfo<DoCallNativeGetterFn>(DoCallNativeGetter);
-
-//
 // This_Fallback
 //
 
 static bool
 DoThisFallback(JSContext *cx, ICThis_Fallback *stub, HandleValue thisv, MutableHandleValue ret)
 {
     FallbackICSpew(cx, stub, "This");
 
@@ -3457,153 +3415,16 @@ IsCacheableSetPropCall(JSObject *obj, JS
     if (!func->hasJITCode())
         return false;
 
     *isScripted = true;
     return true;
 }
 
 static bool
-GetElemNativeStubExists(ICGetElem_Fallback *stub, HandleObject obj, HandleObject holder,
-                        HandlePropertyName propName, bool needsAtomize)
-{
-    bool indirect = (obj.get() != holder.get());
-
-    for (ICStubConstIterator iter = stub->beginChainConst(); !iter.atEnd(); iter++) {
-        if (iter->kind() != ICStub::GetElem_NativeSlot &&
-            iter->kind() != ICStub::GetElem_NativePrototypeSlot &&
-            iter->kind() != ICStub::GetElem_NativePrototypeCallNative &&
-            iter->kind() != ICStub::GetElem_NativePrototypeCallScripted)
-        {
-            continue;
-        }
-
-        if (indirect && (iter->kind() != ICStub::GetElem_NativePrototypeSlot &&
-                         iter->kind() != ICStub::GetElem_NativePrototypeCallNative &&
-                         iter->kind() != ICStub::GetElem_NativePrototypeCallScripted))
-        {
-            continue;
-        }
-
-        ICGetElemNativeStub *getElemNativeStub = reinterpret_cast<ICGetElemNativeStub *>(*iter);
-        if (propName != getElemNativeStub->name())
-            continue;
-
-        if (obj->lastProperty() != getElemNativeStub->shape())
-            continue;
-
-        // If the new stub needs atomization, and the old stub doesn't atomize, then
-        // an appropriate stub doesn't exist.
-        if (needsAtomize && !getElemNativeStub->needsAtomize())
-            continue;
-
-        // For prototype gets, check the holder and holder shape.
-        if (indirect) {
-            if (iter->isGetElem_NativePrototypeSlot()) {
-                ICGetElem_NativePrototypeSlot *protoStub = iter->toGetElem_NativePrototypeSlot();
-
-                if (holder != protoStub->holder())
-                    continue;
-
-                if (holder->lastProperty() != protoStub->holderShape())
-                    continue;
-            } else {
-                JS_ASSERT(iter->isGetElem_NativePrototypeCallNative() ||
-                          iter->isGetElem_NativePrototypeCallScripted());
-
-                ICGetElemNativePrototypeCallStub *protoStub =
-                    reinterpret_cast<ICGetElemNativePrototypeCallStub *>(*iter);
-
-                if (holder != protoStub->holder())
-                    continue;
-
-                if (holder->lastProperty() != protoStub->holderShape())
-                    continue;
-            }
-        }
-
-        return true;
-    }
-    return false;
-}
-
-static void
-RemoveExistingGetElemNativeStubs(JSContext *cx, ICGetElem_Fallback *stub, HandleObject obj,
-                                 HandleObject holder, HandlePropertyName propName,
-                                 bool needsAtomize)
-{
-    bool indirect = (obj.get() != holder.get());
-
-    for (ICStubIterator iter = stub->beginChain(); !iter.atEnd(); iter++) {
-        switch (iter->kind()) {
-          case ICStub::GetElem_NativeSlot:
-            if (indirect)
-                continue;
-          case ICStub::GetElem_NativePrototypeSlot:
-          case ICStub::GetElem_NativePrototypeCallNative:
-          case ICStub::GetElem_NativePrototypeCallScripted:
-            break;
-          default:
-            continue;
-        }
-
-        ICGetElemNativeStub *getElemNativeStub = reinterpret_cast<ICGetElemNativeStub *>(*iter);
-        if (propName != getElemNativeStub->name())
-            continue;
-
-        if (obj->lastProperty() != getElemNativeStub->shape())
-            continue;
-
-        // For prototype gets, check the holder and holder shape.
-        if (indirect) {
-            if (iter->isGetElem_NativePrototypeSlot()) {
-                ICGetElem_NativePrototypeSlot *protoStub = iter->toGetElem_NativePrototypeSlot();
-
-                if (holder != protoStub->holder())
-                    continue;
-
-                // If the holder matches, but the holder's lastProperty doesn't match, then
-                // this stub is invalid anyway.  Unlink it.
-                if (holder->lastProperty() != protoStub->holderShape()) {
-                    iter.unlink(cx->zone());
-                    continue;
-                }
-            } else {
-                JS_ASSERT(iter->isGetElem_NativePrototypeCallNative() ||
-                          iter->isGetElem_NativePrototypeCallScripted());
-
-                ICGetElemNativePrototypeCallStub *protoStub =
-                    reinterpret_cast<ICGetElemNativePrototypeCallStub *>(*iter);
-
-                if (holder != protoStub->holder())
-                    continue;
-
-                // If the holder matches, but the holder's lastProperty doesn't match, then
-                // this stub is invalid anyway.  Unlink it.
-                if (holder->lastProperty() != protoStub->holderShape()) {
-                    iter.unlink(cx->zone());
-                    continue;
-                }
-            }
-        }
-
-        // If the new stub needs atomization, and the old stub doesn't atomize, then
-        // remove the old stub.
-        if (needsAtomize && !getElemNativeStub->needsAtomize()) {
-            iter.unlink(cx->zone());
-            continue;
-        }
-
-        // Should never get here, because this means a matching stub exists, and if
-        // a matching stub exists, this procedure should never have been called.
-        MOZ_ASSUME_UNREACHABLE("Procedure should never have been called.");
-    }
-}
-
-static bool
 TypedArrayGetElemStubExists(ICGetElem_Fallback *stub, HandleObject obj)
 {
     for (ICStubConstIterator iter = stub->beginChainConst(); !iter.atEnd(); iter++) {
         if (!iter->isGetElem_TypedArray())
             continue;
         if (obj->lastProperty() == iter->toGetElem_TypedArray()->shape())
             return true;
     }
@@ -3618,134 +3439,70 @@ ArgumentsGetElemStubExists(ICGetElem_Fal
             continue;
         if (iter->toGetElem_Arguments()->which() == which)
             return true;
     }
     return false;
 }
 
 
-static bool TryAttachNativeGetElemStub(JSContext *cx, HandleScript script, jsbytecode *pc,
+static bool TryAttachNativeGetElemStub(JSContext *cx, HandleScript script,
                                        ICGetElem_Fallback *stub, HandleObject obj,
                                        HandleValue key)
 {
-    // Native-object GetElem stubs can't deal with non-string keys.
-    if (!key.isString())
-        return true;
-
-    // Convert to interned property name.
     RootedId id(cx);
     if (!ValueToId<CanGC>(cx, key, &id))
         return false;
 
     uint32_t dummy;
     if (!JSID_IS_ATOM(id) || JSID_TO_ATOM(id)->isIndex(&dummy))
         return true;
 
     RootedPropertyName propName(cx, JSID_TO_ATOM(id)->asPropertyName());
-    bool needsAtomize = !key.toString()->isAtom();
 
     RootedShape shape(cx);
     RootedObject holder(cx);
     if (!EffectlesslyLookupProperty(cx, obj, propName, &holder, &shape))
         return false;
 
-    if (IsCacheableGetPropReadSlot(obj, holder, shape)) {
-        // If a suitable stub already exists, nothing else to do.
-        if (GetElemNativeStubExists(stub, obj, holder, propName, needsAtomize))
-            return true;
-
-        // Remove any existing stubs that may interfere with the new stub being added.
-        RemoveExistingGetElemNativeStubs(cx, stub, obj, holder, propName, needsAtomize);
-
-        bool isFixedSlot;
-        uint32_t offset;
-        GetFixedOrDynamicSlotOffset(holder, shape->slot(), &isFixedSlot, &offset);
-
-        ICStub *monitorStub = stub->fallbackMonitorStub()->firstMonitorStub();
-        ICStub::Kind kind = (obj == holder) ? ICStub::GetElem_NativeSlot
-                                            : ICStub::GetElem_NativePrototypeSlot;
-
-        IonSpew(IonSpew_BaselineIC, "  Generating GetElem(Native %s%s slot) stub "
-                                    "(obj=%p, shape=%p, holder=%p, holderShape=%p)",
-                    (obj == holder) ? "direct" : "prototype",
-                    needsAtomize ? " atomizing" : "",
-                    obj.get(), obj->lastProperty(), holder.get(), holder->lastProperty());
-
-        ICGetElemNativeStub::AccessType acctype = isFixedSlot ? ICGetElemNativeStub::FixedSlot
-                                                              : ICGetElemNativeStub::DynamicSlot;
-        ICGetElemNativeCompiler compiler(cx, kind, monitorStub, obj, holder, propName, acctype,
-                                         needsAtomize, offset);
-        ICStub *newStub = compiler.getStub(compiler.getStubSpace(script));
-        if (!newStub)
-            return false;
-
-        stub->addNewStub(newStub);
+    if (!IsCacheableGetPropReadSlot(obj, holder, shape))
         return true;
-    }
-
-    bool getterIsScripted = false;
-    if (IsCacheableGetPropCall(obj, holder, shape, &getterIsScripted, /*isDOMProxy=*/false)) {
-        RootedFunction getter(cx, &shape->getterObject()->as<JSFunction>());
-
-        // If a suitable stub already exists, nothing else to do.
-        if (GetElemNativeStubExists(stub, obj, holder, propName, needsAtomize))
-            return true;
-
-        // Remove any existing stubs that may interfere with the new stub being added.
-        RemoveExistingGetElemNativeStubs(cx, stub, obj, holder, propName, needsAtomize);
-
-        ICStub *monitorStub = stub->fallbackMonitorStub()->firstMonitorStub();
-        ICStub::Kind kind = getterIsScripted ? ICStub::GetElem_NativePrototypeCallScripted
-                                             : ICStub::GetElem_NativePrototypeCallNative;
-
-        if (getterIsScripted) {
-            IonSpew(IonSpew_BaselineIC,
-                    "  Generating GetElem(Native %s%s call scripted %s:%d) stub "
-                    "(obj=%p, shape=%p, holder=%p, holderShape=%p)",
-                        (obj == holder) ? "direct" : "prototype",
-                        needsAtomize ? " atomizing" : "",
-                        getter->nonLazyScript()->filename(), getter->nonLazyScript()->lineno,
-                        obj.get(), obj->lastProperty(), holder.get(), holder->lastProperty());
-        } else {
-            IonSpew(IonSpew_BaselineIC,
-                    "  Generating GetElem(Native %s%s call native) stub "
-                    "(obj=%p, shape=%p, holder=%p, holderShape=%p)",
-                        (obj == holder) ? "direct" : "prototype",
-                        needsAtomize ? " atomizing" : "",
-                        obj.get(), obj->lastProperty(), holder.get(), holder->lastProperty());
-        }
-
-        ICGetElemNativeStub::AccessType acctype = getterIsScripted
-                                                           ? ICGetElemNativeStub::ScriptedGetter
-                                                           : ICGetElemNativeStub::NativeGetter;
-        ICGetElemNativeCompiler compiler(cx, kind, monitorStub, obj, holder, propName, acctype,
-                                         needsAtomize, getter, pc - script->code);
-        ICStub *newStub = compiler.getStub(compiler.getStubSpace(script));
-        if (!newStub)
-            return false;
-
-        stub->addNewStub(newStub);
-        return true;
-    }
-
+
+    bool isFixedSlot;
+    uint32_t offset;
+    GetFixedOrDynamicSlotOffset(holder, shape->slot(), &isFixedSlot, &offset);
+
+    ICStub *monitorStub = stub->fallbackMonitorStub()->firstMonitorStub();
+    ICStub::Kind kind = (obj == holder) ? ICStub::GetElem_Native : ICStub::GetElem_NativePrototype;
+
+    IonSpew(IonSpew_BaselineIC, "  Generating GetElem(Native %s) stub (obj=%p, shape=%p, holder=%p, holderShape=%p)",
+                (obj == holder) ? "direct" : "prototype",
+                obj.get(), obj->lastProperty(), holder.get(), holder->lastProperty());
+
+    ICGetElemNativeCompiler compiler(cx, kind, monitorStub, obj, holder, key,
+                                     isFixedSlot, offset);
+    ICStub *newStub = compiler.getStub(compiler.getStubSpace(script));
+    if (!newStub)
+        return false;
+
+    stub->addNewStub(newStub);
     return true;
 }
 
 static bool
 TypedArrayRequiresFloatingPoint(TypedArrayObject *tarr)
 {
     uint32_t type = tarr->type();
     return (type == ScalarTypeRepresentation::TYPE_UINT32 ||
             type == ScalarTypeRepresentation::TYPE_FLOAT32 ||
             type == ScalarTypeRepresentation::TYPE_FLOAT64);
 }
 
 static bool
-TryAttachGetElemStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICGetElem_Fallback *stub,
+TryAttachGetElemStub(JSContext *cx, HandleScript script, ICGetElem_Fallback *stub,
                      HandleValue lhs, HandleValue rhs, HandleValue res)
 {
     // Check for String[i] => Char accesses.
     if (lhs.isString() && rhs.isInt32() && res.isString() &&
         !stub->hasStub(ICStub::GetElem_String))
     {
         IonSpew(IonSpew_BaselineIC, "  Generating GetElem(String[Int32]) stub");
         ICGetElem_String::Compiler compiler(cx);
@@ -3805,17 +3562,17 @@ TryAttachGetElemStub(JSContext *cx, Hand
                 return false;
 
             stub->addNewStub(denseStub);
             return true;
         }
 
         // Check for NativeObject[id] shape-optimizable accesses.
         if (rhs.isString()) {
-            if (!TryAttachNativeGetElemStub(cx, script, pc, stub, obj, rhs))
+            if (!TryAttachNativeGetElemStub(cx, script, stub, obj, rhs))
                 return false;
         }
     }
 
     // Check for TypedArray[int] => Number accesses.
     if (obj->is<TypedArrayObject>() && rhs.isInt32() && res.isNumber() &&
         !TypedArrayGetElemStubExists(stub, obj))
     {
@@ -3883,17 +3640,17 @@ DoGetElemFallback(JSContext *cx, Baselin
 
     if (stub->numOptimizedStubs() >= ICGetElem_Fallback::MAX_OPTIMIZED_STUBS) {
         // TODO: Discard all stubs in this IC and replace with inert megamorphic stub.
         // But for now we just bail.
         return true;
     }
 
     // Try to attach an optimized stub.
-    if (!TryAttachGetElemStub(cx, script, pc, stub, lhs, rhs, res))
+    if (!TryAttachGetElemStub(cx, script, stub, lhs, rhs, res))
         return false;
 
     return true;
 }
 
 typedef bool (*DoGetElemFallbackFn)(JSContext *, BaselineFrame *, ICGetElem_Fallback *,
                                     HandleValue, HandleValue, MutableHandleValue);
 static const VMFunction DoGetElemFallbackInfo =
@@ -3916,333 +3673,81 @@ ICGetElem_Fallback::Compiler::generateSt
     masm.pushValue(R0);
     masm.push(BaselineStubReg);
     masm.pushBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
 
     return tailCallVM(DoGetElemFallbackInfo, masm);
 }
 
 //
-// GetElem_NativeSlot
+// GetElem_Native
 //
 
-static bool
-DoAtomizeString(JSContext *cx, HandleString string, MutableHandleValue result)
-{
-    IonSpew(IonSpew_BaselineIC, "  AtomizeString called");
-
-    RootedValue key(cx, StringValue(string));
-
-    // Convert to interned property name.
-    RootedId id(cx);
-    if (!ValueToId<CanGC>(cx, key, &id))
-        return false;
-
-    if (!JSID_IS_ATOM(id)) {
-        result.set(key);
-        return true;
-    }
-
-    result.set(StringValue(JSID_TO_ATOM(id)));
-    return true;
-}
-
-typedef bool (*DoAtomizeStringFn)(JSContext *, HandleString, MutableHandleValue);
-static const VMFunction DoAtomizeStringInfo = FunctionInfo<DoAtomizeStringFn>(DoAtomizeString);
-
-bool
-ICGetElemNativeCompiler::emitCallNative(MacroAssembler &masm, Register objReg)
-{
-    GeneralRegisterSet regs = availableGeneralRegs(0);
-    regs.takeUnchecked(objReg);
-    regs.takeUnchecked(BaselineTailCallReg);
-
-    enterStubFrame(masm, regs.getAny());
-
-    // Push object.
-    masm.push(objReg);
-
-    // Push native callee.
-    masm.loadPtr(Address(BaselineStubReg, ICGetElemNativeGetterStub::offsetOfGetter()), objReg);
-    masm.push(objReg);
-
-    regs.add(objReg);
-
-    // Profiler hook.
-    {
-        Label skipProfilerUpdate;
-        Register scratch = regs.takeAny();
-        Register pcIdx = regs.takeAny();
-
-        // Check if profiling is enabled.
-        guardProfilingEnabled(masm, scratch, &skipProfilerUpdate);
-
-        // Update profiling entry before leaving function.
-        masm.load32(Address(BaselineStubReg, ICGetElemNativeGetterStub::offsetOfPCOffset()), pcIdx);
-        masm.spsUpdatePCIdx(&cx->runtime()->spsProfiler, pcIdx, scratch);
-
-        masm.bind(&skipProfilerUpdate);
-        regs.add(scratch);
-        regs.add(pcIdx);
-    }
-
-    // Call helper.
-    if (!callVM(DoCallNativeGetterInfo, masm))
-        return false;
-
-    leaveStubFrame(masm);
-
-    return true;
-}
-
-bool
-ICGetElemNativeCompiler::emitCallScripted(MacroAssembler &masm, Register objReg)
-{
-    GeneralRegisterSet regs = availableGeneralRegs(0);
-    regs.takeUnchecked(objReg);
-    regs.takeUnchecked(BaselineTailCallReg);
-
-    // Enter stub frame.
-    enterStubFrame(masm, regs.getAny());
-
-    // Push |this| for getter (target object).
-    {
-        ValueOperand val = regs.takeAnyValue();
-        masm.tagValue(JSVAL_TYPE_OBJECT, objReg, val);
-        masm.Push(val);
-        regs.add(val);
-    }
-
-    regs.add(objReg);
-
-    Register callee = regs.takeAny();
-    masm.loadPtr(Address(BaselineStubReg, ICGetElemNativeGetterStub::offsetOfGetter()), callee);
-
-    // Push argc, callee, and descriptor.
-    {
-        Register callScratch = regs.takeAny();
-        EmitCreateStubFrameDescriptor(masm, callScratch);
-        masm.Push(Imm32(0));  // ActualArgc is 0
-        masm.Push(callee);
-        masm.Push(callScratch);
-        regs.add(callScratch);
-    }
-
-    Register code = regs.takeAnyExcluding(ArgumentsRectifierReg);
-    masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), code);
-    masm.loadBaselineOrIonRaw(code, code, SequentialExecution, NULL);
-
-    Register scratch = regs.takeAny();
-
-    // Handle arguments underflow.
-    Label noUnderflow;
-    masm.load16ZeroExtend(Address(callee, offsetof(JSFunction, nargs)), scratch);
-    masm.branch32(Assembler::Equal, scratch, Imm32(0), &noUnderflow);
-    {
-        // Call the arguments rectifier.
-        JS_ASSERT(ArgumentsRectifierReg != code);
-
-        IonCode *argumentsRectifier =
-            cx->runtime()->ionRuntime()->getArgumentsRectifier(SequentialExecution);
-
-        masm.movePtr(ImmGCPtr(argumentsRectifier), code);
-        masm.loadPtr(Address(code, IonCode::offsetOfCode()), code);
-        masm.mov(Imm32(0), ArgumentsRectifierReg);
-    }
-
-    masm.bind(&noUnderflow);
-
-    // If needed, update SPS Profiler frame entry.  At this point, callee and scratch can
-    // be clobbered.
-    {
-        Label skipProfilerUpdate;
-
-        // Need to avoid using ArgumentsRectifierReg and code register.
-        GeneralRegisterSet availRegs = availableGeneralRegs(0);
-        availRegs.take(ArgumentsRectifierReg);
-        availRegs.take(code);
-        Register scratch = availRegs.takeAny();
-        Register pcIdx = availRegs.takeAny();
-
-        // Check if profiling is enabled.
-        guardProfilingEnabled(masm, scratch, &skipProfilerUpdate);
-
-        // Update profiling entry before leaving function.
-        masm.load32(Address(BaselineStubReg, ICGetElemNativeGetterStub::offsetOfPCOffset()),
-                    pcIdx);
-        masm.spsUpdatePCIdx(&cx->runtime()->spsProfiler, pcIdx, scratch);
-
-        masm.bind(&skipProfilerUpdate);
-    }
-    masm.callIon(code);
-
-    leaveStubFrame(masm, true);
-
-    return true;
-}
-
 bool
 ICGetElemNativeCompiler::generateStubCode(MacroAssembler &masm)
 {
     Label failure;
     Label failurePopR1;
     bool popR1 = false;
 
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
-    masm.branchTestString(Assembler::NotEqual, R1, &failure);
+
+    Address idValAddr(BaselineStubReg, ICGetElemNativeStub::offsetOfIdval());
+    masm.branchTestValue(Assembler::NotEqual, idValAddr, R1, &failure);
 
     GeneralRegisterSet regs(availableGeneralRegs(2));
     Register scratchReg = regs.takeAny();
 
     // Unbox object.
     Register objReg = masm.extractObject(R0, ExtractTemp0);
 
     // Check object shape.
     masm.loadPtr(Address(objReg, JSObject::offsetOfShape()), scratchReg);
     Address shapeAddr(BaselineStubReg, ICGetElemNativeStub::offsetOfShape());
     masm.branchPtr(Assembler::NotEqual, shapeAddr, scratchReg, &failure);
 
-    // Check key identity.  Don't automatically fail if this fails, since the incoming
-    // key maybe a non-interned string.  Switch to a slowpath vm-call based check.
-    Address nameAddr(BaselineStubReg, ICGetElemNativeStub::offsetOfName());
-    Register strExtract = masm.extractString(R1, ExtractTemp1);
-
-    // If needsAtomize_ is true, and the string is not already an atom, then atomize the
-    // string before proceeding.
-    if (needsAtomize_) {
-        Label skipAtomize;
-
-        // If string is already an atom, skip the atomize.
-        masm.branchTestPtr(Assembler::NonZero,
-                           Address(strExtract, JSString::offsetOfLengthAndFlags()),
-                           Imm32(JSString::ATOM_BIT),
-                           &skipAtomize);
-
-        // Stow R0.
-        EmitStowICValues(masm, 1);
-
-        enterStubFrame(masm, R0.scratchReg());
-
-        // Atomize the string into a new value.
-        masm.push(strExtract);
-        if (!callVM(DoAtomizeStringInfo, masm))
-            return false;
-
-        // Atomized string is now in JSReturnOperand (R0).
-        // Leave stub frame, move atomized string into R1.
-        JS_ASSERT(R0 == JSReturnOperand);
-        leaveStubFrame(masm);
-        masm.moveValue(JSReturnOperand, R1);
-
-        // Unstow R0
-        EmitUnstowICValues(masm, 1);
-
-        // Extract string from R1 again.
-        Register strExtract2 = masm.extractString(R1, ExtractTemp1);
-        JS_ASSERT(strExtract2 == strExtract);
-
-        masm.bind(&skipAtomize);
-    }
-
-    // Since this stub sometimes enter a stub frame, we manually set this to true (lie).
-    entersStubFrame_ = true;
-
-    // Key has been atomized if necessary.  Do identity check on string pointer.
-    masm.branchPtr(Assembler::NotEqual, nameAddr, strExtract, &failure);
-
     Register holderReg;
     if (obj_ == holder_) {
         holderReg = objReg;
     } else {
         // Shape guard holder.
         if (regs.empty()) {
             masm.push(R1.scratchReg());
             popR1 = true;
             holderReg = R1.scratchReg();
         } else {
             holderReg = regs.takeAny();
         }
-
-        if (kind == ICStub::GetElem_NativePrototypeCallNative ||
-            kind == ICStub::GetElem_NativePrototypeCallScripted)
-        {
-            masm.loadPtr(Address(BaselineStubReg,
-                                 ICGetElemNativePrototypeCallStub::offsetOfHolder()),
-                         holderReg);
-            masm.loadPtr(Address(BaselineStubReg,
-                                 ICGetElemNativePrototypeCallStub::offsetOfHolderShape()),
-                         scratchReg);
-        } else {
-            masm.loadPtr(Address(BaselineStubReg,
-                                 ICGetElem_NativePrototypeSlot::offsetOfHolder()),
-                         holderReg);
-            masm.loadPtr(Address(BaselineStubReg,
-                                 ICGetElem_NativePrototypeSlot::offsetOfHolderShape()),
-                         scratchReg);
-        }
+        masm.loadPtr(Address(BaselineStubReg, ICGetElem_NativePrototype::offsetOfHolder()),
+                     holderReg);
+        masm.loadPtr(Address(BaselineStubReg, ICGetElem_NativePrototype::offsetOfHolderShape()),
+                     scratchReg);
         masm.branchTestObjShape(Assembler::NotEqual, holderReg, scratchReg,
                                 popR1 ? &failurePopR1 : &failure);
     }
 
-    if (acctype_ == ICGetElemNativeStub::DynamicSlot ||
-        acctype_ == ICGetElemNativeStub::FixedSlot)
-    {
-        // Load from object.
-        if (acctype_ == ICGetElemNativeStub::DynamicSlot)
-            masm.loadPtr(Address(holderReg, JSObject::offsetOfSlots()), holderReg);
-
-        masm.load32(Address(BaselineStubReg, ICGetElemNativeSlotStub::offsetOfOffset()),
-                    scratchReg);
-        masm.loadValue(BaseIndex(holderReg, scratchReg, TimesOne), R0);
-
-        if (popR1)
-            masm.addPtr(ImmWord(sizeof(size_t)), BaselineStackReg);
-    } else {
-        JS_ASSERT(acctype_ == ICGetElemNativeStub::NativeGetter ||
-                  acctype_ == ICGetElemNativeStub::ScriptedGetter);
-        JS_ASSERT(kind == ICStub::GetElem_NativePrototypeCallNative ||
-                  kind == ICStub::GetElem_NativePrototypeCallScripted);
-
-        if (acctype_ == ICGetElemNativeStub::NativeGetter) {
-            // If calling a native getter, there is no chance of failure now.
-
-            // GetElem key (R1) is no longer needed.
-            if (popR1)
-                masm.addPtr(ImmWord(sizeof(size_t)), BaselineStackReg);
-
-            emitCallNative(masm, objReg);
-
-        } else {
-            JS_ASSERT(acctype_ == ICGetElemNativeStub::ScriptedGetter);
-
-            // Load function in scratchReg and ensure that it has a jit script.
-            masm.loadPtr(Address(BaselineStubReg, ICGetElemNativeGetterStub::offsetOfGetter()),
-                         scratchReg);
-            masm.loadBaselineOrIonRaw(scratchReg, scratchReg, SequentialExecution,
-                                      popR1 ? &failurePopR1 : &failure);
-
-            // At this point, we are guaranteed to successfully complete.
-            if (popR1)
-                masm.addPtr(Imm32(sizeof(size_t)), BaselineStackReg);
-
-            emitCallScripted(masm, objReg);
-        }
-    }
-
+    // Load from object.
+    if (!isFixedSlot_)
+        masm.loadPtr(Address(holderReg, JSObject::offsetOfSlots()), holderReg);
+
+    masm.load32(Address(BaselineStubReg, ICGetElem_Native::offsetOfOffset()), scratchReg);
+    masm.loadValue(BaseIndex(holderReg, scratchReg, TimesOne), R0);
+
+    if (popR1)
+        masm.pop(R1.scratchReg());
     // Enter type monitor IC to type-check result.
     EmitEnterTypeMonitorIC(masm);
 
     // Failure case - jump to next stub
     if (popR1) {
         masm.bind(&failurePopR1);
         masm.pop(R1.scratchReg());
     }
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
-
     return true;
 }
 
 //
 // GetElem_String
 //
 
 bool
@@ -6295,16 +5800,37 @@ ICGetProp_CallScripted::Compiler::genera
     leaveStubFrame(masm, false);
 
     // Failure case - jump to next stub
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
     return true;
 }
 
+static bool
+DoCallNativeGetter(JSContext *cx, HandleFunction callee, HandleObject obj,
+                   MutableHandleValue result)
+{
+    JS_ASSERT(callee->isNative());
+    JSNative natfun = callee->native();
+
+    Value vp[2] = { ObjectValue(*callee.get()), ObjectValue(*obj.get()) };
+    AutoValueArray rootVp(cx, vp, 2);
+
+    if (!natfun(cx, 0, vp))
+        return false;
+
+    result.set(vp[0]);
+    return true;
+}
+
+typedef bool (*DoCallNativeGetterFn)(JSContext *, HandleFunction, HandleObject, MutableHandleValue);
+static const VMFunction DoCallNativeGetterInfo =
+    FunctionInfo<DoCallNativeGetterFn>(DoCallNativeGetter);
+
 bool
 ICGetProp_CallNative::Compiler::generateStubCode(MacroAssembler &masm)
 {
     Label failure;
     GeneralRegisterSet regs(availableGeneralRegs(1));
     Register scratch = regs.takeAnyExcluding(BaselineTailCallReg);
 
     // Guard input is an object.
@@ -9022,64 +8548,39 @@ ICTypeUpdate_SingleObject::ICTypeUpdate_
 
 ICTypeUpdate_TypeObject::ICTypeUpdate_TypeObject(IonCode *stubCode, HandleTypeObject type)
   : ICStub(TypeUpdate_TypeObject, stubCode),
     type_(type)
 { }
 
 ICGetElemNativeStub::ICGetElemNativeStub(ICStub::Kind kind, IonCode *stubCode,
                                          ICStub *firstMonitorStub,
-                                         HandleShape shape, HandlePropertyName name,
-                                         AccessType acctype, bool needsAtomize)
+                                         HandleShape shape, HandleValue idval,
+                                         bool isFixedSlot, uint32_t offset)
   : ICMonitoredStub(kind, stubCode, firstMonitorStub),
     shape_(shape),
-    name_(name)
-{
-    extra_ = (static_cast<uint16_t>(acctype) << ACCESSTYPE_SHIFT) |
-             (static_cast<uint16_t>(needsAtomize) << NEEDS_ATOMIZE_SHIFT);
+    idval_(idval),
+    offset_(offset)
+{
+    extra_ = isFixedSlot;
 }
 
 ICGetElemNativeStub::~ICGetElemNativeStub()
 { }
 
-ICGetElemNativeGetterStub::ICGetElemNativeGetterStub(
-                        ICStub::Kind kind, IonCode *stubCode, ICStub *firstMonitorStub,
-                        HandleShape shape, HandlePropertyName name, AccessType acctype,
-                        bool needsAtomize, HandleFunction getter, uint32_t pcOffset)
-  : ICGetElemNativeStub(kind, stubCode, firstMonitorStub, shape, name, acctype, needsAtomize),
-    getter_(getter),
-    pcOffset_(pcOffset)
-{
-    JS_ASSERT(kind == GetElem_NativePrototypeCallNative ||
-              kind == GetElem_NativePrototypeCallScripted);
-    JS_ASSERT(acctype == NativeGetter || acctype == ScriptedGetter);
-}
-
-ICGetElem_NativePrototypeSlot::ICGetElem_NativePrototypeSlot(
-                            IonCode *stubCode, ICStub *firstMonitorStub,
-                            HandleShape shape, HandlePropertyName name,
-                            AccessType acctype, bool needsAtomize, uint32_t offset,
-                            HandleObject holder, HandleShape holderShape)
-  : ICGetElemNativeSlotStub(ICStub::GetElem_NativePrototypeSlot, stubCode, firstMonitorStub, shape,
-                            name, acctype, needsAtomize, offset),
+ICGetElem_NativePrototype::ICGetElem_NativePrototype(IonCode *stubCode, ICStub *firstMonitorStub,
+                                                     HandleShape shape, HandleValue idval,
+                                                     bool isFixedSlot, uint32_t offset,
+                                                     HandleObject holder, HandleShape holderShape)
+  : ICGetElemNativeStub(ICStub::GetElem_NativePrototype, stubCode, firstMonitorStub, shape,
+                        idval, isFixedSlot, offset),
     holder_(holder),
     holderShape_(holderShape)
 { }
 
-ICGetElemNativePrototypeCallStub::ICGetElemNativePrototypeCallStub(
-                                ICStub::Kind kind, IonCode *stubCode, ICStub *firstMonitorStub,
-                                HandleShape shape, HandlePropertyName name,
-                                AccessType acctype, bool needsAtomize, HandleFunction getter,
-                                uint32_t pcOffset, HandleObject holder, HandleShape holderShape)
-  : ICGetElemNativeGetterStub(kind, stubCode, firstMonitorStub, shape, name, acctype, needsAtomize,
-                              getter, pcOffset),
-    holder_(holder),
-    holderShape_(holderShape)
-{}
-
 ICGetElem_Dense::ICGetElem_Dense(IonCode *stubCode, ICStub *firstMonitorStub, HandleShape shape)
     : ICMonitoredStub(GetElem_Dense, stubCode, firstMonitorStub),
       shape_(shape)
 { }
 
 ICGetElem_TypedArray::ICGetElem_TypedArray(IonCode *stubCode, HandleShape shape, uint32_t type)
   : ICStub(GetElem_TypedArray, stubCode),
     shape_(shape)
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -323,20 +323,18 @@ class ICEntry
     _(Call_Fallback)            \
     _(Call_Scripted)            \
     _(Call_AnyScripted)         \
     _(Call_Native)              \
     _(Call_ScriptedApplyArray)  \
     _(Call_ScriptedApplyArguments) \
                                 \
     _(GetElem_Fallback)         \
-    _(GetElem_NativeSlot)       \
-    _(GetElem_NativePrototypeSlot) \
-    _(GetElem_NativePrototypeCallNative) \
-    _(GetElem_NativePrototypeCallScripted) \
+    _(GetElem_Native)           \
+    _(GetElem_NativePrototype)  \
     _(GetElem_String)           \
     _(GetElem_Dense)            \
     _(GetElem_TypedArray)       \
     _(GetElem_Arguments)        \
                                 \
     _(SetElem_Fallback)         \
     _(SetElem_Dense)            \
     _(SetElem_DenseAdd)         \
@@ -732,20 +730,16 @@ class ICStub
         switch (kind) {
           case Call_Fallback:
           case Call_Scripted:
           case Call_AnyScripted:
           case Call_Native:
           case Call_ScriptedApplyArray:
           case Call_ScriptedApplyArguments:
           case UseCount_Fallback:
-          case GetElem_NativeSlot:
-          case GetElem_NativePrototypeSlot:
-          case GetElem_NativePrototypeCallNative:
-          case GetElem_NativePrototypeCallScripted:
           case GetProp_CallScripted:
           case GetProp_CallNative:
           case GetProp_CallDOMProxyNative:
           case GetProp_CallDOMProxyWithGenerationNative:
           case GetProp_DOMProxyShadowed:
           case SetProp_CallScripted:
           case SetProp_CallNative:
           case RetSub_Fallback:
@@ -2840,348 +2834,159 @@ class ICGetElem_Fallback : public ICMoni
                 return NULL;
             return stub;
         }
     };
 };
 
 class ICGetElemNativeStub : public ICMonitoredStub
 {
-  public:
-    enum AccessType { FixedSlot = 0, DynamicSlot, NativeGetter, ScriptedGetter };
+    HeapPtrShape shape_;
+    HeapValue idval_;
+    uint32_t offset_;
 
   protected:
-    HeapPtrShape shape_;
-    HeapPtrPropertyName name_;
-
-    static const unsigned NEEDS_ATOMIZE_SHIFT = 0;
-    static const uint16_t NEEDS_ATOMIZE_MASK = 0x1;
-
-    static const unsigned ACCESSTYPE_SHIFT = 1;
-    static const uint16_t ACCESSTYPE_MASK = 0x3;
-
     ICGetElemNativeStub(ICStub::Kind kind, IonCode *stubCode, ICStub *firstMonitorStub,
-                        HandleShape shape, HandlePropertyName name, AccessType acctype,
-                        bool needsAtomize);
+                        HandleShape shape, HandleValue idval,
+                        bool isFixedSlot, uint32_t offset);
 
     ~ICGetElemNativeStub();
 
   public:
     HeapPtrShape &shape() {
         return shape_;
     }
     static size_t offsetOfShape() {
         return offsetof(ICGetElemNativeStub, shape_);
     }
 
-    HeapPtrPropertyName &name() {
-        return name_;
-    }
-    static size_t offsetOfName() {
-        return offsetof(ICGetElemNativeStub, name_);
-    }
-
-    AccessType accessType() const {
-        return static_cast<AccessType>((extra_ >> ACCESSTYPE_SHIFT) & ACCESSTYPE_MASK);
-    }
-
-    bool needsAtomize() const {
-        return (extra_ >> NEEDS_ATOMIZE_SHIFT) & NEEDS_ATOMIZE_MASK;
-    }
-};
-
-class ICGetElemNativeSlotStub : public ICGetElemNativeStub
-{
-  protected:
-    uint32_t offset_;
-
-    ICGetElemNativeSlotStub(ICStub::Kind kind, IonCode *stubCode, ICStub *firstMonitorStub,
-                            HandleShape shape, HandlePropertyName name,
-                            AccessType acctype, bool needsAtomize, uint32_t offset)
-      : ICGetElemNativeStub(kind, stubCode, firstMonitorStub, shape, name, acctype, needsAtomize),
-        offset_(offset)
-    {
-        JS_ASSERT(kind == GetElem_NativeSlot || kind == GetElem_NativePrototypeSlot);
-        JS_ASSERT(acctype == FixedSlot || acctype == DynamicSlot);
-    }
-
-  public:
+    HeapValue &idval() {
+        return idval_;
+    }
+    static size_t offsetOfIdval() {
+        return offsetof(ICGetElemNativeStub, idval_);
+    }
+
     uint32_t offset() const {
         return offset_;
     }
-
     static size_t offsetOfOffset() {
-        return offsetof(ICGetElemNativeSlotStub, offset_);
+        return offsetof(ICGetElemNativeStub, offset_);
+    }
+
+    bool isFixedSlot() const {
+        return extra_;
     }
 };
 
-class ICGetElemNativeGetterStub : public ICGetElemNativeStub
-{
-  protected:
-    HeapPtrFunction getter_;
-    uint32_t pcOffset_;
-
-    ICGetElemNativeGetterStub(ICStub::Kind kind, IonCode *stubCode, ICStub *firstMonitorStub,
-                            HandleShape shape, HandlePropertyName name, AccessType acctype,
-                            bool needsAtomize, HandleFunction getter, uint32_t pcOffset);
-
-  public:
-    HeapPtrFunction &getter() {
-        return getter_;
-    }
-    static size_t offsetOfGetter() {
-        return offsetof(ICGetElemNativeGetterStub, getter_);
-    }
-
-    static size_t offsetOfPCOffset() {
-        return offsetof(ICGetElemNativeGetterStub, pcOffset_);
-    }
-};
-
-class ICGetElem_NativeSlot : public ICGetElemNativeSlotStub
+class ICGetElem_Native : public ICGetElemNativeStub
 {
     friend class ICStubSpace;
-    ICGetElem_NativeSlot(IonCode *stubCode, ICStub *firstMonitorStub,
-                         HandleShape shape, HandlePropertyName name,
-                         AccessType acctype, bool needsAtomize, uint32_t offset)
-      : ICGetElemNativeSlotStub(ICStub::GetElem_NativeSlot, stubCode, firstMonitorStub, shape,
-                                name, acctype, needsAtomize, offset)
+    ICGetElem_Native(IonCode *stubCode, ICStub *firstMonitorStub,
+                     HandleShape shape, HandleValue idval,
+                     bool isFixedSlot, uint32_t offset)
+      : ICGetElemNativeStub(ICStub::GetElem_Native, stubCode, firstMonitorStub, shape, idval,
+                            isFixedSlot, offset)
     {}
 
   public:
-    static inline ICGetElem_NativeSlot *New(ICStubSpace *space, IonCode *code,
-                                            ICStub *firstMonitorStub,
-                                            HandleShape shape, HandlePropertyName name,
-                                            AccessType acctype, bool needsAtomize, uint32_t offset)
+    static inline ICGetElem_Native *New(ICStubSpace *space, IonCode *code,
+                                        ICStub *firstMonitorStub,
+                                        HandleShape shape, HandleValue idval,
+                                        bool isFixedSlot, uint32_t offset)
     {
         if (!code)
             return NULL;
-        return space->allocate<ICGetElem_NativeSlot>(code, firstMonitorStub, shape, name,
-                                                     acctype, needsAtomize, offset);
+        return space->allocate<ICGetElem_Native>(code, firstMonitorStub, shape, idval,
+                                                 isFixedSlot, offset);
     }
 };
 
-class ICGetElem_NativePrototypeSlot : public ICGetElemNativeSlotStub
+class ICGetElem_NativePrototype : public ICGetElemNativeStub
 {
     friend class ICStubSpace;
     HeapPtrObject holder_;
     HeapPtrShape holderShape_;
 
-    ICGetElem_NativePrototypeSlot(IonCode *stubCode, ICStub *firstMonitorStub,
-                                  HandleShape shape, HandlePropertyName name,
-                                  AccessType acctype, bool needsAtomize, uint32_t offset,
-                                  HandleObject holder, HandleShape holderShape);
+    ICGetElem_NativePrototype(IonCode *stubCode, ICStub *firstMonitorStub,
+                              HandleShape shape, HandleValue idval,
+                              bool isFixedSlot, uint32_t offset,
+                              HandleObject holder, HandleShape holderShape);
 
   public:
-    static inline ICGetElem_NativePrototypeSlot *New(ICStubSpace *space, IonCode *code,
-                                                     ICStub *firstMonitorStub,
-                                                     HandleShape shape, HandlePropertyName name,
-                                                     AccessType acctype, bool needsAtomize,
-                                                     uint32_t offset, HandleObject holder,
-                                                     HandleShape holderShape)
+    static inline ICGetElem_NativePrototype *New(ICStubSpace *space, IonCode *code,
+                                                 ICStub *firstMonitorStub,
+                                                 HandleShape shape, HandleValue idval,
+                                                 bool isFixedSlot, uint32_t offset,
+                                                 HandleObject holder, HandleShape holderShape)
     {
         if (!code)
             return NULL;
-        return space->allocate<ICGetElem_NativePrototypeSlot>(
-                    code, firstMonitorStub, shape, name, acctype, needsAtomize, offset, holder,
-                    holderShape);
+        return space->allocate<ICGetElem_NativePrototype>(code, firstMonitorStub, shape, idval,
+                                                          isFixedSlot, offset, holder, holderShape);
     }
 
     HeapPtrObject &holder() {
         return holder_;
     }
     static size_t offsetOfHolder() {
-        return offsetof(ICGetElem_NativePrototypeSlot, holder_);
-    }
-
-    HeapPtrShape &holderShape() {
-        return holderShape_;
-    }
-    static size_t offsetOfHolderShape() {
-        return offsetof(ICGetElem_NativePrototypeSlot, holderShape_);
-    }
-};
-
-class ICGetElemNativePrototypeCallStub : public ICGetElemNativeGetterStub
-{
-    friend class ICStubSpace;
-    HeapPtrObject holder_;
-    HeapPtrShape holderShape_;
-
-  protected:
-    ICGetElemNativePrototypeCallStub(ICStub::Kind kind, IonCode *stubCode, ICStub *firstMonitorStub,
-                                     HandleShape shape, HandlePropertyName name,
-                                     AccessType acctype, bool needsAtomize, HandleFunction getter,
-                                     uint32_t pcOffset, HandleObject holder,
-                                     HandleShape holderShape);
-
-  public:
-    HeapPtrObject &holder() {
-        return holder_;
-    }
-    static size_t offsetOfHolder() {
-        return offsetof(ICGetElemNativePrototypeCallStub, holder_);
+        return offsetof(ICGetElem_NativePrototype, holder_);
     }
 
     HeapPtrShape &holderShape() {
         return holderShape_;
     }
     static size_t offsetOfHolderShape() {
-        return offsetof(ICGetElemNativePrototypeCallStub, holderShape_);
-    }
-};
-
-class ICGetElem_NativePrototypeCallNative : public ICGetElemNativePrototypeCallStub
-{
-    friend class ICStubSpace;
-
-    ICGetElem_NativePrototypeCallNative(IonCode *stubCode, ICStub *firstMonitorStub,
-                                        HandleShape shape, HandlePropertyName name,
-                                        AccessType acctype, bool needsAtomize,
-                                        HandleFunction getter, uint32_t pcOffset,
-                                        HandleObject holder, HandleShape holderShape)
-      : ICGetElemNativePrototypeCallStub(GetElem_NativePrototypeCallNative,
-                                         stubCode, firstMonitorStub, shape, name,
-                                         acctype, needsAtomize, getter, pcOffset, holder,
-                                         holderShape)
-    {}
-
-  public:
-    static inline ICGetElem_NativePrototypeCallNative *New(
-                    ICStubSpace *space, IonCode *code, ICStub *firstMonitorStub,
-                    HandleShape shape, HandlePropertyName name, AccessType acctype,
-                    bool needsAtomize, HandleFunction getter, uint32_t pcOffset,
-                    HandleObject holder, HandleShape holderShape)
-    {
-        if (!code)
-            return NULL;
-        return space->allocate<ICGetElem_NativePrototypeCallNative>(
-                        code, firstMonitorStub, shape, name, acctype, needsAtomize, getter,
-                        pcOffset, holder, holderShape);
+        return offsetof(ICGetElem_NativePrototype, holderShape_);
     }
 };
 
-class ICGetElem_NativePrototypeCallScripted : public ICGetElemNativePrototypeCallStub
-{
-    friend class ICStubSpace;
-
-    ICGetElem_NativePrototypeCallScripted(IonCode *stubCode, ICStub *firstMonitorStub,
-                                        HandleShape shape, HandlePropertyName name,
-                                        AccessType acctype, bool needsAtomize,
-                                        HandleFunction getter, uint32_t pcOffset,
-                                        HandleObject holder, HandleShape holderShape)
-      : ICGetElemNativePrototypeCallStub(GetElem_NativePrototypeCallScripted,
-                                         stubCode, firstMonitorStub, shape, name,
-                                         acctype, needsAtomize, getter, pcOffset, holder,
-                                         holderShape)
-    {}
-
-  public:
-    static inline ICGetElem_NativePrototypeCallScripted *New(
-                    ICStubSpace *space, IonCode *code, ICStub *firstMonitorStub,
-                    HandleShape shape, HandlePropertyName name, AccessType acctype,
-                    bool needsAtomize, HandleFunction getter, uint32_t pcOffset,
-                    HandleObject holder, HandleShape holderShape)
-    {
-        if (!code)
-            return NULL;
-        return space->allocate<ICGetElem_NativePrototypeCallScripted>(
-                        code, firstMonitorStub, shape, name, acctype, needsAtomize, getter,
-                        pcOffset, holder, holderShape);
-    }
-};
-
-// Compiler for GetElem_NativeSlot and GetElem_NativePrototypeSlot stubs.
+// Compiler for GetElem_Native and GetElem_NativePrototype stubs.
 class ICGetElemNativeCompiler : public ICStubCompiler
 {
     ICStub *firstMonitorStub_;
     HandleObject obj_;
     HandleObject holder_;
-    HandlePropertyName name_;
-    ICGetElemNativeStub::AccessType acctype_;
-    bool needsAtomize_;
+    HandleValue idval_;
+    bool isFixedSlot_;
     uint32_t offset_;
-    HandleFunction getter_;
-    uint32_t pcOffset_;
-
-    bool emitCallNative(MacroAssembler &masm, Register objReg);
-    bool emitCallScripted(MacroAssembler &masm, Register objReg);
+
     bool generateStubCode(MacroAssembler &masm);
 
   protected:
     virtual int32_t getKey() const {
-        return static_cast<int32_t>(kind) | (static_cast<int32_t>(needsAtomize_) << 16) |
-               (static_cast<int32_t>(acctype_) << 17);
+        return static_cast<int32_t>(kind) | (static_cast<int32_t>(isFixedSlot_) << 16);
     }
 
   public:
     ICGetElemNativeCompiler(JSContext *cx, ICStub::Kind kind, ICStub *firstMonitorStub,
-                            HandleObject obj, HandleObject holder, HandlePropertyName name,
-                            ICGetElemNativeStub::AccessType acctype, bool needsAtomize,
-                            uint32_t offset)
+                            HandleObject obj, HandleObject holder, HandleValue idval,
+                            bool isFixedSlot, uint32_t offset)
       : ICStubCompiler(cx, kind),
         firstMonitorStub_(firstMonitorStub),
         obj_(obj),
         holder_(holder),
-        name_(name),
-        acctype_(acctype),
-        needsAtomize_(needsAtomize),
-        offset_(offset),
-        getter_(NULL),
-        pcOffset_(0)
-    {}
-
-    ICGetElemNativeCompiler(JSContext *cx, ICStub::Kind kind, ICStub *firstMonitorStub,
-                            HandleObject obj, HandleObject holder, HandlePropertyName name,
-                            ICGetElemNativeStub::AccessType acctype, bool needsAtomize,
-                            HandleFunction getter, uint32_t pcOffset)
-      : ICStubCompiler(cx, kind),
-        firstMonitorStub_(firstMonitorStub),
-        obj_(obj),
-        holder_(holder),
-        name_(name),
-        acctype_(acctype),
-        needsAtomize_(needsAtomize),
-        offset_(0),
-        getter_(getter),
-        pcOffset_(pcOffset)
+        idval_(idval),
+        isFixedSlot_(isFixedSlot),
+        offset_(offset)
     {}
 
     ICStub *getStub(ICStubSpace *space) {
         RootedShape shape(cx, obj_->lastProperty());
-        if (kind == ICStub::GetElem_NativeSlot) {
+        if (kind == ICStub::GetElem_Native) {
             JS_ASSERT(obj_ == holder_);
-            return ICGetElem_NativeSlot::New(
-                    space, getStubCode(), firstMonitorStub_, shape, name_, acctype_, needsAtomize_,
-                    offset_);
+            return ICGetElem_Native::New(space, getStubCode(), firstMonitorStub_, shape, idval_,
+                                         isFixedSlot_, offset_);
         }
 
         JS_ASSERT(obj_ != holder_);
+        JS_ASSERT(kind == ICStub::GetElem_NativePrototype);
         RootedShape holderShape(cx, holder_->lastProperty());
-        if (kind == ICStub::GetElem_NativePrototypeSlot) {
-            return ICGetElem_NativePrototypeSlot::New(
-                    space, getStubCode(), firstMonitorStub_, shape, name_, acctype_, needsAtomize_,
-                    offset_, holder_, holderShape);
-        }
-
-        if (kind == ICStub::GetElem_NativePrototypeCallNative) {
-            return ICGetElem_NativePrototypeCallNative::New(
-                    space, getStubCode(), firstMonitorStub_, shape, name_, acctype_, needsAtomize_,
-                    getter_, pcOffset_, holder_, holderShape);
-        }
-
-        JS_ASSERT(kind == ICStub::GetElem_NativePrototypeCallScripted);
-        if (kind == ICStub::GetElem_NativePrototypeCallScripted) {
-            return ICGetElem_NativePrototypeCallScripted::New(
-                    space, getStubCode(), firstMonitorStub_, shape, name_, acctype_, needsAtomize_,
-                    getter_, pcOffset_, holder_, holderShape);
-        }
-
-        MOZ_ASSUME_UNREACHABLE("Invalid kind.");
-        return NULL;
+        return ICGetElem_NativePrototype::New(space, getStubCode(), firstMonitorStub_, shape,
+                                              idval_, isFixedSlot_, offset_, holder_, holderShape);
     }
 };
 
 class ICGetElem_String : public ICStub
 {
     friend class ICStubSpace;
 
     ICGetElem_String(IonCode *stubCode)
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -2517,35 +2517,21 @@ MacroAssemblerARMCompat::branchTestValue
 }
 
 void
 MacroAssemblerARMCompat::branchTestValue(Condition cond, const Address &valaddr,
                                          const ValueOperand &value, Label *label)
 {
     JS_ASSERT(cond == Equal || cond == NotEqual);
 
-    // Check payload before tag, since payload is more likely to differ.
-    if (cond == NotEqual) {
-        ma_ldr(payloadOf(valaddr), ScratchRegister);
-        branchPtr(NotEqual, ScratchRegister, value.payloadReg(), label);
-
-        ma_ldr(tagOf(valaddr), ScratchRegister);
-        branchPtr(NotEqual, ScratchRegister, value.typeReg(), label);
-
-    } else {
-        Label fallthrough;
-
-        ma_ldr(payloadOf(valaddr), ScratchRegister);
-        branchPtr(NotEqual, ScratchRegister, value.payloadReg(), &fallthrough);
-
-        ma_ldr(tagOf(valaddr), ScratchRegister);
-        branchPtr(Equal, ScratchRegister, value.typeReg(), label);
-
-        bind(&fallthrough);
-    }
+    ma_ldr(tagOf(valaddr), ScratchRegister);
+    branchPtr(cond, ScratchRegister, value.typeReg(), label);
+
+    ma_ldr(payloadOf(valaddr), ScratchRegister);
+    branchPtr(cond, ScratchRegister, value.payloadReg(), label);
 }
 
 // unboxing code
 void
 MacroAssemblerARMCompat::unboxInt32(const ValueOperand &operand, const Register &dest)
 {
     ma_mov(operand.payloadReg(), dest);
 }
--- a/js/src/jit/x86/MacroAssembler-x86.h
+++ b/js/src/jit/x86/MacroAssembler-x86.h
@@ -418,27 +418,18 @@ class MacroAssemblerX86 : public MacroAs
 
 
 
     void branchTestValue(Condition cond, const ValueOperand &value, const Value &v, Label *label);
     void branchTestValue(Condition cond, const Address &valaddr, const ValueOperand &value,
                          Label *label)
     {
         JS_ASSERT(cond == Equal || cond == NotEqual);
-        // Check payload before tag, since payload is more likely to differ.
-        if (cond == NotEqual) {
-            branchPtr(NotEqual, payloadOf(valaddr), value.payloadReg(), label);
-            branchPtr(NotEqual, tagOf(valaddr), value.typeReg(), label);
-
-        } else {
-            Label fallthrough;
-            branchPtr(NotEqual, payloadOf(valaddr), value.payloadReg(), &fallthrough);
-            branchPtr(Equal, tagOf(valaddr), value.typeReg(), label);
-            bind(&fallthrough);
-        }
+        branchPtr(cond, tagOf(valaddr), value.typeReg(), label);
+        branchPtr(cond, payloadOf(valaddr), value.payloadReg(), label);
     }
 
     void cmpPtr(Register lhs, const ImmWord rhs) {
         cmpl(lhs, Imm32(rhs.value));
     }
     void cmpPtr(Register lhs, const ImmGCPtr rhs) {
         cmpl(lhs, rhs);
     }