Bug 1254164 - Make aliasedBodyLevelLexicalBegin a uint32. r=Waldo, a=lizzard
authorShu-yu Guo <shu@rfrn.org>
Fri, 18 Mar 2016 15:07:27 -0700
changeset 323644 43fc1a8c20e13f2bf1fcddcae5bb5bd12ebe5ef3
parent 323643 372c2ef180b8b5054159170b5330c4cf1f6060e5
child 323645 35a5dfe62c0b08e0af289f0969e6ef91e9b151dc
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo, lizzard
bugs1254164
milestone47.0a2
Bug 1254164 - Make aliasedBodyLevelLexicalBegin a uint32. r=Waldo, a=lizzard
js/src/jit-test/tests/parser/bug-1254164.js
js/src/jsscript.cpp
js/src/jsscript.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1254164.js
@@ -0,0 +1,6 @@
+// |jit-test| slow;
+
+var s = '';
+for (var i = 0; i < 70000; i++)
+    s += 'function x' + i + '() { x' + i + '(); }\n';
+eval("(function() { " + s + " })();");
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -126,17 +126,20 @@ Bindings::initWithTemporaryStorage(Exclu
     // JITs when interpreting/compiling aliasedvar ops.)
 
     // Since unaliased variables are, by definition, only accessed by local
     // operations and never through the scope chain, only give shapes to
     // aliased variables. While the debugger may observe any scope object at
     // any time, such accesses are mediated by DebugScopeProxy (see
     // DebugScopeProxy::handleUnaliasedAccess).
     uint32_t nslots = CallObject::RESERVED_SLOTS;
-    uint32_t aliasedBodyLevelLexicalBegin = UINT16_MAX;
+
+    // Unless there are aliased body-level lexical bindings at all, set the
+    // begin index to an impossible slot number.
+    uint32_t aliasedBodyLevelLexicalBegin = LOCALNO_LIMIT;
     for (BindingIter bi(self); bi; bi++) {
         if (bi->aliased()) {
             // Per ES6, lexical bindings cannot be accessed until
             // initialized. Remember the first aliased slot that is a
             // body-level lexical, so that they may be initialized to sentinel
             // magic values.
             if (numBodyLevelLexicals > 0 &&
                 nslots < aliasedBodyLevelLexicalBegin &&
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -223,18 +223,18 @@ class Bindings
     template <typename Outer> friend class BindingsOperations;
     template <typename Outer> friend class MutableBindingsOperations;
 
     RelocatablePtrShape callObjShape_;
     uintptr_t bindingArrayAndFlag_;
     uint16_t numArgs_;
     uint16_t numBlockScoped_;
     uint16_t numBodyLevelLexicals_;
-    uint16_t aliasedBodyLevelLexicalBegin_;
     uint16_t numUnaliasedBodyLevelLexicals_;
+    uint32_t aliasedBodyLevelLexicalBegin_;
     uint32_t numVars_;
     uint32_t numUnaliasedVars_;
 
 #if JS_BITS_PER_WORD == 32
     // Bindings is allocated inline inside JSScript, which needs to be
     // gc::Cell aligned.
     uint32_t padding_;
 #endif
@@ -351,16 +351,20 @@ class Bindings
 
     Binding* begin() const { return bindingArray(); }
     Binding* end() const { return bindingArray() + count(); }
 
     static void trace(Bindings* self, JSTracer* trc) { self->trace(trc); }
     void trace(JSTracer* trc);
 };
 
+// If this fails, add/remove padding within Bindings.
+static_assert(sizeof(Bindings) % js::gc::CellSize == 0,
+              "Size of Bindings must be an integral multiple of js::gc::CellSize");
+
 template <class Outer>
 class BindingsOperations
 {
     const Bindings& bindings() const { return static_cast<const Outer*>(this)->get(); }
 
   public:
     // Direct data access to the underlying bindings.
     const RelocatablePtrShape& callObjShape() const {
@@ -433,17 +437,17 @@ class MutableBindingsOperations : public
     void setNumArgs(uint16_t num) { bindings().numArgs_ = num; }
     void setNumVars(uint32_t num) { bindings().numVars_ = num; }
     void setNumBodyLevelLexicals(uint16_t num) { bindings().numBodyLevelLexicals_ = num; }
     void setNumBlockScoped(uint16_t num) { bindings().numBlockScoped_ = num; }
     void setNumUnaliasedVars(uint32_t num) { bindings().numUnaliasedVars_ = num; }
     void setNumUnaliasedBodyLevelLexicals(uint16_t num) {
         bindings().numUnaliasedBodyLevelLexicals_ = num;
     }
-    void setAliasedBodyLevelLexicalBegin(uint16_t offset) {
+    void setAliasedBodyLevelLexicalBegin(uint32_t offset) {
         bindings().aliasedBodyLevelLexicalBegin_ = offset;
     }
     uint8_t* switchToScriptStorage(Binding* permanentStorage) {
         return bindings().switchToScriptStorage(permanentStorage);
     }
 };
 
 template <>