<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[245496] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/245496">245496</a></dd>
<dt>Author</dt> <dd>justin_michaud@apple.com</dd>
<dt>Date</dt> <dd>2019-05-17 21:58:36 -0700 (Fri, 17 May 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>[WASM-References] Add support for Anyref in parameters and return types, Ref.null and Ref.is_null for Anyref values.
https://bugs.webkit.org/show_bug.cgi?id=197969

JSTests:

Reviewed by Keith Miller.

Support the anyref type in Builder.js, plus add some extra error logging.
Add new folder for wasm references tests.

* wasm.yaml:
* wasm/Builder.js:
(const._isValidValue):
* wasm/references/anyref_modules.js: Added.
(Call.3.RefIsNull.End.End.WebAssembly.js.ident):
(Call.3.RefIsNull.End.End.WebAssembly.js.make_null):
(Call.3.RefIsNull.End.End.WebAssembly):
(undefined):
* wasm/references/is_null.js: Added.
* wasm/references/is_null_error.js: Added.
* wasm/spec-harness/index.js:
* wasm/wasm.json:

Source/JavaScriptCore:

Reviewed by Keith Miller.

Add a new runtime option for wasm references.
Add support for Anyref as a value type.
Add support for Anyref in parameters and return types of Wasm functions. JSValues are marshalled into/out of wasm Anyrefs
        as a black box, except null which becomes a Nullref value. Nullref is not expressible in the bytecode or in the js API.
Add Ref.null and Ref.is_null for Anyref values. Support for these functions with funcrefs is out of scope.

* runtime/Options.h:
* wasm/WasmAirIRGenerator.cpp:
(JSC::Wasm::AirIRGenerator::tmpForType):
(JSC::Wasm::AirIRGenerator::AirIRGenerator):
(JSC::Wasm::AirIRGenerator::addConstant):
(JSC::Wasm::AirIRGenerator::addRefIsNull):
(JSC::Wasm::AirIRGenerator::addReturn):
* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::B3IRGenerator::addRefIsNull):
* wasm/WasmCallingConvention.h:
(JSC::Wasm::CallingConventionAir::marshallArgument const):
(JSC::Wasm::CallingConventionAir::setupCall const):
* wasm/WasmFormat.h:
(JSC::Wasm::isValueType):
* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser<Context>::FunctionParser):
(JSC::Wasm::FunctionParser<Context>::parseExpression):
(JSC::Wasm::FunctionParser<Context>::parseUnreachableExpression):
* wasm/WasmValidate.cpp:
(JSC::Wasm::Validate::addRefIsNull):
* wasm/generateWasmOpsHeader.py:
(bitSet):
* wasm/js/JSToWasm.cpp:
(JSC::Wasm::createJSToWasmWrapper):
* wasm/js/WasmToJS.cpp:
(JSC::Wasm::wasmToJS):
* wasm/js/WebAssemblyFunction.cpp:
(JSC::callWebAssemblyFunction):
(JSC::WebAssemblyFunction::jsCallEntrypointSlow):
* wasm/wasm.json:

Tools:

Run wasm tests additionally with wasmBBQUsesAir=0.

Reviewed by Keith Miller.

* Scripts/run-jsc-stress-tests:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestswasmBuilderjs">trunk/JSTests/wasm/Builder.js</a></li>
<li><a href="#trunkJSTestswasmspecharnessindexjs">trunk/JSTests/wasm/spec-harness/index.js</a></li>
<li><a href="#trunkJSTestswasmwasmjson">trunk/JSTests/wasm/wasm.json</a></li>
<li><a href="#trunkJSTestswasmyaml">trunk/JSTests/wasm.yaml</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmAirIRGeneratorcpp">trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp">trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmCallingConventionh">trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmFormath">trunk/Source/JavaScriptCore/wasm/WasmFormat.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmFunctionParserh">trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmValidatecpp">trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmgenerateWasmOpsHeaderpy">trunk/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSToWasmcpp">trunk/Source/JavaScriptCore/wasm/js/JSToWasm.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWasmToJScpp">trunk/Source/JavaScriptCore/wasm/js/WasmToJS.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyFunctioncpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmwasmjson">trunk/Source/JavaScriptCore/wasm/wasm.json</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsScriptsrunjscstresstests">trunk/Tools/Scripts/run-jsc-stress-tests</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li>trunk/JSTests/wasm/references/</li>
<li><a href="#trunkJSTestswasmreferencesanyref_modulesjs">trunk/JSTests/wasm/references/anyref_modules.js</a></li>
<li><a href="#trunkJSTestswasmreferencesis_nulljs">trunk/JSTests/wasm/references/is_null.js</a></li>
<li><a href="#trunkJSTestswasmreferencesis_null_errorjs">trunk/JSTests/wasm/references/is_null_error.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog  2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/JSTests/ChangeLog     2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -1,3 +1,26 @@
</span><ins>+2019-05-17  Justin Michaud  <justin_michaud@apple.com>
+
+        [WASM-References] Add support for Anyref in parameters and return types, Ref.null and Ref.is_null for Anyref values.
+        https://bugs.webkit.org/show_bug.cgi?id=197969
+
+        Reviewed by Keith Miller.
+
+        Support the anyref type in Builder.js, plus add some extra error logging.
+        Add new folder for wasm references tests.
+
+        * wasm.yaml:
+        * wasm/Builder.js:
+        (const._isValidValue):
+        * wasm/references/anyref_modules.js: Added.
+        (Call.3.RefIsNull.End.End.WebAssembly.js.ident):
+        (Call.3.RefIsNull.End.End.WebAssembly.js.make_null):
+        (Call.3.RefIsNull.End.End.WebAssembly):
+        (undefined):
+        * wasm/references/is_null.js: Added.
+        * wasm/references/is_null_error.js: Added.
+        * wasm/spec-harness/index.js:
+        * wasm/wasm.json:
+
</ins><span class="cx"> 2019-05-16  Ross Kirsling  <ross.kirsling@sony.com>
</span><span class="cx"> 
</span><span class="cx">         [JSC] Invalid AssignmentTargetType should be an early error.
</span></span></pre></div>
<a id="trunkJSTestswasmBuilderjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/Builder.js (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/Builder.js    2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/JSTests/wasm/Builder.js       2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx">     switch (type) {
</span><span class="cx">     // We allow both signed and unsigned numbers.
</span><span class="cx">     case "i32": return Math.round(value) === value && LLB.varint32Min <= value && value <= LLB.varuint32Max;
</span><ins>+    case "anyref": return true;
</ins><span class="cx">     case "i64": return true; // FIXME https://bugs.webkit.org/show_bug.cgi?id=163420 64-bit values
</span><span class="cx">     case "f32": return typeof(value) === "number" && isFinite(value);
</span><span class="cx">     case "f64": return typeof(value) === "number" && isFinite(value);
</span></span></pre></div>
<a id="trunkJSTestswasmreferencesanyref_modulesjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/references/anyref_modules.js (0 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/references/anyref_modules.js                          (rev 0)
+++ trunk/JSTests/wasm/references/anyref_modules.js     2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -0,0 +1,132 @@
</span><ins>+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const $1 = new WebAssembly.Instance(new WebAssembly.Module((new Builder())
+      .Type().End()
+      .Function().End()
+      .Export()
+          .Function("h")
+          .Function("i")
+          .Function("j")
+          .Function("k")
+      .End()
+      .Code()
+        .Function("h", { params: ["anyref"], ret: "anyref" })
+          .GetLocal(0)
+        .End()
+
+        .Function("i", { params: [], ret: "anyref" })
+            .RefNull()
+            .Call(0)
+        .End()
+
+        .Function("j", { params: ["anyref"], ret: "i32" })
+            .GetLocal(0)
+            .RefIsNull()
+        .End()
+
+        .Function("k", { params: [], ret: "i32" })
+            .RefNull()
+            .RefIsNull()
+        .End()
+      .End().WebAssembly().get()));
+
+const $2 = new WebAssembly.Instance(new WebAssembly.Module((new Builder())
+      .Type().End()
+      .Import()
+          .Function("m1", "h", { params: ["anyref"], ret: "anyref" })
+          .Function("m1", "j", { params: ["anyref"], ret: "i32" })
+          .Function("js", "ident", { params: ["anyref"], ret: "anyref" })
+          .Function("js", "make_null", { params: [], ret: "anyref" })
+      .End()
+      .Function().End()
+      .Export()
+          .Function("call_h")
+          .Function("call_j")
+          .Function("call_h_null")
+          .Function("call_j_null")
+          .Function("call_ident")
+          .Function("call_ident_null")
+          .Function("is_makenull_null")
+      .End()
+      .Code()
+        .Function("call_h", { params: ["anyref"], ret: "anyref" })
+          .GetLocal(0)
+          .Call(0)
+        .End()
+
+        .Function("call_j", { params: ["anyref"], ret: "i32" })
+          .GetLocal(0)
+          .Call(1)
+        .End()
+
+        .Function("call_h_null", { params: [], ret: "anyref" })
+          .RefNull()
+          .Call(0)
+        .End()
+
+        .Function("call_j_null", { params: [], ret: "i32" })
+          .RefNull()
+          .Call(1)
+        .End()
+
+        .Function("call_ident", { params: ["anyref"], ret: "anyref" })
+          .I32Const(1)
+          .If("anyref")
+          .Block("anyref", (b) =>
+            b.GetLocal(0)
+          )
+          .Else()
+          .Block("anyref", (b) =>
+            b.GetLocal(0)
+          )
+          .End()
+          .Call(2)
+        .End()
+
+        .Function("call_ident_null", { params: [], ret: "anyref" })
+          .RefNull()
+          .Call(2)
+        .End()
+
+        .Function("is_makenull_null", { params: [], ret: "i32" })
+          .Call(3)
+          .RefIsNull()
+        .End()
+      .End().WebAssembly().get()), { m1: $1.exports, js: {
+        ident: function(x) { return x; },
+        make_null: function() { return null; },
+      } });
+
+assert.eq($2.exports.call_h(null), null)
+
+const obj = { test: "hi" }
+assert.eq($2.exports.call_h(obj), obj)
+assert.eq($2.exports.call_h(5), 5)
+assert.eq($2.exports.call_h("hi"), "hi")
+assert.eq($2.exports.call_h(undefined), undefined)
+
+assert.eq($2.exports.call_j(obj), 0)
+assert.eq($2.exports.call_j(5), 0)
+assert.eq($2.exports.call_j("hi"), 0)
+assert.eq($2.exports.call_j(null), 1)
+assert.eq($2.exports.call_j(undefined), 0)
+
+assert.eq($2.exports.call_h_null(), null)
+assert.eq($2.exports.call_j_null(), 1)
+
+assert.eq($2.exports.call_ident(null), null)
+assert.eq($2.exports.call_ident(obj), obj)
+assert.eq($2.exports.call_ident(5), 5)
+assert.eq($2.exports.call_ident("hi"), "hi")
+assert.eq($2.exports.call_ident(undefined), undefined)
+
+for (let i=0; i<1000; ++i) {
+    // Trigger the ic path
+    assert.eq($2.exports.call_ident(null), null)
+    assert.eq($2.exports.call_ident(7), 7)
+    assert.eq($2.exports.call_ident("bye"), "bye")
+}
+
+assert.eq($2.exports.call_ident_null(), null)
+assert.eq($2.exports.is_makenull_null(), 1)
</ins></span></pre></div>
<a id="trunkJSTestswasmreferencesis_nulljs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/references/is_null.js (0 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/references/is_null.js                         (rev 0)
+++ trunk/JSTests/wasm/references/is_null.js    2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -0,0 +1,60 @@
</span><ins>+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const builder = (new Builder())
+      .Type().End()
+      .Function().End()
+      .Export()
+          .Function("h")
+          .Function("i")
+          .Function("j")
+          .Function("k")
+      .End()
+      .Code()
+        .Function("h", { params: ["anyref"], ret: "anyref" })
+          .GetLocal(0)
+        .End()
+
+        .Function("i", { params: [], ret: "anyref" })
+            .RefNull()
+            .Call(0)
+        .End()
+
+        .Function("j", { params: ["anyref"], ret: "i32" })
+            .GetLocal(0)
+            .RefIsNull()
+        .End()
+
+        .Function("k", { params: [], ret: "i32" })
+            .RefNull()
+            .RefIsNull()
+        .End()
+      .End();
+
+const bin = builder.WebAssembly().get();
+const module = new WebAssembly.Module(bin);
+const instance = new WebAssembly.Instance(module);
+assert.eq(instance.exports.h(null), null)
+
+const obj = { test: "hi" }
+assert.eq(instance.exports.h(obj), obj)
+assert.eq(instance.exports.h(5), 5)
+assert.eq(instance.exports.h("hi"), "hi")
+assert.eq(instance.exports.h(undefined), undefined)
+
+assert.eq(instance.exports.i(), null)
+
+assert.eq(instance.exports.j(obj), 0)
+assert.eq(instance.exports.j(5), 0)
+assert.eq(instance.exports.j("hi"), 0)
+assert.eq(instance.exports.j(null), 1)
+assert.eq(instance.exports.j(undefined), 0)
+
+assert.eq(instance.exports.k(), 1)
+
+assert.eq(obj.test, "hi")
+const obj2 = instance.exports.h(obj)
+obj2.test = "bye"
+assert.eq(obj.test, "bye")
+
+for (let i=0; i<1000; ++i) assert.eq(instance.exports.h(null), null)
</ins></span></pre></div>
<a id="trunkJSTestswasmreferencesis_null_errorjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/references/is_null_error.js (0 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/references/is_null_error.js                           (rev 0)
+++ trunk/JSTests/wasm/references/is_null_error.js      2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -0,0 +1,22 @@
</span><ins>+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+{
+    const builder = (new Builder())
+      .Type().End()
+      .Function().End()
+      .Export()
+          .Function("j")
+      .End()
+      .Code()
+        .Function("j", { params: [], ret: "i32" })
+            .I32Const(0)
+            .RefIsNull()
+        .End()
+      .End();
+
+    const bin = builder.WebAssembly();
+    bin.trim();
+
+    assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: ref.is_null to type I32 expected Anyref, in function at index 0 (evaluating 'new WebAssembly.Module(bin.get())')");
+}
</ins></span></pre></div>
<a id="trunkJSTestswasmspecharnessindexjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/spec-harness/index.js (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/spec-harness/index.js 2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/JSTests/wasm/spec-harness/index.js    2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -190,6 +190,7 @@
</span><span class="cx">     if (valid) {
</span><span class="cx">         uniqueTest(() => {
</span><span class="cx">             let instantiated = err === null;
</span><ins>+            if (!instantiated) print(err);
</ins><span class="cx">             assert_true(instantiated, err);
</span><span class="cx">         }, "module successfully instantiated");
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkJSTestswasmwasmjson"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/wasm.json (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/wasm.json     2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/JSTests/wasm/wasm.json        2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -12,11 +12,12 @@
</span><span class="cx">         "f32":     { "type": "varint7", "value":  -3, "b3type": "B3::Float" },
</span><span class="cx">         "f64":     { "type": "varint7", "value":  -4, "b3type": "B3::Double" },
</span><span class="cx">         "anyfunc": { "type": "varint7", "value": -16, "b3type": "B3::Void" },
</span><ins>+        "anyref":  { "type": "varint7", "value": -17, "b3type": "B3::Int64" },
</ins><span class="cx">         "func":    { "type": "varint7", "value": -32, "b3type": "B3::Void" },
</span><span class="cx">         "void":    { "type": "varint7", "value": -64, "b3type": "B3::Void" }
</span><span class="cx">     },
</span><del>-    "value_type": ["i32", "i64", "f32", "f64"],
-    "block_type": ["i32", "i64", "f32", "f64", "void"],
</del><ins>+    "value_type": ["i32", "i64", "f32", "f64", "anyref"],
+    "block_type": ["i32", "i64", "f32", "f64", "void", "anyref"],
</ins><span class="cx">     "elem_type": ["anyfunc"],
</span><span class="cx">     "external_kind": {
</span><span class="cx">         "Function": { "type": "uint8", "value": 0 },
</span><span class="lines">@@ -58,6 +59,8 @@
</span><span class="cx">         "i64.const":           { "category": "special",    "value":  66, "return": ["i64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "varint64"}],                                             "description": "a constant value interpreted as i64" },
</span><span class="cx">         "f64.const":           { "category": "special",    "value":  68, "return": ["f64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "double"}],                                               "description": "a constant value interpreted as f64" },
</span><span class="cx">         "f32.const":           { "category": "special",    "value":  67, "return": ["f32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "float"}],                                                "description": "a constant value interpreted as f32" },
</span><ins>+        "ref.null":            { "category": "special",    "value": 208, "return": ["anyref"],   "parameter": [],                       "immediate": [],                                                                                           "description": "a constant null reference" },
+        "ref.is_null":         { "category": "special",    "value": 209, "return": ["i32"],      "parameter": ["anyref"],               "immediate": [],                                                                                           "description": "determine if a reference is null" },
</ins><span class="cx">         "get_local":           { "category": "special",    "value":  32, "return": ["any"],      "parameter": [],                       "immediate": [{"name": "local_index",    "type": "varuint32"}],                                            "description": "read a local variable or parameter" },
</span><span class="cx">         "set_local":           { "category": "special",    "value":  33, "return": [],           "parameter": ["any"],                  "immediate": [{"name": "local_index",    "type": "varuint32"}],                                            "description": "write a local variable or parameter" },
</span><span class="cx">         "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" },
</span></span></pre></div>
<a id="trunkJSTestswasmyaml"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm.yaml (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm.yaml  2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/JSTests/wasm.yaml     2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -29,6 +29,8 @@
</span><span class="cx">   cmd: runNoJIT unless parseRunCommands
</span><span class="cx"> - path: wasm/function-tests
</span><span class="cx">   cmd: runWebAssemblySuite unless parseRunCommands
</span><ins>+- path: wasm/references
+  cmd: runWebAssemblySuite unless parseRunCommands
</ins><span class="cx"> - path: wasm/fuzz
</span><span class="cx">   cmd: runWebAssemblySuite unless parseRunCommands
</span><span class="cx"> - path: wasm/stress
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog    2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/Source/JavaScriptCore/ChangeLog       2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -1,3 +1,47 @@
</span><ins>+2019-05-17  Justin Michaud  <justin_michaud@apple.com>
+
+        [WASM-References] Add support for Anyref in parameters and return types, Ref.null and Ref.is_null for Anyref values.
+        https://bugs.webkit.org/show_bug.cgi?id=197969
+
+        Reviewed by Keith Miller.
+
+        Add a new runtime option for wasm references.
+        Add support for Anyref as a value type.
+        Add support for Anyref in parameters and return types of Wasm functions. JSValues are marshalled into/out of wasm Anyrefs
+                as a black box, except null which becomes a Nullref value. Nullref is not expressible in the bytecode or in the js API.
+        Add Ref.null and Ref.is_null for Anyref values. Support for these functions with funcrefs is out of scope.
+
+        * runtime/Options.h:
+        * wasm/WasmAirIRGenerator.cpp:
+        (JSC::Wasm::AirIRGenerator::tmpForType):
+        (JSC::Wasm::AirIRGenerator::AirIRGenerator):
+        (JSC::Wasm::AirIRGenerator::addConstant):
+        (JSC::Wasm::AirIRGenerator::addRefIsNull):
+        (JSC::Wasm::AirIRGenerator::addReturn):
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::B3IRGenerator::addRefIsNull):
+        * wasm/WasmCallingConvention.h:
+        (JSC::Wasm::CallingConventionAir::marshallArgument const):
+        (JSC::Wasm::CallingConventionAir::setupCall const):
+        * wasm/WasmFormat.h:
+        (JSC::Wasm::isValueType):
+        * wasm/WasmFunctionParser.h:
+        (JSC::Wasm::FunctionParser<Context>::FunctionParser):
+        (JSC::Wasm::FunctionParser<Context>::parseExpression):
+        (JSC::Wasm::FunctionParser<Context>::parseUnreachableExpression):
+        * wasm/WasmValidate.cpp:
+        (JSC::Wasm::Validate::addRefIsNull):
+        * wasm/generateWasmOpsHeader.py:
+        (bitSet):
+        * wasm/js/JSToWasm.cpp:
+        (JSC::Wasm::createJSToWasmWrapper):
+        * wasm/js/WasmToJS.cpp:
+        (JSC::Wasm::wasmToJS):
+        * wasm/js/WebAssemblyFunction.cpp:
+        (JSC::callWebAssemblyFunction):
+        (JSC::WebAssemblyFunction::jsCallEntrypointSlow):
+        * wasm/wasm.json:
+
</ins><span class="cx"> 2019-05-17  Don Olmstead  <don.olmstead@sony.com>
</span><span class="cx"> 
</span><span class="cx">         [CMake] Use builtin FindICU
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h    2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/Source/JavaScriptCore/runtime/Options.h       2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -502,6 +502,7 @@
</span><span class="cx">     v(bool, useWebAssemblyStreamingApi, enableWebAssemblyStreamingApi, Normal, "Allow to run WebAssembly's Streaming API") \
</span><span class="cx">     v(bool, useCallICsForWebAssemblyToJSCalls, true, Normal, "If true, we will use CallLinkInfo to inline cache Wasm to JS calls.") \
</span><span class="cx">     v(bool, useEagerWebAssemblyModuleHashing, false, Normal, "Unnamed WebAssembly modules are identified in backtraces through their hash, if available.") \
</span><ins>+    v(bool, useWebAssemblyReferences, true, Normal, "Allow types from the wasm references spec.") \
</ins><span class="cx">     v(bool, useBigInt, false, Normal, "If true, we will enable BigInt support.") \
</span><span class="cx">     v(bool, useIntlNumberFormatToParts, enableIntlNumberFormatToParts, Normal, "If true, we will enable Intl.NumberFormat.prototype.formatToParts") \
</span><span class="cx">     v(bool, useIntlPluralRules, enableIntlPluralRules, Normal, "If true, we will enable Intl.PluralRules.") \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmAirIRGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp  2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp     2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -41,6 +41,7 @@
</span><span class="cx"> #include "B3ProcedureInlines.h"
</span><span class="cx"> #include "BinarySwitch.h"
</span><span class="cx"> #include "DisallowMacroScratchRegisterUsage.h"
</span><ins>+#include "JSCInlines.h"
</ins><span class="cx"> #include "ScratchRegisterAllocator.h"
</span><span class="cx"> #include "VirtualRegister.h"
</span><span class="cx"> #include "WasmCallingConvention.h"
</span><span class="lines">@@ -230,6 +231,8 @@
</span><span class="cx">     ExpressionType addConstant(Type, uint64_t);
</span><span class="cx">     ExpressionType addConstant(BasicBlock*, Type, uint64_t);
</span><span class="cx"> 
</span><ins>+    PartialResult WARN_UNUSED_RETURN addRefIsNull(ExpressionType& value, ExpressionType& result);
+
</ins><span class="cx">     // Locals
</span><span class="cx">     PartialResult WARN_UNUSED_RETURN getLocal(uint32_t index, ExpressionType& result);
</span><span class="cx">     PartialResult WARN_UNUSED_RETURN setLocal(uint32_t index, ExpressionType value);
</span><span class="lines">@@ -360,6 +363,7 @@
</span><span class="cx">         case Type::I32:
</span><span class="cx">             return g32();
</span><span class="cx">         case Type::I64:
</span><ins>+        case Type::Anyref:
</ins><span class="cx">             return g64();
</span><span class="cx">         case Type::F32:
</span><span class="cx">             return f32();
</span><span class="lines">@@ -786,6 +790,7 @@
</span><span class="cx">             append(Move32, arg, m_locals[i]);
</span><span class="cx">             break;
</span><span class="cx">         case Type::I64:
</span><ins>+        case Type::Anyref:
</ins><span class="cx">             append(Move, arg, m_locals[i]);
</span><span class="cx">             break;
</span><span class="cx">         case Type::F32:
</span><span class="lines">@@ -902,6 +907,7 @@
</span><span class="cx">     switch (type) {
</span><span class="cx">     case Type::I32:
</span><span class="cx">     case Type::I64:
</span><ins>+    case Type::Anyref:
</ins><span class="cx">         append(block, Move, Arg::bigImm(value), result);
</span><span class="cx">         break;
</span><span class="cx">     case Type::F32:
</span><span class="lines">@@ -925,6 +931,18 @@
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+auto AirIRGenerator::addRefIsNull(ExpressionType& value, ExpressionType& result) -> PartialResult
+{
+    ASSERT(value.tmp());
+    result = tmpForType(Type::I32);
+    auto tmp = g64();
+
+    append(Move, Arg::bigImm(JSValue::encode(jsNull())), tmp);
+    append(Compare64, Arg::relCond(MacroAssembler::Equal), value, tmp, result);
+
+    return { };
+}
+
</ins><span class="cx"> auto AirIRGenerator::getLocal(uint32_t index, ExpressionType& result) -> PartialResult
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_locals[index].tmp());
</span><span class="lines">@@ -1509,6 +1527,7 @@
</span><span class="cx">             append(Ret32, returnValueGPR);
</span><span class="cx">             break;
</span><span class="cx">         case Type::I64:
</span><ins>+        case Type::Anyref:
</ins><span class="cx">             append(Move, returnValues[0], returnValueGPR);
</span><span class="cx">             append(Ret64, returnValueGPR);
</span><span class="cx">             break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp   2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp      2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -184,6 +184,8 @@
</span><span class="cx">     PartialResult WARN_UNUSED_RETURN addLocal(Type, uint32_t);
</span><span class="cx">     ExpressionType addConstant(Type, uint64_t);
</span><span class="cx"> 
</span><ins>+    PartialResult WARN_UNUSED_RETURN addRefIsNull(ExpressionType& value, ExpressionType& result);
+
</ins><span class="cx">     // Locals
</span><span class="cx">     PartialResult WARN_UNUSED_RETURN getLocal(uint32_t index, ExpressionType& result);
</span><span class="cx">     PartialResult WARN_UNUSED_RETURN setLocal(uint32_t index, ExpressionType value);
</span><span class="lines">@@ -550,6 +552,12 @@
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+auto B3IRGenerator::addRefIsNull(ExpressionType& value, ExpressionType& result) -> PartialResult
+{
+    result = m_currentBlock->appendNew<Value>(m_proc, B3::Equal, origin(), value, m_currentBlock->appendNew<Const64Value>(m_proc, origin(), JSValue::encode(jsNull())));
+    return { };
+}
+
</ins><span class="cx"> auto B3IRGenerator::getLocal(uint32_t index, ExpressionType& result) -> PartialResult
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_locals[index]);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmCallingConventionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h 2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h    2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -235,6 +235,7 @@
</span><span class="cx">         switch (type) {
</span><span class="cx">         case Type::I32:
</span><span class="cx">         case Type::I64:
</span><ins>+        case Type::Anyref:
</ins><span class="cx">             marshallArgumentImpl(m_gprArgs, gpArgumentCount, stackOffset, regFunc, stackFunc);
</span><span class="cx">             break;
</span><span class="cx">         case Type::F32:
</span><span class="lines">@@ -299,6 +300,7 @@
</span><span class="cx">             break;
</span><span class="cx">         case Type::I32:
</span><span class="cx">         case Type::I64:
</span><ins>+        case Type::Anyref:
</ins><span class="cx">             patchpoint->resultConstraint = B3::ValueRep::reg(GPRInfo::returnValueGPR);
</span><span class="cx">             break;
</span><span class="cx">         default:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFormath"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFormat.h (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFormat.h    2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/Source/JavaScriptCore/wasm/WasmFormat.h       2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -62,6 +62,8 @@
</span><span class="cx">     case F32:
</span><span class="cx">     case F64:
</span><span class="cx">         return true;
</span><ins>+    case Anyref:
+        return Options::useWebAssemblyReferences();
</ins><span class="cx">     default:
</span><span class="cx">         break;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFunctionParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h    2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h       2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -105,7 +105,7 @@
</span><span class="cx">     , m_info(info)
</span><span class="cx"> {
</span><span class="cx">     if (verbose)
</span><del>-        dataLogLn("Parsing function starting at: ", (uintptr_t)functionStart, " of length: ", functionLength);
</del><ins>+        dataLogLn("Parsing function starting at: ", (uintptr_t)functionStart, " of length: ", functionLength, " with signature: ", signature);
</ins><span class="cx">     m_context.setParser(this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -281,6 +281,21 @@
</span><span class="cx">         return { };
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case RefNull: {
+        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
+        m_expressionStack.append(m_context.addConstant(Anyref, JSValue::encode(jsNull())));
+        return { };
+    }
+
+    case RefIsNull: {
+        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
+        ExpressionType result, value;
+        WASM_TRY_POP_EXPRESSION_STACK_INTO(value, "ref.is_null");
+        WASM_TRY_ADD_TO_CONTEXT(addRefIsNull(value, result));
+        m_expressionStack.append(result);
+        return { };
+    }
+
</ins><span class="cx">     case GetLocal: {
</span><span class="cx">         uint32_t index;
</span><span class="cx">         ExpressionType result;
</span><span class="lines">@@ -639,6 +654,16 @@
</span><span class="cx">         return { };
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case RefNull: {
+        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
+        return { };
+    }
+
+    case RefIsNull: {
+        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
+        return { };
+    }
+
</ins><span class="cx">     case GrowMemory:
</span><span class="cx">     case CurrentMemory: {
</span><span class="cx">         uint8_t reserved;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmValidatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp        2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp   2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -100,6 +100,8 @@
</span><span class="cx">     Result WARN_UNUSED_RETURN addLocal(Type, uint32_t);
</span><span class="cx">     ExpressionType addConstant(Type type, uint64_t) { return type; }
</span><span class="cx"> 
</span><ins>+    Result WARN_UNUSED_RETURN addRefIsNull(ExpressionType& value, ExpressionType& result);
+
</ins><span class="cx">     // Locals
</span><span class="cx">     Result WARN_UNUSED_RETURN getLocal(uint32_t index, ExpressionType& result);
</span><span class="cx">     Result WARN_UNUSED_RETURN setLocal(uint32_t index, ExpressionType value);
</span><span class="lines">@@ -169,6 +171,14 @@
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+auto Validate::addRefIsNull(ExpressionType& value, ExpressionType& result) -> Result
+{
+    result = Type::I32;
+    WASM_VALIDATOR_FAIL_IF(Type::Anyref != value, "ref.is_null to type ", value, " expected ", Type::Anyref);
+
+    return { };
+}
+
</ins><span class="cx"> auto Validate::addLocal(Type type, uint32_t count) -> Result
</span><span class="cx"> {
</span><span class="cx">     size_t size = m_locals.size() + count;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmgenerateWasmOpsHeaderpy"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py        2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py   2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -95,7 +95,7 @@
</span><span class="cx"> 
</span><span class="cx"> def bitSet():
</span><span class="cx">     v = ""
</span><del>-    for i in range(ceilDiv(maxOpValue, 8)):
</del><ins>+    for i in range(ceilDiv(maxOpValue + 1, 8)):
</ins><span class="cx">         entry = 0
</span><span class="cx">         for j in range(8):
</span><span class="cx">             if i * 8 + j in opValueSet:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSToWasmcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSToWasm.cpp (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSToWasm.cpp 2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/Source/JavaScriptCore/wasm/js/JSToWasm.cpp    2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -82,6 +82,7 @@
</span><span class="cx">             argumentsIncludeI64 = true;
</span><span class="cx">             FALLTHROUGH;
</span><span class="cx">         case Wasm::I32:
</span><ins>+        case Wasm::Anyref:
</ins><span class="cx">             if (numGPRs >= wasmCallingConvention().m_gprArgs.size())
</span><span class="cx">                 totalFrameSize += sizeof(void*);
</span><span class="cx">             ++numGPRs;
</span><span class="lines">@@ -164,6 +165,7 @@
</span><span class="cx">             switch (signature.argument(i)) {
</span><span class="cx">             case Wasm::I32:
</span><span class="cx">             case Wasm::I64:
</span><ins>+            case Wasm::Anyref:
</ins><span class="cx">                 if (numGPRs >= wasmCallingConvention().m_gprArgs.size()) {
</span><span class="cx">                     if (signature.argument(i) == Wasm::I32) {
</span><span class="cx">                         jit.load32(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchReg);
</span><span class="lines">@@ -247,6 +249,9 @@
</span><span class="cx">     case Wasm::Void:
</span><span class="cx">         jit.moveTrustedValue(jsUndefined(), JSValueRegs { GPRInfo::returnValueGPR });
</span><span class="cx">         break;
</span><ins>+    case Wasm::Anyref:
+        // FIXME: We need to box wasm Funcrefs once they are supported here.
+        break;
</ins><span class="cx">     case Wasm::I32:
</span><span class="cx">         jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, GPRInfo::returnValueGPR);
</span><span class="cx">         jit.boxInt32(GPRInfo::returnValueGPR, JSValueRegs { GPRInfo::returnValueGPR }, DoNotHaveTagRegisters);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWasmToJScpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WasmToJS.cpp (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WasmToJS.cpp 2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/Source/JavaScriptCore/wasm/js/WasmToJS.cpp    2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -165,6 +165,7 @@
</span><span class="cx">             case Anyfunc:
</span><span class="cx">             case I64:
</span><span class="cx">                 RELEASE_ASSERT_NOT_REACHED();
</span><ins>+            case Anyref:
</ins><span class="cx">             case I32: {
</span><span class="cx">                 GPRReg gprReg;
</span><span class="cx">                 if (marshalledGPRs < wasmCC.m_gprArgs.size())
</span><span class="lines">@@ -175,7 +176,8 @@
</span><span class="cx">                     jit.load64(JIT::Address(GPRInfo::callFrameRegister, frOffset), gprReg);
</span><span class="cx">                     frOffset += sizeof(Register);
</span><span class="cx">                 }
</span><del>-                jit.zeroExtend32ToPtr(gprReg, gprReg);
</del><ins>+                if (argType == I32)
+                    jit.zeroExtend32ToPtr(gprReg, gprReg);
</ins><span class="cx">                 jit.store64(gprReg, buffer + bufferOffset);
</span><span class="cx">                 ++marshalledGPRs;
</span><span class="cx">                 break;
</span><span class="lines">@@ -241,6 +243,10 @@
</span><span class="cx">                     case I32:
</span><span class="cx">                         arg = jsNumber(static_cast<int32_t>(buffer[argNum]));
</span><span class="cx">                         break;
</span><ins>+                    case Anyref:
+                        // FIXME: We need to box wasm Funcrefs once they are supported here.
+                        arg = JSValue::decode(buffer[argNum]);
+                        break;
</ins><span class="cx">                     case F32:
</span><span class="cx">                     case F64:
</span><span class="cx">                         arg = jsNumber(purifyNaN(bitwise_cast<double>(buffer[argNum])));
</span><span class="lines">@@ -272,6 +278,10 @@
</span><span class="cx">                     realResult = static_cast<uint64_t>(static_cast<uint32_t>(result.toInt32(exec)));
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><ins>+                case Anyref: {
+                    realResult = JSValue::encode(result);
+                    break;
+                }
</ins><span class="cx">                 case F64:
</span><span class="cx">                 case F32: {
</span><span class="cx">                     realResult = bitwise_cast<uint64_t>(result.toNumber(exec));
</span><span class="lines">@@ -364,6 +374,7 @@
</span><span class="cx">             case Anyfunc:
</span><span class="cx">             case I64:
</span><span class="cx">                 RELEASE_ASSERT_NOT_REACHED(); // Handled above.
</span><ins>+            case Anyref:
</ins><span class="cx">             case I32: {
</span><span class="cx">                 GPRReg gprReg;
</span><span class="cx">                 if (marshalledGPRs < wasmCC.m_gprArgs.size())
</span><span class="lines">@@ -375,8 +386,11 @@
</span><span class="cx">                     frOffset += sizeof(Register);
</span><span class="cx">                 }
</span><span class="cx">                 ++marshalledGPRs;
</span><del>-                jit.zeroExtend32ToPtr(gprReg, gprReg); // Clear non-int32 and non-tag bits.
-                jit.boxInt32(gprReg, JSValueRegs(gprReg), DoNotHaveTagRegisters);
</del><ins>+                if (argType == I32) {
+                    jit.zeroExtend32ToPtr(gprReg, gprReg); // Clear non-int32 and non-tag bits.
+                    jit.boxInt32(gprReg, JSValueRegs(gprReg), DoNotHaveTagRegisters);
+                }
+                // FIXME: We need to box wasm Funcrefs once they are supported here.
</ins><span class="cx">                 jit.store64(gprReg, calleeFrame.withOffset(calleeFrameOffset));
</span><span class="cx">                 calleeFrameOffset += sizeof(Register);
</span><span class="cx">                 break;
</span><span class="lines">@@ -430,6 +444,7 @@
</span><span class="cx">             case Anyfunc:
</span><span class="cx">             case I64:
</span><span class="cx">                 RELEASE_ASSERT_NOT_REACHED(); // Handled above.
</span><ins>+            case Anyref:
</ins><span class="cx">             case I32:
</span><span class="cx">                 // Skipped: handled above.
</span><span class="cx">                 if (marshalledGPRs >= wasmCC.m_gprArgs.size())
</span><span class="lines">@@ -538,6 +553,8 @@
</span><span class="cx">         done.link(&jit);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><ins>+    case Anyref:
+        break;
</ins><span class="cx">     case F32: {
</span><span class="cx">         CCallHelpers::JumpList done;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyFunctioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp      2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp 2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -84,6 +84,8 @@
</span><span class="cx">         case Wasm::I32:
</span><span class="cx">             arg = JSValue::decode(arg.toInt32(exec));
</span><span class="cx">             break;
</span><ins>+        case Wasm::Anyref:
+            break;
</ins><span class="cx">         case Wasm::I64:
</span><span class="cx">             arg = JSValue();
</span><span class="cx">             break;
</span><span class="lines">@@ -225,6 +227,7 @@
</span><span class="cx">         case Wasm::I64:
</span><span class="cx">             argumentsIncludeI64 = true;
</span><span class="cx">             break;
</span><ins>+        case Wasm::Anyref:
</ins><span class="cx">         case Wasm::I32:
</span><span class="cx">             if (numGPRs >= Wasm::wasmCallingConvention().m_gprArgs.size())
</span><span class="cx">                 totalFrameSize += sizeof(CPURegister);
</span><span class="lines">@@ -300,6 +303,18 @@
</span><span class="cx">                     ++numGPRs;
</span><span class="cx">                 }
</span><span class="cx">                 break;
</span><ins>+            case Wasm::Anyref: {
+                jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchGPR);
+
+                if (numGPRs >= Wasm::wasmCallingConvention().m_gprArgs.size()) {
+                    jit.store64(scratchGPR, calleeFrame.withOffset(wasmOffset));
+                    wasmOffset += sizeof(CPURegister);
+                } else {
+                    jit.move(scratchGPR, Wasm::wasmCallingConvention().m_gprArgs[numGPRs].gpr());
+                    ++numGPRs;
+                }
+                break;
+            }
</ins><span class="cx">             case Wasm::F32:
</span><span class="cx">             case Wasm::F64:
</span><span class="cx">                 if (numFPRs >= Wasm::wasmCallingConvention().m_fprArgs.size()) {
</span><span class="lines">@@ -451,6 +466,10 @@
</span><span class="cx">         isNaN.link(&jit);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><ins>+    case Wasm::Anyref: {
+        // FIXME: We need to box wasm Funcrefs once they are supported here.
+        break;
+    }
</ins><span class="cx">     case Wasm::I64:
</span><span class="cx">     case Wasm::Func:
</span><span class="cx">     case Wasm::Anyfunc:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmwasmjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/wasm.json (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/wasm.json       2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/Source/JavaScriptCore/wasm/wasm.json  2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -12,11 +12,12 @@
</span><span class="cx">         "f32":     { "type": "varint7", "value":  -3, "b3type": "B3::Float" },
</span><span class="cx">         "f64":     { "type": "varint7", "value":  -4, "b3type": "B3::Double" },
</span><span class="cx">         "anyfunc": { "type": "varint7", "value": -16, "b3type": "B3::Void" },
</span><ins>+        "anyref":  { "type": "varint7", "value": -17, "b3type": "B3::Int64" },
</ins><span class="cx">         "func":    { "type": "varint7", "value": -32, "b3type": "B3::Void" },
</span><span class="cx">         "void":    { "type": "varint7", "value": -64, "b3type": "B3::Void" }
</span><span class="cx">     },
</span><del>-    "value_type": ["i32", "i64", "f32", "f64"],
-    "block_type": ["i32", "i64", "f32", "f64", "void"],
</del><ins>+    "value_type": ["i32", "i64", "f32", "f64", "anyref"],
+    "block_type": ["i32", "i64", "f32", "f64", "void", "anyref"],
</ins><span class="cx">     "elem_type": ["anyfunc"],
</span><span class="cx">     "external_kind": {
</span><span class="cx">         "Function": { "type": "uint8", "value": 0 },
</span><span class="lines">@@ -58,6 +59,8 @@
</span><span class="cx">         "i64.const":           { "category": "special",    "value":  66, "return": ["i64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "varint64"}],                                             "description": "a constant value interpreted as i64" },
</span><span class="cx">         "f64.const":           { "category": "special",    "value":  68, "return": ["f64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "double"}],                                               "description": "a constant value interpreted as f64" },
</span><span class="cx">         "f32.const":           { "category": "special",    "value":  67, "return": ["f32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "float"}],                                                "description": "a constant value interpreted as f32" },
</span><ins>+        "ref.null":            { "category": "special",    "value": 208, "return": ["anyref"],   "parameter": [],                       "immediate": [],                                                                                           "description": "a constant null reference" },
+        "ref.is_null":         { "category": "special",    "value": 209, "return": ["i32"],      "parameter": ["anyref"],               "immediate": [],                                                                                           "description": "determine if a reference is null" },
</ins><span class="cx">         "get_local":           { "category": "special",    "value":  32, "return": ["any"],      "parameter": [],                       "immediate": [{"name": "local_index",    "type": "varuint32"}],                                            "description": "read a local variable or parameter" },
</span><span class="cx">         "set_local":           { "category": "special",    "value":  33, "return": [],           "parameter": ["any"],                  "immediate": [{"name": "local_index",    "type": "varuint32"}],                                            "description": "write a local variable or parameter" },
</span><span class="cx">         "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" },
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog    2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/Tools/ChangeLog       2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2019-05-17  Justin Michaud  <justin_michaud@apple.com>
+
+        [WASM-References] Add support for Anyref in parameters and return types, Ref.null and Ref.is_null for Anyref values.
+        https://bugs.webkit.org/show_bug.cgi?id=197969
+
+        Run wasm tests additionally with wasmBBQUsesAir=0.
+
+        Reviewed by Keith Miller.
+
+        * Scripts/run-jsc-stress-tests:
+
</ins><span class="cx"> 2019-05-17  Don Olmstead  <don.olmstead@sony.com>
</span><span class="cx"> 
</span><span class="cx">         [CMake] Use builtin FindICU
</span></span></pre></div>
<a id="trunkToolsScriptsrunjscstresstests"></a>
<div class="modfile"><h4>Modified: trunk/Tools/Scripts/run-jsc-stress-tests (245495 => 245496)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/Scripts/run-jsc-stress-tests 2019-05-18 04:44:34 UTC (rev 245495)
+++ trunk/Tools/Scripts/run-jsc-stress-tests    2019-05-18 04:58:36 UTC (rev 245496)
</span><span class="lines">@@ -1080,6 +1080,7 @@
</span><span class="cx">         run("wasm-no-call-ic", "-m", "--useCallICsForWebAssemblyToJSCalls=false", *FTL_OPTIONS)
</span><span class="cx">         run("wasm-no-tls-context", "-m", "--useFastTLSForWasmContext=false", *FTL_OPTIONS)
</span><span class="cx">         run("wasm-slow-memory", "-m", "--useWebAssemblyFastMemory=false", *FTL_OPTIONS)
</span><ins>+        run("wasm-no-air", "-m", "--wasmBBQUsesAir=false", *FTL_OPTIONS)
</ins><span class="cx">     end
</span><span class="cx"> end
</span><span class="cx"> 
</span><span class="lines">@@ -1096,6 +1097,7 @@
</span><span class="cx">         run("wasm-no-call-ic", "-m", "--useCallICsForWebAssemblyToJSCalls=false", *FTL_OPTIONS)
</span><span class="cx">         run("wasm-no-tls-context", "-m", "--useFastTLSForWasmContext=false", *FTL_OPTIONS)
</span><span class="cx">         run("wasm-slow-memory", "-m", "--useWebAssemblyFastMemory=false", *FTL_OPTIONS)
</span><ins>+        run("wasm-no-air", "-m", "--wasmBBQUsesAir=false", *FTL_OPTIONS)
</ins><span class="cx">     end
</span><span class="cx"> end
</span><span class="cx"> 
</span><span class="lines">@@ -1114,6 +1116,7 @@
</span><span class="cx">         run("wasm-eager-jettison", "--forceCodeBlockToJettisonDueToOldAge=true", *FTL_OPTIONS)
</span><span class="cx">         run("wasm-no-call-ic", "--useCallICsForWebAssemblyToJSCalls=false", *FTL_OPTIONS)
</span><span class="cx">         run("wasm-no-tls-context", "--useFastTLSForWasmContext=false", *FTL_OPTIONS)
</span><ins>+        run("wasm-no-air", "--wasmBBQUsesAir=false", *FTL_OPTIONS)
</ins><span class="cx">     end
</span><span class="cx"> end
</span><span class="cx"> 
</span><span class="lines">@@ -1138,6 +1141,7 @@
</span><span class="cx">       runWithOutputHandler("wasm-eager-jettison", noisyOutputHandler, "../spec-harness.js", "--forceCodeBlockToJettisonDueToOldAge=true", *FTL_OPTIONS)
</span><span class="cx">       runWithOutputHandler("wasm-no-call-ic", noisyOutputHandler, "../spec-harness.js", "--useCallICsForWebAssemblyToJSCalls=false", *FTL_OPTIONS)
</span><span class="cx">       runWithOutputHandler("wasm-no-tls-context", noisyOutputHandler, "../spec-harness.js", "--useFastTLSForWasmContext=false", *FTL_OPTIONS)
</span><ins>+      runWithOutputHandler("wasm-no-air", noisyOutputHandler, "../spec-harness.js", "--wasmBBQUsesAir=false", *FTL_OPTIONS)
</ins><span class="cx">     end
</span><span class="cx"> end
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>