Bug 999358 - Fix MLambdaArrow to initialize the unused extended slot too. r=terrence
authorJan de Mooij <jdemooij@mozilla.com>
Wed, 23 Apr 2014 11:31:43 +0200
changeset 180102 b9e4dac08b6e202a363b14cd7ae01bd3260b9892
parent 180101 243bf2777fa46e67016265f46ee2e23e889805a6
child 180103 f8f94f19e05b9cda0f5c81178094c2f2cc581fc5
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersterrence
bugs999358
milestone31.0a1
Bug 999358 - Fix MLambdaArrow to initialize the unused extended slot too. r=terrence
js/src/jit/CodeGenerator.cpp
js/src/jsfun.h
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -1007,19 +1007,22 @@ CodeGenerator::visitLambdaArrow(LLambdaA
         return true;
     }
 
     masm.newGCThing(output, tempReg, info.fun, ool->entry(), gc::DefaultHeap);
     masm.initGCThing(output, tempReg, info.fun);
 
     emitLambdaInit(output, scopeChain, info);
 
-    // Store the lexical |this| value.
+    // Initialize extended slots. Lexical |this| is stored in the first one.
     MOZ_ASSERT(info.flags & JSFunction::EXTENDED);
-    masm.storeValue(thisv, Address(output, FunctionExtended::offsetOfArrowThisSlot()));
+    static_assert(FunctionExtended::NUM_EXTENDED_SLOTS == 2, "All slots must be initialized");
+    static_assert(FunctionExtended::ARROW_THIS_SLOT == 0, "|this| must be stored in first slot");
+    masm.storeValue(thisv, Address(output, FunctionExtended::offsetOfExtendedSlot(0)));
+    masm.storeValue(UndefinedValue(), Address(output, FunctionExtended::offsetOfExtendedSlot(1)));
 
     masm.bind(ool->rejoin());
     return true;
 }
 
 void
 CodeGenerator::emitLambdaInit(Register output, Register scopeChain,
                               const LambdaFunctionInfo &info)
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -539,18 +539,25 @@ bool IsConstructor(const Value &v);
  * Most functions do not have these extensions, but enough do that efficient
  * storage is required (no malloc'ed reserved slots).
  */
 class FunctionExtended : public JSFunction
 {
   public:
     static const unsigned NUM_EXTENDED_SLOTS = 2;
 
+    /* Arrow functions store their lexical |this| in the first extended slot. */
+    static const unsigned ARROW_THIS_SLOT = 0;
+
+    static inline size_t offsetOfExtendedSlot(unsigned which) {
+        MOZ_ASSERT(which < NUM_EXTENDED_SLOTS);
+        return offsetof(FunctionExtended, extendedSlots) + which * sizeof(HeapValue);
+    }
     static inline size_t offsetOfArrowThisSlot() {
-        return offsetof(FunctionExtended, extendedSlots) + 0 * sizeof(HeapValue);
+        return offsetOfExtendedSlot(ARROW_THIS_SLOT);
     }
 
   private:
     friend class JSFunction;
 
     /* Reserved slots available for storage by particular native functions. */
     HeapValue extendedSlots[NUM_EXTENDED_SLOTS];
 };