Bug 1244215 part 1 - Store frame header size in the frame descriptor. r=nbp
authorJan de Mooij <jdemooij@mozilla.com>
Thu, 04 Feb 2016 18:14:46 +0100
changeset 283116 fdaa29338b297a67796a2d02d1c11c8c2de167ef
parent 283115 a7f2b93dd5645b22e82e7fa5dfef6a926e46ea83
child 283117 f852c7bbd5fc539e7757e818226126750e72f878
push id29974
push usercbook@mozilla.com
push dateFri, 05 Feb 2016 10:53:43 +0000
treeherdermozilla-central@1dbe350b57b1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1244215
milestone47.0a1
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
Bug 1244215 part 1 - Store frame header size in the frame descriptor. r=nbp
js/src/asmjs/WasmStubs.cpp
js/src/jit/BaselineBailouts.cpp
js/src/jit/BaselineCompiler.cpp
js/src/jit/BaselineIC.cpp
js/src/jit/CodeGenerator.cpp
js/src/jit/IonCaches.cpp
js/src/jit/JitFrames.cpp
js/src/jit/JitFrames.h
js/src/jit/MacroAssembler-inl.h
js/src/jit/MacroAssembler.cpp
js/src/jit/MacroAssembler.h
js/src/jit/SharedIC.cpp
js/src/jit/arm/MacroAssembler-arm.cpp
js/src/jit/arm/SharedICHelpers-arm.h
js/src/jit/arm/Trampoline-arm.cpp
js/src/jit/arm64/MacroAssembler-arm64.h
js/src/jit/arm64/SharedICHelpers-arm64.h
js/src/jit/arm64/Trampoline-arm64.cpp
js/src/jit/mips32/MacroAssembler-mips32.cpp
js/src/jit/mips32/SharedICHelpers-mips32.h
js/src/jit/mips32/Trampoline-mips32.cpp
js/src/jit/mips64/MacroAssembler-mips64.cpp
js/src/jit/mips64/SharedICHelpers-mips64.h
js/src/jit/mips64/Trampoline-mips64.cpp
js/src/jit/none/SharedICHelpers-none.h
js/src/jit/shared/BaselineCompiler-shared.cpp
js/src/jit/shared/CodeGenerator-shared.cpp
js/src/jit/x64/SharedICHelpers-x64.h
js/src/jit/x64/Trampoline-x64.cpp
js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
js/src/jit/x86/SharedICHelpers-x86.h
js/src/jit/x86/Trampoline-x86.cpp
--- a/js/src/asmjs/WasmStubs.cpp
+++ b/js/src/asmjs/WasmStubs.cpp
@@ -461,17 +461,18 @@ GenerateJitExitStub(ModuleGenerator& mg,
     unsigned totalJitFrameBytes = sizeOfRetAddr + jitFrameBytes + MaybeSavedGlobalReg;
     unsigned jitFramePushed = StackDecrementForCall(masm, JitStackAlignment, totalJitFrameBytes) -
                               sizeOfRetAddr;
 
     GenerateExitPrologue(masm, jitFramePushed, ExitReason::ImportJit, offsets);
 
     // 1. Descriptor
     size_t argOffset = 0;
-    uint32_t descriptor = MakeFrameDescriptor(jitFramePushed, JitFrame_Entry);
+    uint32_t descriptor = MakeFrameDescriptor(jitFramePushed, JitFrame_Entry,
+                                              JitFrameLayout::Size());
     masm.storePtr(ImmWord(uintptr_t(descriptor)), Address(masm.getStackPointer(), argOffset));
     argOffset += sizeof(size_t);
 
     // 2. Callee
     Register callee = ABIArgGenerator::NonArgReturnReg0;   // live until call
     Register scratch = ABIArgGenerator::NonArgReturnReg1;  // repeatedly clobbered
 
     // 2.1. Get ExitDatum
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -1166,17 +1166,18 @@ InitFromBailout(JSContext* cx, HandleScr
 
         return true;
     }
 
     *callPC = pc;
 
     // Write out descriptor of BaselineJS frame.
     size_t baselineFrameDescr = MakeFrameDescriptor((uint32_t) builder.framePushed(),
-                                                    JitFrame_BaselineJS);
+                                                    JitFrame_BaselineJS,
+                                                    BaselineStubFrameLayout::Size());
     if (!builder.writeWord(baselineFrameDescr, "Descriptor"))
         return false;
 
     // Calculate and write out return address.
     // The icEntry in question MUST have an inlinable fallback stub.
     ICEntry& icEntry = baselineScript->icEntryFromPCOffset(pcOff);
     MOZ_ASSERT(IsInlinableFallback(icEntry.firstStub()->getChainFallback()));
     if (!builder.writePtr(baselineScript->returnAddressForIC(icEntry), "ReturnAddr"))
@@ -1269,17 +1270,18 @@ InitFromBailout(JSContext* cx, HandleScr
 
     // In case these arguments need to be copied on the stack again for a rectifier frame,
     // save the framePushed values here for later use.
     size_t endOfBaselineStubArgs = builder.framePushed();
 
     // Calculate frame size for descriptor.
     size_t baselineStubFrameSize = builder.framePushed() - startOfBaselineStubFrame;
     size_t baselineStubFrameDescr = MakeFrameDescriptor((uint32_t) baselineStubFrameSize,
-                                                        JitFrame_BaselineStub);
+                                                        JitFrame_BaselineStub,
+                                                        JitFrameLayout::Size());
 
     // Push actual argc
     if (!builder.writeWord(actualArgc, "ActualArgc"))
         return false;
 
     // Push callee token (must be a JS Function)
     Value callee;
     if (needToSaveArgs) {
@@ -1383,17 +1385,18 @@ InitFromBailout(JSContext* cx, HandleScr
         builder.pointerAtStackOffset<uint8_t>(builder.framePushed() - endOfBaselineStubArgs);
     JitSpew(JitSpew_BaselineBailouts, "      MemCpy from %p", stubArgsEnd.get());
     memcpy(builder.pointerAtStackOffset<uint8_t>(0).get(), stubArgsEnd.get(),
            (actualArgc + 1) * sizeof(Value));
 
     // Calculate frame size for descriptor.
     size_t rectifierFrameSize = builder.framePushed() - startOfRectifierFrame;
     size_t rectifierFrameDescr = MakeFrameDescriptor((uint32_t) rectifierFrameSize,
-                                                     JitFrame_Rectifier);
+                                                     JitFrame_Rectifier,
+                                                     JitFrameLayout::Size());
 
     // Push actualArgc
     if (!builder.writeWord(actualArgc, "ActualArgc"))
         return false;
 
     // Push calleeToken again.
     if (!builder.writePtr(CalleeToToken(calleeFun, JSOp(*pc) == JSOP_NEW), "CalleeToken"))
         return false;
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -4118,17 +4118,17 @@ BaselineCompiler::emit_JSOP_RESUME()
     // Push |undefined| for |this|.
     masm.pushValue(UndefinedValue());
 
     // Update BaselineFrame frameSize field and create the frame descriptor.
     masm.computeEffectiveAddress(Address(BaselineFrameReg, BaselineFrame::FramePointerOffset),
                                  scratch2);
     masm.subStackPtrFrom(scratch2);
     masm.store32(scratch2, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
-    masm.makeFrameDescriptor(scratch2, JitFrame_BaselineJS);
+    masm.makeFrameDescriptor(scratch2, JitFrame_BaselineJS, JitFrameLayout::Size());
 
     masm.Push(Imm32(0)); // actual argc
 
     // Duplicate PushCalleeToken with a variable instead.
     masm.orPtr(constructing, callee);
     masm.Push(callee);
     masm.Push(scratch2); // frame descriptor
 
@@ -4252,17 +4252,17 @@ BaselineCompiler::emit_JSOP_RESUME()
         pushArg(scratch2);
 
         JitCode* code = cx->runtime()->jitRuntime()->getVMWrapper(GeneratorThrowInfo);
         if (!code)
             return false;
 
         // Create the frame descriptor.
         masm.subStackPtrFrom(scratch1);
-        masm.makeFrameDescriptor(scratch1, JitFrame_BaselineJS);
+        masm.makeFrameDescriptor(scratch1, JitFrame_BaselineJS, ExitFrameLayout::Size());
 
         // Push the frame descriptor and a dummy return address (it doesn't
         // matter what we push here, frame iterators will use the frame pc
         // set in jit::GeneratorThrowOrClose).
         masm.push(scratch1);
 
         // On ARM64, the callee will push the return address.
 #ifndef JS_CODEGEN_ARM64
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -1861,17 +1861,17 @@ ICGetElemNativeCompiler<T>::emitCallScri
     regs.add(objReg);
 
     Register callee = regs.takeAny();
     masm.loadPtr(Address(ICStubReg, ICGetElemNativeGetterStub<T>::offsetOfGetter()), callee);
 
     // Push argc, callee, and descriptor.
     {
         Register callScratch = regs.takeAny();
-        EmitBaselineCreateStubFrameDescriptor(masm, callScratch);
+        EmitBaselineCreateStubFrameDescriptor(masm, callScratch, JitFrameLayout::Size());
         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);
@@ -5321,17 +5321,17 @@ ICSetProp_CallScripted::Compiler::genera
     // Setter is called with the new value as the only argument, and |obj| as thisv.
     // Note that we use Push, not push, so that callJit will align the stack
     // properly on ARM.
 
     // To Push R1, read it off of the stowed values on stack.
     // Stack: [ ..., R0, R1, ..STUBFRAME-HEADER.., padding? ]
     masm.PushValue(Address(BaselineFrameReg, STUB_FRAME_SIZE));
     masm.Push(R0);
-    EmitBaselineCreateStubFrameDescriptor(masm, scratch);
+    EmitBaselineCreateStubFrameDescriptor(masm, scratch, JitFrameLayout::Size());
     masm.Push(Imm32(1));  // ActualArgc is 1
     masm.Push(callee);
     masm.Push(scratch);
 
     // Handle arguments underflow.
     Label noUnderflow;
     masm.load16ZeroExtend(Address(callee, JSFunction::offsetOfNargs()), scratch);
     masm.branch32(Assembler::BelowOrEqual, scratch, Imm32(1), &noUnderflow);
@@ -6844,17 +6844,17 @@ ICCallScriptedCompiler::generateStubCode
     else
         pushCallArguments(masm, regs, argcReg, /* isJitCall = */ true, isConstructing_);
 
     // The callee is on top of the stack. Pop and unbox it.
     ValueOperand val = regs.takeAnyValue();
     masm.popValue(val);
     callee = masm.extractObject(val, ExtractTemp0);
 
-    EmitBaselineCreateStubFrameDescriptor(masm, scratch);
+    EmitBaselineCreateStubFrameDescriptor(masm, scratch, JitFrameLayout::Size());
 
     // Note that we use Push, not push, so that callJit will align the stack
     // properly on ARM.
     masm.Push(argcReg);
     masm.PushCalleeToken(callee, isConstructing_);
     masm.Push(scratch);
 
     // Handle arguments underflow.
@@ -7147,17 +7147,17 @@ ICCall_Native::Compiler::generateStubCod
     // Initialize vp.
     Register vpReg = regs.takeAny();
     masm.moveStackPtrTo(vpReg);
 
     // Construct a native exit frame.
     masm.push(argcReg);
 
     Register scratch = regs.takeAny();
-    EmitBaselineCreateStubFrameDescriptor(masm, scratch);
+    EmitBaselineCreateStubFrameDescriptor(masm, scratch, ExitFrameLayout::Size());
     masm.push(scratch);
     masm.push(ICTailCallReg);
     masm.enterFakeExitFrameForNative(isConstructing_);
 
     // Execute call.
     masm.setupUnalignedABICall(scratch);
     masm.loadJSContext(scratch);
     masm.passABIArg(scratch);
@@ -7245,17 +7245,17 @@ ICCall_ClassHook::Compiler::generateStub
 
     // Initialize vp.
     Register vpReg = regs.takeAny();
     masm.moveStackPtrTo(vpReg);
 
     // Construct a native exit frame.
     masm.push(argcReg);
 
-    EmitBaselineCreateStubFrameDescriptor(masm, scratch);
+    EmitBaselineCreateStubFrameDescriptor(masm, scratch, ExitFrameLayout::Size());
     masm.push(scratch);
     masm.push(ICTailCallReg);
     masm.enterFakeExitFrameForNative(isConstructing_);
 
     // Execute call.
     masm.setupUnalignedABICall(scratch);
     masm.loadJSContext(scratch);
     masm.passABIArg(scratch);
@@ -7332,17 +7332,17 @@ ICCall_ScriptedApplyArray::Compiler::gen
     // Can't fail after this, so it's ok to clobber argcReg.
 
     // Push actual argument 0 as |thisv| for call.
     masm.pushValue(Address(BaselineFrameReg, STUB_FRAME_SIZE + sizeof(Value)));
 
     // All pushes after this use Push instead of push to make sure ARM can align
     // stack properly for call.
     Register scratch = regs.takeAny();
-    EmitBaselineCreateStubFrameDescriptor(masm, scratch);
+    EmitBaselineCreateStubFrameDescriptor(masm, scratch, JitFrameLayout::Size());
 
     // Reload argc from length of array.
     masm.extractObject(arrayVal, argcReg);
     masm.loadPtr(Address(argcReg, NativeObject::offsetOfElements()), argcReg);
     masm.load32(Address(argcReg, ObjectElements::offsetOfInitializedLength()), argcReg);
 
     masm.Push(argcReg);
     masm.Push(target);
@@ -7433,17 +7433,17 @@ ICCall_ScriptedApplyArguments::Compiler:
     // Can't fail after this, so it's ok to clobber argcReg.
 
     // Push actual argument 0 as |thisv| for call.
     masm.pushValue(Address(BaselineFrameReg, STUB_FRAME_SIZE + sizeof(Value)));
 
     // All pushes after this use Push instead of push to make sure ARM can align
     // stack properly for call.
     Register scratch = regs.takeAny();
-    EmitBaselineCreateStubFrameDescriptor(masm, scratch);
+    EmitBaselineCreateStubFrameDescriptor(masm, scratch, JitFrameLayout::Size());
 
     masm.loadPtr(Address(BaselineFrameReg, 0), argcReg);
     masm.loadPtr(Address(argcReg, BaselineFrame::offsetOfNumActualArgs()), argcReg);
     masm.Push(argcReg);
     masm.Push(target);
     masm.Push(scratch);
 
     // Load nargs into scratch for underflow check, and then load jitcode pointer into target.
@@ -7566,17 +7566,17 @@ ICCall_ScriptedFunCall::Compiler::genera
     masm.pushValue(UndefinedValue());
 
     masm.bind(&done);
 
     // Unbox scripted callee.
     callee = masm.extractObject(val, ExtractTemp0);
 
     Register scratch = regs.takeAny();
-    EmitBaselineCreateStubFrameDescriptor(masm, scratch);
+    EmitBaselineCreateStubFrameDescriptor(masm, scratch, JitFrameLayout::Size());
 
     // Note that we use Push, not push, so that callJit will align the stack
     // properly on ARM.
     masm.Push(argcReg);
     masm.Push(callee);
     masm.Push(scratch);
 
     // Handle arguments underflow.
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -2022,17 +2022,18 @@ CodeGenerator::emitSharedStub(ICStub::Ki
 #ifdef JS_USE_LINK_REGISTER
     // Some architectures don't push the return address on the stack but
     // use the link register. In that case the stack isn't aligned. Push
     // to make sure we are aligned.
     masm.Push(Imm32(0));
 #endif
 
     // Create descriptor signifying end of Ion frame.
-    uint32_t descriptor = MakeFrameDescriptor(masm.framePushed(), JitFrame_IonJS);
+    uint32_t descriptor = MakeFrameDescriptor(masm.framePushed(), JitFrame_IonJS,
+                                              JitStubFrameLayout::Size());
     masm.Push(Imm32(descriptor));
 
     // Call into the stubcode.
     CodeOffset patchOffset;
     IonICEntry entry(script->pcToOffset(pc), ICEntry::Kind_Op, script);
     EmitCallIC(&patchOffset, masm);
     entry.setReturnOffset(CodeOffset(masm.currentOffset()));
 
@@ -3439,17 +3440,18 @@ CodeGenerator::visitCallGeneric(LCallGen
 
     // Load script jitcode.
     masm.loadBaselineOrIonRaw(objreg, objreg, &invoke);
 
     // Nestle the StackPointer up to the argument vector.
     masm.freeStack(unusedStack);
 
     // Construct the IonFramePrefix.
-    uint32_t descriptor = MakeFrameDescriptor(masm.framePushed(), JitFrame_IonJS);
+    uint32_t descriptor = MakeFrameDescriptor(masm.framePushed(), JitFrame_IonJS,
+                                              JitFrameLayout::Size());
     masm.Push(Imm32(call->numActualArgs()));
     masm.PushCalleeToken(calleereg, call->mir()->isConstructing());
     masm.Push(Imm32(descriptor));
 
     // Check whether the provided arguments satisfy target argc.
     // We cannot have lowered to LCallGeneric with a known target. Assert that we didn't
     // add any undefineds in IonBuilder. NB: MCall::numStackArgs includes |this|.
     DebugOnly<unsigned> numNonArgsOnStack = 1 + call->isConstructing();
@@ -3553,17 +3555,18 @@ CodeGenerator::visitCallKnown(LCallKnown
         masm.loadBaselineOrIonRaw(objreg, objreg, &uncompiled);
     else
         masm.loadBaselineOrIonNoArgCheck(objreg, objreg, &uncompiled);
 
     // Nestle the StackPointer up to the argument vector.
     masm.freeStack(unusedStack);
 
     // Construct the IonFramePrefix.
-    uint32_t descriptor = MakeFrameDescriptor(masm.framePushed(), JitFrame_IonJS);
+    uint32_t descriptor = MakeFrameDescriptor(masm.framePushed(), JitFrame_IonJS,
+                                              JitFrameLayout::Size());
     masm.Push(Imm32(call->numActualArgs()));
     masm.PushCalleeToken(calleereg, call->mir()->isConstructing());
     masm.Push(Imm32(descriptor));
 
     // Finally call the function in objreg.
     uint32_t callOffset = masm.callJit(objreg);
     markSafepointAt(callOffset, call);
 
@@ -3851,17 +3854,17 @@ CodeGenerator::emitApplyGeneric(T* apply
     masm.loadBaselineOrIonRaw(objreg, objreg, &invoke);
 
     // Call with an Ion frame or a rectifier frame.
     {
         // Create the frame descriptor.
         unsigned pushed = masm.framePushed();
         Register stackSpace = extraStackSpace;
         masm.addPtr(Imm32(pushed), stackSpace);
-        masm.makeFrameDescriptor(stackSpace, JitFrame_IonJS);
+        masm.makeFrameDescriptor(stackSpace, JitFrame_IonJS, JitFrameLayout::Size());
 
         masm.Push(argcreg);
         masm.Push(calleereg);
         masm.Push(stackSpace); // descriptor
 
         Label underflow, rejoin;
 
         // Check whether the provided arguments satisfy target argc.
@@ -6751,35 +6754,26 @@ JitRuntime::generateLazyLinkStub(JSConte
     MacroAssembler masm(cx);
 #ifdef JS_USE_LINK_REGISTER
     masm.pushReturnAddress();
 #endif
 
     AllocatableGeneralRegisterSet regs(GeneralRegisterSet::Volatile());
     Register temp0 = regs.takeAny();
 
-    // The caller did not push an exit frame on the stack, it pushed a
-    // JitFrameLayout.  We modify the descriptor to be a valid exit frame and
-    // restore it once the lazy link is complete.
-    Address descriptor(masm.getStackPointer(), CommonFrameLayout::offsetOfDescriptor());
-    size_t convertToExitFrame = JitFrameLayout::Size() - ExitFrameLayout::Size();
-    masm.addPtr(Imm32(convertToExitFrame << FRAMESIZE_SHIFT), descriptor);
-
     masm.enterFakeExitFrame(LazyLinkExitFrameLayoutToken);
     masm.PushStubCode();
 
     masm.setupUnalignedABICall(temp0);
     masm.loadJSContext(temp0);
     masm.passABIArg(temp0);
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, LazyLinkTopActivation));
 
     masm.leaveExitFrame(/* stub code */ sizeof(JitCode*));
 
-    masm.addPtr(Imm32(- (convertToExitFrame << FRAMESIZE_SHIFT)), descriptor);
-
 #ifdef JS_USE_LINK_REGISTER
     // Restore the return address such that the emitPrologue function of the
     // CodeGenerator can push it back on the stack with pushReturnAddress.
     masm.pop(lr);
 #endif
     masm.jump(ReturnReg);
 
     Linker linker(masm);
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -1018,17 +1018,18 @@ EmitGetterCall(JSContext* cx, MacroAssem
         masm.adjustStack(IonOOLPropertyOpExitFrameLayout::Size());
     } else {
         MOZ_ASSERT(IsCacheableGetPropCallScripted(obj, holder, shape));
 
         JSFunction* target = &shape->getterValue().toObject().as<JSFunction>();
         uint32_t framePushedBefore = masm.framePushed();
 
         // Construct IonAccessorICFrameLayout.
-        uint32_t descriptor = MakeFrameDescriptor(masm.framePushed(), JitFrame_IonJS);
+        uint32_t descriptor = MakeFrameDescriptor(masm.framePushed(), JitFrame_IonJS,
+                                                  IonAccessorICFrameLayout::Size());
         attacher.pushStubCodePointer(masm);
         masm.Push(Imm32(descriptor));
         masm.Push(ImmPtr(returnAddr));
 
         // The JitFrameLayout pushed below will be aligned to JitStackAlignment,
         // so we just have to make sure the stack is aligned after we push the
         // |this| + argument Values.
         uint32_t argSize = (target->nargs() + 1) * sizeof(Value);
@@ -1038,17 +1039,18 @@ EmitGetterCall(JSContext* cx, MacroAssem
         masm.reserveStack(padding);
 
         for (size_t i = 0; i < target->nargs(); i++)
             masm.Push(UndefinedValue());
         masm.Push(TypedOrValueRegister(MIRType_Object, AnyRegister(object)));
 
         masm.movePtr(ImmGCPtr(target), scratchReg);
 
-        descriptor = MakeFrameDescriptor(argSize + padding, JitFrame_IonAccessorIC);
+        descriptor = MakeFrameDescriptor(argSize + padding, JitFrame_IonAccessorIC,
+                                         JitFrameLayout::Size());
         masm.Push(Imm32(0)); // argc
         masm.Push(scratchReg);
         masm.Push(Imm32(descriptor));
 
         // Check stack alignment. Add sizeof(uintptr_t) for the return address.
         MOZ_ASSERT(((masm.framePushed() + sizeof(uintptr_t)) % JitStackAlignment) == 0);
 
         // The getter has JIT code now and we will only discard the getter's JIT
@@ -2837,17 +2839,18 @@ GenerateCallSetter(JSContext* cx, IonScr
         masm.adjustStack(IonOOLSetterOpExitFrameLayout::Size());
     } else {
         MOZ_ASSERT(IsCacheableSetPropCallScripted(obj, holder, shape));
 
         JSFunction* target = &shape->setterValue().toObject().as<JSFunction>();
         uint32_t framePushedBefore = masm.framePushed();
 
         // Construct IonAccessorICFrameLayout.
-        uint32_t descriptor = MakeFrameDescriptor(masm.framePushed(), JitFrame_IonJS);
+        uint32_t descriptor = MakeFrameDescriptor(masm.framePushed(), JitFrame_IonJS,
+                                                  IonAccessorICFrameLayout::Size());
         attacher.pushStubCodePointer(masm);
         masm.Push(Imm32(descriptor));
         masm.Push(ImmPtr(returnAddr));
 
         // The JitFrameLayout pushed below will be aligned to JitStackAlignment,
         // so we just have to make sure the stack is aligned after we push the
         // |this| + argument Values.
         uint32_t numArgs = Max(size_t(1), target->nargs());
@@ -2859,17 +2862,18 @@ GenerateCallSetter(JSContext* cx, IonScr
 
         for (size_t i = 1; i < target->nargs(); i++)
             masm.Push(UndefinedValue());
         masm.Push(value);
         masm.Push(TypedOrValueRegister(MIRType_Object, AnyRegister(object)));
 
         masm.movePtr(ImmGCPtr(target), tempReg);
 
-        descriptor = MakeFrameDescriptor(argSize + padding, JitFrame_IonAccessorIC);
+        descriptor = MakeFrameDescriptor(argSize + padding, JitFrame_IonAccessorIC,
+                                         JitFrameLayout::Size());
         masm.Push(Imm32(1)); // argc
         masm.Push(tempReg);
         masm.Push(Imm32(descriptor));
 
         // Check stack alignment. Add sizeof(uintptr_t) for the return address.
         MOZ_ASSERT(((masm.framePushed() + sizeof(uintptr_t)) % JitStackAlignment) == 0);
 
         // The setter has JIT code now and we will only discard the setter's JIT
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -246,63 +246,20 @@ JitFrameIterator::baselineScriptAndPc(JS
 }
 
 Value*
 JitFrameIterator::actualArgs() const
 {
     return jsFrame()->argv() + 1;
 }
 
-static inline size_t
-SizeOfFramePrefix(FrameType type)
-{
-    switch (type) {
-      case JitFrame_Entry:
-        return EntryFrameLayout::Size();
-      case JitFrame_BaselineJS:
-      case JitFrame_IonJS:
-      case JitFrame_Bailout:
-      case JitFrame_Unwound_BaselineJS:
-      case JitFrame_Unwound_IonJS:
-        return JitFrameLayout::Size();
-      case JitFrame_BaselineStub:
-      case JitFrame_Unwound_BaselineStub:
-        return BaselineStubFrameLayout::Size();
-      case JitFrame_IonStub:
-      case JitFrame_Unwound_IonStub:
-        return JitStubFrameLayout::Size();
-      case JitFrame_Rectifier:
-        return RectifierFrameLayout::Size();
-      case JitFrame_Unwound_Rectifier:
-        return IonUnwoundRectifierFrameLayout::Size();
-      case JitFrame_Exit:
-      case JitFrame_LazyLink:
-        return ExitFrameLayout::Size();
-      case JitFrame_IonAccessorIC:
-      case JitFrame_Unwound_IonAccessorIC:
-        return IonAccessorICFrameLayout::Size();
-    }
-
-    MOZ_CRASH("unknown frame type");
-}
-
 uint8_t*
 JitFrameIterator::prevFp() const
 {
-    size_t currentSize = SizeOfFramePrefix(type_);
-    // This quick fix must be removed as soon as bug 717297 land.  This is
-    // needed because the descriptor size of JS-to-JS frame which is just after
-    // a Rectifier frame should not change. (cf EnsureExitFrame function)
-    if (isFakeExitFrame()) {
-        MOZ_ASSERT(SizeOfFramePrefix(JitFrame_BaselineJS) ==
-                   SizeOfFramePrefix(JitFrame_IonJS));
-        currentSize = SizeOfFramePrefix(JitFrame_IonJS);
-    }
-    currentSize += current()->prevFrameLocalSize();
-    return current_ + currentSize;
+    return current_ + current()->prevFrameLocalSize() + current()->headerSize();
 }
 
 JitFrameIterator&
 JitFrameIterator::operator++()
 {
     MOZ_ASSERT(type_ != JitFrame_Entry);
 
     frameSize_ = prevFrameLocalSize();
--- a/js/src/jit/JitFrames.h
+++ b/js/src/jit/JitFrames.h
@@ -180,22 +180,29 @@ class OsiIndex
 //      ...       \ - These are jsvals
 //      arg0      /
 //   -3 this    _/
 //   -2 callee
 //   -1 descriptor
 //    0 returnAddress
 //   .. locals ..
 
-// The descriptor is organized into three sections:
-// [ frame size | has cached saved frame bit | frame type ]
+// The descriptor is organized into four sections:
+// [ frame size | has cached saved frame bit | frame header size | frame type ]
 // < highest - - - - - - - - - - - - - - lowest >
-static const uintptr_t FRAMESIZE_SHIFT = 5;
-static const uintptr_t HASCACHEDSAVEDFRAME_BIT = 1 << 4;
 static const uintptr_t FRAMETYPE_BITS = 4;
+static const uintptr_t FRAME_HEADER_SIZE_SHIFT = FRAMETYPE_BITS;
+static const uintptr_t FRAME_HEADER_SIZE_BITS = 3;
+static const uintptr_t FRAME_HEADER_SIZE_MASK = (1 << FRAME_HEADER_SIZE_BITS) - 1;
+static const uintptr_t HASCACHEDSAVEDFRAME_BIT = 1 << (FRAMETYPE_BITS + FRAME_HEADER_SIZE_BITS);
+static const uintptr_t FRAMESIZE_SHIFT = FRAMETYPE_BITS +
+                                         FRAME_HEADER_SIZE_BITS +
+                                         1 /* cached saved frame bit */;
+static const uintptr_t FRAMESIZE_BITS = 32 - FRAMESIZE_SHIFT;
+static const uintptr_t FRAMESIZE_MASK = (1 << FRAMESIZE_BITS) - 1;
 
 // Ion frames have a few important numbers associated with them:
 //      Local depth:    The number of bytes required to spill local variables.
 //      Argument depth: The number of bytes required to push arguments and make
 //                      a function call.
 //      Slack:          A frame may temporarily use extra stack to resolve cycles.
 //
 // The (local + argument) depth determines the "fixed frame size". The fixed
@@ -281,19 +288,31 @@ void MarkJitActivations(JSRuntime* rt, J
 void MarkIonCompilerRoots(JSTracer* trc);
 
 JSCompartment*
 TopmostIonActivationCompartment(JSRuntime* rt);
 
 void UpdateJitActivationsForMinorGC(JSRuntime* rt, JSTracer* trc);
 
 static inline uint32_t
-MakeFrameDescriptor(uint32_t frameSize, FrameType type)
+EncodeFrameHeaderSize(size_t headerSize)
 {
-    return 0 | (frameSize << FRAMESIZE_SHIFT) | type;
+    MOZ_ASSERT((headerSize % sizeof(uintptr_t)) == 0);
+
+    uint32_t headerSizeWords = headerSize / sizeof(uintptr_t);
+    MOZ_ASSERT(headerSizeWords <= FRAME_HEADER_SIZE_MASK);
+    return headerSizeWords;
+}
+
+static inline uint32_t
+MakeFrameDescriptor(uint32_t frameSize, FrameType type, uint32_t headerSize)
+{
+    MOZ_ASSERT(headerSize < FRAMESIZE_MASK);
+    headerSize = EncodeFrameHeaderSize(headerSize);
+    return 0 | (frameSize << FRAMESIZE_SHIFT) | (headerSize << FRAME_HEADER_SIZE_SHIFT) | type;
 }
 
 // Returns the JSScript associated with the topmost JIT frame.
 inline JSScript*
 GetTopJitJSScript(JSContext* cx)
 {
     JitFrameIterator iter(cx);
     MOZ_ASSERT(iter.type() == JitFrame_Exit);
@@ -343,18 +362,19 @@ class CommonFrameLayout
     }
     void changePrevType(FrameType type) {
         descriptor_ &= ~FrameTypeMask;
         descriptor_ |= type;
     }
     size_t prevFrameLocalSize() const {
         return descriptor_ >> FRAMESIZE_SHIFT;
     }
-    void setFrameDescriptor(size_t size, FrameType type) {
-        descriptor_ = 0 | (size << FRAMESIZE_SHIFT) | type;
+    size_t headerSize() const {
+        return sizeof(uintptr_t) *
+            ((descriptor_ >> FRAME_HEADER_SIZE_SHIFT) & FRAME_HEADER_SIZE_MASK);
     }
     bool hasCachedSavedFrame() const {
         return descriptor_ & HASCACHEDSAVEDFRAME_BIT;
     }
     void setHasCachedSavedFrame() {
         descriptor_ |= HASCACHEDSAVEDFRAME_BIT;
     }
     uint8_t* returnAddress() const {
--- a/js/src/jit/MacroAssembler-inl.h
+++ b/js/src/jit/MacroAssembler-inl.h
@@ -203,29 +203,31 @@ uint32_t
 MacroAssembler::callJit(JitCode* callee)
 {
     AutoProfilerCallInstrumentation profiler(*this);
     call(callee);
     return currentOffset();
 }
 
 void
-MacroAssembler::makeFrameDescriptor(Register frameSizeReg, FrameType type)
+MacroAssembler::makeFrameDescriptor(Register frameSizeReg, FrameType type, uint32_t headerSize)
 {
     // See JitFrames.h for a description of the frame descriptor format.
+    // The saved-frame bit is zero for new frames. See js::SavedStacks.
 
     lshiftPtr(Imm32(FRAMESIZE_SHIFT), frameSizeReg);
-    // The saved-frame bit is zero for new frames. See js::SavedStacks.
-    orPtr(Imm32(type), frameSizeReg);
+
+    headerSize = EncodeFrameHeaderSize(headerSize);
+    orPtr(Imm32((headerSize << FRAME_HEADER_SIZE_SHIFT) | type), frameSizeReg);
 }
 
 void
-MacroAssembler::pushStaticFrameDescriptor(FrameType type)
+MacroAssembler::pushStaticFrameDescriptor(FrameType type, uint32_t headerSize)
 {
-    uint32_t descriptor = MakeFrameDescriptor(framePushed(), type);
+    uint32_t descriptor = MakeFrameDescriptor(framePushed(), type, headerSize);
     Push(Imm32(descriptor));
 }
 
 void
 MacroAssembler::PushCalleeToken(Register callee, bool constructing)
 {
     if (constructing) {
         orPtr(Imm32(CalleeToken_FunctionConstructing), callee);
@@ -253,17 +255,17 @@ MacroAssembler::loadFunctionFromCalleeTo
     andPtr(Imm32(uint32_t(CalleeTokenMask)), dest);
 }
 
 uint32_t
 MacroAssembler::buildFakeExitFrame(Register scratch)
 {
     mozilla::DebugOnly<uint32_t> initialDepth = framePushed();
 
-    pushStaticFrameDescriptor(JitFrame_IonJS);
+    pushStaticFrameDescriptor(JitFrame_IonJS, ExitFrameLayout::Size());
     uint32_t retAddr = pushFakeReturnAddress(scratch);
 
     MOZ_ASSERT(framePushed() == initialDepth + ExitFrameLayout::Size());
     return retAddr;
 }
 
 // ===============================================================
 // Exit frame footer.
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -1313,17 +1313,17 @@ MacroAssembler::generateBailoutTail(Regi
             store32(temp, Address(getStackPointer(), 0));
             jump(&copyLoop);
             bind(&endOfCopy);
         }
 
         // Enter exit frame for the FinishBailoutToBaseline call.
         loadPtr(Address(bailoutInfo, offsetof(BaselineBailoutInfo, resumeFramePtr)), temp);
         load32(Address(temp, BaselineFrame::reverseOffsetOfFrameSize()), temp);
-        makeFrameDescriptor(temp, JitFrame_BaselineJS);
+        makeFrameDescriptor(temp, JitFrame_BaselineJS, ExitFrameLayout::Size());
         push(temp);
         push(Address(bailoutInfo, offsetof(BaselineBailoutInfo, resumeAddr)));
         // No GC things to mark on the stack, push a bare token.
         enterFakeExitFrame(ExitFrameLayoutBareToken);
 
         // If monitorStub is non-null, handle resumeAddr appropriately.
         Label noMonitor;
         Label done;
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -614,20 +614,20 @@ class MacroAssembler : public MacroAssem
     // the return address to index the safepoints, which are used to list all
     // live registers.
     inline uint32_t callJitNoProfiler(Register callee);
     inline uint32_t callJit(Register callee);
     inline uint32_t callJit(JitCode* code);
 
     // The frame descriptor is the second field of all Jit frames, pushed before
     // calling the Jit function.  It is a composite value defined in JitFrames.h
-    inline void makeFrameDescriptor(Register frameSizeReg, FrameType type);
+    inline void makeFrameDescriptor(Register frameSizeReg, FrameType type, uint32_t headerSize);
 
     // Push the frame descriptor, based on the statically known framePushed.
-    inline void pushStaticFrameDescriptor(FrameType type);
+    inline void pushStaticFrameDescriptor(FrameType type, uint32_t headerSize);
 
     // Push the callee token of a JSFunction which pointer is stored in the
     // |callee| register. The callee token is packed with a |constructing| flag
     // which correspond to the fact that the JS function is called with "new" or
     // not.
     inline void PushCalleeToken(Register callee, bool constructing);
 
     // Unpack a callee token located at the |token| address, and return the
--- a/js/src/jit/SharedIC.cpp
+++ b/js/src/jit/SharedIC.cpp
@@ -3623,17 +3623,17 @@ ICGetProp_CallScripted::Compiler::genera
     // Align the stack such that the JitFrameLayout is aligned on
     // JitStackAlignment.
     masm.alignJitStackBasedOnNArgs(0);
 
     // Getter is called with 0 arguments, just |obj| as thisv.
     // Note that we use Push, not push, so that callJit will align the stack
     // properly on ARM.
     masm.Push(R0);
-    EmitBaselineCreateStubFrameDescriptor(masm, scratch);
+    EmitBaselineCreateStubFrameDescriptor(masm, scratch, JitFrameLayout::Size());
     masm.Push(Imm32(0));  // ActualArgc is 0
     masm.Push(callee);
     masm.Push(scratch);
 
     // Handle arguments underflow.
     Label noUnderflow;
     masm.load16ZeroExtend(Address(callee, JSFunction::offsetOfNargs()), scratch);
     masm.branch32(Assembler::Equal, scratch, Imm32(0), &noUnderflow);
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -1818,17 +1818,18 @@ MacroAssemblerARM::ma_vstr(VFPRegister s
     as_add(scratch, base, lsl(index, shift), LeaveCC, cc);
     return ma_vstr(src, Address(scratch, offset), cc);
 }
 
 bool
 MacroAssemblerARMCompat::buildOOLFakeExitFrame(void* fakeReturnAddr)
 {
     DebugOnly<uint32_t> initialDepth = asMasm().framePushed();
-    uint32_t descriptor = MakeFrameDescriptor(asMasm().framePushed(), JitFrame_IonJS);
+    uint32_t descriptor = MakeFrameDescriptor(asMasm().framePushed(), JitFrame_IonJS,
+                                              ExitFrameLayout::Size());
 
     asMasm().Push(Imm32(descriptor)); // descriptor_
     asMasm().Push(ImmPtr(fakeReturnAddr));
 
     return true;
 }
 
 void
--- a/js/src/jit/arm/SharedICHelpers-arm.h
+++ b/js/src/jit/arm/SharedICHelpers-arm.h
@@ -94,17 +94,17 @@ EmitBaselineTailCallVM(JitCode* target, 
     masm.ma_sub(r0, Imm32(argSize), r1);
     masm.store32(r1, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
 
     // Push frame descriptor and perform the tail call.
     // ICTailCallReg (lr) already contains the return address (as we keep
     // it there through the stub calls), but the VMWrapper code being called
     // expects the return address to also be pushed on the stack.
     MOZ_ASSERT(ICTailCallReg == lr);
-    masm.makeFrameDescriptor(r0, JitFrame_BaselineJS);
+    masm.makeFrameDescriptor(r0, JitFrame_BaselineJS, ExitFrameLayout::Size());
     masm.push(r0);
     masm.push(lr);
     masm.branch(target);
 }
 
 inline void
 EmitIonTailCallVM(JitCode* target, MacroAssembler& masm, uint32_t stackSize)
 {
@@ -116,46 +116,47 @@ EmitIonTailCallVM(JitCode* target, Macro
     masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), r0);
     masm.add32(Imm32(stackSize + JitStubFrameLayout::Size() - sizeof(intptr_t)), r0);
 
     // Push frame descriptor and perform the tail call.
     // ICTailCallReg (lr) already contains the return address (as we keep
     // it there through the stub calls), but the VMWrapper code being called
     // expects the return address to also be pushed on the stack.
     MOZ_ASSERT(ICTailCallReg == lr);
-    masm.makeFrameDescriptor(r0, JitFrame_IonJS);
+    masm.makeFrameDescriptor(r0, JitFrame_IonJS, ExitFrameLayout::Size());
     masm.push(r0);
     masm.push(lr);
     masm.branch(target);
 }
 
 inline void
-EmitBaselineCreateStubFrameDescriptor(MacroAssembler& masm, Register reg)
+EmitBaselineCreateStubFrameDescriptor(MacroAssembler& masm, Register reg, uint32_t headerSize)
 {
     // Compute stub frame size. We have to add two pointers: the stub reg and
     // previous frame pointer pushed by EmitEnterStubFrame.
     masm.mov(BaselineFrameReg, reg);
     masm.ma_add(Imm32(sizeof(void*) * 2), reg);
     masm.ma_sub(BaselineStackReg, reg);
 
-    masm.makeFrameDescriptor(reg, JitFrame_BaselineStub);
+    masm.makeFrameDescriptor(reg, JitFrame_BaselineStub, headerSize);
 }
 
 inline void
 EmitBaselineCallVM(JitCode* target, MacroAssembler& masm)
 {
-    EmitBaselineCreateStubFrameDescriptor(masm, r0);
+    EmitBaselineCreateStubFrameDescriptor(masm, r0, ExitFrameLayout::Size());
     masm.push(r0);
     masm.call(target);
 }
 
 inline void
 EmitIonCallVM(JitCode* target, size_t stackSlots, MacroAssembler& masm)
 {
-    uint32_t descriptor = MakeFrameDescriptor(masm.framePushed(), JitFrame_IonStub);
+    uint32_t descriptor = MakeFrameDescriptor(masm.framePushed(), JitFrame_IonStub,
+                                              ExitFrameLayout::Size());
     masm.Push(Imm32(descriptor));
     masm.callJit(target);
 
     // Remove rest of the frame left on the stack. We remove the return address
     // which is implicitly popped when returning.
     size_t framePop = sizeof(ExitFrameLayout) - sizeof(void*);
 
     // Pop arguments from framePushed.
@@ -177,17 +178,17 @@ EmitBaselineEnterStubFrame(MacroAssemble
     masm.ma_sub(BaselineStackReg, scratch);
 
     masm.store32(scratch, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
 
     // Note: when making changes here, don't forget to update STUB_FRAME_SIZE if
     // needed.
 
     // Push frame descriptor and return address.
-    masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS);
+    masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS, BaselineStubFrameLayout::Size());
     masm.Push(scratch);
     masm.Push(ICTailCallReg);
 
     // Save old frame pointer, stack pointer and stub reg.
     masm.Push(ICStubReg);
     masm.Push(BaselineFrameReg);
     masm.mov(BaselineStackReg, BaselineFrameReg);
 
--- a/js/src/jit/arm/Trampoline-arm.cpp
+++ b/js/src/jit/arm/Trampoline-arm.cpp
@@ -200,17 +200,17 @@ JitRuntime::generateEnterJIT(JSContext* 
         // BIG FAT WARNING: this loads both r6 and r7.
         aasm->as_extdtr(IsLoad,  64, true, PostIndex, r6, EDtrAddr(r2, EDtrOffImm(8)));
         aasm->as_extdtr(IsStore, 64, true, PostIndex, r6, EDtrAddr(r4, EDtrOffImm(8)));
         aasm->as_b(&header, Assembler::NonZero);
         masm.bind(&footer);
     }
 
     masm.ma_sub(r8, sp, r8);
-    masm.makeFrameDescriptor(r8, JitFrame_Entry);
+    masm.makeFrameDescriptor(r8, JitFrame_Entry, JitFrameLayout::Size());
 
     masm.startDataTransferM(IsStore, sp, IB, NoWriteBack);
                            // [sp]    = return address (written later)
     masm.transferReg(r8);  // [sp',4] = descriptor, argc*8+20
     masm.transferReg(r9);  // [sp',8]  = callee token
     masm.transferReg(r10); // [sp',12]  = actual arguments
     masm.finishDataTransfer();
 
@@ -278,17 +278,17 @@ JitRuntime::generateEnterJIT(JSContext* 
 #endif
 
         // Reserve space for locals and stack values.
         masm.ma_lsl(Imm32(3), numStackValues, scratch);
         masm.ma_sub(sp, scratch, sp);
 
         // Enter exit frame.
         masm.addPtr(Imm32(BaselineFrame::Size() + BaselineFrame::FramePointerOffset), scratch);
-        masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS);
+        masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS, ExitFrameLayout::Size());
         masm.push(scratch);
         masm.push(Imm32(0)); // Fake return address.
         // No GC things to mark on the stack, push a bare token.
         masm.enterFakeExitFrame(ExitFrameLayoutBareToken);
 
         masm.push(framePtr); // BaselineFrame
         masm.push(r0); // jitcode
 
@@ -523,17 +523,17 @@ JitRuntime::generateArgumentsRectifier(J
         masm.ma_b(&copyLoopTop, Assembler::NotSigned);
     }
 
     // translate the framesize from values into bytes
     masm.ma_add(r6, Imm32(1), r6);
     masm.ma_lsl(Imm32(3), r6, r6);
 
     // Construct sizeDescriptor.
-    masm.makeFrameDescriptor(r6, JitFrame_Rectifier);
+    masm.makeFrameDescriptor(r6, JitFrame_Rectifier, JitFrameLayout::Size());
 
     // Construct JitFrameLayout.
     masm.ma_push(r0); // actual arguments.
     masm.ma_push(r1); // callee token
     masm.ma_push(r6); // frame descriptor.
 
     // Call the target function.
     // Note that this code assumes the function is JITted.
--- a/js/src/jit/arm64/MacroAssembler-arm64.h
+++ b/js/src/jit/arm64/MacroAssembler-arm64.h
@@ -2931,17 +2931,18 @@ class MacroAssemblerCompat : public vixl
     // FIXME: Should be in Assembler?
     // FIXME: Should be const?
     uint32_t currentOffset() const {
         return nextOffset().getOffset();
     }
 
   protected:
     bool buildOOLFakeExitFrame(void* fakeReturnAddr) {
-        uint32_t descriptor = MakeFrameDescriptor(framePushed(), JitFrame_IonJS);
+        uint32_t descriptor = MakeFrameDescriptor(framePushed(), JitFrame_IonJS,
+                                                  ExitFrameLayout::Size());
         Push(Imm32(descriptor));
         Push(ImmPtr(fakeReturnAddr));
         return true;
     }
 };
 
 typedef MacroAssemblerCompat MacroAssemblerSpecific;
 
--- a/js/src/jit/arm64/SharedICHelpers-arm64.h
+++ b/js/src/jit/arm64/SharedICHelpers-arm64.h
@@ -95,17 +95,17 @@ EmitBaselineTailCallVM(JitCode* target, 
 
         masm.Sub(scratch32, w0, Operand(argSize));
         masm.store32(scratch32.asUnsized(),
                      Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
     }
 
     // Push frame descriptor (minus the return address) and perform the tail call.
     MOZ_ASSERT(ICTailCallReg == lr);
-    masm.makeFrameDescriptor(r0, JitFrame_BaselineJS);
+    masm.makeFrameDescriptor(r0, JitFrame_BaselineJS, ExitFrameLayout::Size());
     masm.push(r0);
 
     // The return address will be pushed by the VM wrapper, for compatibility
     // with direct calls. Refer to the top of generateVMWrapper().
     // ICTailCallReg (lr) already contains the return address (as we keep
     // it there through the stub calls).
 
     masm.branch(target);
@@ -113,31 +113,31 @@ EmitBaselineTailCallVM(JitCode* target, 
 
 inline void
 EmitIonTailCallVM(JitCode* target, MacroAssembler& masm, uint32_t stackSize)
 {
     MOZ_CRASH("Not implemented yet.");
 }
 
 inline void
-EmitBaselineCreateStubFrameDescriptor(MacroAssembler& masm, Register reg)
+EmitBaselineCreateStubFrameDescriptor(MacroAssembler& masm, Register reg, uint32_t headerSize)
 {
     ARMRegister reg64(reg, 64);
 
     // Compute stub frame size.
     masm.Sub(reg64, masm.GetStackPointer64(), Operand(sizeof(void*) * 2));
     masm.Sub(reg64, BaselineFrameReg64, reg64);
 
-    masm.makeFrameDescriptor(reg, JitFrame_BaselineStub);
+    masm.makeFrameDescriptor(reg, JitFrame_BaselineStub, headerSize);
 }
 
 inline void
 EmitBaselineCallVM(JitCode* target, MacroAssembler& masm)
 {
-    EmitBaselineCreateStubFrameDescriptor(masm, r0);
+    EmitBaselineCreateStubFrameDescriptor(masm, r0, ExitFrameLayout::Size());
     masm.push(r0);
     masm.call(target);
 }
 
 inline void
 EmitIonCallVM(JitCode* target, size_t stackSlots, MacroAssembler& masm)
 {
     MOZ_CRASH("Not implemented yet.");
@@ -157,17 +157,17 @@ EmitBaselineEnterStubFrame(MacroAssemble
     masm.Sub(ARMRegister(scratch, 64), ARMRegister(scratch, 64), masm.GetStackPointer64());
 
     masm.store32(scratch, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
 
     // Note: when making changes here, don't forget to update STUB_FRAME_SIZE.
 
     // Push frame descriptor and return address.
     // Save old frame pointer, stack pointer, and stub reg.
-    masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS);
+    masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS, BaselineStubFrameLayout::Size());
     masm.Push(scratch, ICTailCallReg, ICStubReg, BaselineFrameReg);
 
     // Update the frame register.
     masm.Mov(BaselineFrameReg64, masm.GetStackPointer64());
 
     // Stack should remain 16-byte aligned.
     masm.checkStackAlignment();
 }
--- a/js/src/jit/arm64/Trampoline-arm64.cpp
+++ b/js/src/jit/arm64/Trampoline-arm64.cpp
@@ -158,17 +158,17 @@ JitRuntime::generateEnterJIT(JSContext* 
     masm.unboxInt32(Address(reg_vp, 0x0), ip0);
     masm.push(ip0, reg_callee);
     masm.checkStackAlignment();
 
     // Calculate the number of bytes pushed so far.
     masm.subStackPtrFrom(r19);
 
     // Push the frameDescriptor.
-    masm.makeFrameDescriptor(r19, JitFrame_Entry);
+    masm.makeFrameDescriptor(r19, JitFrame_Entry, JitFrameLayout::Size());
     masm.Push(r19);
 
     Label osrReturnPoint;
     if (type == EnterJitBaseline) {
         // Check for OSR.
         Label notOsr;
         masm.branchTestPtr(Assembler::Zero, OsrFrameReg, OsrFrameReg, &notOsr);
 
@@ -181,17 +181,17 @@ JitRuntime::generateEnterJIT(JSContext* 
         masm.moveStackPtrTo(BaselineFrameReg);
 
         // Reserve space for locals and stack values.
         masm.Lsl(w19, ARMRegister(reg_osrNStack, 32), 3); // w19 = num_stack_values * sizeof(Value).
         masm.subFromStackPtr(r19);
 
         // Enter exit frame.
         masm.addPtr(Imm32(BaselineFrame::Size() + BaselineFrame::FramePointerOffset), r19);
-        masm.makeFrameDescriptor(r19, JitFrame_BaselineJS);
+        masm.makeFrameDescriptor(r19, JitFrame_BaselineJS, ExitFrameLayout::Size());
         masm.asVIXL().Push(x19, xzr); // Push xzr for a fake return address.
         // No GC things to mark: push a bare token.
         masm.enterFakeExitFrame(ExitFrameLayoutBareToken);
 
         masm.push(BaselineFrameReg, reg_code);
 
         // Initialize the frame, including filling in the slots.
         masm.setupUnalignedABICall(r19);
@@ -391,17 +391,17 @@ JitRuntime::generateArgumentsRectifier(J
         masm.B(&copyLoopTop, Assembler::NotSigned);
     }
 
     // Fix up the size of the stack frame. +1 accounts for |this|.
     masm.Add(x6, x7, Operand(1));
     masm.Lsl(x6, x6, 3);
 
     // Make that into a frame descriptor.
-    masm.makeFrameDescriptor(r6, JitFrame_Rectifier);
+    masm.makeFrameDescriptor(r6, JitFrame_Rectifier, JitFrameLayout::Size());
 
     masm.push(r0,  // Number of actual arguments.
               r1,  // Callee token.
               r6); // Frame descriptor.
 
     // Load the address of the code that is getting called.
     masm.Ldr(x3, MemOperand(x5, JSFunction::offsetOfNativeOrScript()));
     masm.loadBaselineOrIonRaw(r3, r3, nullptr);
@@ -943,17 +943,17 @@ JitRuntime::generateProfilerExitFrameTai
 #endif
 
     // Load the frame descriptor into |scratch1|, figure out what to do depending on its type.
     masm.loadPtr(Address(masm.getStackPointer(), JitFrameLayout::offsetOfDescriptor()), scratch1);
 
     // Going into the conditionals, we will have:
     //      FrameDescriptor.size in scratch1
     //      FrameDescriptor.type in scratch2
-    masm.and32(Imm32((1 << FRAMESIZE_SHIFT) - 1), scratch1, scratch2);
+    masm.and32(Imm32((1 << FRAMETYPE_BITS) - 1), scratch1, scratch2);
     masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), scratch1);
 
     // Handling of each case is dependent on FrameDescriptor.type
     Label handle_IonJS;
     Label handle_BaselineStub;
     Label handle_Rectifier;
     Label handle_IonAccessorIC;
     Label handle_Entry;
--- a/js/src/jit/mips32/MacroAssembler-mips32.cpp
+++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp
@@ -706,17 +706,18 @@ MacroAssemblerMIPS::ma_push(FloatRegiste
 {
     as_addiu(StackPointer, StackPointer, -sizeof(double));
     ma_sd(fs.doubleOverlay(0), Address(StackPointer, 0));
 }
 
 bool
 MacroAssemblerMIPSCompat::buildOOLFakeExitFrame(void* fakeReturnAddr)
 {
-    uint32_t descriptor = MakeFrameDescriptor(asMasm().framePushed(), JitFrame_IonJS);
+    uint32_t descriptor = MakeFrameDescriptor(asMasm().framePushed(), JitFrame_IonJS,
+                                              ExitFrameLayout::Size());
 
     asMasm().Push(Imm32(descriptor)); // descriptor_
     asMasm().Push(ImmPtr(fakeReturnAddr));
 
     return true;
 }
 
 void
--- a/js/src/jit/mips32/SharedICHelpers-mips32.h
+++ b/js/src/jit/mips32/SharedICHelpers-mips32.h
@@ -93,46 +93,46 @@ EmitBaselineTailCallVM(JitCode* target, 
     masm.ma_subu(t7, t6, Imm32(argSize));
     masm.storePtr(t7, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
 
     // Push frame descriptor and perform the tail call.
     // ICTailCallReg (ra) already contains the return address (as we
     // keep it there through the stub calls), but the VMWrapper code being
     // called expects the return address to also be pushed on the stack.
     MOZ_ASSERT(ICTailCallReg == ra);
-    masm.makeFrameDescriptor(t6, JitFrame_BaselineJS);
+    masm.makeFrameDescriptor(t6, JitFrame_BaselineJS, ExitFrameLayout::Size());
     masm.subPtr(Imm32(sizeof(CommonFrameLayout)), StackPointer);
     masm.storePtr(t6, Address(StackPointer, CommonFrameLayout::offsetOfDescriptor()));
     masm.storePtr(ra, Address(StackPointer, CommonFrameLayout::offsetOfReturnAddress()));
 
     masm.branch(target);
 }
 
 inline void
 EmitIonTailCallVM(JitCode* target, MacroAssembler& masm, uint32_t stackSize)
 {
     MOZ_CRASH("Not implemented yet.");
 }
 
 inline void
-EmitBaselineCreateStubFrameDescriptor(MacroAssembler& masm, Register reg)
+EmitBaselineCreateStubFrameDescriptor(MacroAssembler& masm, Register reg, uint32_t headerSize)
 {
     // Compute stub frame size. We have to add two pointers: the stub reg and
     // previous frame pointer pushed by EmitEnterStubFrame.
     masm.movePtr(BaselineFrameReg, reg);
     masm.addPtr(Imm32(sizeof(intptr_t) * 2), reg);
     masm.subPtr(BaselineStackReg, reg);
 
-    masm.makeFrameDescriptor(reg, JitFrame_BaselineStub);
+    masm.makeFrameDescriptor(reg, JitFrame_BaselineStub, headerSize);
 }
 
 inline void
 EmitBaselineCallVM(JitCode* target, MacroAssembler& masm)
 {
-    EmitBaselineCreateStubFrameDescriptor(masm, t6);
+    EmitBaselineCreateStubFrameDescriptor(masm, t6, ExitFrameLayout::Size());
     masm.push(t6);
     masm.call(target);
 }
 
 inline void
 EmitIonCallVM(JitCode* target, size_t stackSlots, MacroAssembler& masm)
 {
     MOZ_CRASH("Not implemented yet.");
@@ -159,17 +159,17 @@ EmitBaselineEnterStubFrame(MacroAssemble
     masm.subPtr(BaselineStackReg, scratch);
 
     masm.storePtr(scratch, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
 
     // Note: when making changes here, don't forget to update
     // BaselineStubFrame if needed.
 
     // Push frame descriptor and return address.
-    masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS);
+    masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS, BaselineStubFrameLayout::Size());
     masm.subPtr(Imm32(STUB_FRAME_SIZE), StackPointer);
     masm.storePtr(scratch, Address(StackPointer, offsetof(BaselineStubFrame, descriptor)));
     masm.storePtr(ICTailCallReg, Address(StackPointer,
                                                offsetof(BaselineStubFrame, returnAddress)));
 
     // Save old frame pointer, stack pointer and stub reg.
     masm.storePtr(ICStubReg, Address(StackPointer,
                                            offsetof(BaselineStubFrame, savedStub)));
--- a/js/src/jit/mips32/Trampoline-mips32.cpp
+++ b/js/src/jit/mips32/Trampoline-mips32.cpp
@@ -195,17 +195,17 @@ JitRuntime::generateEnterJIT(JSContext* 
     }
     masm.bind(&footer);
 
     masm.subPtr(Imm32(2 * sizeof(uintptr_t)), StackPointer);
     masm.storePtr(s3, Address(StackPointer, sizeof(uintptr_t))); // actual arguments
     masm.storePtr(s2, Address(StackPointer, 0)); // callee token
 
     masm.subPtr(StackPointer, s4);
-    masm.makeFrameDescriptor(s4, JitFrame_Entry);
+    masm.makeFrameDescriptor(s4, JitFrame_Entry, JitFrameLayout::Size());
     masm.push(s4); // descriptor
 
     CodeLabel returnLabel;
     CodeLabel oomReturnLabel;
     if (type == EnterJitBaseline) {
         // Handle OSR.
         AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
         regs.take(OsrFrameReg);
@@ -241,17 +241,17 @@ JitRuntime::generateEnterJIT(JSContext* 
         masm.movePtr(StackPointer, framePtr);
 
         // Reserve space for locals and stack values.
         masm.ma_sll(scratch, numStackValues, Imm32(3));
         masm.subPtr(scratch, StackPointer);
 
         // Enter exit frame.
         masm.addPtr(Imm32(BaselineFrame::Size() + BaselineFrame::FramePointerOffset), scratch);
-        masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS);
+        masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS, ExitFrameLayout::Size());
 
         // Push frame descriptor and fake return address.
         masm.reserveStack(2 * sizeof(uintptr_t));
         masm.storePtr(scratch, Address(StackPointer, sizeof(uintptr_t))); // Frame descriptor
         masm.storePtr(zero, Address(StackPointer, 0)); // fake return address
 
         // No GC things to mark, push a bare token.
         masm.enterFakeExitFrame(ExitFrameLayoutBareToken);
@@ -505,17 +505,17 @@ JitRuntime::generateArgumentsRectifier(J
         masm.ma_b(s3, s3, &copyLoopTop, Assembler::NonZero, ShortJump);
     }
 
     // translate the framesize from values into bytes
     masm.ma_addu(t0, numArgsReg, Imm32(1));
     masm.lshiftPtr(Imm32(3), t0);
 
     // Construct sizeDescriptor.
-    masm.makeFrameDescriptor(t0, JitFrame_Rectifier);
+    masm.makeFrameDescriptor(t0, JitFrame_Rectifier, JitFrameLayout::Size());
 
     // Construct JitFrameLayout.
     masm.subPtr(Imm32(3 * sizeof(uintptr_t)), StackPointer);
     // Push actual arguments.
     masm.storePtr(numActArgsReg, Address(StackPointer, 2 * sizeof(uintptr_t)));
     // Push callee token.
     masm.storePtr(calleeTokenReg, Address(StackPointer, sizeof(uintptr_t)));
     // Push frame descriptor.
--- a/js/src/jit/mips64/MacroAssembler-mips64.cpp
+++ b/js/src/jit/mips64/MacroAssembler-mips64.cpp
@@ -845,17 +845,18 @@ MacroAssemblerMIPS64::ma_push(FloatRegis
 {
     as_daddiu(StackPointer, StackPointer, (int32_t)-sizeof(double));
     ma_sd(fs, Address(StackPointer, 0));
 }
 
 bool
 MacroAssemblerMIPS64Compat::buildOOLFakeExitFrame(void* fakeReturnAddr)
 {
-    uint32_t descriptor = MakeFrameDescriptor(asMasm().framePushed(), JitFrame_IonJS);
+    uint32_t descriptor = MakeFrameDescriptor(asMasm().framePushed(), JitFrame_IonJS,
+                                              ExitFrameLayout::Size());
 
     asMasm().Push(Imm32(descriptor)); // descriptor_
     asMasm().Push(ImmPtr(fakeReturnAddr));
 
     return true;
 }
 
 void
--- a/js/src/jit/mips64/SharedICHelpers-mips64.h
+++ b/js/src/jit/mips64/SharedICHelpers-mips64.h
@@ -93,46 +93,46 @@ EmitBaselineTailCallVM(JitCode* target, 
     masm.ma_dsubu(a7, a6, Imm32(argSize));
     masm.store32(a7, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
 
     // Push frame descriptor and perform the tail call.
     // ICTailCallReg (ra) already contains the return address (as we
     // keep it there through the stub calls), but the VMWrapper code being
     // called expects the return address to also be pushed on the stack.
     MOZ_ASSERT(ICTailCallReg == ra);
-    masm.makeFrameDescriptor(a6, JitFrame_BaselineJS);
+    masm.makeFrameDescriptor(a6, JitFrame_BaselineJS, ExitFrameLayout::Size());
     masm.subPtr(Imm32(sizeof(CommonFrameLayout)), StackPointer);
     masm.storePtr(a6, Address(StackPointer, CommonFrameLayout::offsetOfDescriptor()));
     masm.storePtr(ra, Address(StackPointer, CommonFrameLayout::offsetOfReturnAddress()));
 
     masm.branch(target);
 }
 
 inline void
 EmitIonTailCallVM(JitCode* target, MacroAssembler& masm, uint32_t stackSize)
 {
     MOZ_CRASH("Not implemented yet.");
 }
 
 inline void
-EmitBaselineCreateStubFrameDescriptor(MacroAssembler& masm, Register reg)
+EmitBaselineCreateStubFrameDescriptor(MacroAssembler& masm, Register reg, uint32_t headerSize)
 {
     // Compute stub frame size. We have to add two pointers: the stub reg and
     // previous frame pointer pushed by EmitEnterStubFrame.
     masm.movePtr(BaselineFrameReg, reg);
     masm.addPtr(Imm32(sizeof(intptr_t) * 2), reg);
     masm.subPtr(BaselineStackReg, reg);
 
-    masm.makeFrameDescriptor(reg, JitFrame_BaselineStub);
+    masm.makeFrameDescriptor(reg, JitFrame_BaselineStub, headerSize);
 }
 
 inline void
 EmitBaselineCallVM(JitCode* target, MacroAssembler& masm)
 {
-    EmitBaselineCreateStubFrameDescriptor(masm, a6);
+    EmitBaselineCreateStubFrameDescriptor(masm, a6, ExitFrameLayout::Size());
     masm.push(a6);
     masm.call(target);
 }
 
 inline void
 EmitIonCallVM(JitCode* target, size_t stackSlots, MacroAssembler& masm)
 {
     MOZ_CRASH("Not implemented yet.");
@@ -159,17 +159,17 @@ EmitBaselineEnterStubFrame(MacroAssemble
     masm.subPtr(BaselineStackReg, scratch);
 
     masm.store32(scratch, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
 
     // Note: when making changes here, don't forget to update
     // BaselineStubFrame if needed.
 
     // Push frame descriptor and return address.
-    masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS);
+    masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS, BaselineStubFrameLayout::Size());
     masm.subPtr(Imm32(STUB_FRAME_SIZE), StackPointer);
     masm.storePtr(scratch, Address(StackPointer, offsetof(BaselineStubFrame, descriptor)));
     masm.storePtr(ICTailCallReg, Address(StackPointer,
                                                offsetof(BaselineStubFrame, returnAddress)));
 
     // Save old frame pointer, stack pointer and stub reg.
     masm.storePtr(ICStubReg, Address(StackPointer,
                                            offsetof(BaselineStubFrame, savedStub)));
--- a/js/src/jit/mips64/Trampoline-mips64.cpp
+++ b/js/src/jit/mips64/Trampoline-mips64.cpp
@@ -188,17 +188,17 @@ JitRuntime::generateEnterJIT(JSContext* 
     }
     masm.bind(&footer);
 
     masm.subPtr(Imm32(2 * sizeof(uintptr_t)), StackPointer);
     masm.storePtr(s3, Address(StackPointer, sizeof(uintptr_t))); // actual arguments
     masm.storePtr(reg_token, Address(StackPointer, 0)); // callee token
 
     masm.subPtr(StackPointer, s4);
-    masm.makeFrameDescriptor(s4, JitFrame_Entry);
+    masm.makeFrameDescriptor(s4, JitFrame_Entry, JitFrameLayout::Size());
     masm.push(s4); // descriptor
 
     CodeLabel returnLabel;
     CodeLabel oomReturnLabel;
     if (type == EnterJitBaseline) {
         // Handle OSR.
         AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
         regs.take(OsrFrameReg);
@@ -229,17 +229,17 @@ JitRuntime::generateEnterJIT(JSContext* 
         masm.movePtr(StackPointer, framePtr);
 
         // Reserve space for locals and stack values.
         masm.ma_dsll(scratch, numStackValues, Imm32(3));
         masm.subPtr(scratch, StackPointer);
 
         // Enter exit frame.
         masm.addPtr(Imm32(BaselineFrame::Size() + BaselineFrame::FramePointerOffset), scratch);
-        masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS);
+        masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS, ExitFrameLayout::Size());
 
         // Push frame descriptor and fake return address.
         masm.reserveStack(2 * sizeof(uintptr_t));
         masm.storePtr(scratch, Address(StackPointer, sizeof(uintptr_t))); // Frame descriptor
         masm.storePtr(zero, Address(StackPointer, 0)); // fake return address
 
         // No GC things to mark, push a bare token.
         masm.enterFakeExitFrame(ExitFrameLayoutBareToken);
@@ -518,17 +518,17 @@ JitRuntime::generateArgumentsRectifier(J
     // [arg2] [arg1] [this] [[argc] [callee] [descr] [raddr]] <- t2
     //
     //
     // Rectifier frame:
     // [undef] [undef] [undef] [arg2] [arg1] [this] <- sp [[argc] [callee] [descr] [raddr]]
 
     // Construct sizeDescriptor.
     masm.subPtr(StackPointer, t2);
-    masm.makeFrameDescriptor(t2, JitFrame_Rectifier);
+    masm.makeFrameDescriptor(t2, JitFrame_Rectifier, JitFrameLayout::Size());
 
     // Construct JitFrameLayout.
     masm.subPtr(Imm32(3 * sizeof(uintptr_t)), StackPointer);
     // Push actual arguments.
     masm.storePtr(numActArgsReg, Address(StackPointer, 2 * sizeof(uintptr_t)));
     // Push callee token.
     masm.storePtr(calleeTokenReg, Address(StackPointer, sizeof(uintptr_t)));
     // Push frame descriptor.
--- a/js/src/jit/none/SharedICHelpers-none.h
+++ b/js/src/jit/none/SharedICHelpers-none.h
@@ -17,17 +17,17 @@ static const uint32_t STUB_FRAME_SAVED_S
 inline void EmitRestoreTailCallReg(MacroAssembler&) { MOZ_CRASH(); }
 inline void EmitRepushTailCallReg(MacroAssembler&) { MOZ_CRASH(); }
 inline void EmitCallIC(CodeOffset*, MacroAssembler&) { MOZ_CRASH(); }
 inline void EmitEnterTypeMonitorIC(MacroAssembler&, size_t v = 0) { MOZ_CRASH(); }
 inline void EmitReturnFromIC(MacroAssembler&) { MOZ_CRASH(); }
 inline void EmitChangeICReturnAddress(MacroAssembler&, Register) { MOZ_CRASH(); }
 inline void EmitBaselineTailCallVM(JitCode*, MacroAssembler&, uint32_t) { MOZ_CRASH(); }
 inline void EmitIonTailCallVM(JitCode*, MacroAssembler&, uint32_t) { MOZ_CRASH(); }
-inline void EmitBaselineCreateStubFrameDescriptor(MacroAssembler&, Register) { MOZ_CRASH(); }
+inline void EmitBaselineCreateStubFrameDescriptor(MacroAssembler&, Register, uint32_t) { MOZ_CRASH(); }
 inline void EmitBaselineCallVM(JitCode*, MacroAssembler&) { MOZ_CRASH(); }
 inline void EmitIonCallVM(JitCode*, size_t, MacroAssembler&) { MOZ_CRASH(); }
 inline void EmitBaselineEnterStubFrame(MacroAssembler&, Register) { MOZ_CRASH(); }
 inline void EmitIonEnterStubFrame(MacroAssembler&, Register) { MOZ_CRASH(); }
 inline void EmitBaselineLeaveStubFrame(MacroAssembler&, bool v = false) { MOZ_CRASH(); }
 inline void EmitIonLeaveStubFrame(MacroAssembler&) { MOZ_CRASH(); }
 inline void EmitStowICValues(MacroAssembler&, int) { MOZ_CRASH(); }
 inline void EmitUnstowICValues(MacroAssembler&, int, bool v = false) { MOZ_CRASH(); }
--- a/js/src/jit/shared/BaselineCompiler-shared.cpp
+++ b/js/src/jit/shared/BaselineCompiler-shared.cpp
@@ -84,22 +84,24 @@ BaselineCompilerShared::callVM(const VMF
     MOZ_ASSERT(masm.framePushed() - pushedBeforeCall_ == argSize);
 
     Address frameSizeAddress(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize());
     uint32_t frameVals = frame.nlocals() + frame.stackDepth();
     uint32_t frameBaseSize = BaselineFrame::FramePointerOffset + BaselineFrame::Size();
     uint32_t frameFullSize = frameBaseSize + (frameVals * sizeof(Value));
     if (phase == POST_INITIALIZE) {
         masm.store32(Imm32(frameFullSize), frameSizeAddress);
-        uint32_t descriptor = MakeFrameDescriptor(frameFullSize + argSize, JitFrame_BaselineJS);
+        uint32_t descriptor = MakeFrameDescriptor(frameFullSize + argSize, JitFrame_BaselineJS,
+                                                  ExitFrameLayout::Size());
         masm.push(Imm32(descriptor));
 
     } else if (phase == PRE_INITIALIZE) {
         masm.store32(Imm32(frameBaseSize), frameSizeAddress);
-        uint32_t descriptor = MakeFrameDescriptor(frameBaseSize + argSize, JitFrame_BaselineJS);
+        uint32_t descriptor = MakeFrameDescriptor(frameBaseSize + argSize, JitFrame_BaselineJS,
+                                                  ExitFrameLayout::Size());
         masm.push(Imm32(descriptor));
 
     } else {
         MOZ_ASSERT(phase == CHECK_OVER_RECURSED);
         Label afterWrite;
         Label writePostInitialize;
 
         // If OVER_RECURSED is set, then frame locals haven't been pushed yet.
@@ -112,17 +114,17 @@ BaselineCompilerShared::callVM(const VMF
         masm.jump(&afterWrite);
 
         masm.bind(&writePostInitialize);
         masm.move32(Imm32(frameFullSize), ICTailCallReg);
 
         masm.bind(&afterWrite);
         masm.store32(ICTailCallReg, frameSizeAddress);
         masm.add32(Imm32(argSize), ICTailCallReg);
-        masm.makeFrameDescriptor(ICTailCallReg, JitFrame_BaselineJS);
+        masm.makeFrameDescriptor(ICTailCallReg, JitFrame_BaselineJS, ExitFrameLayout::Size());
         masm.push(ICTailCallReg);
     }
     MOZ_ASSERT(fun.expectTailCall == NonTailCall);
     // Perform the call.
     masm.call(code);
     uint32_t callOffset = masm.currentOffset();
     masm.pop(BaselineFrameReg);
 
--- a/js/src/jit/shared/CodeGenerator-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-shared.cpp
@@ -1356,20 +1356,20 @@ CodeGeneratorShared::callVM(const VMFunc
         StoreAllLiveRegs(masm, ins->safepoint()->liveRegs());
 #endif
 
     // Push an exit frame descriptor. If |dynStack| is a valid pointer to a
     // register, then its value is added to the value of the |framePushed()| to
     // fill the frame descriptor.
     if (dynStack) {
         masm.addPtr(Imm32(masm.framePushed()), *dynStack);
-        masm.makeFrameDescriptor(*dynStack, JitFrame_IonJS);
+        masm.makeFrameDescriptor(*dynStack, JitFrame_IonJS, ExitFrameLayout::Size());
         masm.Push(*dynStack); // descriptor
     } else {
-        masm.pushStaticFrameDescriptor(JitFrame_IonJS);
+        masm.pushStaticFrameDescriptor(JitFrame_IonJS, ExitFrameLayout::Size());
     }
 
     // Call the wrapper function.  The wrapper is in charge to unwind the stack
     // when returning from the call.  Failures are handled with exceptions based
     // on the return value of the C functions.  To guard the outcome of the
     // returned value, use another LIR instruction.
     uint32_t callOffset = masm.callJit(wrapper);
     markSafepointAt(callOffset, ins);
--- a/js/src/jit/x64/SharedICHelpers-x64.h
+++ b/js/src/jit/x64/SharedICHelpers-x64.h
@@ -80,17 +80,17 @@ EmitBaselineTailCallVM(JitCode* target, 
     masm.subq(BaselineStackReg, scratch);
 
     // Store frame size without VMFunction arguments for GC marking.
     masm.movq(scratch, rdx);
     masm.subq(Imm32(argSize), rdx);
     masm.store32(rdx, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
 
     // Push frame descriptor and perform the tail call.
-    masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS);
+    masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS, ExitFrameLayout::Size());
     masm.push(scratch);
     masm.push(ICTailCallReg);
     masm.jmp(target);
 }
 
 inline void
 EmitIonTailCallVM(JitCode* target, MacroAssembler& masm, uint32_t stackSize)
 {
@@ -101,53 +101,54 @@ EmitIonTailCallVM(JitCode* target, Macro
 
     ScratchRegisterScope scratch(masm);
 
     masm.loadPtr(Address(esp, stackSize), scratch);
     masm.shrq(Imm32(FRAMESIZE_SHIFT), scratch);
     masm.addq(Imm32(stackSize + JitStubFrameLayout::Size() - sizeof(intptr_t)), scratch);
 
     // Push frame descriptor and perform the tail call.
-    masm.makeFrameDescriptor(scratch, JitFrame_IonJS);
+    masm.makeFrameDescriptor(scratch, JitFrame_IonJS, ExitFrameLayout::Size());
     masm.push(scratch);
     masm.push(ICTailCallReg);
     masm.jmp(target);
 }
 
 inline void
-EmitBaselineCreateStubFrameDescriptor(MacroAssembler& masm, Register reg)
+EmitBaselineCreateStubFrameDescriptor(MacroAssembler& masm, Register reg, uint32_t headerSize)
 {
     // Compute stub frame size. We have to add two pointers: the stub reg and previous
     // frame pointer pushed by EmitEnterStubFrame.
     masm.movq(BaselineFrameReg, reg);
     masm.addq(Imm32(sizeof(void*) * 2), reg);
     masm.subq(BaselineStackReg, reg);
 
-    masm.makeFrameDescriptor(reg, JitFrame_BaselineStub);
+    masm.makeFrameDescriptor(reg, JitFrame_BaselineStub, headerSize);
 }
 
 inline void
 EmitBaselineCallVM(JitCode* target, MacroAssembler& masm)
 {
     ScratchRegisterScope scratch(masm);
-    EmitBaselineCreateStubFrameDescriptor(masm, scratch);
+    EmitBaselineCreateStubFrameDescriptor(masm, scratch, ExitFrameLayout::Size());
     masm.push(scratch);
     masm.call(target);
 }
 
 inline void
 EmitIonCallVM(JitCode* target, size_t stackSlots, MacroAssembler& masm)
 {
     // Stubs often use the return address. Which is actually accounted by the
     // caller of the stub. Though in the stubcode we fake that is part of the
     // stub. In order to make it possible to pop it. As a result we have to
     // fix it here, by subtracting it. Else it would be counted twice.
     uint32_t framePushed = masm.framePushed() - sizeof(void*);
 
-    uint32_t descriptor = MakeFrameDescriptor(framePushed, JitFrame_IonStub);
+    uint32_t descriptor = MakeFrameDescriptor(framePushed, JitFrame_IonStub,
+                                              ExitFrameLayout::Size());
     masm.Push(Imm32(descriptor));
     masm.call(target);
 
     // Remove rest of the frame left on the stack. We remove the return address
     // which is implicitly poped when returning.
     size_t framePop = sizeof(ExitFrameLayout) - sizeof(void*);
 
     // Pop arguments from framePushed.
@@ -171,17 +172,17 @@ EmitBaselineEnterStubFrame(MacroAssemble
     masm.subq(BaselineStackReg, scratch);
 
     masm.store32(scratch, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
 
     // Note: when making changes here,  don't forget to update STUB_FRAME_SIZE
     // if needed.
 
     // Push frame descriptor and return address.
-    masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS);
+    masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS, BaselineStubFrameLayout::Size());
     masm.Push(scratch);
     masm.Push(ICTailCallReg);
 
     // Save old frame pointer, stack pointer and stub reg.
     masm.Push(ICStubReg);
     masm.Push(BaselineFrameReg);
     masm.mov(BaselineStackReg, BaselineFrameReg);
 }
--- a/js/src/jit/x64/Trampoline-x64.cpp
+++ b/js/src/jit/x64/Trampoline-x64.cpp
@@ -153,17 +153,17 @@ JitRuntime::generateEnterJIT(JSContext* 
     masm.push(token);
 
     /*****************************************************************
     Push the number of bytes we've pushed so far on the stack and call
     *****************************************************************/
     masm.subq(rsp, r14);
 
     // Create a frame descriptor.
-    masm.makeFrameDescriptor(r14, JitFrame_Entry);
+    masm.makeFrameDescriptor(r14, JitFrame_Entry, JitFrameLayout::Size());
     masm.push(r14);
 
     CodeLabel returnLabel;
     CodeLabel oomReturnLabel;
     if (type == EnterJitBaseline) {
         // Handle OSR.
         AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
         regs.takeUnchecked(OsrFrameReg);
@@ -218,17 +218,17 @@ JitRuntime::generateEnterJIT(JSContext* 
         // Reserve space for locals and stack values.
         Register valuesSize = regs.takeAny();
         masm.mov(numStackValues, valuesSize);
         masm.shll(Imm32(3), valuesSize);
         masm.subPtr(valuesSize, rsp);
 
         // Enter exit frame.
         masm.addPtr(Imm32(BaselineFrame::Size() + BaselineFrame::FramePointerOffset), valuesSize);
-        masm.makeFrameDescriptor(valuesSize, JitFrame_BaselineJS);
+        masm.makeFrameDescriptor(valuesSize, JitFrame_BaselineJS, ExitFrameLayout::Size());
         masm.push(valuesSize);
         masm.push(Imm32(0)); // Fake return address.
         // No GC things to mark, push a bare token.
         masm.enterFakeExitFrame(ExitFrameLayoutBareToken);
 
         regs.add(valuesSize);
 
         masm.push(framePtr);
@@ -511,17 +511,17 @@ JitRuntime::generateArgumentsRectifier(J
     //
     //
     // Rectifier frame:
     // [undef] [undef] [undef] [arg2] [arg1] [this] <- rsp [[argc] [callee] [descr] [raddr]]
     //
 
     // Construct descriptor.
     masm.subq(rsp, r9);
-    masm.makeFrameDescriptor(r9, JitFrame_Rectifier);
+    masm.makeFrameDescriptor(r9, JitFrame_Rectifier, JitFrameLayout::Size());
 
     // Construct JitFrameLayout.
     masm.push(rdx); // numActualArgs
     masm.push(rax); // callee token
     masm.push(r9); // descriptor
 
     // Call the target function.
     // Note that this code assumes the function is JITted.
--- a/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
+++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
@@ -73,17 +73,18 @@ void
 MacroAssembler::restoreFrameAlignmentForICArguments(AfterICSaveLive& aic)
 {
     // Exists for MIPS compatibility.
 }
 
 bool
 MacroAssemblerX86Shared::buildOOLFakeExitFrame(void* fakeReturnAddr)
 {
-    uint32_t descriptor = MakeFrameDescriptor(asMasm().framePushed(), JitFrame_IonJS);
+    uint32_t descriptor = MakeFrameDescriptor(asMasm().framePushed(), JitFrame_IonJS,
+                                              ExitFrameLayout::Size());
     asMasm().Push(Imm32(descriptor));
     asMasm().Push(ImmPtr(fakeReturnAddr));
     return true;
 }
 
 void
 MacroAssemblerX86Shared::branchNegativeZero(FloatRegister reg,
                                             Register scratch,
--- a/js/src/jit/x86/SharedICHelpers-x86.h
+++ b/js/src/jit/x86/SharedICHelpers-x86.h
@@ -81,17 +81,17 @@ EmitBaselineTailCallVM(JitCode* target, 
     masm.subl(BaselineStackReg, eax);
 
     // Store frame size without VMFunction arguments for GC marking.
     masm.movl(eax, ebx);
     masm.subl(Imm32(argSize), ebx);
     masm.store32(ebx, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
 
     // Push frame descriptor and perform the tail call.
-    masm.makeFrameDescriptor(eax, JitFrame_BaselineJS);
+    masm.makeFrameDescriptor(eax, JitFrame_BaselineJS, ExitFrameLayout::Size());
     masm.push(eax);
     masm.push(ICTailCallReg);
     masm.jmp(target);
 }
 
 inline void
 EmitIonTailCallVM(JitCode* target, MacroAssembler& masm, uint32_t stackSize)
 {
@@ -100,52 +100,53 @@ EmitIonTailCallVM(JitCode* target, Macro
     // JitFrame_IonJS with the extra stacksize, rendering the original
     // JitFrame_IonJS obsolete.
 
     masm.loadPtr(Address(esp, stackSize), eax);
     masm.shrl(Imm32(FRAMESIZE_SHIFT), eax);
     masm.addl(Imm32(stackSize + JitStubFrameLayout::Size() - sizeof(intptr_t)), eax);
 
     // Push frame descriptor and perform the tail call.
-    masm.makeFrameDescriptor(eax, JitFrame_IonJS);
+    masm.makeFrameDescriptor(eax, JitFrame_IonJS, ExitFrameLayout::Size());
     masm.push(eax);
     masm.push(ICTailCallReg);
     masm.jmp(target);
 }
 
 inline void
-EmitBaselineCreateStubFrameDescriptor(MacroAssembler& masm, Register reg)
+EmitBaselineCreateStubFrameDescriptor(MacroAssembler& masm, Register reg, uint32_t headerSize)
 {
     // Compute stub frame size. We have to add two pointers: the stub reg and previous
     // frame pointer pushed by EmitEnterStubFrame.
     masm.movl(BaselineFrameReg, reg);
     masm.addl(Imm32(sizeof(void*) * 2), reg);
     masm.subl(BaselineStackReg, reg);
 
-    masm.makeFrameDescriptor(reg, JitFrame_BaselineStub);
+    masm.makeFrameDescriptor(reg, JitFrame_BaselineStub, headerSize);
 }
 
 inline void
 EmitBaselineCallVM(JitCode* target, MacroAssembler& masm)
 {
-    EmitBaselineCreateStubFrameDescriptor(masm, eax);
+    EmitBaselineCreateStubFrameDescriptor(masm, eax, ExitFrameLayout::Size());
     masm.push(eax);
     masm.call(target);
 }
 
 inline void
 EmitIonCallVM(JitCode* target, size_t stackSlots, MacroAssembler& masm)
 {
     // Stubs often use the return address. Which is actually accounted by the
     // caller of the stub. Though in the stubcode we fake that is part of the
     // stub. In order to make it possible to pop it. As a result we have to
     // fix it here, by subtracting it. Else it would be counted twice.
     uint32_t framePushed = masm.framePushed() - sizeof(void*);
 
-    uint32_t descriptor = MakeFrameDescriptor(framePushed, JitFrame_IonStub);
+    uint32_t descriptor = MakeFrameDescriptor(framePushed, JitFrame_IonStub,
+                                              ExitFrameLayout::Size());
     masm.Push(Imm32(descriptor));
     masm.call(target);
 
     // Remove rest of the frame left on the stack. We remove the return address
     // which is implicitly poped when returning.
     size_t framePop = sizeof(ExitFrameLayout) - sizeof(void*);
 
     // Pop arguments from framePushed.
@@ -169,17 +170,17 @@ EmitBaselineEnterStubFrame(MacroAssemble
     masm.subl(BaselineStackReg, scratch);
 
     masm.store32(scratch, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
 
     // Note: when making changes here,  don't forget to update STUB_FRAME_SIZE
     // if needed.
 
     // Push frame descriptor and return address.
-    masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS);
+    masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS, BaselineStubFrameLayout::Size());
     masm.Push(scratch);
     masm.Push(ICTailCallReg);
 
     // Save old frame pointer, stack pointer and stub reg.
     masm.Push(ICStubReg);
     masm.Push(BaselineFrameReg);
     masm.mov(BaselineStackReg, BaselineFrameReg);
 }
--- a/js/src/jit/x86/Trampoline-x86.cpp
+++ b/js/src/jit/x86/Trampoline-x86.cpp
@@ -147,17 +147,17 @@ JitRuntime::generateEnterJIT(JSContext* 
     // This address is also used for setting the constructing bit on all paths.
     masm.loadPtr(Address(ebp, ARG_STACKFRAME), OsrFrameReg);
 
     /*****************************************************************
     Push the number of bytes we've pushed so far on the stack and call
     *****************************************************************/
     // Create a frame descriptor.
     masm.subl(esp, esi);
-    masm.makeFrameDescriptor(esi, JitFrame_Entry);
+    masm.makeFrameDescriptor(esi, JitFrame_Entry, JitFrameLayout::Size());
     masm.push(esi);
 
     CodeLabel returnLabel;
     CodeLabel oomReturnLabel;
     if (type == EnterJitBaseline) {
         // Handle OSR.
         AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
         regs.take(JSReturnOperand);
@@ -211,17 +211,17 @@ JitRuntime::generateEnterJIT(JSContext* 
 
         // Reserve space for locals and stack values.
         masm.mov(numStackValues, scratch);
         masm.shll(Imm32(3), scratch);
         masm.subPtr(scratch, esp);
 
         // Enter exit frame.
         masm.addPtr(Imm32(BaselineFrame::Size() + BaselineFrame::FramePointerOffset), scratch);
-        masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS);
+        masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS, ExitFrameLayout::Size());
         masm.push(scratch); // Fake return address.
         masm.push(Imm32(0));
         // No GC things to mark on the stack, push a bare token.
         masm.enterFakeExitFrame(ExitFrameLayoutBareToken);
 
         masm.push(framePtr);
         masm.push(jitcode);
 
@@ -503,17 +503,17 @@ JitRuntime::generateArgumentsRectifier(J
         masm.storeValue(newTarget, dst);
 
         masm.bind(&notConstructing);
     }
 
     // Construct descriptor, accounting for pushed frame pointer above
     masm.lea(Operand(FramePointer, sizeof(void*)), ebx);
     masm.subl(esp, ebx);
-    masm.makeFrameDescriptor(ebx, JitFrame_Rectifier);
+    masm.makeFrameDescriptor(ebx, JitFrame_Rectifier, JitFrameLayout::Size());
 
     // Construct JitFrameLayout.
     masm.push(edx); // number of actual arguments
     masm.push(eax); // callee token
     masm.push(ebx); // descriptor
 
     // Call the target function.
     // Note that this assumes the function is JITted.