Bug 1253115 - BaldrMonkey: Implement initial load/store offset support. r=luke
authorDan Gohman <sunfish@mozilla.com>
Fri, 04 Mar 2016 07:57:29 -0800
changeset 323129 c7f58f4320c518f1c00b2d3cfc2ef111bbf9f527
parent 323128 590ae9fe87592f60b50597c68dd8a0d338d90925
child 323130 b7b05662f609a82cd3ee724bed7e9be144f3fb54
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)
reviewersluke
bugs1253115
milestone47.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 1253115 - BaldrMonkey: Implement initial load/store offset support. r=luke
js/src/asmjs/Wasm.cpp
js/src/asmjs/WasmIonCompile.cpp
js/src/jit-test/tests/wasm/basic-memory.js
--- a/js/src/asmjs/Wasm.cpp
+++ b/js/src/asmjs/Wasm.cpp
@@ -381,19 +381,16 @@ DecodeIfElse(FunctionDecoder& f, bool ha
 
 static bool
 DecodeLoadStoreAddress(FunctionDecoder &f)
 {
     uint32_t offset;
     if (!f.d().readVarU32(&offset))
         return f.fail("expected memory access offset");
 
-    if (offset != 0)
-        return f.fail("NYI: address offsets");
-
     uint32_t align;
     if (!f.d().readVarU32(&align))
         return f.fail("expected memory access alignment");
 
     if (!mozilla::IsPowerOfTwo(align))
         return f.fail("memory access alignment must be a power of two");
 
     return DecodeExpr(f, ExprType::I32);
--- a/js/src/asmjs/WasmIonCompile.cpp
+++ b/js/src/asmjs/WasmIonCompile.cpp
@@ -1360,32 +1360,42 @@ EmitLoadGlobal(FunctionCompiler& f, Expr
 }
 
 static bool EmitExpr(FunctionCompiler&, ExprType, MDefinition**);
 
 static bool
 EmitHeapAddress(FunctionCompiler& f, MDefinition** base, MAsmJSHeapAccess* access)
 {
     uint32_t offset = f.readVarU32();
-    MOZ_ASSERT(offset == 0, "Non-zero offsets not supported yet");
     access->setOffset(offset);
 
     uint32_t align = f.readVarU32();
     access->setAlign(align);
 
     if (!EmitExpr(f, ExprType::I32, base))
         return false;
 
-    // TODO Remove this (and the viewType param) after implementing unaligned
-    // loads/stores.
     if (f.mg().isAsmJS()) {
         MOZ_ASSERT(offset == 0 && "asm.js validation does not produce load/store offsets");
         return true;
     }
 
+    // TODO Remove this after implementing non-wraparound offset semantics.
+    uint32_t endOffset = access->endOffset();
+    if (endOffset < offset)
+        return false;
+    bool accessNeedsBoundsCheck = true;
+    if (endOffset > f.mirGen().foldableOffsetRange(accessNeedsBoundsCheck)) {
+        MDefinition* rhs = f.constant(Int32Value(offset), MIRType_Int32);
+        *base = f.binary<MAdd>(*base, rhs, MIRType_Int32);
+        offset = 0;
+        access->setOffset(offset);
+    }
+
+    // TODO Remove this after implementing unaligned loads/stores.
     int32_t maskVal = ~(Scalar::byteSize(access->accessType()) - 1);
     if (maskVal == -1)
         return true;
 
     offset &= maskVal;
     access->setOffset(offset);
 
     MDefinition* mask = f.constant(Int32Value(maskVal), MIRType_Int32);
--- a/js/src/jit-test/tests/wasm/basic-memory.js
+++ b/js/src/jit-test/tests/wasm/basic-memory.js
@@ -73,30 +73,30 @@ function testStoreError(type, ext, base,
   ), Error, errorMsg);
 }
 
 testLoad('i32', '', 0, 0, 0, 0x03020100);
 
 testLoad('i32', '', 1, 0, 0, 0x03020100);   // TODO: unaligned NYI
 //testLoad('i32', '', 1, 0, 0, 0x04030201); // TODO: unaligned NYI
 
-//testLoad('i32', '', 0, 1, 0, 0x01020304); // TODO: offsets NYI
-//testLoad('i32', '', 1, 1, 4, 0x02030405); // TODO: offsets NYI
+testLoad('i32', '', 0, 4, 0, 0x07060504);
+//testLoad('i32', '', 1, 3, 4, 0x07060504); // TODO: unaligned base NYI
 //testLoad('i64', '', 0, 0, 0, 0x0001020304050607); // TODO: i64 NYI
 //testLoad('i64', '', 1, 0, 0, 0x0102030405060708); // TODO: i64 NYI
 //testLoad('i64', '', 0, 1, 0, 0x0102030405060708); // TODO: i64 NYI
 //testLoad('i64', '', 1, 1, 4, 0x0203040506070809); // TODO: i64 NYI
 testLoad('f32', '', 0, 0, 0, 3.820471434542632e-37);
 //testLoad('f32', '', 1, 0, 0, 1.539989614439558e-36); // TODO: unaligned NYI
-//testLoad('f32', '', 0, 1, 0, 0x01020304); // TODO: offsets NYI
-//testLoad('f32', '', 1, 1, 4, 0x02030405); // TODO: offsets NYI
+testLoad('f32', '', 0, 4, 0, 1.0082513512365273e-34);
+//testLoad('f32', '', 1, 3, 4, 1.0082513512365273e-34); // TODO: unaligned base NYI
 testLoad('f64', '', 0, 0, 0, 7.949928895127363e-275);
 //testLoad('f64', '', 1, 0, 0, 5.447603722011605e-270); // TODO: unaligned NYI
-//testLoad('f64', '', 0, 1, 0, 0x01020304); // TODO: offsets NYI
-//testLoad('f64', '', 1, 1, 4, 0x02030405); // TODO: offsets NYI
+testLoad('f64', '', 0, 8, 0, 3.6919162048650923e-236);
+//testLoad('f64', '', 1, 7, 4, 3.6919162048650923e-236); // TODO: unaligned base NYI
 
 testLoad('i32', '8_s', 16, 0, 0, -0x10);
 testLoad('i32', '8_u', 16, 0, 0, 0xf0);
 testLoad('i32', '16_s', 16, 0, 0, -0xe10);
 testLoad('i32', '16_u', 16, 0, 0, 0xf1f0);
 
 // When these tests fail, uncomment the load/store tests below.
 function testLoadNYI(ext) {
@@ -133,22 +133,22 @@ testStoreNYI('32');
 //testStore('i64', '', 0, 1, 0, 0xc0c1d3d4e6e7090a); // TODO: i64 NYI
 //testStore('i64', '', 1, 1, 4, 0xc0c1d3d4e6e7090a); // TODO: i64 NYI
 //testStore('i64', '8', 0, 0, 0, 0x23); // TODO: i64 NYI
 //testStore('i64', '16', 0, 0, 0, 0x23); // TODO: i64 NYI
 //testStore('i64', '32', 0, 0, 0, 0x23); // TODO: i64 NYI
 
 testStore('f32', '', 0, 0, 0, 0.01234566979110241);
 //testStore('f32', '', 1, 0, 0, 0.01234566979110241); // TODO: unaligned NYI
-//testStore('f32', '', 0, 1, 0, 0.01234567); // TODO: offsets NYI
-//testStore('f32', '', 1, 1, 4, 0.01234567); // TODO: offsets NYI
+testStore('f32', '', 0, 4, 0, 0.01234566979110241);
+//testStore('f32', '', 1, 3, 4, 0.01234566979110241); // TODO: unaligned base NYI
 testStore('f64', '', 0, 0, 0, 0.89012345);
 //testStore('f64', '', 1, 0, 0, 0.89012345); // TODO: unaligned NYI
-//testStore('f64', '', 0, 1, 0, 0.89012345); // TODO: offsets NYI
-//testStore('f64', '', 1, 1, 4, 0.89012345); // TODO: offsets NYI
+testStore('f64', '', 0, 8, 0, 0.89012345);
+testStore('f64', '', 1, 7, 4, 0.89012345);
 
 testStore('i32', '8', 0, 0, 0, 0x23);
 testStore('i32', '16', 0, 0, 0, 0x2345);
 
 testLoadError('i32', '', 0, 0, 3, /memory access alignment must be a power of two/);
 testStoreError('i32', '', 0, 0, 3, /memory access alignment must be a power of two/);
 
 assertErrorMessage(() => wasmEvalText('(module (memory 1) (func (f64.store offset=0 (i32.const 0) (i32.const 0))))'), TypeError, mismatchError("i32", "f64"));