Make sure trace native stack is 16-byte aligned (bug 534590, r=lw).
authorDavid Anderson <danderson@mozilla.com>
Thu, 07 Jan 2010 17:20:00 -0800
changeset 37037 404c6c7b32c348ab37a866aa693d3ac196d39dcb
parent 37036 ad40bcea2f5af26b67381dfe92555fcb9fccb0f6
child 37038 52f371d2e19424fd8ae7d44ca0e3a0901feb0311
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslw
bugs534590
milestone1.9.3a1pre
Make sure trace native stack is 16-byte aligned (bug 534590, r=lw).
js/src/jscntxt.h
js/src/jstracer.cpp
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -209,17 +209,17 @@ struct JSTraceMonitor {
      */
     JSContext               *tracecx;
 
     /*
      * Cached storage to use when executing on trace. While we may enter nested
      * traces, we always reuse the outer trace's storage, so never need more
      * than of these.
      */
-    TraceNativeStorage      storage;
+    TraceNativeStorage      *storage;
 
     /*
      * There are 5 allocators here.  This might seem like overkill, but they
      * have different lifecycles, and by keeping them separate we keep the
      * amount of retained memory down significantly.  They are flushed (ie.
      * all the allocated memory is freed) periodically.
      *
      * - dataAlloc has the lifecycle of the monitor.  It's flushed only when
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -102,16 +102,17 @@ using namespace nanojit;
  * Never use JSVAL_IS_BOOLEAN because it restricts the value (true, false) and
  * the type. What you want to use is JSVAL_IS_SPECIAL(x) and then handle the
  * undefined case properly (bug 457363).
  */
 #undef JSVAL_IS_BOOLEAN
 #define JSVAL_IS_BOOLEAN(x) JS_STATIC_ASSERT(0)
 
 JS_STATIC_ASSERT(sizeof(JSTraceType) == 1);
+JS_STATIC_ASSERT(offsetof(TraceNativeStorage, stack_global_buf) % 16 == 0);
 
 /* Map to translate a type tag into a printable representation. */
 static const char typeChar[] = "OIDXSNBF";
 static const char tagChar[]  = "OIDISIBI";
 
 /* Blacklist parameters. */
 
 /*
@@ -6448,20 +6449,20 @@ FindVMCompatiblePeer(JSContext* cx, JSOb
  * This reuse depends on the invariant that only one trace uses |tm->storage| at
  * a time. This is subtley correct in lieu of deep bail; see comment for
  * |deepBailSp| in js_DeepBail.
  */
 JS_ALWAYS_INLINE
 InterpState::InterpState(JSContext* cx, JSTraceMonitor* tm, TreeFragment* f,
                          uintN& inlineCallCount, VMSideExit** innermostNestedGuardp)
   : cx(cx),
-    stackBase(tm->storage.stack()),
+    stackBase(tm->storage->stack()),
     sp(stackBase + f->nativeStackBase / sizeof(double)),
-    eos(tm->storage.global()),
-    callstackBase(tm->storage.callstack()),
+    eos(tm->storage->global()),
+    callstackBase(tm->storage->callstack()),
     sor(callstackBase),
     rp(callstackBase),
     eor(callstackBase + JS_MIN(MAX_CALL_STACK_ENTRIES,
                                JS_MAX_INLINE_CALL_COUNT - inlineCallCount)),
     lastTreeExitGuard(NULL),
     lastTreeCallGuard(NULL),
     rpAtLastTreeCall(NULL),
     outermostTree(f),
@@ -6488,18 +6489,18 @@ InterpState::InterpState(JSContext* cx, 
      */
     JS_ASSERT(inlineCallCount <= JS_MAX_INLINE_CALL_COUNT);
 
 #ifdef DEBUG
     /*
      * Cannot 0xCD-fill global frame since it may overwrite a bailed outer
      * ExecuteTree's 0xdeadbeefdeadbeef marker.
      */
-    memset(tm->storage.stack(), 0xCD, MAX_NATIVE_STACK_SLOTS * sizeof(double));
-    memset(tm->storage.callstack(), 0xCD, MAX_CALL_STACK_ENTRIES * sizeof(FrameInfo*));
+    memset(tm->storage->stack(), 0xCD, MAX_NATIVE_STACK_SLOTS * sizeof(double));
+    memset(tm->storage->callstack(), 0xCD, MAX_CALL_STACK_ENTRIES * sizeof(FrameInfo*));
 #endif
 }
 
 JS_ALWAYS_INLINE
 InterpState::~InterpState()
 {
     JS_ASSERT(!nativeVp);
 
@@ -6584,18 +6585,18 @@ ExecuteTree(JSContext* cx, TreeFragment*
     JS_ASSERT(f->root == f && f->code());
     JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
 
     if (!ScopeChainCheck(cx, f))
         return NULL;
 
     /* Initialize trace state. */
     InterpState state(cx, tm, f, inlineCallCount, innermostNestedGuardp);
-    double* stack = tm->storage.stack();
-    double* global = tm->storage.global();
+    double* stack = tm->storage->stack();
+    double* global = tm->storage->global();
     JSObject* globalObj = f->globalObj;
     unsigned ngslots = f->globalSlots->length();
     uint16* gslots = f->globalSlots->data();
 
     BuildNativeFrame(cx, globalObj, 0 /* callDepth */, ngslots, gslots,
                      f->typeMap.data(), global, stack);
 
     AUDIT(traceTriggered);
@@ -6603,26 +6604,26 @@ ExecuteTree(JSContext* cx, TreeFragment*
                       "entering trace at %s:%u@%u, native stack slots: %u code: %p\n",
                       cx->fp->script->filename,
                       js_FramePCToLineNumber(cx, cx->fp),
                       FramePCOffset(cx->fp),
                       f->maxNativeStackSlots,
                       f->code());
 
     debug_only_stmt(uint32 globalSlots = STOBJ_NSLOTS(globalObj);)
-    debug_only_stmt(*(uint64*)&tm->storage.global()[globalSlots] = 0xdeadbeefdeadbeefLL;)
+    debug_only_stmt(*(uint64*)&tm->storage->global()[globalSlots] = 0xdeadbeefdeadbeefLL;)
 
     /* Execute trace. */
 #ifdef MOZ_TRACEVIS
     VMSideExit* lr = (TraceVisStateObj(cx, S_NATIVE), ExecuteTrace(cx, f, state));
 #else
     VMSideExit* lr = ExecuteTrace(cx, f, state);
 #endif
 
-    JS_ASSERT(*(uint64*)&tm->storage.global()[globalSlots] == 0xdeadbeefdeadbeefLL);
+    JS_ASSERT(*(uint64*)&tm->storage->global()[globalSlots] == 0xdeadbeefdeadbeefLL);
     JS_ASSERT_IF(lr->exitType == LOOP_EXIT, !lr->calldepth);
 
     /* Restore interpreter state. */
     LeaveTree(state, lr);
     return state.innermost;
 }
 
 class Guardian {
@@ -7636,16 +7637,17 @@ js_InitJIT(JSTraceMonitor *tm)
 
     JS_ASSERT(!tm->dataAlloc && !tm->traceAlloc && !tm->codeAlloc);
     tm->dataAlloc = new VMAllocator();
     tm->traceAlloc = new VMAllocator();
     tm->tempAlloc = new VMAllocator();
     tm->reTempAlloc = new VMAllocator();
     tm->codeAlloc = new CodeAlloc();
     tm->frameCache = new FrameInfoCache(tm->dataAlloc);
+    tm->storage = new TraceNativeStorage();
     tm->flush();
     verbose_only( tm->branches = NULL; )
 
 #if !defined XP_WIN
     debug_only(memset(&jitstats, 0, sizeof(jitstats)));
 #endif
 
 #ifdef JS_JIT_SPEW
@@ -7767,16 +7769,21 @@ js_FinishJIT(JSTraceMonitor *tm)
         delete tm->tempAlloc;
         tm->tempAlloc = NULL;
     }
 
     if (tm->reTempAlloc) {
         delete tm->reTempAlloc;
         tm->reTempAlloc = NULL;
     }
+
+    if (tm->storage) {
+        delete tm->storage;
+        tm->storage = NULL;
+    }
 }
 
 void
 js_PurgeJITOracle()
 {
     oracle.clear();
 }