Bug 965880 - OdinMonkey: don't forget to AutoUnprotectCode and prepareForAsmJS (r=bbouvier)
authorLuke Wagner <luke@mozilla.com>
Thu, 09 Oct 2014 20:04:41 -0500
changeset 233072 0fbe7cd05a11269bcdd7e43da91ff16994fd97ff
parent 233071 0402daa909e416b596ddac2980e916907ed27205
child 233073 8ac5fed378308a056073c03a4834aabda14860c9
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbouvier
bugs965880
milestone35.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 965880 - OdinMonkey: don't forget to AutoUnprotectCode and prepareForAsmJS (r=bbouvier)
js/src/asmjs/AsmJSLink.cpp
js/src/asmjs/AsmJSModule.cpp
js/src/asmjs/AsmJSModule.h
js/src/jit-test/tests/asm.js/testResize.js
--- a/js/src/asmjs/AsmJSLink.cpp
+++ b/js/src/asmjs/AsmJSLink.cpp
@@ -565,19 +565,29 @@ ChangeHeap(JSContext *cx, AsmJSModule &m
 {
     HandleValue bufferArg = args.get(0);
     if (!IsArrayBuffer(bufferArg)) {
         ReportIncompatible(cx, args);
         return false;
     }
 
     Rooted<ArrayBufferObject*> newBuffer(cx, &bufferArg.toObject().as<ArrayBufferObject>());
-    bool rval = module.changeHeap(newBuffer, cx);
+    uint32_t heapLength = newBuffer->byteLength();
+    if (heapLength & module.heapLengthMask() || heapLength < module.minHeapLength()) {
+        args.rval().set(BooleanValue(false));
+        return true;
+    }
 
-    args.rval().set(BooleanValue(rval));
+    MOZ_ASSERT(IsValidAsmJSHeapLength(heapLength));
+    MOZ_ASSERT(!IsDeprecatedAsmJSHeapLength(heapLength));
+
+    if (!ArrayBufferObject::prepareForAsmJS(cx, newBuffer, module.usesSignalHandlersForOOB()))
+        return false;
+
+    args.rval().set(BooleanValue(module.changeHeap(newBuffer, cx)));
     return true;
 }
 
 // An asm.js function stores, in its extended slots:
 //  - a pointer to the module from which it was returned
 //  - its index in the ordered list of exported functions
 static const unsigned ASM_MODULE_SLOT = 0;
 static const unsigned ASM_EXPORT_INDEX_SLOT = 1;
--- a/js/src/asmjs/AsmJSModule.cpp
+++ b/js/src/asmjs/AsmJSModule.cpp
@@ -726,16 +726,18 @@ AsmJSModule::staticallyLink(ExclusiveCon
     }
 
     MOZ_ASSERT(isStaticallyLinked());
 }
 
 void
 AsmJSModule::initHeap(Handle<ArrayBufferObjectMaybeShared *> heap, JSContext *cx)
 {
+    MOZ_ASSERT_IF(heap->is<ArrayBufferObject>(),
+                  heap->as<ArrayBufferObject>().isAsmJSArrayBuffer());
     MOZ_ASSERT(IsValidAsmJSHeapLength(heap->byteLength()));
     MOZ_ASSERT(dynamicallyLinked_);
     MOZ_ASSERT(!maybeHeap_);
 
     maybeHeap_ = heap;
     heapDatum() = heap->dataPointer();
 
 #if defined(JS_CODEGEN_X86)
@@ -767,16 +769,17 @@ AsmJSModule::initHeap(Handle<ArrayBuffer
     uint32_t heapLength = heap->byteLength();
     for (unsigned i = 0; i < heapAccesses_.length(); i++) {
         jit::Assembler::UpdateBoundsCheck(heapLength,
                                           (jit::Instruction*)(heapAccesses_[i].offset() + code_));
     }
 #endif
 }
 
+// This method assumes the caller has a live AutoUnprotectCode.
 void
 AsmJSModule::restoreHeapToInitialState(ArrayBufferObjectMaybeShared *maybePrevBuffer)
 {
 #if defined(JS_CODEGEN_X86)
     if (maybePrevBuffer) {
         // Subtract out the base-pointer added by AsmJSModule::initHeap.
         uint8_t *ptrBase = maybePrevBuffer->dataPointer();
         for (unsigned i = 0; i < heapAccesses_.length(); i++) {
@@ -788,16 +791,17 @@ AsmJSModule::restoreHeapToInitialState(A
         }
     }
 #endif
 
     maybeHeap_ = nullptr;
     heapDatum() = nullptr;
 }
 
+// This method assumes the caller has a live AutoUnprotectCode.
 void
 AsmJSModule::restoreToInitialState(ArrayBufferObjectMaybeShared *maybePrevBuffer,
                                    uint8_t *prevCode,
                                    ExclusiveContext *cx)
 {
 #ifdef DEBUG
     // Put the absolute links back to -1 so PatchDataWithValueCheck assertions
     // in staticallyLink are valid.
@@ -1545,34 +1549,28 @@ AsmJSModule::clone(JSContext *cx, Scoped
     // flush all of them at once.
     out.setAutoFlushICacheRange();
 
     out.restoreToInitialState(maybeHeap_, code_, cx);
     return true;
 }
 
 bool
-AsmJSModule::changeHeap(Handle<ArrayBufferObject*> newBuffer, JSContext *cx)
+AsmJSModule::changeHeap(Handle<ArrayBufferObject*> newHeap, JSContext *cx)
 {
     // Content JS should not be able to run (and change heap) from within an
     // interrupt callback, but in case it does, fail to change heap. Otherwise,
     // the heap can change at every single instruction which would prevent
     // future optimizations like heap-base hoisting.
     if (interrupted_)
         return false;
 
-    uint32_t heapLength = newBuffer->byteLength();
-    if (heapLength & pod.heapLengthMask_ || heapLength < pod.minHeapLength_)
-        return false;
-
-    MOZ_ASSERT(IsValidAsmJSHeapLength(heapLength));
-    MOZ_ASSERT(!IsDeprecatedAsmJSHeapLength(heapLength));
-
+    AutoUnprotectCode auc(cx, *this);
     restoreHeapToInitialState(maybeHeap_);
-    initHeap(newBuffer, cx);
+    initHeap(newHeap, cx);
     return true;
 }
 
 void
 AsmJSModule::setProfilingEnabled(bool enabled, JSContext *cx)
 {
     MOZ_ASSERT(isDynamicallyLinked());
 
--- a/js/src/asmjs/AsmJSModule.h
+++ b/js/src/asmjs/AsmJSModule.h
@@ -879,16 +879,20 @@ class AsmJSModule
         return srcBodyStart_;
     }
 
     // While these functions may be accessed at any time, their values will
     // change as the module is compiled.
     uint32_t minHeapLength() const {
         return pod.minHeapLength_;
     }
+    uint32_t heapLengthMask() const {
+        MOZ_ASSERT(pod.hasFixedMinHeapLength_);
+        return pod.heapLengthMask_;
+    }
     unsigned numFunctionCounts() const {
         return functionCounts_.length();
     }
     jit::IonScriptCounts *functionCounts(unsigned i) {
         return functionCounts_[i];
     }
 
     // about:memory reporting
--- a/js/src/jit-test/tests/asm.js/testResize.js
+++ b/js/src/jit-test/tests/asm.js/testResize.js
@@ -198,26 +198,29 @@ var {get, set, changeHeap} = asmLink(m, 
 
 assertEq(m.toString(), "function anonymous(glob, ffis, b) {\n" + USE_ASM + body + "\n}");
 assertEq(m.toSource(), "(function anonymous(glob, ffis, b) {\n" + USE_ASM + body + "\n})");
 assertEq(changeHeap.toString(), changeHeapSource);
 assertEq(changeHeap.toSource(), changeHeapSource);
 
 set(0, 42);
 set(4, 13);
+set(4, 13);
 assertEq(get(0), 42);
 assertEq(get(4), 13);
 set(BUF_CHANGE_MIN, 262);
 assertEq(get(BUF_CHANGE_MIN), 0);
 var buf2 = new ArrayBuffer(2*BUF_CHANGE_MIN);
 assertEq(changeHeap(buf2), true);
 assertEq(get(0), 0);
 assertEq(get(4), 0);
 set(BUF_CHANGE_MIN, 262);
 assertEq(get(BUF_CHANGE_MIN), 262);
+set(2*BUF_CHANGE_MIN, 262);
+assertEq(get(2*BUF_CHANGE_MIN), 0);
 changeHeap(buf1);
 assertEq(get(0), 42);
 assertEq(get(4), 13);
 set(BUF_CHANGE_MIN, 262);
 assertEq(get(BUF_CHANGE_MIN), 0);
 
 var buf1 = new ArrayBuffer(BUF_CHANGE_MIN);
 new Int32Array(buf1)[0] = 13;