Bug 1260660 - Avoid unaligned memory accesses when patching code r=nbp
authorJan de Mooij <jdemooij@mozilla.com>
Wed, 05 Oct 2016 16:29:37 +0200
changeset 421216 9b92a393ace0aeed531730cb94a5ac366c23e32f
parent 421215 102781b7f2693d4876fc38de46dcc58957e677fa
child 421217 357de2a44d10d04ef93cd701ae3dc2a7aed6ec54
push id31424
push userbmo:afarre@mozilla.com
push dateWed, 05 Oct 2016 16:04:50 +0000
reviewersnbp
bugs1260660
milestone52.0a1
Bug 1260660 - Avoid unaligned memory accesses when patching code r=nbp
js/src/jit/x86-shared/Assembler-x86-shared.cpp
js/src/jit/x86-shared/Patching-x86-shared.h
--- a/js/src/jit/x86-shared/Assembler-x86-shared.cpp
+++ b/js/src/jit/x86-shared/Assembler-x86-shared.cpp
@@ -46,39 +46,41 @@ AssemblerX86Shared::copyPreBarrierTable(
         memcpy(dest, preBarriers_.buffer(), preBarriers_.length());
 }
 
 static void
 TraceDataRelocations(JSTracer* trc, uint8_t* buffer, CompactBufferReader& reader)
 {
     while (reader.more()) {
         size_t offset = reader.readUnsigned();
-        void** ptr = X86Encoding::GetPointerRef(buffer + offset);
+        void* ptr = X86Encoding::GetPointer(buffer + offset);
 
 #ifdef JS_PUNBOX64
         // All pointers on x64 will have the top bits cleared. If those bits
         // are not cleared, this must be a Value.
-        uintptr_t* word = reinterpret_cast<uintptr_t*>(ptr);
-        if (*word >> JSVAL_TAG_SHIFT) {
+        uintptr_t word = reinterpret_cast<uintptr_t>(ptr);
+        if (word >> JSVAL_TAG_SHIFT) {
             jsval_layout layout;
-            layout.asBits = *word;
+            layout.asBits = word;
             Value v = IMPL_TO_JSVAL(layout);
-            TraceManuallyBarrieredEdge(trc, &v, "ion-masm-value");
-            if (*word != JSVAL_TO_IMPL(v).asBits) {
+            TraceManuallyBarrieredEdge(trc, &v, "jit-masm-value");
+            if (word != JSVAL_TO_IMPL(v).asBits) {
                 // Only update the code if the Value changed, because the code
                 // is not writable if we're not moving objects.
-                *word = JSVAL_TO_IMPL(v).asBits;
+                X86Encoding::SetPointer(buffer + offset, (void*)JSVAL_TO_IMPL(v).asBits);
             }
             continue;
         }
 #endif
 
         // No barrier needed since these are constants.
-        TraceManuallyBarrieredGenericPointerEdge(trc, reinterpret_cast<gc::Cell**>(ptr),
-                                                 "ion-masm-ptr");
+        gc::Cell* cellPtr = reinterpret_cast<gc::Cell*>(ptr);
+        TraceManuallyBarrieredGenericPointerEdge(trc, &cellPtr, "jit-masm-ptr");
+        if (cellPtr != ptr)
+            X86Encoding::SetPointer(buffer + offset, cellPtr);
     }
 }
 
 
 void
 AssemblerX86Shared::TraceDataRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader)
 {
     ::TraceDataRelocations(trc, code->raw(), reader);
--- a/js/src/jit/x86-shared/Patching-x86-shared.h
+++ b/js/src/jit/x86-shared/Patching-x86-shared.h
@@ -10,41 +10,39 @@
 namespace js {
 namespace jit {
 
 namespace X86Encoding {
 
 inline void*
 GetPointer(const void* where)
 {
-    return reinterpret_cast<void* const*>(where)[-1];
-}
-
-inline void**
-GetPointerRef(void* where)
-{
-    return &reinterpret_cast<void**>(where)[-1];
+    void* res;
+    memcpy(&res, (const char*)where - sizeof(void*), sizeof(void*));
+    return res;
 }
 
 inline void
 SetPointer(void* where, const void* value)
 {
-    reinterpret_cast<const void**>(where)[-1] = value;
+    memcpy((char*)where - sizeof(void*), &value, sizeof(void*));
 }
 
 inline int32_t
 GetInt32(const void* where)
 {
-    return reinterpret_cast<const int32_t*>(where)[-1];
+    int32_t res;
+    memcpy(&res, (const char*)where - sizeof(int32_t), sizeof(int32_t));
+    return res;
 }
 
 inline void
 SetInt32(void* where, int32_t value)
 {
-    reinterpret_cast<int32_t*>(where)[-1] = value;
+    memcpy((char*)where - sizeof(int32_t), &value, sizeof(int32_t));
 }
 
 inline void
 SetRel32(void* from, void* to)
 {
     intptr_t offset = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(from);
     MOZ_ASSERT(offset == static_cast<int32_t>(offset),
                "offset is too great for a 32-bit relocation");