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

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

Issue 2709613008: Merged: [wasm] Embedder can control what buffers wasm compilation works on. (Closed)
Patch Set: Created 3 years, 10 months 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/runtime/runtime-test.cc ('k') | test/mjsunit/wasm/test-wasm-compilation-control.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/api-natives.h" 5 #include "src/api-natives.h"
6 #include "src/api.h" 6 #include "src/api.h"
7 #include "src/asmjs/asm-js.h" 7 #include "src/asmjs/asm-js.h"
8 #include "src/asmjs/asm-typer.h" 8 #include "src/asmjs/asm-typer.h"
9 #include "src/asmjs/asm-wasm-builder.h" 9 #include "src/asmjs/asm-wasm-builder.h"
10 #include "src/assert-scope.h" 10 #include "src/assert-scope.h"
(...skipping 12 matching lines...) Expand all
23 #include "src/wasm/wasm-objects.h" 23 #include "src/wasm/wasm-objects.h"
24 #include "src/wasm/wasm-result.h" 24 #include "src/wasm/wasm-result.h"
25 25
26 typedef uint8_t byte; 26 typedef uint8_t byte;
27 27
28 using v8::internal::wasm::ErrorThrower; 28 using v8::internal::wasm::ErrorThrower;
29 29
30 namespace v8 { 30 namespace v8 {
31 31
32 namespace { 32 namespace {
33
34 #define RANGE_ERROR_MSG \
35 "Wasm compilation exceeds internal limits in this context for the provided " \
36 "arguments"
37
33 i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) { 38 i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) {
34 return isolate->factory()->NewStringFromAsciiChecked(str); 39 return isolate->factory()->NewStringFromAsciiChecked(str);
35 } 40 }
36 Local<String> v8_str(Isolate* isolate, const char* str) { 41 Local<String> v8_str(Isolate* isolate, const char* str) {
37 return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str)); 42 return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str));
38 } 43 }
39 44
40 struct RawBuffer { 45 struct RawBuffer {
41 const byte* start; 46 const byte* start;
42 const byte* end; 47 const byte* end;
43 size_t size() { return static_cast<size_t>(end - start); } 48 size_t size() { return static_cast<size_t>(end - start); }
44 }; 49 };
45 50
51 bool IsCompilationAllowed(i::Isolate* isolate, ErrorThrower* thrower,
52 v8::Local<v8::Value> source, bool is_async) {
53 // Allow caller to do one final check on thrower state, rather than
54 // one at each step. No information is lost - failure reason is captured
55 // in the thrower state.
56 if (thrower->error()) return false;
57
58 AllowWasmCompileCallback callback = isolate->allow_wasm_compile_callback();
59 if (callback != nullptr &&
60 !callback(reinterpret_cast<v8::Isolate*>(isolate), source, is_async)) {
61 thrower->RangeError(RANGE_ERROR_MSG);
62 return false;
63 }
64 return true;
65 }
66
67 bool IsInstantiationAllowed(i::Isolate* isolate, ErrorThrower* thrower,
68 v8::Local<v8::Value> module_or_bytes,
69 i::MaybeHandle<i::JSReceiver> ffi, bool is_async) {
70 // Allow caller to do one final check on thrower state, rather than
71 // one at each step. No information is lost - failure reason is captured
72 // in the thrower state.
73 if (thrower->error()) return false;
74 v8::MaybeLocal<v8::Value> v8_ffi;
75 if (!ffi.is_null()) {
76 v8_ffi = v8::Local<v8::Value>::Cast(Utils::ToLocal(ffi.ToHandleChecked()));
77 }
78 AllowWasmInstantiateCallback callback =
79 isolate->allow_wasm_instantiate_callback();
80 if (callback != nullptr &&
81 !callback(reinterpret_cast<v8::Isolate*>(isolate), module_or_bytes,
82 v8_ffi, is_async)) {
83 thrower->RangeError(RANGE_ERROR_MSG);
84 return false;
85 }
86 return true;
87 }
88
89 i::wasm::ModuleWireBytes GetFirstArgumentAsBytes(
90 const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) {
91 if (args.Length() < 1) {
92 thrower->TypeError("Argument 0 must be a buffer source");
93 return i::wasm::ModuleWireBytes(nullptr, nullptr);
94 }
95
96 const byte* start = nullptr;
97 size_t length = 0;
98 v8::Local<v8::Value> source = args[0];
99 if (source->IsArrayBuffer()) {
100 // A raw array buffer was passed.
101 Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(source);
102 ArrayBuffer::Contents contents = buffer->GetContents();
103
104 start = reinterpret_cast<const byte*>(contents.Data());
105 length = contents.ByteLength();
106 } else if (source->IsTypedArray()) {
107 // A TypedArray was passed.
108 Local<TypedArray> array = Local<TypedArray>::Cast(source);
109 Local<ArrayBuffer> buffer = array->Buffer();
110
111 ArrayBuffer::Contents contents = buffer->GetContents();
112
113 start =
114 reinterpret_cast<const byte*>(contents.Data()) + array->ByteOffset();
115 length = array->ByteLength();
116 } else {
117 thrower->TypeError("Argument 0 must be a buffer source");
118 }
119 DCHECK_IMPLIES(length, start != nullptr);
120 if (length == 0) {
121 thrower->CompileError("BufferSource argument is empty");
122 }
123 if (length > i::wasm::kV8MaxWasmModuleSize) {
124 thrower->RangeError("buffer source exceeds maximum size of %zu (is %zu)",
125 i::wasm::kV8MaxWasmModuleSize, length);
126 }
127 if (thrower->error()) return i::wasm::ModuleWireBytes(nullptr, nullptr);
128 // TODO(titzer): use the handle as well?
129 return i::wasm::ModuleWireBytes(start, start + length);
130 }
131
132 i::MaybeHandle<i::JSReceiver> GetSecondArgumentAsImports(
133 const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) {
134 if (args.Length() < 2) return {};
135 if (args[1]->IsUndefined()) return {};
136
137 if (!args[1]->IsObject()) {
138 thrower->TypeError("Argument 1 must be an object");
139 return {};
140 }
141 Local<Object> obj = Local<Object>::Cast(args[1]);
142 return i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj));
143 }
144
46 RawBuffer GetRawBufferSource( 145 RawBuffer GetRawBufferSource(
47 v8::Local<v8::Value> source, ErrorThrower* thrower) { 146 v8::Local<v8::Value> source, ErrorThrower* thrower) {
48 const byte* start = nullptr; 147 const byte* start = nullptr;
49 const byte* end = nullptr; 148 const byte* end = nullptr;
50 149
51 if (source->IsArrayBuffer()) { 150 if (source->IsArrayBuffer()) {
52 // A raw array buffer was passed. 151 // A raw array buffer was passed.
53 Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(source); 152 Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(source);
54 ArrayBuffer::Contents contents = buffer->GetContents(); 153 ArrayBuffer::Contents contents = buffer->GetContents();
55 154
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 if (has_brand.IsNothing()) return false; 224 if (has_brand.IsNothing()) return false;
126 if (has_brand.ToChecked()) return true; 225 if (has_brand.ToChecked()) return true;
127 } 226 }
128 v8::Local<v8::Value> e = v8::Exception::TypeError(v8_str(isolate, msg)); 227 v8::Local<v8::Value> e = v8::Exception::TypeError(v8_str(isolate, msg));
129 isolate->ThrowException(e); 228 isolate->ThrowException(e);
130 return false; 229 return false;
131 } 230 }
132 231
133 void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) { 232 void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) {
134 v8::Isolate* isolate = args.GetIsolate(); 233 v8::Isolate* isolate = args.GetIsolate();
234 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
135 HandleScope scope(isolate); 235 HandleScope scope(isolate);
136 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), 236 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate),
137 "WebAssembly.compile()"); 237 "WebAssembly.compile()");
138 238
139 Local<Context> context = isolate->GetCurrentContext(); 239 Local<Context> context = isolate->GetCurrentContext();
140 v8::Local<v8::Promise::Resolver> resolver; 240 v8::Local<v8::Promise::Resolver> resolver;
141 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; 241 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return;
142 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); 242 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
143 return_value.Set(resolver->GetPromise()); 243 return_value.Set(resolver->GetPromise());
144 244
145 if (args.Length() < 1) { 245 if (args.Length() < 1) {
146 thrower.TypeError("Argument 0 must be a buffer source"); 246 thrower.TypeError("Argument 0 must be a buffer source");
147 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); 247 resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
148 return; 248 return;
149 } 249 }
250 auto bytes = GetFirstArgumentAsBytes(args, &thrower);
JaideepBajwa 2017/02/25 05:13:57 USE(bytes); to suppress compiler unused variable w
251 if (!IsCompilationAllowed(i_isolate, &thrower, args[0], true)) {
252 resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
253 return;
254 }
150 i::MaybeHandle<i::JSObject> module_obj = 255 i::MaybeHandle<i::JSObject> module_obj =
151 CreateModuleObject(isolate, args[0], &thrower); 256 CreateModuleObject(isolate, args[0], &thrower);
152 257
153 if (thrower.error()) { 258 if (thrower.error()) {
154 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); 259 resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
155 } else { 260 } else {
156 resolver->Resolve(context, Utils::ToLocal(module_obj.ToHandleChecked())); 261 resolver->Resolve(context, Utils::ToLocal(module_obj.ToHandleChecked()));
157 } 262 }
158 } 263 }
159 264
(...skipping 12 matching lines...) Expand all
172 if (ValidateModule(isolate, args[0], &thrower)) { 277 if (ValidateModule(isolate, args[0], &thrower)) {
173 return_value.Set(v8::True(isolate)); 278 return_value.Set(v8::True(isolate));
174 } else { 279 } else {
175 if (thrower.wasm_error()) thrower.Reify(); // Clear error. 280 if (thrower.wasm_error()) thrower.Reify(); // Clear error.
176 return_value.Set(v8::False(isolate)); 281 return_value.Set(v8::False(isolate));
177 } 282 }
178 } 283 }
179 284
180 void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { 285 void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
181 v8::Isolate* isolate = args.GetIsolate(); 286 v8::Isolate* isolate = args.GetIsolate();
287 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
182 HandleScope scope(isolate); 288 HandleScope scope(isolate);
183 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), 289 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate),
184 "WebAssembly.Module()"); 290 "WebAssembly.Module()");
185 291
186 if (args.Length() < 1) { 292 if (args.Length() < 1) {
187 thrower.TypeError("Argument 0 must be a buffer source"); 293 thrower.TypeError("Argument 0 must be a buffer source");
188 return; 294 return;
189 } 295 }
296 auto bytes = GetFirstArgumentAsBytes(args, &thrower);
JaideepBajwa 2017/02/25 05:13:57 USE(bytes); to suppress compiler unused variable w
297 if (!IsCompilationAllowed(i_isolate, &thrower, args[0], false)) return;
190 298
191 i::MaybeHandle<i::JSObject> module_obj = 299 i::MaybeHandle<i::JSObject> module_obj =
192 CreateModuleObject(isolate, args[0], &thrower); 300 CreateModuleObject(isolate, args[0], &thrower);
193 if (module_obj.is_null()) return; 301 if (module_obj.is_null()) return;
194 302
195 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); 303 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
196 return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked())); 304 return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked()));
197 } 305 }
198 306
199 MaybeLocal<Value> InstantiateModuleImpl( 307 MaybeLocal<Value> InstantiateModuleImpl(
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 } 426 }
319 427
320 void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { 428 void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
321 HandleScope scope(args.GetIsolate()); 429 HandleScope scope(args.GetIsolate());
322 v8::Isolate* isolate = args.GetIsolate(); 430 v8::Isolate* isolate = args.GetIsolate();
323 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 431 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
324 432
325 ErrorThrower thrower(i_isolate, "WebAssembly.Instance()"); 433 ErrorThrower thrower(i_isolate, "WebAssembly.Instance()");
326 434
327 auto maybe_module = GetFirstArgumentAsModule(args, thrower); 435 auto maybe_module = GetFirstArgumentAsModule(args, thrower);
436 if (thrower.error()) return;
437 auto maybe_imports = GetSecondArgumentAsImports(args, &thrower);
438 if (!IsInstantiationAllowed(i_isolate, &thrower, args[0], maybe_imports,
439 false)) {
440 return;
441 }
442 DCHECK(!thrower.error());
328 443
329 if (!maybe_module.is_null()) { 444 if (!maybe_module.is_null()) {
330 MaybeLocal<Value> instance = InstantiateModuleImpl( 445 MaybeLocal<Value> instance = InstantiateModuleImpl(
331 i_isolate, maybe_module.ToHandleChecked(), args, &thrower); 446 i_isolate, maybe_module.ToHandleChecked(), args, &thrower);
332 if (instance.IsEmpty()) { 447 if (instance.IsEmpty()) {
333 DCHECK(thrower.error()); 448 DCHECK(thrower.error());
334 return; 449 return;
335 } 450 }
336 args.GetReturnValue().Set(instance.ToLocalChecked()); 451 args.GetReturnValue().Set(instance.ToLocalChecked());
337 } 452 }
(...skipping 22 matching lines...) Expand all
360 return; 475 return;
361 } 476 }
362 477
363 i::Handle<i::Object> first_arg = Utils::OpenHandle(*args[0]); 478 i::Handle<i::Object> first_arg = Utils::OpenHandle(*args[0]);
364 if (!first_arg->IsJSObject()) { 479 if (!first_arg->IsJSObject()) {
365 thrower.TypeError( 480 thrower.TypeError(
366 "Argument 0 must be a buffer source or a WebAssembly.Module object"); 481 "Argument 0 must be a buffer source or a WebAssembly.Module object");
367 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); 482 resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
368 return; 483 return;
369 } 484 }
485
370 bool want_pair = !BrandCheck( 486 bool want_pair = !BrandCheck(
371 isolate, first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym())); 487 isolate, first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym()));
488 auto maybe_imports = GetSecondArgumentAsImports(args, &thrower);
489 if (thrower.error()) {
490 resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
491 return;
492 }
493 if (!IsInstantiationAllowed(i_isolate, &thrower, args[0], maybe_imports,
494 true)) {
495 resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
496 return;
497 }
372 i::Handle<i::WasmModuleObject> module_obj; 498 i::Handle<i::WasmModuleObject> module_obj;
373 if (want_pair) { 499 if (want_pair) {
374 i::MaybeHandle<i::WasmModuleObject> maybe_module_obj = 500 i::MaybeHandle<i::WasmModuleObject> maybe_module_obj =
375 CreateModuleObject(isolate, args[0], &thrower); 501 CreateModuleObject(isolate, args[0], &thrower);
376 if (!maybe_module_obj.ToHandle(&module_obj)) { 502 if (!maybe_module_obj.ToHandle(&module_obj)) {
377 DCHECK(thrower.error()); 503 DCHECK(thrower.error());
378 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); 504 resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
379 return; 505 return;
380 } 506 }
381 } else { 507 } else {
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after
964 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); 1090 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate);
965 return HasBrand(value, symbol); 1091 return HasBrand(value, symbol);
966 } 1092 }
967 1093
968 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { 1094 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) {
969 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); 1095 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate);
970 return HasBrand(value, symbol); 1096 return HasBrand(value, symbol);
971 } 1097 }
972 } // namespace internal 1098 } // namespace internal
973 } // namespace v8 1099 } // namespace v8
OLDNEW
« no previous file with comments | « src/runtime/runtime-test.cc ('k') | test/mjsunit/wasm/test-wasm-compilation-control.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698