Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/wasm/wasm-js.cc

Issue 1504713014: Initial import of v8-native WASM. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/wasm/wasm-js.h ('k') | src/wasm/wasm-macro-gen.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/api.h"
6 #include "src/api-natives.h"
7 #include "src/assert-scope.h"
8 #include "src/ast/ast.h"
9 #include "src/ast/scopes.h"
10 #include "src/factory.h"
11 #include "src/handles.h"
12 #include "src/isolate.h"
13 #include "src/objects.h"
14 #include "src/parsing/parser.h"
15 #include "src/typing-asm.h"
16
17 #include "src/wasm/asm-wasm-builder.h"
18 #include "src/wasm/encoder.h"
19 #include "src/wasm/module-decoder.h"
20 #include "src/wasm/wasm-js.h"
21 #include "src/wasm/wasm-module.h"
22 #include "src/wasm/wasm-result.h"
23
24 typedef uint8_t byte;
25
26 using v8::internal::wasm::ErrorThrower;
27
28 namespace v8 {
29
30 namespace {
31 struct RawBuffer {
32 const byte* start;
33 const byte* end;
34 size_t size() { return static_cast<size_t>(end - start); }
35 };
36
37
38 RawBuffer GetRawBufferArgument(
39 ErrorThrower& thrower, const v8::FunctionCallbackInfo<v8::Value>& args) {
40 if (args.Length() < 1 || !args[0]->IsArrayBuffer()) {
41 thrower.Error("Argument 0 must be an array buffer");
42 return {nullptr, nullptr};
43 }
44 Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[0]);
45 ArrayBuffer::Contents contents =
46 buffer->IsExternal() ? buffer->GetContents() : buffer->Externalize();
47
48 // TODO(titzer): allow offsets into buffers, views, etc.
49
50 const byte* start = reinterpret_cast<const byte*>(contents.Data());
51 const byte* end = start + contents.ByteLength();
52
53 if (start == nullptr) {
54 thrower.Error("ArrayBuffer argument is empty");
55 }
56 return {start, end};
57 }
58
59
60 void VerifyModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
61 HandleScope scope(args.GetIsolate());
62 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
63 ErrorThrower thrower(isolate, "WASM.verifyModule()");
64
65 RawBuffer buffer = GetRawBufferArgument(thrower, args);
66 if (thrower.error()) return;
67
68 i::Zone zone;
69 internal::wasm::ModuleResult result = internal::wasm::DecodeWasmModule(
70 isolate, &zone, buffer.start, buffer.end, true, false);
71
72 if (result.failed()) {
73 thrower.Failed("", result);
74 }
75
76 if (result.val) delete result.val;
77 }
78
79
80 void VerifyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) {
81 HandleScope scope(args.GetIsolate());
82 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
83 ErrorThrower thrower(isolate, "WASM.verifyFunction()");
84
85 // TODO(titzer): no need to externalize to get the bytes for verification.
86 RawBuffer buffer = GetRawBufferArgument(thrower, args);
87 if (thrower.error()) return;
88
89 internal::wasm::FunctionResult result;
90 {
91 // Verification of a single function shouldn't allocate.
92 i::DisallowHeapAllocation no_allocation;
93 i::Zone zone;
94 result = internal::wasm::DecodeWasmFunction(isolate, &zone, nullptr,
95 buffer.start, buffer.end);
96 }
97
98 if (result.failed()) {
99 thrower.Failed("", result);
100 }
101
102 if (result.val) delete result.val;
103 }
104
105
106 void CompileRun(const v8::FunctionCallbackInfo<v8::Value>& args) {
107 HandleScope scope(args.GetIsolate());
108 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
109 ErrorThrower thrower(isolate, "WASM.compileRun()");
110
111 RawBuffer buffer = GetRawBufferArgument(thrower, args);
112 if (thrower.error()) return;
113
114 // Decode and pre-verify the functions before compiling and running.
115 i::Zone zone;
116 internal::wasm::ModuleResult result = internal::wasm::DecodeWasmModule(
117 isolate, &zone, buffer.start, buffer.end, true, false);
118
119 if (result.failed()) {
120 thrower.Failed("", result);
121 } else {
122 // Success. Compile and run!
123 int32_t retval = i::wasm::CompileAndRunWasmModule(isolate, result.val);
124 args.GetReturnValue().Set(retval);
125 }
126
127 if (result.val) delete result.val;
128 }
129
130
131 v8::internal::wasm::WasmModuleIndex* TranslateAsmModule(i::ParseInfo* info) {
132 info->set_global();
133 info->set_lazy(false);
134 info->set_allow_lazy_parsing(false);
135 info->set_toplevel(true);
136
137 CHECK(i::Compiler::ParseAndAnalyze(info));
138 info->set_literal(
139 info->scope()->declarations()->at(0)->AsFunctionDeclaration()->fun());
140
141 v8::internal::AsmTyper typer(info->isolate(), info->zone(), *(info->script()),
142 info->literal());
143 if (!typer.Validate()) {
144 return NULL;
145 }
146
147 auto module = v8::internal::wasm::AsmWasmBuilder(
148 info->isolate(), info->zone(), info->literal())
149 .Run();
150 return module;
151 }
152
153
154 void AsmCompileRun(const v8::FunctionCallbackInfo<v8::Value>& args) {
155 HandleScope scope(args.GetIsolate());
156 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
157 ErrorThrower thrower(isolate, "WASM.asmCompileRun()");
158
159 if (args.Length() != 1) {
160 thrower.Error("Invalid argument count");
161 return;
162 }
163 if (!args[0]->IsString()) {
164 thrower.Error("Invalid argument count");
165 return;
166 }
167
168 i::Factory* factory = isolate->factory();
169 i::Zone zone;
170 Local<String> source = Local<String>::Cast(args[0]);
171 i::Handle<i::Script> script = factory->NewScript(Utils::OpenHandle(*source));
172 i::ParseInfo info(&zone, script);
173
174 auto module = TranslateAsmModule(&info);
175 if (module == NULL) {
176 thrower.Error("Asm.js validation failed");
177 return;
178 }
179
180 int32_t result = v8::internal::wasm::CompileAndRunWasmModule(
181 isolate, module->Begin(), module->End(), true);
182 args.GetReturnValue().Set(result);
183 }
184
185
186 // TODO(aseemgarg): deal with arraybuffer and foreign functions
187 void InstantiateModuleFromAsm(const v8::FunctionCallbackInfo<v8::Value>& args) {
188 HandleScope scope(args.GetIsolate());
189 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
190 ErrorThrower thrower(isolate, "WASM.instantiateModuleFromAsm()");
191
192 if (args.Length() != 1) {
193 thrower.Error("Invalid argument count");
194 return;
195 }
196 if (!args[0]->IsString()) {
197 thrower.Error("Invalid argument count");
198 return;
199 }
200
201 i::Factory* factory = isolate->factory();
202 i::Zone zone;
203 Local<String> source = Local<String>::Cast(args[0]);
204 i::Handle<i::Script> script = factory->NewScript(Utils::OpenHandle(*source));
205 i::ParseInfo info(&zone, script);
206
207 auto module = TranslateAsmModule(&info);
208 if (module == NULL) {
209 thrower.Error("Asm.js validation failed");
210 return;
211 }
212
213 i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null();
214 internal::wasm::ModuleResult result = internal::wasm::DecodeWasmModule(
215 isolate, &zone, module->Begin(), module->End(), false, false);
216
217 if (result.failed()) {
218 thrower.Failed("", result);
219 } else {
220 // Success. Instantiate the module and return the object.
221 i::Handle<i::JSObject> ffi = i::Handle<i::JSObject>::null();
222
223 i::MaybeHandle<i::JSObject> object =
224 result.val->Instantiate(isolate, ffi, memory);
225
226 if (!object.is_null()) {
227 args.GetReturnValue().Set(v8::Utils::ToLocal(object.ToHandleChecked()));
228 }
229 }
230
231 if (result.val) delete result.val;
232 }
233
234
235 void InstantiateModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
236 HandleScope scope(args.GetIsolate());
237 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
238 ErrorThrower thrower(isolate, "WASM.instantiateModule()");
239
240 RawBuffer buffer = GetRawBufferArgument(thrower, args);
241 if (buffer.start == nullptr) return;
242
243 i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null();
244 if (args.Length() > 2 && args[2]->IsArrayBuffer()) {
245 Local<Object> obj = Local<Object>::Cast(args[2]);
246 i::Handle<i::Object> mem_obj = v8::Utils::OpenHandle(*obj);
247 memory = i::Handle<i::JSArrayBuffer>(i::JSArrayBuffer::cast(*mem_obj));
248 i::Isolate* isolate = memory->GetIsolate();
249 memory->set_is_external(true);
250 isolate->heap()->UnregisterArrayBuffer(*memory);
251 }
252
253 // Decode but avoid a redundant pass over function bodies for verification.
254 // Verification will happen during compilation.
255 i::Zone zone;
256 internal::wasm::ModuleResult result = internal::wasm::DecodeWasmModule(
257 isolate, &zone, buffer.start, buffer.end, false, false);
258
259 if (result.failed()) {
260 thrower.Failed("", result);
261 } else {
262 // Success. Instantiate the module and return the object.
263 i::Handle<i::JSObject> ffi = i::Handle<i::JSObject>::null();
264 if (args.Length() > 1 && args[1]->IsObject()) {
265 Local<Object> obj = Local<Object>::Cast(args[1]);
266 ffi = i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*obj));
267 }
268
269 i::MaybeHandle<i::JSObject> object =
270 result.val->Instantiate(isolate, ffi, memory);
271
272 if (!object.is_null()) {
273 args.GetReturnValue().Set(v8::Utils::ToLocal(object.ToHandleChecked()));
274 }
275 }
276
277 if (result.val) delete result.val;
278 }
279 } // namespace
280
281
282 // TODO(titzer): we use the API to create the function template because the
283 // internal guts are too ugly to replicate here.
284 static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate,
285 FunctionCallback func) {
286 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
287 Local<FunctionTemplate> local = FunctionTemplate::New(isolate, func);
288 return v8::Utils::OpenHandle(*local);
289 }
290
291
292 namespace internal {
293 static Handle<String> v8_str(Isolate* isolate, const char* str) {
294 return isolate->factory()->NewStringFromAsciiChecked(str);
295 }
296
297
298 static void InstallFunc(Isolate* isolate, Handle<JSObject> object,
299 const char* str, FunctionCallback func) {
300 Handle<String> name = v8_str(isolate, str);
301 Handle<FunctionTemplateInfo> temp = NewTemplate(isolate, func);
302 Handle<JSFunction> function =
303 ApiNatives::InstantiateFunction(temp).ToHandleChecked();
304 PropertyAttributes attributes =
305 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
306 JSObject::AddProperty(object, name, function, attributes);
307 }
308
309
310 void WasmJs::Install(Isolate* isolate, Handle<JSGlobalObject> global) {
311 // Bind the WASM object.
312 Factory* factory = isolate->factory();
313 Handle<String> name = v8_str(isolate, "WASM");
314 Handle<JSFunction> cons = factory->NewFunction(name);
315 JSFunction::SetInstancePrototype(
316 cons, Handle<Object>(global->native_context()->initial_object_prototype(),
317 isolate));
318 cons->shared()->set_instance_class_name(*name);
319 Handle<JSObject> wasm_object = factory->NewJSObject(cons, TENURED);
320 PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM);
321 JSObject::AddProperty(global, name, wasm_object, attributes);
322
323 // Install functions on the WASM object.
324 InstallFunc(isolate, wasm_object, "instantiateModule", InstantiateModule);
325 InstallFunc(isolate, wasm_object, "verifyModule", VerifyModule);
326 InstallFunc(isolate, wasm_object, "verifyFunction", VerifyFunction);
327 InstallFunc(isolate, wasm_object, "compileRun", CompileRun);
328 InstallFunc(isolate, wasm_object, "asmCompileRun", AsmCompileRun);
329 InstallFunc(isolate, wasm_object, "instantiateModuleFromAsm",
330 InstantiateModuleFromAsm);
331 }
332 } // namespace internal
333 } // namespace v8
OLDNEW
« no previous file with comments | « src/wasm/wasm-js.h ('k') | src/wasm/wasm-macro-gen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698