Bug 1002878 - Fix misalignment caused by TypeScript being empty. r=bhackett
authorJim Chen <nchen@mozilla.com>
Tue, 06 May 2014 10:17:00 -0400
changeset 201089 f60a35a375f65e6bc43d873cdca422271a73e1a7
parent 201088 02422599064327df97111d600148187cd95984a5
child 201090 6f4bd1dcbc0f06a873e018b00bc7d155dc1c0737
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs1002878
milestone32.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 1002878 - Fix misalignment caused by TypeScript being empty. r=bhackett
js/src/jsinfer.cpp
js/src/jsinfer.h
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -1187,17 +1187,17 @@ types::FinishCompilation(JSContext *cx, 
         types.compilerOutputs->back().invalidate();
         script->resetUseCount();
         return false;
     }
 
     return true;
 }
 
-MOZ_NEVER_INLINE void
+static void
 CheckDefinitePropertiesTypeSet(JSContext *cx, TemporaryTypeSet *frozen, StackTypeSet *actual)
 {
     // The definite properties analysis happens on the main thread, so no new
     // types can have been added to actual. The analysis may have updated the
     // contents of |frozen| though with new speculative types, and these need
     // to be reflected in |actual| for AddClearDefiniteFunctionUsesInScript
     // to work.
     if (!frozen->isSubset(actual)) {
@@ -3616,17 +3616,18 @@ bool
 JSScript::makeTypes(JSContext *cx)
 {
     JS_ASSERT(!types);
 
     AutoEnterAnalysis enter(cx);
 
     unsigned count = TypeScript::NumTypeSets(this);
 
-    TypeScript *typeScript = (TypeScript *) cx->calloc_(sizeof(TypeScript) + (sizeof(StackTypeSet) * count));
+    TypeScript *typeScript = (TypeScript *)
+        cx->calloc_(TypeScript::SizeIncludingTypeArray(count));
     if (!typeScript)
         return false;
 
     new(typeScript) TypeScript();
 
     TypeSet *typeArray = typeScript->typeArray();
 
     for (unsigned i = 0; i < count; i++)
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -1262,19 +1262,34 @@ ArrayPrototypeHasIndexedProperty(Compile
 bool
 TypeCanHaveExtraIndexedProperties(CompilerConstraintList *constraints, TemporaryTypeSet *types);
 
 /* Persistent type information for a script, retained across GCs. */
 class TypeScript
 {
     friend class ::JSScript;
 
+    // Variable-size array
+    StackTypeSet typeArray_[1];
+
   public:
     /* Array of type type sets for variables and JOF_TYPESET ops. */
-    StackTypeSet *typeArray() const { return (StackTypeSet *) (uintptr_t(this) + sizeof(TypeScript)); }
+    StackTypeSet *typeArray() const {
+        // Ensure typeArray_ is the last data member of TypeScript.
+        JS_STATIC_ASSERT(sizeof(TypeScript) ==
+            sizeof(typeArray_) + offsetof(TypeScript, typeArray_));
+        return const_cast<StackTypeSet *>(typeArray_);
+    }
+
+    static inline size_t SizeIncludingTypeArray(size_t arraySize) {
+        // Ensure typeArray_ is the last data member of TypeScript.
+        JS_STATIC_ASSERT(sizeof(TypeScript) ==
+            sizeof(StackTypeSet) + offsetof(TypeScript, typeArray_));
+        return offsetof(TypeScript, typeArray_) + arraySize * sizeof(StackTypeSet);
+    }
 
     static inline unsigned NumTypeSets(JSScript *script);
 
     static inline StackTypeSet *ThisTypes(JSScript *script);
     static inline StackTypeSet *ArgTypes(JSScript *script, unsigned i);
 
     /* Get the type set for values observed at an opcode. */
     static inline StackTypeSet *BytecodeTypes(JSScript *script, jsbytecode *pc);