Unreviewed, reland r230697, r230720, and r230724.
[WebKit-https.git] / Source / JavaScriptCore / wasm / js / WebAssemblyModuleRecord.cpp
1 /*
2  * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WebAssemblyModuleRecord.h"
28
29 #if ENABLE(WEBASSEMBLY)
30
31 #include "Error.h"
32 #include "JSCInlines.h"
33 #include "JSLexicalEnvironment.h"
34 #include "JSModuleEnvironment.h"
35 #include "JSWebAssemblyHelpers.h"
36 #include "JSWebAssemblyInstance.h"
37 #include "JSWebAssemblyLinkError.h"
38 #include "JSWebAssemblyModule.h"
39 #include "ProtoCallFrame.h"
40 #include "WasmSignature.h"
41 #include "WebAssemblyFunction.h"
42 #include <limits>
43
44 namespace JSC {
45
46 const ClassInfo WebAssemblyModuleRecord::s_info = { "WebAssemblyModuleRecord", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(WebAssemblyModuleRecord) };
47
48 Structure* WebAssemblyModuleRecord::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
49 {
50     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
51 }
52
53 WebAssemblyModuleRecord* WebAssemblyModuleRecord::create(ExecState* exec, VM& vm, Structure* structure, const Identifier& moduleKey, const Wasm::ModuleInformation& moduleInformation)
54 {
55     WebAssemblyModuleRecord* instance = new (NotNull, allocateCell<WebAssemblyModuleRecord>(vm.heap)) WebAssemblyModuleRecord(vm, structure, moduleKey);
56     instance->finishCreation(exec, vm, moduleInformation);
57     return instance;
58 }
59
60 WebAssemblyModuleRecord::WebAssemblyModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey)
61     : Base(vm, structure, moduleKey)
62 {
63 }
64
65 void WebAssemblyModuleRecord::destroy(JSCell* cell)
66 {
67     WebAssemblyModuleRecord* thisObject = static_cast<WebAssemblyModuleRecord*>(cell);
68     thisObject->WebAssemblyModuleRecord::~WebAssemblyModuleRecord();
69 }
70
71 void WebAssemblyModuleRecord::finishCreation(ExecState* exec, VM& vm, const Wasm::ModuleInformation& moduleInformation)
72 {
73     Base::finishCreation(exec, vm);
74     ASSERT(inherits(vm, info()));
75     for (const auto& exp : moduleInformation.exports) {
76         Identifier field = Identifier::fromString(&vm, String::fromUTF8(exp.field));
77         addExportEntry(ExportEntry::createLocal(field, field));
78     }
79 }
80
81 void WebAssemblyModuleRecord::visitChildren(JSCell* cell, SlotVisitor& visitor)
82 {
83     WebAssemblyModuleRecord* thisObject = jsCast<WebAssemblyModuleRecord*>(cell);
84     Base::visitChildren(thisObject, visitor);
85     visitor.append(thisObject->m_instance);
86     visitor.append(thisObject->m_startFunction);
87 }
88
89 void WebAssemblyModuleRecord::prepareLink(VM& vm, JSWebAssemblyInstance* instance)
90 {
91     RELEASE_ASSERT(!m_instance);
92     m_instance.set(vm, this, instance);
93 }
94
95 void WebAssemblyModuleRecord::link(ExecState* exec, JSValue, JSObject* importObject, Wasm::CreationMode creationMode)
96 {
97     VM& vm = exec->vm();
98     auto scope = DECLARE_THROW_SCOPE(vm);
99     UNUSED_PARAM(scope);
100     auto* globalObject = exec->lexicalGlobalObject();
101
102     RELEASE_ASSERT(m_instance);
103
104     Wasm::CodeBlock* codeBlock = m_instance->instance().codeBlock();
105     JSWebAssemblyModule* module = m_instance->module();
106     const Wasm::ModuleInformation& moduleInformation = module->moduleInformation();
107
108     auto exception = [&] (JSObject* error) {
109         throwException(exec, scope, error);
110     };
111
112     auto importFailMessage = [&] (const Wasm::Import& import, const char* before, const char* after) {
113         return makeString(before, " ", String::fromUTF8(import.module), ":", String::fromUTF8(import.field), " ", after);
114     };
115
116     for (const auto& import : moduleInformation.imports) {
117         // Validation and linking other than Wasm::ExternalKind::Function is already done in JSWebAssemblyInstance.
118         // Eventually we will move all the linking code in JSWebAssemblyInstance here and remove this switch statement.
119         switch (import.kind) {
120         case Wasm::ExternalKind::Function:
121             break;
122         case Wasm::ExternalKind::Table:
123         case Wasm::ExternalKind::Memory:
124         case Wasm::ExternalKind::Global:
125             continue;
126         }
127
128         Identifier moduleName = Identifier::fromString(&vm, String::fromUTF8(import.module));
129         Identifier fieldName = Identifier::fromString(&vm, String::fromUTF8(import.field));
130         JSValue value;
131         if (creationMode == Wasm::CreationMode::FromJS) {
132             // 1. Let o be the resultant value of performing Get(importObject, i.module_name).
133             JSValue importModuleValue = importObject->get(exec, moduleName);
134             RETURN_IF_EXCEPTION(scope, void());
135             // 2. If Type(o) is not Object, throw a TypeError.
136             if (!importModuleValue.isObject())
137                 return exception(createTypeError(exec, importFailMessage(import, "import", "must be an object"), defaultSourceAppender, runtimeTypeForValue(importModuleValue)));
138
139             // 3. Let v be the value of performing Get(o, i.item_name)
140             JSObject* object = jsCast<JSObject*>(importModuleValue);
141             value = object->get(exec, fieldName);
142             RETURN_IF_EXCEPTION(scope, void());
143         } else {
144             AbstractModuleRecord* importedModule = hostResolveImportedModule(exec, moduleName);
145             RETURN_IF_EXCEPTION(scope, void());
146             Resolution resolution = importedModule->resolveExport(exec, fieldName);
147             RETURN_IF_EXCEPTION(scope, void());
148             switch (resolution.type) {
149             case Resolution::Type::NotFound:
150                 throwSyntaxError(exec, scope, makeString("Importing binding name '", String(fieldName.impl()), "' is not found."));
151                 return;
152
153             case Resolution::Type::Ambiguous:
154                 throwSyntaxError(exec, scope, makeString("Importing binding name '", String(fieldName.impl()), "' cannot be resolved due to ambiguous multiple bindings."));
155                 return;
156
157             case Resolution::Type::Error:
158                 throwSyntaxError(exec, scope, makeString("Importing binding name 'default' cannot be resolved by star export entries."));
159                 return;
160
161             case Resolution::Type::Resolved:
162                 break;
163             }
164
165             AbstractModuleRecord* importedRecord = resolution.moduleRecord;
166             JSModuleEnvironment* importedEnvironment = importedRecord->moduleEnvironmentMayBeNull();
167             // It means that target module is not linked yet. In wasm loading, we allow this since we do not solve cyclic resolution as if JS's bindings.
168             // At that time, error occurs since |value| is an empty, and later |value| becomes an undefined.
169             // https://github.com/WebAssembly/esm-integration/tree/master/proposals/esm-integration#js---wasm-cycle-where-js-is-higher-in-the-module-graph
170             if (importedEnvironment) {
171                 SymbolTable* symbolTable = importedEnvironment->symbolTable();
172                 ConcurrentJSLocker locker(symbolTable->m_lock);
173                 auto iter = symbolTable->find(locker, resolution.localName.impl());
174                 ASSERT(iter != symbolTable->end(locker));
175                 SymbolTableEntry& entry = iter->value;
176                 ASSERT(!entry.isNull());
177                 ASSERT(importedEnvironment->isValidScopeOffset(entry.scopeOffset()));
178
179                 // Snapshotting a value.
180                 value = importedEnvironment->variableAt(entry.scopeOffset()).get();
181             }
182         }
183         if (!value)
184             value = jsUndefined();
185
186         switch (import.kind) {
187         case Wasm::ExternalKind::Function: {
188             // 4. If i is a function import:
189             // i. If IsCallable(v) is false, throw a WebAssembly.LinkError.
190             if (!value.isFunction())
191                 return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "import function", "must be callable")));
192
193             Wasm::Instance* calleeInstance = nullptr;
194             WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation = nullptr;
195             JSObject* function = jsCast<JSObject*>(value);
196
197             // ii. If v is an Exported Function Exotic Object:
198             WebAssemblyFunction* wasmFunction;
199             WebAssemblyWrapperFunction* wasmWrapperFunction;
200             if (isWebAssemblyHostFunction(vm, function, wasmFunction, wasmWrapperFunction)) {
201                 // a. If the signature of v does not match the signature of i, throw a WebAssembly.LinkError.
202                 Wasm::SignatureIndex importedSignatureIndex;
203                 if (wasmFunction) {
204                     importedSignatureIndex = wasmFunction->signatureIndex();
205                     calleeInstance = &wasmFunction->instance()->instance();
206                     entrypointLoadLocation = wasmFunction->entrypointLoadLocation();
207                 } else {
208                     importedSignatureIndex = wasmWrapperFunction->signatureIndex();
209                     // b. Let closure be v.[[Closure]].
210                     function = wasmWrapperFunction->function();
211                 }
212                 Wasm::SignatureIndex expectedSignatureIndex = moduleInformation.importFunctionSignatureIndices[import.kindIndex];
213                 if (importedSignatureIndex != expectedSignatureIndex)
214                     return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "imported function", "signature doesn't match the provided WebAssembly function's signature")));
215             }
216             // iii. Otherwise:
217             // a. Let closure be a new host function of the given signature which calls v by coercing WebAssembly arguments to JavaScript arguments via ToJSValue and returns the result, if any, by coercing via ToWebAssemblyValue.
218             // Note: done as part of Plan compilation.
219             // iv. Append v to funcs.
220             // Note: adding the JSCell to the instance list fulfills closure requirements b. above (the WebAssembly.Instance wil be kept alive) and v. below (the JSFunction).
221
222             auto* info = m_instance->instance().importFunctionInfo(import.kindIndex);
223             info->targetInstance = calleeInstance;
224             info->wasmEntrypointLoadLocation = entrypointLoadLocation;
225             m_instance->instance().importFunction<JSWebAssemblyInstance::PoisonedBarrier<JSObject>>(import.kindIndex)->set(vm, m_instance.get(), function);
226             break;
227         }
228         case Wasm::ExternalKind::Table:
229         case Wasm::ExternalKind::Memory:
230         case Wasm::ExternalKind::Global:
231             break;
232         }
233     }
234
235     SymbolTable* exportSymbolTable = module->exportSymbolTable();
236     unsigned functionImportCount = codeBlock->functionImportCount();
237
238     // Let exports be a list of (string, JS value) pairs that is mapped from each external value e in instance.exports as follows:
239     JSModuleEnvironment* moduleEnvironment = JSModuleEnvironment::create(vm, globalObject, nullptr, exportSymbolTable, JSValue(), this);
240     for (const auto& exp : moduleInformation.exports) {
241         JSValue exportedValue;
242         switch (exp.kind) {
243         case Wasm::ExternalKind::Function: {
244             // 1. If e is a closure c:
245             //   i. If there is an Exported Function Exotic Object func in funcs whose func.[[Closure]] equals c, then return func.
246             //   ii. (Note: At most one wrapper is created for any closure, so func is unique, even if there are multiple occurrances in the list. Moreover, if the item was an import that is already an Exported Function Exotic Object, then the original function object will be found. For imports that are regular JS functions, a new wrapper will be created.)
247             if (exp.kindIndex < functionImportCount) {
248                 unsigned functionIndex = exp.kindIndex;
249                 JSObject* functionImport = m_instance->instance().importFunction<JSWebAssemblyInstance::PoisonedBarrier<JSObject>>(functionIndex)->get();
250                 if (isWebAssemblyHostFunction(vm, functionImport))
251                     exportedValue = functionImport;
252                 else {
253                     Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(functionIndex);
254                     exportedValue = WebAssemblyWrapperFunction::create(vm, globalObject, functionImport, functionIndex, m_instance.get(), signatureIndex);
255                 }
256             } else {
257                 //   iii. Otherwise:
258                 //     a. Let func be an Exported Function Exotic Object created from c.
259                 //     b. Append func to funcs.
260                 //     c. Return func.
261                 Wasm::Callee& embedderEntrypointCallee = codeBlock->embedderEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
262                 Wasm::WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation = codeBlock->entrypointLoadLocationFromFunctionIndexSpace(exp.kindIndex);
263                 Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(exp.kindIndex);
264                 const Wasm::Signature& signature = Wasm::SignatureInformation::get(signatureIndex);
265                 WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature.argumentCount(), String::fromUTF8(exp.field), m_instance.get(), embedderEntrypointCallee, entrypointLoadLocation, signatureIndex);
266                 exportedValue = function;
267             }
268             break;
269         }
270         case Wasm::ExternalKind::Table: {
271             // This should be guaranteed by module verification.
272             RELEASE_ASSERT(m_instance->table()); 
273             ASSERT(exp.kindIndex == 0);
274
275             exportedValue = m_instance->table();
276             break;
277         }
278         case Wasm::ExternalKind::Memory: {
279             ASSERT(exp.kindIndex == 0);
280
281             exportedValue = m_instance->memory();
282             break;
283         }
284         case Wasm::ExternalKind::Global: {
285             // Assert: the global is immutable by MVP validation constraint.
286             const Wasm::Global& global = moduleInformation.globals[exp.kindIndex];
287             ASSERT(global.mutability == Wasm::Global::Immutable);
288             // Return ToJSValue(v).
289             switch (global.type) {
290             case Wasm::I32:
291                 exportedValue = JSValue(m_instance->instance().loadI32Global(exp.kindIndex));
292                 break;
293
294             case Wasm::I64:
295                 throwException(exec, scope, createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("exported global cannot be an i64")));
296                 return;
297
298             case Wasm::F32:
299                 exportedValue = JSValue(m_instance->instance().loadF32Global(exp.kindIndex));
300                 break;
301
302             case Wasm::F64:
303                 exportedValue = JSValue(m_instance->instance().loadF64Global(exp.kindIndex));
304                 break;
305
306             default:
307                 RELEASE_ASSERT_NOT_REACHED();
308             }
309             break;
310         }
311         }
312
313         bool shouldThrowReadOnlyError = false;
314         bool ignoreReadOnlyErrors = true;
315         bool putResult = false;
316         symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, Identifier::fromString(&vm, String::fromUTF8(exp.field)), exportedValue, shouldThrowReadOnlyError, ignoreReadOnlyErrors, putResult);
317         scope.assertNoException();
318         RELEASE_ASSERT(putResult);
319     }
320
321     bool hasStart = !!moduleInformation.startFunctionIndexSpace;
322     if (hasStart) {
323         auto startFunctionIndexSpace = moduleInformation.startFunctionIndexSpace.value_or(0);
324         Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(startFunctionIndexSpace);
325         const Wasm::Signature& signature = Wasm::SignatureInformation::get(signatureIndex);
326         // The start function must not take any arguments or return anything. This is enforced by the parser.
327         ASSERT(!signature.argumentCount());
328         ASSERT(signature.returnType() == Wasm::Void);
329         if (startFunctionIndexSpace < codeBlock->functionImportCount()) {
330             JSObject* startFunction = m_instance->instance().importFunction<JSWebAssemblyInstance::PoisonedBarrier<JSObject>>(startFunctionIndexSpace)->get();
331             m_startFunction.set(vm, this, startFunction);
332         } else {
333             Wasm::Callee& embedderEntrypointCallee = codeBlock->embedderEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
334             Wasm::WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation = codeBlock->entrypointLoadLocationFromFunctionIndexSpace(startFunctionIndexSpace);
335             WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature.argumentCount(), "start", m_instance.get(), embedderEntrypointCallee, entrypointLoadLocation, signatureIndex);
336             m_startFunction.set(vm, this, function);
337         }
338     }
339     m_moduleEnvironment.set(vm, this, moduleEnvironment);
340 }
341
342 template <typename Scope, typename M, typename N, typename ...Args>
343 NEVER_INLINE static JSValue dataSegmentFail(ExecState* exec, VM& vm, Scope& scope, M memorySize, N segmentSize, N offset, Args... args)
344 {
345     return throwException(exec, scope, createJSWebAssemblyLinkError(exec, vm, makeString(ASCIILiteral("Invalid data segment initialization: segment of "), String::number(segmentSize), ASCIILiteral(" bytes memory of "), String::number(memorySize), ASCIILiteral(" bytes, at offset "), String::number(offset), args...)));
346 }
347
348 JSValue WebAssemblyModuleRecord::evaluate(ExecState* exec)
349 {
350     VM& vm = exec->vm();
351     auto scope = DECLARE_THROW_SCOPE(vm);
352
353     Wasm::Module& module = m_instance->instance().module();
354     Wasm::CodeBlock* codeBlock = m_instance->instance().codeBlock();
355     const Wasm::ModuleInformation& moduleInformation = module.moduleInformation();
356     JSWebAssemblyTable* table = m_instance->table();
357
358     const Vector<Wasm::Segment::Ptr>& data = moduleInformation.data;
359     
360     std::optional<JSValue> exception;
361
362     auto forEachElement = [&] (auto fn) {
363         for (const Wasm::Element& element : moduleInformation.elements) {
364             // It should be a validation error to have any elements without a table.
365             // Also, it could be that a table wasn't imported, or that the table
366             // imported wasn't compatible. However, those should error out before
367             // getting here.
368             ASSERT(!!table);
369
370             if (!element.functionIndices.size())
371                 continue;
372
373             uint32_t tableIndex = element.offset.isGlobalImport()
374                 ? static_cast<uint32_t>(m_instance->instance().loadI32Global(element.offset.globalImportIndex()))
375                 : element.offset.constValue();
376
377             fn(element, tableIndex);
378
379             if (exception)
380                 break;
381         }
382     };
383
384     auto forEachSegment = [&] (auto fn) {
385         uint8_t* memory = reinterpret_cast<uint8_t*>(m_instance->instance().cachedMemory());
386         uint64_t sizeInBytes = m_instance->instance().cachedMemorySize();
387
388         for (const Wasm::Segment::Ptr& segment : data) {
389             uint32_t offset = segment->offset.isGlobalImport()
390                 ? static_cast<uint32_t>(m_instance->instance().loadI32Global(segment->offset.globalImportIndex()))
391                 : segment->offset.constValue();
392
393             fn(memory, sizeInBytes, segment, offset);
394
395             if (exception)
396                 break;
397         }
398     };
399
400     // Validation of all element ranges comes before all Table and Memory initialization.
401     forEachElement([&] (const Wasm::Element& element, uint32_t tableIndex) {
402         uint64_t lastWrittenIndex = static_cast<uint64_t>(tableIndex) + static_cast<uint64_t>(element.functionIndices.size()) - 1;
403         if (UNLIKELY(lastWrittenIndex >= table->length()))
404             exception = JSValue(throwException(exec, scope, createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Element is trying to set an out of bounds table index"))));
405     });
406
407     if (UNLIKELY(exception))
408         return exception.value();
409
410     // Validation of all segment ranges comes before all Table and Memory initialization.
411     forEachSegment([&] (uint8_t*, uint64_t sizeInBytes, const Wasm::Segment::Ptr& segment, uint32_t offset) {
412         if (UNLIKELY(sizeInBytes < segment->sizeInBytes))
413             exception = dataSegmentFail(exec, vm, scope, sizeInBytes, segment->sizeInBytes, offset, ASCIILiteral(", segment is too big"));
414         else if (UNLIKELY(offset > sizeInBytes - segment->sizeInBytes))
415             exception = dataSegmentFail(exec, vm, scope, sizeInBytes, segment->sizeInBytes, offset, ASCIILiteral(", segment writes outside of memory"));
416     });
417
418     if (UNLIKELY(exception))
419         return exception.value();
420
421     forEachElement([&] (const Wasm::Element& element, uint32_t tableIndex) {
422         for (uint32_t i = 0; i < element.functionIndices.size(); ++i) {
423             // FIXME: This essentially means we're exporting an import.
424             // We need a story here. We need to create a WebAssemblyFunction
425             // for the import.
426             // https://bugs.webkit.org/show_bug.cgi?id=165510
427             uint32_t functionIndex = element.functionIndices[i];
428             Wasm::SignatureIndex signatureIndex = module.signatureIndexFromFunctionIndexSpace(functionIndex);
429             if (functionIndex < codeBlock->functionImportCount()) {
430                 JSObject* functionImport = m_instance->instance().importFunction<JSWebAssemblyInstance::PoisonedBarrier<JSObject>>(functionIndex)->get();
431                 if (isWebAssemblyHostFunction(vm, functionImport)) {
432                     WebAssemblyFunction* wasmFunction = jsDynamicCast<WebAssemblyFunction*>(vm, functionImport);
433                     // If we ever import a WebAssemblyWrapperFunction, we set the import as the unwrapped value.
434                     // Because a WebAssemblyWrapperFunction can never wrap another WebAssemblyWrapperFunction,
435                     // the only type this could be is WebAssemblyFunction.
436                     RELEASE_ASSERT(wasmFunction);
437                     table->setFunction(vm, tableIndex, wasmFunction);
438                     ++tableIndex;
439                     continue;
440                 }
441
442                 table->setFunction(vm, tableIndex,
443                     WebAssemblyWrapperFunction::create(vm, m_instance->globalObject(), functionImport, functionIndex, m_instance.get(), signatureIndex));
444                 ++tableIndex;
445                 continue;
446             }
447
448             Wasm::Callee& embedderEntrypointCallee = codeBlock->embedderEntrypointCalleeFromFunctionIndexSpace(functionIndex);
449             Wasm::WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation = codeBlock->entrypointLoadLocationFromFunctionIndexSpace(functionIndex);
450             const Wasm::Signature& signature = Wasm::SignatureInformation::get(signatureIndex);
451             // FIXME: Say we export local function "foo" at function index 0.
452             // What if we also set it to the table an Element w/ index 0.
453             // Does (new Instance(...)).exports.foo === table.get(0)?
454             // https://bugs.webkit.org/show_bug.cgi?id=165825
455             WebAssemblyFunction* function = WebAssemblyFunction::create(
456                 vm, m_instance->globalObject(), signature.argumentCount(), String(), m_instance.get(), embedderEntrypointCallee, entrypointLoadLocation, signatureIndex);
457
458             table->setFunction(vm, tableIndex, function);
459             ++tableIndex;
460         }
461     });
462
463     ASSERT(!exception);
464
465     forEachSegment([&] (uint8_t* memory, uint64_t, const Wasm::Segment::Ptr& segment, uint32_t offset) {
466         // Empty segments are valid, but only if memory isn't present, which would be undefined behavior in memcpy.
467         if (segment->sizeInBytes) {
468             RELEASE_ASSERT(memory);
469             memcpy(memory + offset, &segment->byte(0), segment->sizeInBytes);
470         }
471     });
472
473     ASSERT(!exception);
474
475     if (JSObject* startFunction = m_startFunction.get()) {
476         CallData callData;
477         CallType callType = JSC::getCallData(startFunction, callData);
478         call(exec, startFunction, callType, callData, jsUndefined(), *vm.emptyList);
479         RETURN_IF_EXCEPTION(scope, { });
480     }
481
482     return jsUndefined();
483 }
484
485 } // namespace JSC
486
487 #endif // ENABLE(WEBASSEMBLY)