[WebAssembly][Modules] Import globals from wasm modules
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 18 Apr 2018 16:33:33 +0000 (16:33 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 18 Apr 2018 16:33:33 +0000 (16:33 +0000)
https://bugs.webkit.org/show_bug.cgi?id=184736

Reviewed by JF Bastien.

JSTests:

* wasm.yaml:
* wasm/modules/wasm-imports-js-re-exports-wasm-exports.js:
* wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wasm:
* wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wat:
* wasm/modules/wasm-imports-js-re-exports-wasm-exports/re-export.js:
* wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wasm:
* wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wat:
* wasm/modules/wasm-imports-wasm-exports.js:
* wasm/modules/wasm-imports-wasm-exports/imports.wasm:
* wasm/modules/wasm-imports-wasm-exports/imports.wat:
* wasm/modules/wasm-imports-wasm-exports/sum.wasm:
* wasm/modules/wasm-imports-wasm-exports/sum.wat:

Source/JavaScriptCore:

This patch implements a feature importing globals to/from wasm modules.
Since we are not supporting mutable globals now, we can just copy the
global data when importing. Currently we do not support importing/exporting
i64 globals. This will be supported once (1) mutable global bindings are
specified and (2) BigInt based i64 importing/exporting is specified.

* wasm/js/JSWebAssemblyInstance.cpp:
(JSC::JSWebAssemblyInstance::create):
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::link):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@230763 268f45cc-cd09-0410-ab3c-d52691b4dbfc

22 files changed:
JSTests/ChangeLog
JSTests/wasm.yaml
JSTests/wasm/modules/wasm-import-wasm-export-i64-error.js [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports.js
JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wasm
JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wat
JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/re-export.js
JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wasm
JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wat
JSTests/wasm/modules/wasm-imports-wasm-exports-i64-error/answer.wasm [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-wasm-exports-i64-error/answer.wat [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-wasm-exports-i64-error/imports.wasm [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-wasm-exports-i64-error/imports.wat [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-wasm-exports.js
JSTests/wasm/modules/wasm-imports-wasm-exports/imports.wasm
JSTests/wasm/modules/wasm-imports-wasm-exports/imports.wat
JSTests/wasm/modules/wasm-imports-wasm-exports/sum.wasm
JSTests/wasm/modules/wasm-imports-wasm-exports/sum.wat
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/jsc.cpp
Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp

index 49979099e61acd98ec568e20d5ffcdb337c335d9..7806395cdf389d99890fe1af52d9c983d75722d0 100644 (file)
@@ -1,3 +1,23 @@
+2018-04-18  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [WebAssembly][Modules] Import globals from wasm modules
+        https://bugs.webkit.org/show_bug.cgi?id=184736
+
+        Reviewed by JF Bastien.
+
+        * wasm.yaml:
+        * wasm/modules/wasm-imports-js-re-exports-wasm-exports.js:
+        * wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wasm:
+        * wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wat:
+        * wasm/modules/wasm-imports-js-re-exports-wasm-exports/re-export.js:
+        * wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wasm:
+        * wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wat:
+        * wasm/modules/wasm-imports-wasm-exports.js:
+        * wasm/modules/wasm-imports-wasm-exports/imports.wasm:
+        * wasm/modules/wasm-imports-wasm-exports/imports.wat:
+        * wasm/modules/wasm-imports-wasm-exports/sum.wasm:
+        * wasm/modules/wasm-imports-wasm-exports/sum.wat:
+
 2018-04-18  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         Unreviewed, reland r230697, r230720, and r230724.
index 02c5cb2d9b7bc674cf6d5c9924594f49d3160439..3c1a5fcf1fd8ba194f786eea243e6f5ca41bf23f 100644 (file)
@@ -38,7 +38,7 @@
 - path: wasm/regress/
   cmd: runWebAssemblySuite unless parseRunCommands
 - path: wasm/modules/
-  cmd: runWebAssemblySuite unless parseRunCommands
+  cmd: runWebAssembly unless parseRunCommands
 
 - path: wasm/spec-tests/address.wast.js
   cmd: runWebAssemblySpecTest :normal
diff --git a/JSTests/wasm/modules/wasm-import-wasm-export-i64-error.js b/JSTests/wasm/modules/wasm-import-wasm-export-i64-error.js
new file mode 100644 (file)
index 0000000..75ed569
--- /dev/null
@@ -0,0 +1,4 @@
+import * as assert from '../assert.js';
+import("./wasm-imports-wasm-exports-i64-error/imports.wasm").then($vm.abort, function (error) {
+    assert.eq(String(error), `Error: exported global cannot be an i64`);
+}).catch($vm.abort);
index 939c23465195d2d38f52ebb50eeacaae71af4642..72341b463e19fefe214a8375c2463a993182ae2c 100644 (file)
@@ -1,7 +1,9 @@
-import { addOne } from "./wasm-imports-js-re-exports-wasm-exports/imports.wasm"
+import { addOne, getAnswer } from "./wasm-imports-js-re-exports-wasm-exports/imports.wasm"
 import * as assert from '../assert.js';
 
 assert.isFunction(addOne);
 assert.eq(addOne(32), 33);
 assert.eq(addOne(-2), -1);
 assert.eq(addOne(0x7fffffff), -2147483648);
+
+assert.eq(getAnswer(), 42);
index 35b65222ffea790ff0c95feff6afdcb48b4227a6..eb3ea897e166ef633692d7bac05597fd7a344787 100644 (file)
Binary files a/JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wasm and b/JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wasm differ
index 54e967dc3d8789b7ade406a60cdda315b1ed8bb8..449bc46e7cba1454e771f762c51748424a919019 100644 (file)
@@ -1,7 +1,11 @@
 (module
     (import "./re-export.js" "sum" (func $sum (param i32 i32) (result i32)))
+    (import "./re-export.js" "answer" (global i32))
     (type $t0 (func (param i32) (result i32)))
     (func $addOne (export "addOne") (type $t0) (param $p0 i32) (result i32)
         i32.const 1
         get_local $p0
-        call $sum))
+        call $sum)
+    (type $t1 (func (result i32)))
+    (func $getAnswer (export "getAnswer") (type $t1) (result i32)
+        get_global 0))
index e16ba1c03733f1f59f071095793347a7f4f0e81c..591232c68bb0b16bd032417a16cde376cc7f3054 100644 (file)
@@ -1 +1 @@
-export { sum } from "./sum.wasm"
+export { sum, answer } from "./sum.wasm"
index 4c722a7c3b7fe21039c4846341ab14dfa9a499cf..16644dbe48acc59694b7334b16e47ba59b0404c0 100644 (file)
Binary files a/JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wasm and b/JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wasm differ
index ba3f2a3593830813c413a0a136258c00b4d56938..8d936a7cf7264803fc5254fef82619f238f0886f 100644 (file)
@@ -3,4 +3,5 @@
     (func $sum (export "sum") (type $t0) (param $p0 i32) (param $p1 i32) (result i32)
         get_local $p1
         get_local $p0
-        i32.add))
+        i32.add)
+    (global (export "answer") i32 i32.const 42))
diff --git a/JSTests/wasm/modules/wasm-imports-wasm-exports-i64-error/answer.wasm b/JSTests/wasm/modules/wasm-imports-wasm-exports-i64-error/answer.wasm
new file mode 100644 (file)
index 0000000..f8ca7a4
Binary files /dev/null and b/JSTests/wasm/modules/wasm-imports-wasm-exports-i64-error/answer.wasm differ
diff --git a/JSTests/wasm/modules/wasm-imports-wasm-exports-i64-error/answer.wat b/JSTests/wasm/modules/wasm-imports-wasm-exports-i64-error/answer.wat
new file mode 100644 (file)
index 0000000..0865b46
--- /dev/null
@@ -0,0 +1,2 @@
+(module
+    (global (export "answer") i64 i64.const 42))
diff --git a/JSTests/wasm/modules/wasm-imports-wasm-exports-i64-error/imports.wasm b/JSTests/wasm/modules/wasm-imports-wasm-exports-i64-error/imports.wasm
new file mode 100644 (file)
index 0000000..c5e719e
Binary files /dev/null and b/JSTests/wasm/modules/wasm-imports-wasm-exports-i64-error/imports.wasm differ
diff --git a/JSTests/wasm/modules/wasm-imports-wasm-exports-i64-error/imports.wat b/JSTests/wasm/modules/wasm-imports-wasm-exports-i64-error/imports.wat
new file mode 100644 (file)
index 0000000..d9f3202
--- /dev/null
@@ -0,0 +1,2 @@
+(module
+    (import "./answer.wasm" "answer" (global i64)))
index 709d0bcad89b5b5689e3b19dc29e390a9878a1d5..285f072a8e1269da296978cab69b8be427853a49 100644 (file)
@@ -1,7 +1,14 @@
-import { addOne } from "./wasm-imports-js-exports/imports.wasm"
+import { addOne, getAnswer, getAnswer1, getAnswer2, getAnswer3, getAnswer4 } from "./wasm-imports-wasm-exports/imports.wasm"
 import * as assert from '../assert.js';
 
 assert.isFunction(addOne);
 assert.eq(addOne(32), 33);
 assert.eq(addOne(-2), -1);
 assert.eq(addOne(0x7fffffff), -2147483648);
+
+assert.eq(getAnswer(), 42);
+assert.eq(getAnswer1(), 0.5);
+assert.eq(getAnswer2(), 0.5);
+
+assert.truthy(isPureNaN(getAnswer3()));
+assert.truthy(isPureNaN(getAnswer4()));
index 0fe79e3a9a75b12bdb26d8ba445a7998bd652728..2b4ee92b8cbe13cae0848c1b178776a3a1865f93 100644 (file)
Binary files a/JSTests/wasm/modules/wasm-imports-wasm-exports/imports.wasm and b/JSTests/wasm/modules/wasm-imports-wasm-exports/imports.wasm differ
index a6029e7d6e1320eaba5b2886ed376e2f13ff77bf..42180c8b6c2ad2308b3a01b67cac095db7668189 100644 (file)
@@ -1,7 +1,26 @@
 (module
     (import "./sum.wasm" "sum" (func $sum (param i32 i32) (result i32)))
+    (import "./sum.wasm" "answer" (global i32))
+    (import "./sum.wasm" "answer1" (global f32))
+    (import "./sum.wasm" "answer2" (global f64))
+    (import "./sum.wasm" "answer3" (global f32))
+    (import "./sum.wasm" "answer4" (global f64))
     (type $t0 (func (param i32) (result i32)))
     (func $addOne (export "addOne") (type $t0) (param $p0 i32) (result i32)
         i32.const 1
         get_local $p0
-        call $sum))
+        call $sum)
+    (type $t1 (func (result i32)))
+    (func $getAnswer (export "getAnswer") (type $t1) (result i32)
+        get_global 0)
+    (type $t2 (func (result f32)))
+    (func $getAnswer1 (export "getAnswer1") (type $t2) (result f32)
+        get_global 1)
+    (type $t3 (func (result f64)))
+    (func $getAnswer2 (export "getAnswer2") (type $t3) (result f64)
+        get_global 2)
+    (func $getAnswer3 (export "getAnswer3") (type $t2) (result f32)
+        get_global 3)
+    (func $getAnswer4 (export "getAnswer4") (type $t3) (result f64)
+        get_global 4)
+    )
index 4c722a7c3b7fe21039c4846341ab14dfa9a499cf..744f0c5aa840f9c364ebf2a4c7ffa231168cd4de 100644 (file)
Binary files a/JSTests/wasm/modules/wasm-imports-wasm-exports/sum.wasm and b/JSTests/wasm/modules/wasm-imports-wasm-exports/sum.wasm differ
index ba3f2a3593830813c413a0a136258c00b4d56938..3e882f63965903bbb2b3ff610d7ab77dd70863db 100644 (file)
@@ -3,4 +3,9 @@
     (func $sum (export "sum") (type $t0) (param $p0 i32) (param $p1 i32) (result i32)
         get_local $p1
         get_local $p0
-        i32.add))
+        i32.add)
+    (global (export "answer") i32 i32.const 42)
+    (global (export "answer1") f32 f32.const 0.5)
+    (global (export "answer2") f64 f64.const 0.5)
+    (global (export "answer3") f32 f32.const nan)
+    (global (export "answer4") f64 f64.const nan))
index 6504c3f7d8c6185e0052149d4698613e6c7b98f0..c52d1d554625dca550d0fa0ae800e05102bf7d5c 100644 (file)
@@ -1,3 +1,21 @@
+2018-04-18  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [WebAssembly][Modules] Import globals from wasm modules
+        https://bugs.webkit.org/show_bug.cgi?id=184736
+
+        Reviewed by JF Bastien.
+
+        This patch implements a feature importing globals to/from wasm modules.
+        Since we are not supporting mutable globals now, we can just copy the
+        global data when importing. Currently we do not support importing/exporting
+        i64 globals. This will be supported once (1) mutable global bindings are
+        specified and (2) BigInt based i64 importing/exporting is specified.
+
+        * wasm/js/JSWebAssemblyInstance.cpp:
+        (JSC::JSWebAssemblyInstance::create):
+        * wasm/js/WebAssemblyModuleRecord.cpp:
+        (JSC::WebAssemblyModuleRecord::link):
+
 2018-04-18  Tomas Popela  <tpopela@redhat.com>
 
         Unreviewed, fix build on ARM
index 744de30ef7e4fe8c92809716b1b4339f6ff0c9c2..5d2712e5bc208981dd9429b40c69a4b72df5c7c1 100644 (file)
@@ -294,6 +294,7 @@ static EncodedJSValue JSC_HOST_CALL functionFalse(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionIsPureNaN(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState*);
@@ -520,6 +521,7 @@ protected:
         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isFinalTier"), 0, functionFalse, IsFinalTierIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "predictInt32"), 0, functionUndefined2, SetInt32HeapPredictionIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isInt32"), 0, functionIsInt32, CheckInt32Intrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
+        putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isPureNaN"), 0, functionIsPureNaN, CheckInt32Intrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "fiatInt52"), 0, functionIdentity, FiatInt52Intrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
         
         addFunction(vm, "effectful42", functionEffectful42, 0);
@@ -1879,6 +1881,21 @@ EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState* exec)
     return JSValue::encode(jsBoolean(true));
 }
 
+EncodedJSValue JSC_HOST_CALL functionIsPureNaN(ExecState* exec)
+{
+    for (size_t i = 0; i < exec->argumentCount(); ++i) {
+        JSValue value = exec->argument(i);
+        if (!value.isNumber())
+            return JSValue::encode(jsBoolean(false));
+        double number = value.asNumber();
+        if (!std::isnan(number))
+            return JSValue::encode(jsBoolean(false));
+        if (isImpureNaN(number))
+            return JSValue::encode(jsBoolean(false));
+    }
+    return JSValue::encode(jsBoolean(true));
+}
+
 EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState* exec) { return JSValue::encode(exec->argument(0)); }
 
 EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*)
index 9e58f7476da89bf67e89b2353c0ee16d6c3a8883..aab3b90b3502cd0c829e429709ac5c6e08c76188 100644 (file)
@@ -180,8 +180,6 @@ JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, co
 
     // Let funcs, memories and tables be initially-empty lists of callable JavaScript objects, WebAssembly.Memory objects and WebAssembly.Table objects, respectively.
     // Let imports be an initially-empty list of external values.
-    unsigned numImportGlobals = 0;
-
     bool hasMemoryImport = false;
     bool hasTableImport = false;
 
@@ -207,10 +205,10 @@ JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, co
         // Eventually we will move all the linking code here to WebAssemblyModuleRecord::link.
         switch (import.kind) {
         case Wasm::ExternalKind::Function:
+        case Wasm::ExternalKind::Global:
             continue;
         case Wasm::ExternalKind::Table:
         case Wasm::ExternalKind::Memory:
-        case Wasm::ExternalKind::Global:
             break;
         }
 
@@ -232,9 +230,10 @@ JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, co
             value = jsUndefined();
 
         switch (import.kind) {
-        case Wasm::ExternalKind::Function: {
+        case Wasm::ExternalKind::Function:
+        case Wasm::ExternalKind::Global:
             break;
-        }
+
         case Wasm::ExternalKind::Table: {
             RELEASE_ASSERT(!hasTableImport); // This should be guaranteed by a validation failure.
             // 7. Otherwise (i is a table import):
@@ -294,33 +293,6 @@ JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, co
             RETURN_IF_EXCEPTION(throwScope, nullptr);
             break;
         }
-        case Wasm::ExternalKind::Global: {
-            // 5. If i is a global import:
-            // i. If i is not an immutable global, throw a TypeError.
-            ASSERT(moduleInformation.globals[import.kindIndex].mutability == Wasm::Global::Immutable);
-            // ii. If the global_type of i is i64 or Type(v) is not Number, throw a WebAssembly.LinkError.
-            if (moduleInformation.globals[import.kindIndex].type == Wasm::I64)
-                return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "imported global", "cannot be an i64")));
-            if (!value.isNumber())
-                return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "imported global", "must be a number")));
-            // iii. Append ToWebAssemblyValue(v) to imports.
-            ASSERT(numImportGlobals == import.kindIndex);
-            switch (moduleInformation.globals[import.kindIndex].type) {
-            case Wasm::I32:
-                jsInstance->instance().setGlobal(numImportGlobals++, value.toInt32(exec));
-                break;
-            case Wasm::F32:
-                jsInstance->instance().setGlobal(numImportGlobals++, bitwise_cast<uint32_t>(value.toFloat(exec)));
-                break;
-            case Wasm::F64:
-                jsInstance->instance().setGlobal(numImportGlobals++, bitwise_cast<uint64_t>(value.asNumber()));
-                break;
-            default:
-                RELEASE_ASSERT_NOT_REACHED();
-            }
-            throwScope.assertNoException();
-            break;
-        }
         }
     }
     ASSERT(moduleRecord->importEntries().size() == moduleInformation.imports.size());
@@ -335,7 +307,7 @@ JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, co
             // We create a memory when it's a memory definition.
             RELEASE_ASSERT(!moduleInformation.memory.isImport());
 
-            auto* jsMemory = JSWebAssemblyMemory::create(exec, vm, exec->lexicalGlobalObject()->WebAssemblyMemoryStructure());
+            auto* jsMemory = JSWebAssemblyMemory::create(exec, vm, globalObject->WebAssemblyMemoryStructure());
             RETURN_IF_EXCEPTION(throwScope, nullptr);
 
             RefPtr<Wasm::Memory> memory = Wasm::Memory::create(moduleInformation.memory.initial(), moduleInformation.memory.maximum(),
@@ -363,7 +335,7 @@ JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, co
             RefPtr<Wasm::Table> wasmTable = Wasm::Table::create(moduleInformation.tableInformation.initial(), moduleInformation.tableInformation.maximum());
             if (!wasmTable)
                 return exception(createJSWebAssemblyLinkError(exec, vm, "couldn't create Table"));
-            JSWebAssemblyTable* table = JSWebAssemblyTable::create(exec, vm, exec->lexicalGlobalObject()->WebAssemblyTableStructure(), wasmTable.releaseNonNull());
+            JSWebAssemblyTable* table = JSWebAssemblyTable::create(exec, vm, globalObject->WebAssemblyTableStructure(), wasmTable.releaseNonNull());
             // We should always be able to allocate a JSWebAssemblyTable we've defined.
             // If it's defined to be too large, we should have thrown a validation error.
             throwScope.assertNoException();
@@ -375,26 +347,12 @@ JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, co
     
     if (!jsInstance->memory()) {
         // Make sure we have a dummy memory, so that wasm -> wasm thunks avoid checking for a nullptr Memory when trying to set pinned registers.
-        auto* jsMemory = JSWebAssemblyMemory::create(exec, vm, exec->lexicalGlobalObject()->WebAssemblyMemoryStructure());
+        auto* jsMemory = JSWebAssemblyMemory::create(exec, vm, globalObject->WebAssemblyMemoryStructure());
         jsMemory->adopt(Wasm::Memory::create().releaseNonNull());
         jsInstance->setMemory(vm, jsMemory);
         RETURN_IF_EXCEPTION(throwScope, nullptr);
     }
     
-    // Globals
-    {
-        ASSERT(numImportGlobals == moduleInformation.firstInternalGlobal);
-        for (size_t globalIndex = numImportGlobals; globalIndex < moduleInformation.globals.size(); ++globalIndex) {
-            const auto& global = moduleInformation.globals[globalIndex];
-            ASSERT(global.initializationType != Wasm::Global::IsImport);
-            if (global.initializationType == Wasm::Global::FromGlobalImport) {
-                ASSERT(global.initialBitsOrImportNumber < numImportGlobals);
-                jsInstance->instance().setGlobal(globalIndex, jsInstance->instance().loadI64Global(global.initialBitsOrImportNumber));
-            } else
-                jsInstance->instance().setGlobal(globalIndex, global.initialBitsOrImportNumber);
-        }
-    }
-
     return jsInstance;
 }
 
index 178d9a5d3cadf6d4c83dac49a17031aac96056b2..1f5bd8f179d24caae525c4bad3cc5fab73f69385 100644 (file)
@@ -118,10 +118,10 @@ void WebAssemblyModuleRecord::link(ExecState* exec, JSValue, JSObject* importObj
         // Eventually we will move all the linking code in JSWebAssemblyInstance here and remove this switch statement.
         switch (import.kind) {
         case Wasm::ExternalKind::Function:
+        case Wasm::ExternalKind::Global:
             break;
         case Wasm::ExternalKind::Table:
         case Wasm::ExternalKind::Memory:
-        case Wasm::ExternalKind::Global:
             continue;
         }
 
@@ -225,13 +225,53 @@ void WebAssemblyModuleRecord::link(ExecState* exec, JSValue, JSObject* importObj
             m_instance->instance().importFunction<JSWebAssemblyInstance::PoisonedBarrier<JSObject>>(import.kindIndex)->set(vm, m_instance.get(), function);
             break;
         }
+
+        case Wasm::ExternalKind::Global: {
+            // 5. If i is a global import:
+            // i. If i is not an immutable global, throw a TypeError.
+            ASSERT(moduleInformation.globals[import.kindIndex].mutability == Wasm::Global::Immutable);
+            // ii. If the global_type of i is i64 or Type(v) is not Number, throw a WebAssembly.LinkError.
+            if (moduleInformation.globals[import.kindIndex].type == Wasm::I64)
+                return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "imported global", "cannot be an i64")));
+            if (!value.isNumber())
+                return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "imported global", "must be a number")));
+            // iii. Append ToWebAssemblyValue(v) to imports.
+            switch (moduleInformation.globals[import.kindIndex].type) {
+            case Wasm::I32:
+                m_instance->instance().setGlobal(import.kindIndex, value.toInt32(exec));
+                break;
+            case Wasm::F32:
+                m_instance->instance().setGlobal(import.kindIndex, bitwise_cast<uint32_t>(value.toFloat(exec)));
+                break;
+            case Wasm::F64:
+                m_instance->instance().setGlobal(import.kindIndex, bitwise_cast<uint64_t>(value.asNumber()));
+                break;
+            default:
+                RELEASE_ASSERT_NOT_REACHED();
+            }
+            scope.assertNoException();
+            break;
+        }
+
         case Wasm::ExternalKind::Table:
         case Wasm::ExternalKind::Memory:
-        case Wasm::ExternalKind::Global:
             break;
         }
     }
 
+    // Globals
+    {
+        for (size_t globalIndex = moduleInformation.firstInternalGlobal; globalIndex < moduleInformation.globals.size(); ++globalIndex) {
+            const auto& global = moduleInformation.globals[globalIndex];
+            ASSERT(global.initializationType != Wasm::Global::IsImport);
+            if (global.initializationType == Wasm::Global::FromGlobalImport) {
+                ASSERT(global.initialBitsOrImportNumber < moduleInformation.firstInternalGlobal);
+                m_instance->instance().setGlobal(globalIndex, m_instance->instance().loadI64Global(global.initialBitsOrImportNumber));
+            } else
+                m_instance->instance().setGlobal(globalIndex, global.initialBitsOrImportNumber);
+        }
+    }
+
     SymbolTable* exportSymbolTable = module->exportSymbolTable();
     unsigned functionImportCount = codeBlock->functionImportCount();