3480a508034c05198edc225dd6a7704fab0473c4
[WebKit-https.git] / Source / JavaScriptCore / wasm / js / WebAssemblyModuleRecord.cpp
1 /*
2  * Copyright (C) 2016 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 "JSWebAssemblyInstance.h"
36 #include "JSWebAssemblyModule.h"
37 #include "WasmFormat.h"
38 #include "WebAssemblyFunction.h"
39
40 namespace JSC {
41
42 const ClassInfo WebAssemblyModuleRecord::s_info = { "WebAssemblyModuleRecord", &Base::s_info, nullptr, CREATE_METHOD_TABLE(WebAssemblyModuleRecord) };
43
44 Structure* WebAssemblyModuleRecord::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
45 {
46     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
47 }
48
49 WebAssemblyModuleRecord* WebAssemblyModuleRecord::create(ExecState* exec, VM& vm, Structure* structure, const Identifier& moduleKey, const Wasm::ModuleInformation& moduleInformation)
50 {
51     WebAssemblyModuleRecord* instance = new (NotNull, allocateCell<WebAssemblyModuleRecord>(vm.heap)) WebAssemblyModuleRecord(vm, structure, moduleKey);
52     instance->finishCreation(exec, vm, moduleInformation);
53     return instance;
54 }
55
56 WebAssemblyModuleRecord::WebAssemblyModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey)
57     : Base(vm, structure, moduleKey)
58 {
59 }
60
61 void WebAssemblyModuleRecord::destroy(JSCell* cell)
62 {
63     WebAssemblyModuleRecord* thisObject = jsCast<WebAssemblyModuleRecord*>(cell);
64     thisObject->WebAssemblyModuleRecord::~WebAssemblyModuleRecord();
65 }
66
67 void WebAssemblyModuleRecord::finishCreation(ExecState* exec, VM& vm, const Wasm::ModuleInformation& moduleInformation)
68 {
69     Base::finishCreation(exec, vm);
70     ASSERT(inherits(info()));
71     for (const auto& exp : moduleInformation.exports) {
72         switch (exp.kind) {
73         case Wasm::External::Function: {
74             addExportEntry(ExportEntry::createLocal(exp.field, exp.field));
75             break;
76         }
77         case Wasm::External::Table: {
78             // FIXME https://bugs.webkit.org/show_bug.cgi?id=164135
79             break;
80         }
81         case Wasm::External::Memory: {
82             // FIXME: https://bugs.webkit.org/show_bug.cgi?id=165671
83             break;
84         }
85         case Wasm::External::Global: {
86             // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133
87             // In the MVP, only immutable global variables can be exported.
88             break;
89         }
90         }
91     }
92 }
93
94 void WebAssemblyModuleRecord::visitChildren(JSCell* cell, SlotVisitor& visitor)
95 {
96     WebAssemblyModuleRecord* thisObject = jsCast<WebAssemblyModuleRecord*>(cell);
97     Base::visitChildren(thisObject, visitor);
98     visitor.append(&thisObject->m_instance);
99 }
100
101 void WebAssemblyModuleRecord::link(ExecState* state, JSWebAssemblyInstance* instance)
102 {
103     VM& vm = state->vm();
104     auto scope = DECLARE_THROW_SCOPE(vm);
105     UNUSED_PARAM(scope);
106     auto* globalObject = state->lexicalGlobalObject();
107
108     JSWebAssemblyModule* module = instance->module();
109     const Wasm::ModuleInformation& moduleInformation = module->moduleInformation();
110     SymbolTable* exportSymbolTable = module->exportSymbolTable();
111     unsigned importCount = module->importCount();
112
113     // FIXME wire up the imports. https://bugs.webkit.org/show_bug.cgi?id=165118
114
115     // Let exports be a list of (string, JS value) pairs that is mapped from each external value e in instance.exports as follows:
116     JSModuleEnvironment* moduleEnvironment = JSModuleEnvironment::create(vm, globalObject, nullptr, exportSymbolTable, JSValue(), this);
117     for (const auto& exp : moduleInformation.exports) {
118         JSValue exportedValue;
119         switch (exp.kind) {
120         case Wasm::External::Function: {
121             // 1. If e is a closure c:
122             //   i. If there is an Exported Function Exotic Object func in funcs whose func.[[Closure]] equals c, then return func.
123             //   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.)
124             if (exp.functionIndex < importCount) {
125                 // FIXME Implement re-exporting an import. https://bugs.webkit.org/show_bug.cgi?id=165510
126                 RELEASE_ASSERT_NOT_REACHED();
127             }
128             //   iii. Otherwise:
129             //     a. Let func be an Exported Function Exotic Object created from c.
130             //     b. Append func to funcs.
131             //     c. Return func.
132             JSWebAssemblyCallee* wasmCallee = module->calleeFromFunctionIndexSpace(exp.functionIndex);
133             Wasm::Signature* signature = module->signatureForFunctionIndexSpace(exp.functionIndex);
134             WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->arguments.size(), exp.field.string(), instance, wasmCallee, signature);
135             exportedValue = function;
136             break;
137         }
138         case Wasm::External::Table: {
139             // FIXME https://bugs.webkit.org/show_bug.cgi?id=164135
140             break;
141         }
142         case Wasm::External::Memory: {
143             // FIXME: https://bugs.webkit.org/show_bug.cgi?id=165671
144             break;
145         }
146         case Wasm::External::Global: {
147             // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133
148             // In the MVP, only immutable global variables can be exported.
149             break;
150         }
151         }
152
153         bool shouldThrowReadOnlyError = false;
154         bool ignoreReadOnlyErrors = true;
155         bool putResult = false;
156         symbolTablePutTouchWatchpointSet(moduleEnvironment, state, exp.field, exportedValue, shouldThrowReadOnlyError, ignoreReadOnlyErrors, putResult);
157         RELEASE_ASSERT(putResult);
158     }
159
160     RELEASE_ASSERT(!m_instance);
161     m_instance.set(vm, this, instance);
162     m_moduleEnvironment.set(vm, this, moduleEnvironment);
163 }
164
165 JSValue WebAssemblyModuleRecord::evaluate(ExecState* state)
166 {
167     // FIXME this should call the module's `start` function, if any. https://bugs.webkit.org/show_bug.cgi?id=165150
168     // https://github.com/WebAssembly/design/blob/master/Modules.md#module-start-function
169     // The start function must not take any arguments or return anything
170     UNUSED_PARAM(state);
171     return jsUndefined();
172 }
173
174 } // namespace JSC
175
176 #endif // ENABLE(WEBASSEMBLY)