<!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>[279265] 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/279265">279265</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2021-06-24 19:23:28 -0700 (Thu, 24 Jun 2021)</dd>
</dl>

<h3>Log Message</h3>
<pre>[WASM-Function-References] Add support for (ref null? $t) type constructor
https://bugs.webkit.org/show_bug.cgi?id=226296

JSTests:

Adds additional tests for uses of `(ref $t)` and `(ref null $t)`
types, including with non-null extern/funcrefs.

Patch by Asumu Takikawa <asumu@igalia.com> on 2021-06-24
Reviewed by Yusuke Suzuki.

* wasm/function-references/ref_types.js: Added.
(module):
(async testRefTypeLocal):
(async testNonNullRefTypeLocal):
(async testRefTypeInSignature):
(async testRefTypeParamCheck):
(async testRefGlobalCheck):
(async testExternFuncrefNonNullCheck):
(async testExternrefCompatibility):
(async testNonNullExternrefIncompatible):
(async testFuncrefCompatibility):
(async testNonNullFuncrefIncompatible):
* wasm/wasm.json:

Source/JavaScriptCore:

Patch by Asumu Takikawa <asumu@igalia.com> on 2021-06-24
Reviewed by Yusuke Suzuki.

Adds the `ref` type constructor from the typed function references proposal:

  https://github.com/WebAssembly/function-references/blob/master/proposals/function-references/Overview.md

It's also required for the type imports and GC proposals as well. Ref types represent
references to any heap type (including existing funcref and externref) with a specified
nullability.

This requires a new isNullable flag in the type representation. This flag also enables
non-null externref and funcrefs, and hence this commit also adds the necessary checks
at Wasm/JS boundaries.

Non-null reference types also generally cannot be used as function locals.

* wasm/WasmAirIRGenerator.cpp:
(JSC::Wasm::AirIRGenerator::gTypeIdx):
(JSC::Wasm::AirIRGenerator::tmpForType):
(JSC::Wasm::AirIRGenerator::emitCCall):
(JSC::Wasm::AirIRGenerator::moveOpForValueType):
(JSC::Wasm::AirIRGenerator::AirIRGenerator):
(JSC::Wasm::AirIRGenerator::addLocal):
(JSC::Wasm::AirIRGenerator::addConstant):
(JSC::Wasm::AirIRGenerator::addRefFunc):
* wasm/WasmCallingConvention.h:
(JSC::Wasm::WasmCallingConvention::marshallLocation const):
(JSC::Wasm::JSCallingConvention::marshallLocation const):
* wasm/WasmFormat.h:
(JSC::Wasm::isSubtype):
(JSC::Wasm::isValidHeapTypeKind):
(JSC::Wasm::isDefaultableType):
* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser<Context>::parse):
(JSC::Wasm::FunctionParser<Context>::parseAnnotatedSelectImmediates):
(JSC::Wasm::FunctionParser<Context>::checkBranchTarget):
(JSC::Wasm::FunctionParser<Context>::parseExpression):
* wasm/WasmGlobal.cpp:
(JSC::Wasm::Global::get const):
(JSC::Wasm::Global::set):
* wasm/WasmLLIntGenerator.cpp:
(JSC::Wasm::LLIntGenerator::callInformationForCaller):
(JSC::Wasm::LLIntGenerator::callInformationForCallee):
(JSC::Wasm::LLIntGenerator::addArguments):
* wasm/WasmParser.h:
(JSC::Wasm::Parser<SuccessType>::parseBlockSignature):
(JSC::Wasm::Parser<SuccessType>::parseValueType):
(JSC::Wasm::Parser<SuccessType>::parseRefType):
* wasm/WasmSectionParser.cpp:
(JSC::Wasm::SectionParser::parseType):
(JSC::Wasm::SectionParser::parseElement):
(JSC::Wasm::SectionParser::parseInitExpr):
(JSC::Wasm::SectionParser::parseElementSegmentVectorOfExpressions):
(JSC::Wasm::SectionParser::parseGlobalType):
* wasm/WasmSignature.cpp:
(JSC::Wasm::computeHash):
* wasm/generateWasmOpsHeader.py:
* wasm/js/WasmToJS.cpp:
(JSC::Wasm::wasmToJS):
* wasm/js/WebAssemblyFunction.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::WebAssemblyFunction::jsCallEntrypointSlow):
* wasm/js/WebAssemblyFunctionBase.h:
(JSC::WebAssemblyFunctionBase::offsetOfSignatureIndex):
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::linkImpl):
* wasm/wasm.json:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestswasmwasmjson">trunk/JSTests/wasm/wasm.json</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmAirIRGeneratorcpp">trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.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="#trunkSourceJavaScriptCorewasmWasmGlobalcpp">trunk/Source/JavaScriptCore/wasm/WasmGlobal.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmLLIntGeneratorcpp">trunk/Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmParserh">trunk/Source/JavaScriptCore/wasm/WasmParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmSectionParsercpp">trunk/Source/JavaScriptCore/wasm/WasmSectionParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmSignaturecpp">trunk/Source/JavaScriptCore/wasm/WasmSignature.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmgenerateWasmOpsHeaderpy">trunk/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py</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="#trunkSourceJavaScriptCorewasmjsWebAssemblyFunctionBaseh">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunctionBase.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyModuleRecordcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmwasmjson">trunk/Source/JavaScriptCore/wasm/wasm.json</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestswasmfunctionreferencesref_typesjs">trunk/JSTests/wasm/function-references/ref_types.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (279264 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog  2021-06-25 01:27:32 UTC (rev 279264)
+++ trunk/JSTests/ChangeLog     2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -1,3 +1,27 @@
</span><ins>+2021-06-24  Asumu Takikawa  <asumu@igalia.com>
+
+        [WASM-Function-References] Add support for (ref null? $t) type constructor
+        https://bugs.webkit.org/show_bug.cgi?id=226296
+
+        Adds additional tests for uses of `(ref $t)` and `(ref null $t)`
+        types, including with non-null extern/funcrefs.
+
+        Reviewed by Yusuke Suzuki.
+
+        * wasm/function-references/ref_types.js: Added.
+        (module):
+        (async testRefTypeLocal):
+        (async testNonNullRefTypeLocal):
+        (async testRefTypeInSignature):
+        (async testRefTypeParamCheck):
+        (async testRefGlobalCheck):
+        (async testExternFuncrefNonNullCheck):
+        (async testExternrefCompatibility):
+        (async testNonNullExternrefIncompatible):
+        (async testFuncrefCompatibility):
+        (async testNonNullFuncrefIncompatible):
+        * wasm/wasm.json:
+
</ins><span class="cx"> 2021-06-24  Guillaume Emont  <guijemont@igalia.com>
</span><span class="cx"> 
</span><span class="cx">         Improve our checking of NaN values in DataView tests
</span></span></pre></div>
<a id="trunkJSTestswasmfunctionreferencesref_typesjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/function-references/ref_types.js (0 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/function-references/ref_types.js                              (rev 0)
+++ trunk/JSTests/wasm/function-references/ref_types.js 2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -0,0 +1,316 @@
</span><ins>+//@ runWebAssemblySuite("--useWebAssemblyTypedFunctionReferences=true")
+import * as assert from "../assert.js";
+import { instantiate } from "../wabt-wrapper.js";
+
+function module(bytes, valid = true) {
+  let buffer = new ArrayBuffer(bytes.length);
+  let view = new Uint8Array(buffer);
+  for (let i = 0; i < bytes.length; ++i) {
+    view[i] = bytes.charCodeAt(i);
+  }
+  return new WebAssembly.Module(buffer);
+}
+
+async function testRefTypeLocal() {
+  /*
+   * (module
+   *   (type (func (param i32) (result i32)))
+   *   (func (result (ref null 0)) (local (ref null 0))
+   *     (local.get 0)))
+   */
+  new WebAssembly.Instance(
+    module(
+      "\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x0b\x02\x60\x01\x7f\x01\x7f\x60\x00\x01\x6c\x00\x03\x02\x01\x01\x0a\x09\x01\x07\x01\x01\x6c\x00\x20\x00\x0b"
+    )
+  );
+}
+
+async function testNonNullRefTypeLocal() {
+  /*
+   * (module
+   *   (type (func (param i32) (result i32)))
+   *   (func (local (ref 0))))
+   */
+  assert.throws(
+    () =>
+      module(
+        "\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x09\x02\x60\x01\x7f\x01\x7f\x60\x00\x00\x03\x02\x01\x01\x0a\x07\x01\x05\x01\x01\x6b\x00\x0b"
+      ),
+    WebAssembly.CompileError,
+    "Function locals must have a defaultable type"
+  );
+}
+
+async function testRefTypeInSignature() {
+  /*
+   * (module
+   *   (elem declare funcref (ref.func $f))
+   *   (type $t1 (func (param i32) (result i32)))
+   *   (type $t2 (func (param) (result (ref $t1))))
+   *   (func $f (type $t1) (i32.const 1))
+   *   (func $g (type $t2) (ref.func $f)))
+   */
+  new WebAssembly.Instance(
+    module(
+      "\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x0b\x02\x60\x01\x7f\x01\x7f\x60\x00\x01\x6b\x00\x03\x03\x02\x00\x01\x09\x05\x01\x03\x00\x01\x00\x0a\x0b\x02\x04\x00\x41\x01\x0b\x04\x00\xd2\x00\x0b\x00\x0e\x04\x6e\x61\x6d\x65\x01\x07\x02\x00\x01\x66\x01\x01\x67"
+    )
+  );
+}
+
+async function testRefTypeParamCheck() {
+  const wat1 = `
+    (module
+      (func (export "f") (param f64) (result f64)
+        (local.get 0)))
+    `;
+
+  const instance1 = await instantiate(wat1);
+
+  /*
+   * (module
+   *   (type $t1 (func (param i32) (result i32)))
+   *   (type $t2 (func (param (ref $t1)) (result)))
+   *   (func (export "f") (type $t2)))
+   */
+  const m2 = module(
+    "\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x0b\x02\x60\x01\x7f\x01\x7f\x60\x01\x6b\x00\x00\x03\x02\x01\x01\x07\x05\x01\x01\x66\x00\x00\x0a\x04\x01\x02\x00\x0b"
+  );
+  const instance2 = new WebAssembly.Instance(m2);
+
+  /*
+   * (module
+   *   (type $t1 (func (param i32) (result i32)))
+   *   (type $t2 (func (param (ref null $t1)) (result)))
+   *   (func (export "f") (type $t2)))
+   */
+  const m3 = module(
+    "\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x0b\x02\x60\x01\x7f\x01\x7f\x60\x01\x6c\x00\x00\x03\x02\x01\x01\x07\x05\x01\x01\x66\x00\x00\x0a\x04\x01\x02\x00\x0b"
+  );
+  const instance3 = new WebAssembly.Instance(m3);
+
+  for (let i=0; i<1000; ++i) {
+    // Trigger the ic path
+    assert.throws(
+      () => instance2.exports.f(null),
+      WebAssembly.RuntimeError,
+      "Funcref must be an exported wasm function"
+    );
+    assert.throws(
+      () => instance2.exports.f(instance1.exports.f),
+      WebAssembly.RuntimeError,
+      "Argument function did not match the reference type"
+    );
+    instance3.exports.f(null);
+  }
+}
+
+async function testRefGlobalCheck() {
+  const wat = `
+    (module
+      (global (export "g") funcref (ref.null func))
+      (func (export "f") (param f64) (result f64)
+        (local.get 0)))
+    `;
+
+  const providerInstance = await instantiate(
+    wat,
+    {},
+    { reference_types: true }
+  );
+
+  /*
+   * (module
+   *   (global (export "g") (mut (ref func)) (ref.func $f))
+   *   (func $f))
+   */
+  const m1 = module(
+    "\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x04\x01\x60\x00\x00\x03\x02\x01\x00\x06\x07\x01\x6b\x70\x01\xd2\x00\x0b\x07\x05\x01\x01\x67\x03\x00\x0a\x04\x01\x02\x00\x0b\x00\x0b\x04\x6e\x61\x6d\x65\x01\x04\x01\x00\x01\x66"
+  );
+  const instance1 = new WebAssembly.Instance(m1);
+  assert.throws(
+    () => (instance1.exports.g.value = null),
+    WebAssembly.RuntimeError,
+    "Funcref must be an exported wasm function"
+  );
+
+  /*
+   * (module
+   *   (type (func))
+   *   (global (export "g") (mut (ref 0)) (ref.func $f))
+   *   (func $f (type 0)))
+   */
+  const m2 = module(
+    "\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x04\x01\x60\x00\x00\x03\x02\x01\x00\x06\x07\x01\x6b\x00\x01\xd2\x00\x0b\x07\x05\x01\x01\x67\x03\x00\x0a\x04\x01\x02\x00\x0b\x00\x0b\x04\x6e\x61\x6d\x65\x01\x04\x01\x00\x01\x66"
+  );
+  const instance2 = new WebAssembly.Instance(m2);
+  assert.throws(
+    () => (instance2.exports.g.value = null),
+    WebAssembly.RuntimeError,
+    "Funcref must be an exported wasm function"
+  );
+  assert.throws(
+    () => (instance2.exports.g.value = providerInstance.exports.f),
+    WebAssembly.RuntimeError,
+    "Argument function did not match the reference type"
+  );
+
+  /*
+   * (module
+   *   (import "m" "g" (global (ref func))))
+   */
+  const m3 = module(
+    "\x00\x61\x73\x6d\x01\x00\x00\x00\x02\x09\x01\x01\x6d\x01\x67\x03\x6b\x70\x00"
+  );
+  assert.throws(
+    () =>
+      new WebAssembly.Instance(m3, { m: { g: providerInstance.exports.g } }),
+    WebAssembly.LinkError,
+    "imported global m:g must be a same type"
+  );
+
+  /*
+   * (module
+   *   (type (func))
+   *   (import "m" "g" (global (ref 0))))
+   */
+  const m4 = module(
+    "\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x04\x01\x60\x00\x00\x02\x09\x01\x01\x6d\x01\x67\x03\x6b\x00\x00"
+  );
+  assert.throws(
+    () =>
+      new WebAssembly.Instance(m4, { m: { g: providerInstance.exports.g } }),
+    WebAssembly.LinkError,
+    "imported global m:g must be a same type"
+  );
+
+  /*
+   * (module
+   *   (import "m" "g" (global (ref extern))))
+   */
+  const m5 = module(
+    "\x00\x61\x73\x6d\x01\x00\x00\x00\x02\x09\x01\x01\x6d\x01\x67\x03\x6b\x6f\x00"
+  );
+  assert.throws(
+    () => new WebAssembly.Instance(m5, { m: { g: null } }),
+    WebAssembly.LinkError,
+    "imported global m:g must be a non-null value"
+  );
+
+  /*
+   * (module
+   *   (global $g (import "m" "g") (mut (ref extern)))
+   *   (func (global.set $g (ref.null extern))))
+   */
+  assert.throws(
+    () => {
+      module(
+        "\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x04\x01\x60\x00\x00\x02\x09\x01\x01\x6d\x01\x67\x03\x6b\x6f\x01\x03\x02\x01\x00\x0a\x08\x01\x06\x00\xd0\x6f\x24\x00\x0b"
+      )
+    },
+    WebAssembly.CompileError,
+    "WebAssembly.Module doesn't validate: set_global 0 with type Externref"
+  );
+}
+
+async function testExternFuncrefNonNullCheck() {
+  /*
+   * (module
+   *   (type $t (func (param (ref extern)) (result)))
+   *   (func (export "f") (type $t)))
+   */
+  const m1 = module(
+    "\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x06\x01\x60\x01\x6b\x6f\x00\x03\x02\x01\x00\x07\x05\x01\x01\x66\x00\x00\x0a\x04\x01\x02\x00\x0b"
+  );
+  const instance1 = new WebAssembly.Instance(m1);
+
+  /*
+   * (module
+   *   (type $t (func (param (ref func)) (result)))
+   *   (func (export "f") (type $t)))
+   */
+  const m2 = module(
+    "\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x06\x01\x60\x01\x6b\x70\x00\x03\x02\x01\x00\x07\x05\x01\x01\x66\x00\x00\x0a\x04\x01\x02\x00\x0b"
+  );
+  const instance2 = new WebAssembly.Instance(m2);
+
+  for (let i=0; i<1000; ++i) {
+    // Trigger the ic path
+    assert.throws(
+      () => instance1.exports.f(null),
+      WebAssembly.RuntimeError,
+      "Non-null Externref cannot be null"
+    );
+    assert.throws(
+      () => instance2.exports.f(null),
+      WebAssembly.RuntimeError,
+      "Funcref must be an exported wasm function"
+    );
+  }
+}
+
+// Ensure two ways of writing externref are equivalent.
+async function testExternrefCompatibility() {
+  /*
+   * (module
+   *   (type $t (func (param externref) (result (ref null extern))))
+   *   (func $f (type $t) (local.get 0)))
+   */
+  module(
+    "\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x07\x01\x60\x01\x6f\x01\x6c\x6f\x03\x02\x01\x00\x0a\x06\x01\x04\x00\x20\x00\x0b\x00\x0b\x04\x6e\x61\x6d\x65\x01\x04\x01\x00\x01\x66"
+  );
+}
+
+async function testNonNullExternrefIncompatible() {
+  /*
+   * (module
+   *   (type $t (func (param externref) (result (ref extern))))
+   *   (func $f (type $t) (local.get 0)))
+   */
+  assert.throws(
+    () =>
+      module(
+        "\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x07\x01\x60\x01\x6f\x01\x6b\x6f\x03\x02\x01\x00\x0a\x06\x01\x04\x00\x20\x00\x0b\x00\x0b\x04\x6e\x61\x6d\x65\x01\x04\x01\x00\x01\x66"
+      ),
+    WebAssembly.CompileError,
+    "control flow returns with unexpected type. Externref"
+  );
+}
+
+// Ensure two ways of writing funcref are equivalent.
+async function testFuncrefCompatibility() {
+  /*
+   * (module
+   *   (type $t (func (param funcref) (result (ref null func))))
+   *   (func $f (type $t) (local.get 0)))
+   */
+  module(
+    "\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x07\x01\x60\x01\x70\x01\x6c\x70\x03\x02\x01\x00\x0a\x06\x01\x04\x00\x20\x00\x0b\x00\x0b\x04\x6e\x61\x6d\x65\x01\x04\x01\x00\x01\x66"
+  );
+}
+
+async function testNonNullFuncrefIncompatible() {
+  /*
+   * (module
+   *   (type $t (func (param funcref) (result (ref func))))
+   *   (func $f (type $t) (local.get 0)))
+   */
+  assert.throws(
+    () =>
+      module(
+        "\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x07\x01\x60\x01\x70\x01\x6b\x70\x03\x02\x01\x00\x0a\x06\x01\x04\x00\x20\x00\x0b\x00\x0b\x04\x6e\x61\x6d\x65\x01\x04\x01\x00\x01\x66"
+      ),
+    WebAssembly.CompileError,
+    "control flow returns with unexpected type. Funcref"
+  );
+}
+
+assert.asyncTest(testRefTypeLocal());
+assert.asyncTest(testNonNullRefTypeLocal());
+assert.asyncTest(testRefTypeInSignature());
+assert.asyncTest(testRefTypeParamCheck());
+assert.asyncTest(testRefGlobalCheck());
+assert.asyncTest(testExternFuncrefNonNullCheck());
+assert.asyncTest(testExternrefCompatibility());
+assert.asyncTest(testNonNullExternrefIncompatible());
+assert.asyncTest(testFuncrefCompatibility());
+assert.asyncTest(testNonNullFuncrefIncompatible());
</ins></span></pre></div>
<a id="trunkJSTestswasmwasmjson"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/wasm.json (279264 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/wasm.json     2021-06-25 01:27:32 UTC (rev 279264)
+++ trunk/JSTests/wasm/wasm.json        2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -13,6 +13,8 @@
</span><span class="cx">         "f64":       { "type": "varint7", "value":   -4, "b3type": "B3::Double" },
</span><span class="cx">         "funcref":   { "type": "varint7", "value":  -16, "b3type": "B3::Int64" },
</span><span class="cx">         "externref": { "type": "varint7", "value":  -17, "b3type": "B3::Int64" },
</span><ins>+        "ref_null":  { "type": "varint7", "value":  -20, "b3type": "B3::Int64" },
+        "ref":       { "type": "varint7", "value":  -21, "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">         "type_idx":  { "type": "varint7", "value": -128, "b3type": "B3::Int64" }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (279264 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog    2021-06-25 01:27:32 UTC (rev 279264)
+++ trunk/Source/JavaScriptCore/ChangeLog       2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -1,3 +1,76 @@
</span><ins>+2021-06-24  Asumu Takikawa  <asumu@igalia.com>
+
+        [WASM-Function-References] Add support for (ref null? $t) type constructor
+        https://bugs.webkit.org/show_bug.cgi?id=226296
+
+        Reviewed by Yusuke Suzuki.
+
+        Adds the `ref` type constructor from the typed function references proposal:
+
+          https://github.com/WebAssembly/function-references/blob/master/proposals/function-references/Overview.md
+
+        It's also required for the type imports and GC proposals as well. Ref types represent
+        references to any heap type (including existing funcref and externref) with a specified
+        nullability.
+
+        This requires a new isNullable flag in the type representation. This flag also enables
+        non-null externref and funcrefs, and hence this commit also adds the necessary checks
+        at Wasm/JS boundaries.
+
+        Non-null reference types also generally cannot be used as function locals.
+
+        * wasm/WasmAirIRGenerator.cpp:
+        (JSC::Wasm::AirIRGenerator::gTypeIdx):
+        (JSC::Wasm::AirIRGenerator::tmpForType):
+        (JSC::Wasm::AirIRGenerator::emitCCall):
+        (JSC::Wasm::AirIRGenerator::moveOpForValueType):
+        (JSC::Wasm::AirIRGenerator::AirIRGenerator):
+        (JSC::Wasm::AirIRGenerator::addLocal):
+        (JSC::Wasm::AirIRGenerator::addConstant):
+        (JSC::Wasm::AirIRGenerator::addRefFunc):
+        * wasm/WasmCallingConvention.h:
+        (JSC::Wasm::WasmCallingConvention::marshallLocation const):
+        (JSC::Wasm::JSCallingConvention::marshallLocation const):
+        * wasm/WasmFormat.h:
+        (JSC::Wasm::isSubtype):
+        (JSC::Wasm::isValidHeapTypeKind):
+        (JSC::Wasm::isDefaultableType):
+        * wasm/WasmFunctionParser.h:
+        (JSC::Wasm::FunctionParser<Context>::parse):
+        (JSC::Wasm::FunctionParser<Context>::parseAnnotatedSelectImmediates):
+        (JSC::Wasm::FunctionParser<Context>::checkBranchTarget):
+        (JSC::Wasm::FunctionParser<Context>::parseExpression):
+        * wasm/WasmGlobal.cpp:
+        (JSC::Wasm::Global::get const):
+        (JSC::Wasm::Global::set):
+        * wasm/WasmLLIntGenerator.cpp:
+        (JSC::Wasm::LLIntGenerator::callInformationForCaller):
+        (JSC::Wasm::LLIntGenerator::callInformationForCallee):
+        (JSC::Wasm::LLIntGenerator::addArguments):
+        * wasm/WasmParser.h:
+        (JSC::Wasm::Parser<SuccessType>::parseBlockSignature):
+        (JSC::Wasm::Parser<SuccessType>::parseValueType):
+        (JSC::Wasm::Parser<SuccessType>::parseRefType):
+        * wasm/WasmSectionParser.cpp:
+        (JSC::Wasm::SectionParser::parseType):
+        (JSC::Wasm::SectionParser::parseElement):
+        (JSC::Wasm::SectionParser::parseInitExpr):
+        (JSC::Wasm::SectionParser::parseElementSegmentVectorOfExpressions):
+        (JSC::Wasm::SectionParser::parseGlobalType):
+        * wasm/WasmSignature.cpp:
+        (JSC::Wasm::computeHash):
+        * wasm/generateWasmOpsHeader.py:
+        * wasm/js/WasmToJS.cpp:
+        (JSC::Wasm::wasmToJS):
+        * wasm/js/WebAssemblyFunction.cpp:
+        (JSC::JSC_DEFINE_HOST_FUNCTION):
+        (JSC::WebAssemblyFunction::jsCallEntrypointSlow):
+        * wasm/js/WebAssemblyFunctionBase.h:
+        (JSC::WebAssemblyFunctionBase::offsetOfSignatureIndex):
+        * wasm/js/WebAssemblyModuleRecord.cpp:
+        (JSC::WebAssemblyModuleRecord::linkImpl):
+        * wasm/wasm.json:
+
</ins><span class="cx"> 2021-06-24  Mark Lam  <mark.lam@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Use ldp and stp more for saving / restoring registers on ARM64.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmAirIRGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp (279264 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp  2021-06-25 01:27:32 UTC (rev 279264)
+++ trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp     2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -413,6 +413,7 @@
</span><span class="cx">     TypedTmp g64() { return { newTmp(B3::GP), Types::I64 }; }
</span><span class="cx">     TypedTmp gExternref() { return { newTmp(B3::GP), Types::Externref }; }
</span><span class="cx">     TypedTmp gFuncref() { return { newTmp(B3::GP), Types::Funcref }; }
</span><ins>+    TypedTmp gTypeIdx(Type type) { return { newTmp(B3::GP), type }; }
</ins><span class="cx">     TypedTmp f32() { return { newTmp(B3::FP), Types::F32 }; }
</span><span class="cx">     TypedTmp f64() { return { newTmp(B3::FP), Types::F64 }; }
</span><span class="cx"> 
</span><span class="lines">@@ -425,6 +426,8 @@
</span><span class="cx">             return g64();
</span><span class="cx">         case TypeKind::Funcref:
</span><span class="cx">             return gFuncref();
</span><ins>+        case TypeKind::TypeIdx:
+            return gTypeIdx(type);
</ins><span class="cx">         case TypeKind::Externref:
</span><span class="cx">             return gExternref();
</span><span class="cx">         case TypeKind::F32:
</span><span class="lines">@@ -601,6 +604,7 @@
</span><span class="cx">             case TypeKind::I64:
</span><span class="cx">             case TypeKind::Externref:
</span><span class="cx">             case TypeKind::Funcref:
</span><ins>+            case TypeKind::TypeIdx:
</ins><span class="cx">                 resultType = B3::Int64;
</span><span class="cx">                 break;
</span><span class="cx">             case TypeKind::F32:
</span><span class="lines">@@ -650,6 +654,7 @@
</span><span class="cx">         case TypeKind::I64:
</span><span class="cx">         case TypeKind::Externref:
</span><span class="cx">         case TypeKind::Funcref:
</span><ins>+        case TypeKind::TypeIdx:
</ins><span class="cx">             return Move;
</span><span class="cx">         case TypeKind::F32:
</span><span class="cx">             return MoveFloat;
</span><span class="lines">@@ -907,6 +912,7 @@
</span><span class="cx">         case TypeKind::I64:
</span><span class="cx">         case TypeKind::Externref:
</span><span class="cx">         case TypeKind::Funcref:
</span><ins>+        case TypeKind::TypeIdx:
</ins><span class="cx">             append(Move, arg, m_locals[i]);
</span><span class="cx">             break;
</span><span class="cx">         case TypeKind::F32:
</span><span class="lines">@@ -1009,6 +1015,7 @@
</span><span class="cx">         switch (type.kind) {
</span><span class="cx">         case TypeKind::Externref:
</span><span class="cx">         case TypeKind::Funcref:
</span><ins>+        case TypeKind::TypeIdx:
</ins><span class="cx">             append(Move, Arg::imm(JSValue::encode(jsNull())), local);
</span><span class="cx">             break;
</span><span class="cx">         case TypeKind::I32:
</span><span class="lines">@@ -1044,6 +1051,7 @@
</span><span class="cx">     case TypeKind::I64:
</span><span class="cx">     case TypeKind::Externref:
</span><span class="cx">     case TypeKind::Funcref:
</span><ins>+    case TypeKind::TypeIdx:
</ins><span class="cx">         append(block, Move, Arg::bigImm(value), result);
</span><span class="cx">         break;
</span><span class="cx">     case TypeKind::F32:
</span><span class="lines">@@ -1088,7 +1096,11 @@
</span><span class="cx"> auto AirIRGenerator::addRefFunc(uint32_t index, ExpressionType& result) -> PartialResult
</span><span class="cx"> {
</span><span class="cx">     // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>.
</span><del>-    result = tmpForType(Types::Funcref);
</del><ins>+    if (Options::useWebAssemblyTypedFunctionReferences()) {
+        SignatureIndex signatureIndex = m_info.signatureIndexFromFunctionIndexSpace(index);
+        result = tmpForType(Type { TypeKind::TypeIdx, Nullable::No, signatureIndex });
+    } else
+        result = tmpForType(Types::Funcref);
</ins><span class="cx">     emitCCall(&operationWasmRefFunc, result, instanceValue(), addConstant(Types::I32, index));
</span><span class="cx"> 
</span><span class="cx">     return { };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmCallingConventionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h (279264 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h 2021-06-25 01:27:32 UTC (rev 279264)
+++ trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h    2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -107,6 +107,7 @@
</span><span class="cx">         case TypeKind::I64:
</span><span class="cx">         case TypeKind::Funcref:
</span><span class="cx">         case TypeKind::Externref:
</span><ins>+        case TypeKind::TypeIdx:
</ins><span class="cx">             return marshallLocationImpl(role, gprArgs, gpArgumentCount, stackOffset);
</span><span class="cx">         case TypeKind::F32:
</span><span class="cx">         case TypeKind::F64:
</span><span class="lines">@@ -195,6 +196,7 @@
</span><span class="cx">         case TypeKind::I64:
</span><span class="cx">         case TypeKind::Funcref:
</span><span class="cx">         case TypeKind::Externref:
</span><ins>+        case TypeKind::TypeIdx:
</ins><span class="cx">             return marshallLocationImpl(role, gprArgs, gpArgumentCount, stackOffset);
</span><span class="cx">         case TypeKind::F32:
</span><span class="cx">         case TypeKind::F64:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFormath"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFormat.h (279264 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFormat.h    2021-06-25 01:27:32 UTC (rev 279264)
+++ trunk/Source/JavaScriptCore/wasm/WasmFormat.h       2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -79,6 +79,9 @@
</span><span class="cx"> 
</span><span class="cx"> inline bool isSubtype(Type sub, Type parent)
</span><span class="cx"> {
</span><ins>+    if (sub.isNullable() && !parent.isNullable())
+        return false;
+
</ins><span class="cx">     if (sub.isTypeIdx() && parent.isFuncref())
</span><span class="cx">         return true;
</span><span class="cx"> 
</span><span class="lines">@@ -90,6 +93,23 @@
</span><span class="cx">     return type.isFuncref() || type.isExternref() || type.isTypeIdx();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool isValidHeapTypeKind(TypeKind kind)
+{
+    switch (kind) {
+    case TypeKind::Funcref:
+    case TypeKind::Externref:
+        return true;
+    default:
+        break;
+    }
+    return false;
+}
+
+inline bool isDefaultableType(Type type)
+{
+    return !isRefType(type) || type.isNullable();
+}
+
</ins><span class="cx"> enum class ExternalKind : uint8_t {
</span><span class="cx">     // FIXME auto-generate this. https://bugs.webkit.org/show_bug.cgi?id=165231
</span><span class="cx">     Function = 0,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFunctionParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h (279264 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h    2021-06-25 01:27:32 UTC (rev 279264)
+++ trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h       2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -243,7 +243,8 @@
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarUInt32(numberOfLocals), "can't get Function's number of locals in group ", i);
</span><span class="cx">         totalNumberOfLocals += numberOfLocals;
</span><span class="cx">         WASM_PARSER_FAIL_IF(totalNumberOfLocals > maxFunctionLocals, "Function's number of locals is too big ", totalNumberOfLocals, " maximum ", maxFunctionLocals);
</span><del>-        WASM_PARSER_FAIL_IF(!parseValueType(typeOfLocal), "can't get Function local's type in group ", i);
</del><ins>+        WASM_PARSER_FAIL_IF(!parseValueType(m_info, typeOfLocal), "can't get Function local's type in group ", i);
+        WASM_PARSER_FAIL_IF(!isDefaultableType(typeOfLocal), "Function locals must have a defaultable type");
</ins><span class="cx"> 
</span><span class="cx">         WASM_PARSER_FAIL_IF(!m_locals.tryReserveCapacity(totalNumberOfLocals), "can't allocate enough memory for function's ", totalNumberOfLocals, " locals");
</span><span class="cx">         for (uint32_t i = 0; i < numberOfLocals; ++i)
</span><span class="lines">@@ -644,7 +645,7 @@
</span><span class="cx">     WASM_PARSER_FAIL_IF(sizeOfAnnotationVector != 1, "select invalid result arity for");
</span><span class="cx"> 
</span><span class="cx">     Type targetType;
</span><del>-    WASM_PARSER_FAIL_IF(!parseValueType(targetType), "select can't parse annotations");
</del><ins>+    WASM_PARSER_FAIL_IF(!parseValueType(m_info, targetType), "select can't parse annotations");
</ins><span class="cx"> 
</span><span class="cx">     result.sizeOfAnnotationVector = sizeOfAnnotationVector;
</span><span class="cx">     result.targetType = targetType;
</span><span class="lines">@@ -699,7 +700,7 @@
</span><span class="cx"> 
</span><span class="cx">     unsigned offset = m_expressionStack.size() - target.branchTargetArity();
</span><span class="cx">     for (unsigned i = 0; i < target.branchTargetArity(); ++i)
</span><del>-        WASM_VALIDATOR_FAIL_IF(!isSubtype(target.branchTargetType(i), m_expressionStack[offset + i].type()), "branch's stack type is not a block's type branch target type. Stack value has type", m_expressionStack[offset + i].type().kind, " but branch target expects a value of ", target.branchTargetType(i).kind, " at index ", i);
</del><ins>+        WASM_VALIDATOR_FAIL_IF(!isSubtype(m_expressionStack[offset + i].type(), target.branchTargetType(i)), "branch's stack type is not a block's type branch target type. Stack value has type ", m_expressionStack[offset + i].type().kind, " but branch target expects a value of ", target.branchTargetType(i).kind, " at index ", i);
</ins><span class="cx"> 
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="lines">@@ -1079,7 +1080,7 @@
</span><span class="cx">     case RefNull: {
</span><span class="cx">         WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
</span><span class="cx">         Type typeOfNull;
</span><del>-        WASM_PARSER_FAIL_IF(!parseRefType(typeOfNull), "ref.null type must be a reference type");
</del><ins>+        WASM_PARSER_FAIL_IF(!parseRefType(m_info, typeOfNull), "ref.null type must be a reference type");
</ins><span class="cx">         m_expressionStack.constructAndAppend(typeOfNull, m_context.addConstant(typeOfNull, JSValue::encode(jsNull())));
</span><span class="cx">         return { };
</span><span class="cx">     }
</span><span class="lines">@@ -1109,7 +1110,7 @@
</span><span class="cx"> 
</span><span class="cx">         if (Options::useWebAssemblyTypedFunctionReferences()) {
</span><span class="cx">             SignatureIndex signatureIndex = m_info.signatureIndexFromFunctionIndexSpace(index);
</span><del>-            m_expressionStack.constructAndAppend(Type {TypeKind::TypeIdx, signatureIndex}, result);
</del><ins>+            m_expressionStack.constructAndAppend(Type {TypeKind::TypeIdx, Nullable::No, signatureIndex}, result);
</ins><span class="cx">             return { };
</span><span class="cx">         }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmGlobalcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmGlobal.cpp (279264 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmGlobal.cpp  2021-06-25 01:27:32 UTC (rev 279264)
+++ trunk/Source/JavaScriptCore/wasm/WasmGlobal.cpp     2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -48,6 +48,7 @@
</span><span class="cx">         return jsNumber(purifyNaN(bitwise_cast<double>(m_value.m_primitive)));
</span><span class="cx">     case TypeKind::Externref:
</span><span class="cx">     case TypeKind::Funcref:
</span><ins>+    case TypeKind::TypeIdx:
</ins><span class="cx">         return m_value.m_externref.get();
</span><span class="cx">     default:
</span><span class="cx">         return jsUndefined();
</span><span class="lines">@@ -86,15 +87,35 @@
</span><span class="cx">     }
</span><span class="cx">     case TypeKind::Externref: {
</span><span class="cx">         RELEASE_ASSERT(m_owner);
</span><ins>+        if (!m_type.isNullable() && argument.isNull()) {
+            throwException(globalObject, throwScope, createJSWebAssemblyRuntimeError(globalObject, vm, "Non-null Externref cannot be null"));
+            return;
+        }
</ins><span class="cx">         m_value.m_externref.set(m_owner->vm(), m_owner, argument);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><ins>+    case TypeKind::TypeIdx:
</ins><span class="cx">     case TypeKind::Funcref: {
</span><span class="cx">         RELEASE_ASSERT(m_owner);
</span><del>-        if (!isWebAssemblyHostFunction(vm, argument) && !argument.isNull()) {
</del><ins>+        bool isNullable = m_type.isNullable();
+        WebAssemblyFunction* wasmFunction = nullptr;
+        WebAssemblyWrapperFunction* wasmWrapperFunction = nullptr;
+        if (!isWebAssemblyHostFunction(vm, argument, wasmFunction, wasmWrapperFunction) && (!isNullable || !argument.isNull())) {
</ins><span class="cx">             throwException(globalObject, throwScope, createJSWebAssemblyRuntimeError(globalObject, vm, "Funcref must be an exported wasm function"));
</span><span class="cx">             return;
</span><span class="cx">         }
</span><ins>+        if (m_type.kind == TypeKind::TypeIdx && (wasmFunction || wasmWrapperFunction)) {
+            Wasm::SignatureIndex paramIndex = m_type.index;
+            Wasm::SignatureIndex argIndex;
+            if (wasmFunction)
+                argIndex = wasmFunction->signatureIndex();
+            else
+                argIndex = wasmWrapperFunction->signatureIndex();
+            if (paramIndex != argIndex) {
+                throwException(globalObject, throwScope, createJSWebAssemblyRuntimeError(globalObject, vm, "Argument function did not match the reference type"));
+                return;
+            }
+        }
</ins><span class="cx">         m_value.m_externref.set(m_owner->vm(), m_owner, argument);
</span><span class="cx">         break;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmLLIntGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp (279264 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp  2021-06-25 01:27:32 UTC (rev 279264)
+++ trunk/Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp     2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -562,6 +562,8 @@
</span><span class="cx">             break;
</span><span class="cx">         case TypeKind::Void:
</span><span class="cx">         case TypeKind::Func:
</span><ins>+        case TypeKind::RefNull:
+        case TypeKind::Ref:
</ins><span class="cx">             RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         }
</span><span class="cx">     };
</span><span class="lines">@@ -618,6 +620,8 @@
</span><span class="cx">             break;
</span><span class="cx">         case TypeKind::Void:
</span><span class="cx">         case TypeKind::Func:
</span><ins>+        case TypeKind::RefNull:
+        case TypeKind::Ref:
</ins><span class="cx">             RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -646,6 +650,8 @@
</span><span class="cx">             break;
</span><span class="cx">         case TypeKind::Void:
</span><span class="cx">         case TypeKind::Func:
</span><ins>+        case TypeKind::RefNull:
+        case TypeKind::Ref:
</ins><span class="cx">             RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -702,6 +708,8 @@
</span><span class="cx">             break;
</span><span class="cx">         case TypeKind::Void:
</span><span class="cx">         case TypeKind::Func:
</span><ins>+        case TypeKind::RefNull:
+        case TypeKind::Ref:
</ins><span class="cx">             RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -751,6 +759,8 @@
</span><span class="cx">             break;
</span><span class="cx">         case TypeKind::Void:
</span><span class="cx">         case TypeKind::Func:
</span><ins>+        case TypeKind::RefNull:
+        case TypeKind::Ref:
</ins><span class="cx">             RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmParser.h (279264 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmParser.h    2021-06-25 01:27:32 UTC (rev 279264)
+++ trunk/Source/JavaScriptCore/wasm/WasmParser.h       2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -84,8 +84,8 @@
</span><span class="cx">     bool WARN_UNUSED_RETURN parseVarInt64(int64_t&);
</span><span class="cx"> 
</span><span class="cx">     PartialResult WARN_UNUSED_RETURN parseBlockSignature(const ModuleInformation&, BlockSignature&);
</span><del>-    bool WARN_UNUSED_RETURN parseValueType(Type&);
-    bool WARN_UNUSED_RETURN parseRefType(Type&);
</del><ins>+    bool WARN_UNUSED_RETURN parseValueType(const ModuleInformation&, Type&);
+    bool WARN_UNUSED_RETURN parseRefType(const ModuleInformation&, Type&);
</ins><span class="cx">     bool WARN_UNUSED_RETURN parseExternalKind(ExternalKind&);
</span><span class="cx"> 
</span><span class="cx">     size_t m_offset = 0;
</span><span class="lines">@@ -277,7 +277,7 @@
</span><span class="cx"> {
</span><span class="cx">     int8_t typeKind;
</span><span class="cx">     if (peekInt7(typeKind) && isValidTypeKind(typeKind)) {
</span><del>-        Type type = {static_cast<TypeKind>(typeKind), 0};
</del><ins>+        Type type = {static_cast<TypeKind>(typeKind), Nullable::Yes, 0};
</ins><span class="cx">         WASM_PARSER_FAIL_IF(!(isValueType(type) || type.isVoid()), "result type of block: ", makeString(type.kind), " is not a value type or Void");
</span><span class="cx">         result = m_signatureInformation.thunkFor(type);
</span><span class="cx">         m_offset++;
</span><span class="lines">@@ -296,22 +296,50 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template<typename SuccessType>
</span><del>-ALWAYS_INLINE bool Parser<SuccessType>::parseValueType(Type& result)
</del><ins>+ALWAYS_INLINE bool Parser<SuccessType>::parseValueType(const ModuleInformation& info, Type& result)
</ins><span class="cx"> {
</span><span class="cx">     int8_t kind;
</span><span class="cx">     if (!parseInt7(kind))
</span><span class="cx">         return false;
</span><del>-    Type type = {static_cast<TypeKind>(kind), 0};
-    if (!isValidTypeKind(kind) || !isValueType(type))
</del><ins>+    if (!isValidTypeKind(kind))
</ins><span class="cx">         return false;
</span><ins>+
+    TypeKind typeKind = static_cast<TypeKind>(kind);
+    bool isNullable = true;
+    SignatureIndex sigIndex = 0;
+    if (typeKind == TypeKind::Ref || typeKind == TypeKind::RefNull) {
+        if (!Options::useWebAssemblyTypedFunctionReferences())
+            return false;
+
+        int32_t heapType;
+        isNullable = typeKind == TypeKind::RefNull;
+
+        if (!parseVarInt32(heapType))
+            return false;
+        if (heapType < 0) {
+            TypeKind heapKind = static_cast<TypeKind>(heapType);
+            if (!isValidHeapTypeKind(heapKind))
+                return false;
+            typeKind = heapKind;
+        } else {
+            typeKind = TypeKind::TypeIdx;
+            if (static_cast<size_t>(heapType) >= info.usedSignatures.size())
+                return false;
+            sigIndex = SignatureInformation::get(info.usedSignatures[heapType].get());
+        }
+    }
+
+    Type type = { typeKind, static_cast<Nullable>(isNullable), sigIndex };
+    if (!isValueType(type))
+        return false;
</ins><span class="cx">     result = type;
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template<typename SuccessType>
</span><del>-ALWAYS_INLINE bool Parser<SuccessType>::parseRefType(Type& result)
</del><ins>+ALWAYS_INLINE bool Parser<SuccessType>::parseRefType(const ModuleInformation& info, Type& result)
</ins><span class="cx"> {
</span><del>-    const bool parsed = parseValueType(result);
</del><ins>+    const bool parsed = parseValueType(info, result);
</ins><span class="cx">     return parsed && isRefType(result);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmSectionParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmSectionParser.cpp (279264 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmSectionParser.cpp   2021-06-25 01:27:32 UTC (rev 279264)
+++ trunk/Source/JavaScriptCore/wasm/WasmSectionParser.cpp      2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -60,7 +60,7 @@
</span><span class="cx"> 
</span><span class="cx">         for (unsigned i = 0; i < argumentCount; ++i) {
</span><span class="cx">             Type argumentType;
</span><del>-            WASM_PARSER_FAIL_IF(!parseValueType(argumentType), "can't get ", i, "th argument Type");
</del><ins>+            WASM_PARSER_FAIL_IF(!parseValueType(m_info, argumentType), "can't get ", i, "th argument Type");
</ins><span class="cx">             arguments.append(argumentType);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -72,7 +72,7 @@
</span><span class="cx">         WASM_PARSER_FAIL_IF(!returnTypes.tryReserveCapacity(argumentCount), "can't allocate enough memory for Type section's ", i, "th signature");
</span><span class="cx">         for (unsigned i = 0; i < returnCount; ++i) {
</span><span class="cx">             Type value;
</span><del>-            WASM_PARSER_FAIL_IF(!parseValueType(value), "can't get ", i, "th Type's return value");
</del><ins>+            WASM_PARSER_FAIL_IF(!parseValueType(m_info, value), "can't get ", i, "th Type's return value");
</ins><span class="cx">             returnTypes.append(value);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -483,7 +483,7 @@
</span><span class="cx">         case 0x05: {
</span><span class="cx">             WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
</span><span class="cx">             Type refType;
</span><del>-            WASM_PARSER_FAIL_IF(!parseRefType(refType), "can't parse reftype in elem section");
</del><ins>+            WASM_PARSER_FAIL_IF(!parseRefType(m_info, refType), "can't parse reftype in elem section");
</ins><span class="cx">             WASM_PARSER_FAIL_IF(!refType.isFuncref(), "reftype in element section should be funcref");
</span><span class="cx"> 
</span><span class="cx">             uint32_t indexCount;
</span><span class="lines">@@ -507,7 +507,7 @@
</span><span class="cx">             WASM_FAIL_IF_HELPER_FAILS(parseI32InitExprForElementSection(initExpr));
</span><span class="cx"> 
</span><span class="cx">             Type refType;
</span><del>-            WASM_PARSER_FAIL_IF(!parseRefType(refType), "can't parse reftype in elem section");
</del><ins>+            WASM_PARSER_FAIL_IF(!parseRefType(m_info, refType), "can't parse reftype in elem section");
</ins><span class="cx">             WASM_PARSER_FAIL_IF(!refType.isFuncref(), "reftype in element section should be funcref");
</span><span class="cx"> 
</span><span class="cx">             uint32_t indexCount;
</span><span class="lines">@@ -525,7 +525,7 @@
</span><span class="cx">             WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
</span><span class="cx"> 
</span><span class="cx">             Type refType;
</span><del>-            WASM_PARSER_FAIL_IF(!parseRefType(refType), "can't parse reftype in elem section");
</del><ins>+            WASM_PARSER_FAIL_IF(!parseRefType(m_info, refType), "can't parse reftype in elem section");
</ins><span class="cx">             WASM_PARSER_FAIL_IF(!refType.isFuncref(), "reftype in element section should be funcref");
</span><span class="cx"> 
</span><span class="cx">             uint32_t indexCount;
</span><span class="lines">@@ -605,7 +605,7 @@
</span><span class="cx"> 
</span><span class="cx">     case RefNull: {
</span><span class="cx">         Type typeOfNull;
</span><del>-        WASM_PARSER_FAIL_IF(!parseRefType(typeOfNull), "ref.null type must be a reference type");
</del><ins>+        WASM_PARSER_FAIL_IF(!parseRefType(m_info, typeOfNull), "ref.null type must be a reference type");
</ins><span class="cx">         resultType = typeOfNull;
</span><span class="cx">         bitsOrImportNumber = JSValue::encode(jsNull());
</span><span class="cx">         break;
</span><span class="lines">@@ -616,7 +616,12 @@
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarUInt32(index), "can't get ref.func index");
</span><span class="cx">         WASM_PARSER_FAIL_IF(index >= m_info->functions.size(), "ref.func index", index, " exceeds the number of functions ", m_info->functions.size());
</span><span class="cx"> 
</span><del>-        resultType = Types::Funcref;
</del><ins>+        if (Options::useWebAssemblyTypedFunctionReferences()) {
+            SignatureIndex signatureIndex = m_info->signatureIndexFromFunctionIndexSpace(index);
+            resultType = { TypeKind::TypeIdx, Nullable::No, signatureIndex };
+        } else
+            resultType = Types::Funcref;
+
</ins><span class="cx">         bitsOrImportNumber = index;
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="lines">@@ -691,7 +696,7 @@
</span><span class="cx">             m_info->addDeclaredFunction(functionIndex);
</span><span class="cx">         } else {
</span><span class="cx">             Type typeOfNull;
</span><del>-            WASM_PARSER_FAIL_IF(!parseRefType(typeOfNull), "ref.null type must be a func type in elem section");
</del><ins>+            WASM_PARSER_FAIL_IF(!parseRefType(m_info, typeOfNull), "ref.null type must be a func type in elem section");
</ins><span class="cx">             WASM_PARSER_FAIL_IF(!typeOfNull.isFuncref(), "ref.null extern is forbidden in element section's, ", elementNum, "th element's ", index, "th index");
</span><span class="cx">             functionIndex = Element::nullFuncIndex;
</span><span class="cx">         }
</span><span class="lines">@@ -727,7 +732,7 @@
</span><span class="cx"> auto SectionParser::parseGlobalType(GlobalInformation& global) -> PartialResult
</span><span class="cx"> {
</span><span class="cx">     uint8_t mutability;
</span><del>-    WASM_PARSER_FAIL_IF(!parseValueType(global.type), "can't get Global's value type");
</del><ins>+    WASM_PARSER_FAIL_IF(!parseValueType(m_info, global.type), "can't get Global's value type");
</ins><span class="cx">     WASM_PARSER_FAIL_IF(!parseUInt8(mutability), "can't get Global type's mutability");
</span><span class="cx">     WASM_PARSER_FAIL_IF(mutability != 0x0 && mutability != 0x1, "invalid Global's mutability: 0x", hex(mutability, 2, Lowercase));
</span><span class="cx">     global.mutability = static_cast<GlobalInformation::Mutability>(mutability);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmSignaturecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmSignature.cpp (279264 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmSignature.cpp       2021-06-25 01:27:32 UTC (rev 279264)
+++ trunk/Source/JavaScriptCore/wasm/WasmSignature.cpp  2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -70,10 +70,12 @@
</span><span class="cx">     unsigned accumulator = 0xa1bcedd8u;
</span><span class="cx">     for (uint32_t i = 0; i < argumentCount; ++i) {
</span><span class="cx">         accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<uint8_t>::hash(static_cast<uint8_t>(argumentTypes[i].kind)));
</span><ins>+        accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<uint8_t>::hash(static_cast<uint8_t>(argumentTypes[i].nullable)));
</ins><span class="cx">         accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<unsigned>::hash(argumentTypes[i].index));
</span><span class="cx">     }
</span><span class="cx">     for (uint32_t i = 0; i < returnCount; ++i) {
</span><span class="cx">         accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<uint8_t>::hash(static_cast<uint8_t>(returnTypes[i].kind)));
</span><ins>+        accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<uint8_t>::hash(static_cast<uint8_t>(returnTypes[i].nullable)));
</ins><span class="cx">         accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<unsigned>::hash(returnTypes[i].index));
</span><span class="cx">     }
</span><span class="cx">     return accumulator;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmgenerateWasmOpsHeaderpy"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py (279264 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py        2021-06-25 01:27:32 UTC (rev 279264)
+++ trunk/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py   2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -212,15 +212,21 @@
</span><span class="cx"> };
</span><span class="cx"> #undef CREATE_ENUM_VALUE
</span><span class="cx"> 
</span><ins>+enum class Nullable : bool {
+  No = false,
+  Yes = true,
+};
+
</ins><span class="cx"> using SignatureIndex = uintptr_t;
</span><span class="cx"> 
</span><span class="cx"> struct Type {
</span><span class="cx">     TypeKind kind;
</span><ins>+    Nullable nullable;
</ins><span class="cx">     SignatureIndex index;
</span><span class="cx"> 
</span><span class="cx">     bool operator==(const Type& other) const
</span><span class="cx">     {
</span><del>-        return other.kind == kind && other.index == index;
</del><ins>+        return other.kind == kind && other.nullable == nullable && other.index == index;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool operator!=(const Type& other) const
</span><span class="lines">@@ -228,6 +234,11 @@
</span><span class="cx">         return !(other == *this);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    bool isNullable() const
+    {
+        return static_cast<bool>(nullable);
+    }
+
</ins><span class="cx">     #define CREATE_PREDICATE(name, ...) bool is ## name() const { return kind == TypeKind::name; }
</span><span class="cx">     FOR_EACH_WASM_TYPE(CREATE_PREDICATE)
</span><span class="cx">     #undef CREATE_PREDICATE
</span><span class="lines">@@ -235,7 +246,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace Types
</span><span class="cx"> {
</span><del>-#define CREATE_CONSTANT(name, id, ...) constexpr Type name = Type{TypeKind::name, 0u};
</del><ins>+#define CREATE_CONSTANT(name, id, ...) constexpr Type name = Type{TypeKind::name, Nullable::Yes, 0u};
</ins><span class="cx"> FOR_EACH_WASM_TYPE(CREATE_CONSTANT)
</span><span class="cx"> #undef CREATE_CONSTANT
</span><span class="cx"> } // namespace Types
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWasmToJScpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WasmToJS.cpp (279264 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WasmToJS.cpp 2021-06-25 01:27:32 UTC (rev 279264)
+++ trunk/Source/JavaScriptCore/wasm/js/WasmToJS.cpp    2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -104,6 +104,8 @@
</span><span class="cx">             switch (argType.kind) {
</span><span class="cx">             case TypeKind::Void:
</span><span class="cx">             case TypeKind::Func:
</span><ins>+            case TypeKind::RefNull:
+            case TypeKind::Ref:
</ins><span class="cx">                 RELEASE_ASSERT_NOT_REACHED(); // Handled above.
</span><span class="cx">             case TypeKind::TypeIdx:
</span><span class="cx">             case TypeKind::Externref:
</span><span class="lines">@@ -177,6 +179,8 @@
</span><span class="cx">             switch (argType.kind) {
</span><span class="cx">             case TypeKind::Void:
</span><span class="cx">             case TypeKind::Func:
</span><ins>+            case TypeKind::RefNull:
+            case TypeKind::Ref:
</ins><span class="cx">                 RELEASE_ASSERT_NOT_REACHED(); // Handled above.
</span><span class="cx">             case TypeKind::TypeIdx:
</span><span class="cx">             case TypeKind::Externref:
</span><span class="lines">@@ -278,6 +282,8 @@
</span><span class="cx">         switch (signature.returnType(0).kind) {
</span><span class="cx">         case TypeKind::Void:
</span><span class="cx">         case TypeKind::Func:
</span><ins>+        case TypeKind::RefNull:
+        case TypeKind::Ref:
</ins><span class="cx">             // For the JavaScript embedding, imports with these types in their signature return are a WebAssembly.Module validation error.
</span><span class="cx">             RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">             break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyFunctioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp (279264 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp      2021-06-25 01:27:32 UTC (rev 279264)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp 2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -85,11 +85,26 @@
</span><span class="cx">             break;
</span><span class="cx">         case Wasm::TypeKind::TypeIdx:
</span><span class="cx">         case Wasm::TypeKind::Funcref: {
</span><del>-            if (!isWebAssemblyHostFunction(vm, arg) && !arg.isNull())
</del><ins>+            bool isNullable = signature.argument(argIndex).isNullable();
+            WebAssemblyFunction* wasmFunction = nullptr;
+            WebAssemblyWrapperFunction* wasmWrapperFunction = nullptr;
+            if (!isWebAssemblyHostFunction(vm, arg, wasmFunction, wasmWrapperFunction) && (!isNullable || !arg.isNull()))
</ins><span class="cx">                 return JSValue::encode(throwException(globalObject, scope, createJSWebAssemblyRuntimeError(globalObject, vm, "Funcref must be an exported wasm function")));
</span><ins>+            if (signature.argument(argIndex).kind == Wasm::TypeKind::TypeIdx && (wasmFunction || wasmWrapperFunction)) {
+                Wasm::SignatureIndex paramIndex = signature.argument(argIndex).index;
+                Wasm::SignatureIndex argIndex;
+                if (wasmFunction)
+                    argIndex = wasmFunction->signatureIndex();
+                else
+                    argIndex = wasmWrapperFunction->signatureIndex();
+                if (paramIndex != argIndex)
+                    return JSValue::encode(throwException(globalObject, scope, createJSWebAssemblyRuntimeError(globalObject, vm, "Argument function did not match the reference type")));
+            }
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case Wasm::TypeKind::Externref:
</span><ins>+            if (!signature.argument(argIndex).isNullable() && arg.isNull())
+                return JSValue::encode(throwException(globalObject, scope, createJSWebAssemblyRuntimeError(globalObject, vm, "Non-null Externref cannot be null")));
</ins><span class="cx">             break;
</span><span class="cx">         case Wasm::TypeKind::I64:
</span><span class="cx">             arg = JSValue::decode(bitwise_cast<uint64_t>(arg.toBigInt64(globalObject)));
</span><span class="lines">@@ -102,6 +117,8 @@
</span><span class="cx">             break;
</span><span class="cx">         case Wasm::TypeKind::Void:
</span><span class="cx">         case Wasm::TypeKind::Func:
</span><ins>+        case Wasm::TypeKind::RefNull:
+        case Wasm::TypeKind::Ref:
</ins><span class="cx">             RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         }
</span><span class="cx">         RETURN_IF_EXCEPTION(scope, encodedJSValue());
</span><span class="lines">@@ -277,10 +294,13 @@
</span><span class="cx">                 jit.zeroExtend32ToWord(scratchGPR, wasmCallInfo.params[i].gpr());
</span><span class="cx">             break;
</span><span class="cx">         }
</span><ins>+        case Wasm::TypeKind::TypeIdx:
</ins><span class="cx">         case Wasm::TypeKind::Funcref: {
</span><span class="cx">             // Ensure we have a WASM exported function.
</span><span class="cx">             jit.load64(jsParam, scratchGPR);
</span><span class="cx">             auto isNull = jit.branchIfNull(scratchGPR);
</span><ins>+            if (!type.isNullable())
+                slowPath.append(isNull);
</ins><span class="cx">             slowPath.append(jit.branchIfNotCell(scratchGPR));
</span><span class="cx"> 
</span><span class="cx">             stackLimitGPRIsClobbered = true;
</span><span class="lines">@@ -294,15 +314,28 @@
</span><span class="cx">             slowPath.append(jit.branchPtr(CCallHelpers::NotEqual, scratchGPR, CCallHelpers::TrustedImmPtr(WebAssemblyWrapperFunction::info())));
</span><span class="cx"> 
</span><span class="cx">             isWasmFunction.link(&jit);
</span><del>-            isNull.link(&jit);
</del><ins>+            if (type.kind == Wasm::TypeKind::TypeIdx) {
+                jit.load64(jsParam, scratchGPR);
+                jit.loadPtr(CCallHelpers::Address(scratchGPR, WebAssemblyFunctionBase::offsetOfSignatureIndex()), scratchGPR);
+                slowPath.append(jit.branchPtr(CCallHelpers::NotEqual, scratchGPR, CCallHelpers::TrustedImmPtr(type.index)));
+            }
+
+            if (type.isNullable())
+                isNull.link(&jit);
</ins><span class="cx">             FALLTHROUGH;
</span><span class="cx">         }
</span><span class="cx">         case Wasm::TypeKind::Externref: {
</span><span class="cx">             if (isStack) {
</span><span class="cx">                 jit.load64(jsParam, scratchGPR);
</span><ins>+                if (!type.isNullable())
+                    slowPath.append(jit.branchIfNull(scratchGPR));
</ins><span class="cx">                 jit.store64(scratchGPR, calleeFrame.withOffset(wasmCallInfo.params[i].offsetFromSP()));
</span><del>-            } else
-                jit.load64(jsParam, wasmCallInfo.params[i].gpr());
</del><ins>+            } else {
+                auto externGPR = wasmCallInfo.params[i].gpr();
+                jit.load64(jsParam, externGPR);
+                if (!type.isNullable())
+                    slowPath.append(jit.branchIfNull(externGPR));
+            }
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case Wasm::TypeKind::F32:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyFunctionBaseh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunctionBase.h (279264 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunctionBase.h    2021-06-25 01:27:32 UTC (rev 279264)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunctionBase.h       2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -52,6 +52,8 @@
</span><span class="cx"> 
</span><span class="cx">     static ptrdiff_t offsetOfInstance() { return OBJECT_OFFSETOF(WebAssemblyFunctionBase, m_instance); }
</span><span class="cx"> 
</span><ins>+    static ptrdiff_t offsetOfSignatureIndex() { return OBJECT_OFFSETOF(WebAssemblyFunctionBase, m_importableFunction) + WasmToWasmImportableFunction::offsetOfSignatureIndex(); }
+
</ins><span class="cx">     static ptrdiff_t offsetOfEntrypointLoadLocation() { return OBJECT_OFFSETOF(WebAssemblyFunctionBase, m_importableFunction) + WasmToWasmImportableFunction::offsetOfEntrypointLoadLocation(); }
</span><span class="cx"> 
</span><span class="cx"> protected:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyModuleRecordcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp (279264 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp  2021-06-25 01:27:32 UTC (rev 279264)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp     2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -247,16 +247,35 @@
</span><span class="cx">                     if (globalValue->global()->mutability() != Wasm::GlobalInformation::Immutable)
</span><span class="cx">                         return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported global", "must be a same mutability")));
</span><span class="cx">                     switch (moduleInformation.globals[import.kindIndex].type.kind) {
</span><del>-                    case Wasm::TypeKind::Funcref:
</del><ins>+                    case Wasm::TypeKind::TypeIdx:
+                    case Wasm::TypeKind::Funcref: {
+                        bool isNullable = global.type.isNullable();
+                        WebAssemblyFunction* wasmFunction = nullptr;
+                        WebAssemblyWrapperFunction* wasmWrapperFunction = nullptr;
</ins><span class="cx">                         value = globalValue->global()->get(globalObject);
</span><span class="cx">                         RETURN_IF_EXCEPTION(scope, void());
</span><del>-                        if (!isWebAssemblyHostFunction(vm, value) && !value.isNull())
-                            return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported global", "must be a wasm exported function or null")));
</del><ins>+                        if (!isWebAssemblyHostFunction(vm, value, wasmFunction, wasmWrapperFunction) && (!isNullable || !value.isNull())) {
+                            const char* msg = isNullable ? "must be a wasm exported function or null" : "must be a wasm exported function";
+                            return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported global", msg)));
+                        }
+                        if (global.type.kind == Wasm::TypeKind::TypeIdx && (wasmFunction || wasmWrapperFunction)) {
+                            Wasm::SignatureIndex paramIndex = global.type.index;
+                            Wasm::SignatureIndex argIndex;
+                            if (wasmFunction)
+                                argIndex = wasmFunction->signatureIndex();
+                            else
+                                argIndex = wasmWrapperFunction->signatureIndex();
+                            if (paramIndex != argIndex)
+                                return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported global", "Argument function did not match the reference type")));
+                        }
</ins><span class="cx">                         m_instance->instance().setGlobal(import.kindIndex, value);
</span><span class="cx">                         break;
</span><ins>+                    }
</ins><span class="cx">                     case Wasm::TypeKind::Externref:
</span><span class="cx">                         value = globalValue->global()->get(globalObject);
</span><span class="cx">                         RETURN_IF_EXCEPTION(scope, void());
</span><ins>+                        if (!global.type.isNullable() && value.isNull())
+                            return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported global", "non-null externref cannot be null")));
</ins><span class="cx">                         m_instance->instance().setGlobal(import.kindIndex, value);
</span><span class="cx">                         break;
</span><span class="cx">                     case Wasm::TypeKind::I32:
</span><span class="lines">@@ -283,12 +302,31 @@
</span><span class="cx"> 
</span><span class="cx">                     // iii. Append ToWebAssemblyValue(v) to imports.
</span><span class="cx">                     switch (globalType.kind) {
</span><del>-                    case Wasm::TypeKind::Funcref:
-                        if (!isWebAssemblyHostFunction(vm, value) && !value.isNull())
-                            return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported global", "must be a wasm exported function or null")));
</del><ins>+                    case Wasm::TypeKind::TypeIdx:
+                    case Wasm::TypeKind::Funcref: {
+                        bool isNullable = globalType.isNullable();
+                        WebAssemblyFunction* wasmFunction = nullptr;
+                        WebAssemblyWrapperFunction* wasmWrapperFunction = nullptr;
+                        if (!isWebAssemblyHostFunction(vm, value, wasmFunction, wasmWrapperFunction) && (!isNullable || !value.isNull())) {
+                            const char* msg = isNullable ? "must be a wasm exported function or null" : "must be a wasm exported function";
+                            return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported global", msg)));
+                        }
+                        if (globalType.kind == Wasm::TypeKind::TypeIdx && (wasmFunction || wasmWrapperFunction)) {
+                            Wasm::SignatureIndex paramIndex = global.type.index;
+                            Wasm::SignatureIndex argIndex;
+                            if (wasmFunction)
+                                argIndex = wasmFunction->signatureIndex();
+                            else
+                                argIndex = wasmWrapperFunction->signatureIndex();
+                            if (paramIndex != argIndex)
+                                return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported global", "Argument function did not match the reference type")));
+                        }
</ins><span class="cx">                         m_instance->instance().setGlobal(import.kindIndex, value);
</span><span class="cx">                         break;
</span><ins>+                    }
</ins><span class="cx">                     case Wasm::TypeKind::Externref:
</span><ins>+                        if (!globalType.isNullable() && value.isNull())
+                            return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported global", "must be a non-null value")));
</ins><span class="cx">                         m_instance->instance().setGlobal(import.kindIndex, value);
</span><span class="cx">                         break;
</span><span class="cx">                     case Wasm::TypeKind::I32:
</span><span class="lines">@@ -490,6 +528,7 @@
</span><span class="cx">             switch (global.type.kind) {
</span><span class="cx">             case Wasm::TypeKind::Externref:
</span><span class="cx">             case Wasm::TypeKind::Funcref:
</span><ins>+            case Wasm::TypeKind::TypeIdx:
</ins><span class="cx">             case Wasm::TypeKind::I32:
</span><span class="cx">             case Wasm::TypeKind::I64:
</span><span class="cx">             case Wasm::TypeKind::F32:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmwasmjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/wasm.json (279264 => 279265)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/wasm.json       2021-06-25 01:27:32 UTC (rev 279264)
+++ trunk/Source/JavaScriptCore/wasm/wasm.json  2021-06-25 02:23:28 UTC (rev 279265)
</span><span class="lines">@@ -13,6 +13,8 @@
</span><span class="cx">         "f64":       { "type": "varint7", "value":   -4, "b3type": "B3::Double" },
</span><span class="cx">         "funcref":   { "type": "varint7", "value":  -16, "b3type": "B3::Int64" },
</span><span class="cx">         "externref": { "type": "varint7", "value":  -17, "b3type": "B3::Int64" },
</span><ins>+        "ref_null":  { "type": "varint7", "value":  -20, "b3type": "B3::Int64" },
+        "ref":       { "type": "varint7", "value":  -21, "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">         "type_idx":  { "type": "varint7", "value": -128, "b3type": "B3::Int64" }
</span></span></pre>
</div>
</div>

</body>
</html>