Title: [209852] trunk
Revision
209852
Author
[email protected]
Date
2016-12-14 20:36:08 -0800 (Wed, 14 Dec 2016)

Log Message

Wasm should decode constants correctly
https://bugs.webkit.org/show_bug.cgi?id=165886

Reviewed by Saam Barati.

JSTests:

* wasm/Builder.js:
(const._isValidValue):
* wasm/Builder_WebAssemblyBinary.js:
(const.putOp):
* wasm/LowLevelBinary.js:
(export.default.LowLevelBinary.prototype.float):
(export.default.LowLevelBinary.prototype.double):
* wasm/function-tests/f32-const.js: Added.
* wasm/function-tests/f64-const.js: Added.
* wasm/function-tests/i32-const.js: Added.
* wasm/wasm.json:

Source/_javascript_Core:

This patch fixes how we decode the constant part of i32, i64, f32,
and f64.const opcodes.

* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser<Context>::parseExpression):
* wasm/wasm.json:

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (209851 => 209852)


--- trunk/JSTests/ChangeLog	2016-12-15 03:48:49 UTC (rev 209851)
+++ trunk/JSTests/ChangeLog	2016-12-15 04:36:08 UTC (rev 209852)
@@ -1,3 +1,22 @@
+2016-12-14  Keith Miller  <[email protected]>
+
+        Wasm should decode constants correctly
+        https://bugs.webkit.org/show_bug.cgi?id=165886
+
+        Reviewed by Saam Barati.
+
+        * wasm/Builder.js:
+        (const._isValidValue):
+        * wasm/Builder_WebAssemblyBinary.js:
+        (const.putOp):
+        * wasm/LowLevelBinary.js:
+        (export.default.LowLevelBinary.prototype.float):
+        (export.default.LowLevelBinary.prototype.double):
+        * wasm/function-tests/f32-const.js: Added.
+        * wasm/function-tests/f64-const.js: Added.
+        * wasm/function-tests/i32-const.js: Added.
+        * wasm/wasm.json:
+
 2016-12-14  Saam Barati  <[email protected]>
 
         WebAssembly: Add various low hanging fruit that will allow us to run the LLVM torture tests in Wasm

Modified: trunk/JSTests/wasm/Builder.js (209851 => 209852)


--- trunk/JSTests/wasm/Builder.js	2016-12-15 03:48:49 UTC (rev 209851)
+++ trunk/JSTests/wasm/Builder.js	2016-12-15 04:36:08 UTC (rev 209852)
@@ -35,7 +35,8 @@
 
 const _isValidValue = (value, type) => {
     switch (type) {
-    case "i32": return ((value & 0xFFFFFFFF) >>> 0) === value;
+    // We allow both signed and unsigned numbers.
+    case "i32": return -(2 ** 31) <= value && value < 2 ** 32;
     case "i64": throw new Error(`Unimplemented: value check for ${type}`); // FIXME https://bugs.webkit.org/show_bug.cgi?id=163420 64-bit values
     case "f32": return typeof(value) === "number" && isFinite(value);
     case "f64": return typeof(value) === "number" && isFinite(value);

Modified: trunk/JSTests/wasm/Builder_WebAssemblyBinary.js (209851 => 209852)


--- trunk/JSTests/wasm/Builder_WebAssemblyBinary.js	2016-12-15 03:48:49 UTC (rev 209851)
+++ trunk/JSTests/wasm/Builder_WebAssemblyBinary.js	2016-12-15 04:36:08 UTC (rev 209852)
@@ -72,6 +72,15 @@
             put(bin, type, op.immediates[i]);
         }
         break;
+    case "i32.const": {
+        assert.eq(op.immediates.length, 1);
+        let imm = op.immediates[0];
+        // Do a static cast to make large int32s signed.
+        if (imm >= 2 ** 31)
+            imm = imm - (2 ** 32);
+        put(bin, "varint32", imm);
+        break;
+    }
     case "br_table":
         put(bin, "varuint32", op.immediates.length - 1);
         for (let imm of op.immediates)

Modified: trunk/JSTests/wasm/LowLevelBinary.js (209851 => 209852)


--- trunk/JSTests/wasm/LowLevelBinary.js	2016-12-15 03:48:49 UTC (rev 209851)
+++ trunk/JSTests/wasm/LowLevelBinary.js	2016-12-15 04:36:08 UTC (rev 209852)
@@ -122,6 +122,30 @@
         this._push8(v >>> 16);
         this._push8(v >>> 24);
     }
+    float(v) {
+        if (isNaN(v))
+            throw new RangeError("unimplemented, NaNs");
+        // Unfortunately, we cannot just view the actual buffer as a Float32Array since it needs to be 4 byte aligned
+        let buffer = new ArrayBuffer(4);
+        let floatView = new Float32Array(buffer);
+        let int8View = new Uint8Array(buffer);
+        floatView[0] = v;
+        for (let byte of int8View)
+            this._push8(byte);
+    }
+
+    double(v) {
+        if (isNaN(v))
+            throw new RangeError("unimplemented, NaNs");
+        // Unfortunately, we cannot just view the actual buffer as a Float64Array since it needs to be 4 byte aligned
+        let buffer = new ArrayBuffer(8);
+        let floatView = new Float64Array(buffer);
+        let int8View = new Uint8Array(buffer);
+        floatView[0] = v;
+        for (let byte of int8View)
+            this._push8(byte);
+    }
+
     varuint32(v) {
         assert.isNumber(v);
         if (v < varuint32Min || varuint32Max < v)

Added: trunk/JSTests/wasm/function-tests/f32-const.js (0 => 209852)


--- trunk/JSTests/wasm/function-tests/f32-const.js	                        (rev 0)
+++ trunk/JSTests/wasm/function-tests/f32-const.js	2016-12-15 04:36:08 UTC (rev 209852)
@@ -0,0 +1,26 @@
+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const builder = (new Builder())
+      .Type().End()
+      .Function().End()
+      .Export()
+          .Function("answer")
+          .Function("minInt")
+      .End()
+      .Code()
+          .Function("answer", { params: [], ret: "f32" })
+              .F32Const(.5)
+          .End()
+
+          .Function("minInt", { params: [], ret: "f32" })
+             .F32Const(-1)
+          .End()
+
+      .End();
+
+const bin = builder.WebAssembly().get();
+const module = new WebAssembly.Module(bin);
+const instance = new WebAssembly.Instance(module);
+assert.eq(instance.exports.answer(), .5);
+assert.eq(instance.exports.minInt(), -1);

Added: trunk/JSTests/wasm/function-tests/f64-const.js (0 => 209852)


--- trunk/JSTests/wasm/function-tests/f64-const.js	                        (rev 0)
+++ trunk/JSTests/wasm/function-tests/f64-const.js	2016-12-15 04:36:08 UTC (rev 209852)
@@ -0,0 +1,26 @@
+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const builder = (new Builder())
+      .Type().End()
+      .Function().End()
+      .Export()
+          .Function("answer")
+          .Function("minInt")
+      .End()
+      .Code()
+          .Function("answer", { params: [], ret: "f64" })
+              .F64Const(42.424242)
+          .End()
+
+          .Function("minInt", { params: [], ret: "f64" })
+             .F64Const(-1)
+          .End()
+
+      .End();
+
+const bin = builder.WebAssembly().get();
+const module = new WebAssembly.Module(bin);
+const instance = new WebAssembly.Instance(module);
+assert.eq(instance.exports.answer(), 42.424242);
+assert.eq(instance.exports.minInt(), -1);

Added: trunk/JSTests/wasm/function-tests/i32-const.js (0 => 209852)


--- trunk/JSTests/wasm/function-tests/i32-const.js	                        (rev 0)
+++ trunk/JSTests/wasm/function-tests/i32-const.js	2016-12-15 04:36:08 UTC (rev 209852)
@@ -0,0 +1,31 @@
+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+
+const builder = (new Builder())
+      .Type().End()
+      .Function().End()
+      .Export()
+          .Function("answer")
+          .Function("minInt")
+      .End()
+      .Code()
+          .Function("answer", { params: [], ret: "i32" })
+              .I32Const(42)
+          .End()
+
+          .Function("minInt", { params: [], ret: "i32" })
+             .I32Const(-1)
+          .End()
+
+          .Function("minInt", { params: [], ret: "i32" })
+             .I32Const(0xffffffff)
+          .End()
+      .End();
+
+const bin = builder.WebAssembly().get();
+const module = new WebAssembly.Module(bin);
+const instance = new WebAssembly.Instance(module);
+assert.eq(instance.exports.answer(), 42);
+assert.eq(instance.exports.minInt(), -1);
+assert.eq(instance.exports.minInt(), -1);

Modified: trunk/JSTests/wasm/wasm.json (209851 => 209852)


--- trunk/JSTests/wasm/wasm.json	2016-12-15 03:48:49 UTC (rev 209851)
+++ trunk/JSTests/wasm/wasm.json	2016-12-15 04:36:08 UTC (rev 209852)
@@ -56,8 +56,8 @@
         "end":                 { "category": "control",    "value":  11, "return": [],           "parameter": [],                       "immediate": [],                                                                                         "description": "end a block, loop, or if" },
         "i32.const":           { "category": "special",    "value":  65, "return": ["i32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "varint32"}],                                           "description": "a constant value interpreted as i32" },
         "i64.const":           { "category": "special",    "value":  66, "return": ["i64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "varint64"}],                                           "description": "a constant value interpreted as i64" },
-        "f64.const":           { "category": "special",    "value":  68, "return": ["f64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "uint64"}],                                             "description": "a constant value interpreted as f64" },
-        "f32.const":           { "category": "special",    "value":  67, "return": ["f32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "uint32"}],                                             "description": "a constant value interpreted as f32" },
+        "f64.const":           { "category": "special",    "value":  68, "return": ["f64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "double"}],                                             "description": "a constant value interpreted as f64" },
+        "f32.const":           { "category": "special",    "value":  67, "return": ["f32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "float"}],                                             "description": "a constant value interpreted as f32" },
         "get_local":           { "category": "special",    "value":  32, "return": ["any"],    "parameter": [],                       "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "read a local variable or parameter" },
         "set_local":           { "category": "special",    "value":  33, "return": [],           "parameter": ["any"],                "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter" },
         "tee_local":           { "category": "special",    "value":  34, "return": ["any"],     "parameter": ["any"],                  "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter and return the same value" },

Modified: trunk/Source/_javascript_Core/ChangeLog (209851 => 209852)


--- trunk/Source/_javascript_Core/ChangeLog	2016-12-15 03:48:49 UTC (rev 209851)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-12-15 04:36:08 UTC (rev 209852)
@@ -1,3 +1,17 @@
+2016-12-14  Keith Miller  <[email protected]>
+
+        Wasm should decode constants correctly
+        https://bugs.webkit.org/show_bug.cgi?id=165886
+
+        Reviewed by Saam Barati.
+
+        This patch fixes how we decode the constant part of i32, i64, f32,
+        and f64.const opcodes.
+
+        * wasm/WasmFunctionParser.h:
+        (JSC::Wasm::FunctionParser<Context>::parseExpression):
+        * wasm/wasm.json:
+
 2016-12-14  Saam Barati  <[email protected]>
 
         WebAssembly: Add various low hanging fruit that will allow us to run the LLVM torture tests in Wasm

Modified: trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h (209851 => 209852)


--- trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h	2016-12-15 03:48:49 UTC (rev 209851)
+++ trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h	2016-12-15 04:36:08 UTC (rev 209852)
@@ -302,20 +302,34 @@
     }
 #undef CREATE_CASE
 
-    case OpType::F32Const:
-    case OpType::I32Const: {
+    case OpType::F32Const: {
         uint32_t constant;
-        if (!parseVarUInt32(constant))
+        if (!parseUInt32(constant))
             return false;
+        m_expressionStack.append(m_context.addConstant(F32, constant));
+        return true;
+    }
+
+    case OpType::I32Const: {
+        int32_t constant;
+        if (!parseVarInt32(constant))
+            return false;
         m_expressionStack.append(m_context.addConstant(I32, constant));
         return true;
     }
 
-    case OpType::F64Const:
-    case OpType::I64Const: {
+    case OpType::F64Const: {
         uint64_t constant;
-        if (!parseVarUInt64(constant))
+        if (!parseUInt64(constant))
             return false;
+        m_expressionStack.append(m_context.addConstant(F64, constant));
+        return true;
+    }
+
+    case OpType::I64Const: {
+        int64_t constant;
+        if (!parseVarInt64(constant))
+            return false;
         m_expressionStack.append(m_context.addConstant(I64, constant));
         return true;
     }

Modified: trunk/Source/_javascript_Core/wasm/wasm.json (209851 => 209852)


--- trunk/Source/_javascript_Core/wasm/wasm.json	2016-12-15 03:48:49 UTC (rev 209851)
+++ trunk/Source/_javascript_Core/wasm/wasm.json	2016-12-15 04:36:08 UTC (rev 209852)
@@ -56,13 +56,13 @@
         "end":                 { "category": "control",    "value":  11, "return": [],           "parameter": [],                       "immediate": [],                                                                                         "description": "end a block, loop, or if" },
         "i32.const":           { "category": "special",    "value":  65, "return": ["i32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "varint32"}],                                           "description": "a constant value interpreted as i32" },
         "i64.const":           { "category": "special",    "value":  66, "return": ["i64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "varint64"}],                                           "description": "a constant value interpreted as i64" },
-        "f64.const":           { "category": "special",    "value":  68, "return": ["f64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "uint64"}],                                             "description": "a constant value interpreted as f64" },
-        "f32.const":           { "category": "special",    "value":  67, "return": ["f32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "uint32"}],                                             "description": "a constant value interpreted as f32" },
-        "get_local":           { "category": "special",    "value":  32, "return": ["local"],    "parameter": [],                       "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "read a local variable or parameter" },
-        "set_local":           { "category": "special",    "value":  33, "return": [],           "parameter": ["local"],                "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter" },
-        "tee_local":           { "category": "special",    "value":  34, "return": ["prev"],     "parameter": ["any"],                  "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter and return the same value" },
-        "get_global":          { "category": "special",    "value":  35, "return": ["global"],   "parameter": [],                       "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "read a global variable" },
-        "set_global":          { "category": "special",    "value":  36, "return": [""],         "parameter": ["global"],               "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "write a global variable" },
+        "f64.const":           { "category": "special",    "value":  68, "return": ["f64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "double"}],                                             "description": "a constant value interpreted as f64" },
+        "f32.const":           { "category": "special",    "value":  67, "return": ["f32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "float"}],                                             "description": "a constant value interpreted as f32" },
+        "get_local":           { "category": "special",    "value":  32, "return": ["any"],    "parameter": [],                       "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "read a local variable or parameter" },
+        "set_local":           { "category": "special",    "value":  33, "return": [],           "parameter": ["any"],                "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter" },
+        "tee_local":           { "category": "special",    "value":  34, "return": ["any"],     "parameter": ["any"],                  "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter and return the same value" },
+        "get_global":          { "category": "special",    "value":  35, "return": ["any"],   "parameter": [],                       "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "read a global variable" },
+        "set_global":          { "category": "special",    "value":  36, "return": [],         "parameter": ["any"],               "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "write a global variable" },
         "call":                { "category": "call",       "value":  16, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "function_index", "type": "varuint32"}],                                          "description": "call a function by its index" },
         "call_indirect":       { "category": "call",       "value":  17, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "type_index",     "type": "varuint32"}, {"name": "reserved",     "type": "varuint1"}], "description": "call a function indirect with an expected signature" },
         "i32.load8_s":         { "category": "memory",     "value":  44, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to