OLD | NEW |
---|---|
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 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
101 if (buffer.start == nullptr) return false; | 101 if (buffer.start == nullptr) return false; |
102 | 102 |
103 DCHECK(source->IsArrayBuffer() || source->IsTypedArray()); | 103 DCHECK(source->IsArrayBuffer() || source->IsTypedArray()); |
104 return i::wasm::ValidateModuleBytes(i_isolate, buffer.start, buffer.end, | 104 return i::wasm::ValidateModuleBytes(i_isolate, buffer.start, buffer.end, |
105 thrower, | 105 thrower, |
106 i::wasm::ModuleOrigin::kWasmOrigin); | 106 i::wasm::ModuleOrigin::kWasmOrigin); |
107 } | 107 } |
108 | 108 |
109 // TODO(wasm): move brand check to the respective types, and don't throw | 109 // TODO(wasm): move brand check to the respective types, and don't throw |
110 // in it, rather, use a provided ErrorThrower, or let caller handle it. | 110 // in it, rather, use a provided ErrorThrower, or let caller handle it. |
111 static bool BrandCheck(Isolate* isolate, i::Handle<i::Object> value, | 111 static bool HasBrand(Isolate* isolate, i::Handle<i::Object> value, |
112 i::Handle<i::Symbol> sym) { | 112 i::Handle<i::Symbol> sym) { |
113 if (!value->IsJSObject()) return false; | 113 if (!value->IsJSObject()) return false; |
114 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); | 114 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); |
115 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); | 115 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); |
116 if (has_brand.IsNothing()) return false; | 116 if (has_brand.IsNothing()) return false; |
rossberg
2017/01/25 09:47:34
Nit: could similarly combine this into
return !ha
titzer
2017/01/25 09:54:33
Done.
| |
117 return has_brand.ToChecked(); | 117 return has_brand.ToChecked(); |
118 } | 118 } |
119 | 119 |
120 static bool BrandCheck(Isolate* isolate, i::Handle<i::Object> value, | 120 static bool BrandCheck(ErrorThrower* thrower, i::Handle<i::Object> value, |
rossberg
2017/01/25 09:47:34
Why not avoid repetition and simplify this functio
titzer
2017/01/25 09:54:33
Done.
| |
121 i::Handle<i::Symbol> sym, const char* msg) { | 121 i::Handle<i::Symbol> sym, const char* msg) { |
122 if (value->IsJSObject()) { | 122 if (value->IsJSObject()) { |
123 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); | 123 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); |
124 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); | 124 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); |
125 if (has_brand.IsNothing()) return false; | 125 if (!has_brand.IsNothing() && has_brand.ToChecked()) return true; |
126 if (has_brand.ToChecked()) return true; | |
127 } | 126 } |
128 v8::Local<v8::Value> e = v8::Exception::TypeError(v8_str(isolate, msg)); | 127 thrower->TypeError("%s", msg); |
129 isolate->ThrowException(e); | |
130 return false; | 128 return false; |
131 } | 129 } |
132 | 130 |
133 void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) { | 131 void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) { |
134 v8::Isolate* isolate = args.GetIsolate(); | 132 v8::Isolate* isolate = args.GetIsolate(); |
135 HandleScope scope(isolate); | 133 HandleScope scope(isolate); |
136 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | 134 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), |
137 "WebAssembly.compile()"); | 135 "WebAssembly.compile()"); |
138 | 136 |
139 Local<Context> context = isolate->GetCurrentContext(); | 137 Local<Context> context = isolate->GetCurrentContext(); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
226 if (!thrower->error()) | 224 if (!thrower->error()) |
227 thrower->RuntimeError("Could not instantiate module"); | 225 thrower->RuntimeError("Could not instantiate module"); |
228 return nothing; | 226 return nothing; |
229 } | 227 } |
230 DCHECK(!i_isolate->has_pending_exception()); | 228 DCHECK(!i_isolate->has_pending_exception()); |
231 return Utils::ToLocal(instance.ToHandleChecked()); | 229 return Utils::ToLocal(instance.ToHandleChecked()); |
232 } | 230 } |
233 | 231 |
234 namespace { | 232 namespace { |
235 i::MaybeHandle<i::WasmModuleObject> GetFirstArgumentAsModule( | 233 i::MaybeHandle<i::WasmModuleObject> GetFirstArgumentAsModule( |
236 const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower& thrower) { | 234 const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) { |
237 v8::Isolate* isolate = args.GetIsolate(); | 235 v8::Isolate* isolate = args.GetIsolate(); |
238 i::MaybeHandle<i::WasmModuleObject> nothing; | 236 i::MaybeHandle<i::WasmModuleObject> nothing; |
239 if (args.Length() < 1) { | 237 if (args.Length() < 1) { |
240 thrower.TypeError("Argument 0 must be a WebAssembly.Module"); | 238 thrower->TypeError("Argument 0 must be a WebAssembly.Module"); |
241 return nothing; | 239 return nothing; |
242 } | 240 } |
243 | 241 |
244 Local<Context> context = isolate->GetCurrentContext(); | 242 Local<Context> context = isolate->GetCurrentContext(); |
245 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 243 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
246 if (!BrandCheck(isolate, Utils::OpenHandle(*args[0]), | 244 if (!BrandCheck(thrower, Utils::OpenHandle(*args[0]), |
247 i::Handle<i::Symbol>(i_context->wasm_module_sym()), | 245 i::Handle<i::Symbol>(i_context->wasm_module_sym()), |
248 "Argument 0 must be a WebAssembly.Module")) { | 246 "Argument 0 must be a WebAssembly.Module")) { |
249 return nothing; | 247 return nothing; |
250 } | 248 } |
251 | 249 |
252 Local<Object> module_obj = Local<Object>::Cast(args[0]); | 250 Local<Object> module_obj = Local<Object>::Cast(args[0]); |
253 return i::Handle<i::WasmModuleObject>::cast( | 251 return i::Handle<i::WasmModuleObject>::cast( |
254 v8::Utils::OpenHandle(*module_obj)); | 252 v8::Utils::OpenHandle(*module_obj)); |
255 } | 253 } |
256 } // namespace | 254 } // namespace |
257 | 255 |
258 void WebAssemblyModuleImports(const v8::FunctionCallbackInfo<v8::Value>& args) { | 256 void WebAssemblyModuleImports(const v8::FunctionCallbackInfo<v8::Value>& args) { |
259 HandleScope scope(args.GetIsolate()); | 257 HandleScope scope(args.GetIsolate()); |
260 v8::Isolate* isolate = args.GetIsolate(); | 258 v8::Isolate* isolate = args.GetIsolate(); |
261 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 259 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
262 ErrorThrower thrower(i_isolate, "WebAssembly.Module.imports()"); | 260 ErrorThrower thrower(i_isolate, "WebAssembly.Module.imports()"); |
263 | 261 |
264 auto maybe_module = GetFirstArgumentAsModule(args, thrower); | 262 auto maybe_module = GetFirstArgumentAsModule(args, &thrower); |
265 | 263 |
266 if (!maybe_module.is_null()) { | 264 if (!maybe_module.is_null()) { |
267 auto imports = | 265 auto imports = |
268 i::wasm::GetImports(i_isolate, maybe_module.ToHandleChecked()); | 266 i::wasm::GetImports(i_isolate, maybe_module.ToHandleChecked()); |
269 args.GetReturnValue().Set(Utils::ToLocal(imports)); | 267 args.GetReturnValue().Set(Utils::ToLocal(imports)); |
270 } | 268 } |
271 } | 269 } |
272 | 270 |
273 void WebAssemblyModuleExports(const v8::FunctionCallbackInfo<v8::Value>& args) { | 271 void WebAssemblyModuleExports(const v8::FunctionCallbackInfo<v8::Value>& args) { |
274 HandleScope scope(args.GetIsolate()); | 272 HandleScope scope(args.GetIsolate()); |
275 v8::Isolate* isolate = args.GetIsolate(); | 273 v8::Isolate* isolate = args.GetIsolate(); |
276 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 274 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
277 | |
278 ErrorThrower thrower(i_isolate, "WebAssembly.Module.exports()"); | 275 ErrorThrower thrower(i_isolate, "WebAssembly.Module.exports()"); |
279 | 276 |
280 auto maybe_module = GetFirstArgumentAsModule(args, thrower); | 277 auto maybe_module = GetFirstArgumentAsModule(args, &thrower); |
281 | 278 |
282 if (!maybe_module.is_null()) { | 279 if (!maybe_module.is_null()) { |
283 auto exports = | 280 auto exports = |
284 i::wasm::GetExports(i_isolate, maybe_module.ToHandleChecked()); | 281 i::wasm::GetExports(i_isolate, maybe_module.ToHandleChecked()); |
285 args.GetReturnValue().Set(Utils::ToLocal(exports)); | 282 args.GetReturnValue().Set(Utils::ToLocal(exports)); |
286 } | 283 } |
287 } | 284 } |
288 | 285 |
289 void WebAssemblyModuleCustomSections( | 286 void WebAssemblyModuleCustomSections( |
290 const v8::FunctionCallbackInfo<v8::Value>& args) { | 287 const v8::FunctionCallbackInfo<v8::Value>& args) { |
291 HandleScope scope(args.GetIsolate()); | 288 HandleScope scope(args.GetIsolate()); |
292 v8::Isolate* isolate = args.GetIsolate(); | 289 v8::Isolate* isolate = args.GetIsolate(); |
293 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 290 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
294 | |
295 ErrorThrower thrower(i_isolate, "WebAssembly.Module.customSections()"); | 291 ErrorThrower thrower(i_isolate, "WebAssembly.Module.customSections()"); |
296 | 292 |
297 auto maybe_module = GetFirstArgumentAsModule(args, thrower); | 293 auto maybe_module = GetFirstArgumentAsModule(args, &thrower); |
298 | 294 |
299 if (args.Length() < 2) { | 295 if (args.Length() < 2) { |
300 thrower.TypeError("Argument 1 must be a string"); | 296 thrower.TypeError("Argument 1 must be a string"); |
301 return; | 297 return; |
302 } | 298 } |
303 | 299 |
304 i::Handle<i::Object> name = Utils::OpenHandle(*args[1]); | 300 i::Handle<i::Object> name = Utils::OpenHandle(*args[1]); |
305 if (!name->IsString()) { | 301 if (!name->IsString()) { |
306 thrower.TypeError("Argument 1 must be a string"); | 302 thrower.TypeError("Argument 1 must be a string"); |
307 return; | 303 return; |
308 } | 304 } |
309 | 305 |
310 if (!maybe_module.is_null()) { | 306 if (!maybe_module.is_null()) { |
311 auto custom_sections = | 307 auto custom_sections = |
312 i::wasm::GetCustomSections(i_isolate, maybe_module.ToHandleChecked(), | 308 i::wasm::GetCustomSections(i_isolate, maybe_module.ToHandleChecked(), |
313 i::Handle<i::String>::cast(name), &thrower); | 309 i::Handle<i::String>::cast(name), &thrower); |
314 if (!thrower.error()) { | 310 if (!thrower.error()) { |
315 args.GetReturnValue().Set(Utils::ToLocal(custom_sections)); | 311 args.GetReturnValue().Set(Utils::ToLocal(custom_sections)); |
316 } | 312 } |
317 } | 313 } |
318 } | 314 } |
319 | 315 |
320 void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { | 316 void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { |
321 HandleScope scope(args.GetIsolate()); | 317 HandleScope scope(args.GetIsolate()); |
322 v8::Isolate* isolate = args.GetIsolate(); | 318 v8::Isolate* isolate = args.GetIsolate(); |
323 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 319 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
324 | |
325 ErrorThrower thrower(i_isolate, "WebAssembly.Instance()"); | 320 ErrorThrower thrower(i_isolate, "WebAssembly.Instance()"); |
326 | 321 |
327 auto maybe_module = GetFirstArgumentAsModule(args, thrower); | 322 auto maybe_module = GetFirstArgumentAsModule(args, &thrower); |
328 | 323 |
329 if (!maybe_module.is_null()) { | 324 if (!maybe_module.is_null()) { |
330 MaybeLocal<Value> instance = InstantiateModuleImpl( | 325 MaybeLocal<Value> instance = InstantiateModuleImpl( |
331 i_isolate, maybe_module.ToHandleChecked(), args, &thrower); | 326 i_isolate, maybe_module.ToHandleChecked(), args, &thrower); |
332 | 327 |
333 if (instance.IsEmpty()) { | 328 if (instance.IsEmpty()) { |
334 DCHECK(thrower.error()); | 329 DCHECK(thrower.error()); |
335 return; | 330 return; |
336 } | 331 } |
337 args.GetReturnValue().Set(instance.ToLocalChecked()); | 332 args.GetReturnValue().Set(instance.ToLocalChecked()); |
338 } | 333 } |
339 } | 334 } |
340 | 335 |
341 void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) { | 336 void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) { |
342 v8::Isolate* isolate = args.GetIsolate(); | 337 v8::Isolate* isolate = args.GetIsolate(); |
343 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 338 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
339 ErrorThrower thrower(i_isolate, "WebAssembly.instantiate()"); | |
344 | 340 |
345 HandleScope scope(isolate); | 341 HandleScope scope(isolate); |
346 ErrorThrower thrower(i_isolate, "WebAssembly.instantiate()"); | |
347 | 342 |
348 Local<Context> context = isolate->GetCurrentContext(); | 343 Local<Context> context = isolate->GetCurrentContext(); |
349 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 344 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
350 | 345 |
351 v8::Local<v8::Promise::Resolver> resolver; | 346 v8::Local<v8::Promise::Resolver> resolver; |
352 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; | 347 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; |
353 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 348 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
354 return_value.Set(resolver->GetPromise()); | 349 return_value.Set(resolver->GetPromise()); |
355 | 350 |
356 if (args.Length() < 1) { | 351 if (args.Length() < 1) { |
357 thrower.TypeError( | 352 thrower.TypeError( |
358 "Argument 0 must be provided and must be either a buffer source or a " | 353 "Argument 0 must be provided and must be either a buffer source or a " |
359 "WebAssembly.Module object"); | 354 "WebAssembly.Module object"); |
360 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 355 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
361 return; | 356 return; |
362 } | 357 } |
363 | 358 |
364 i::Handle<i::Object> first_arg = Utils::OpenHandle(*args[0]); | 359 i::Handle<i::Object> first_arg = Utils::OpenHandle(*args[0]); |
365 if (!first_arg->IsJSObject()) { | 360 if (!first_arg->IsJSObject()) { |
366 thrower.TypeError( | 361 thrower.TypeError( |
367 "Argument 0 must be a buffer source or a WebAssembly.Module object"); | 362 "Argument 0 must be a buffer source or a WebAssembly.Module object"); |
368 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 363 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
369 return; | 364 return; |
370 } | 365 } |
371 bool want_pair = !BrandCheck( | 366 bool want_pair = !HasBrand( |
372 isolate, first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym())); | 367 isolate, first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym())); |
373 i::Handle<i::WasmModuleObject> module_obj; | 368 i::Handle<i::WasmModuleObject> module_obj; |
374 if (want_pair) { | 369 if (want_pair) { |
375 i::MaybeHandle<i::WasmModuleObject> maybe_module_obj = | 370 i::MaybeHandle<i::WasmModuleObject> maybe_module_obj = |
376 CreateModuleObject(isolate, args[0], &thrower); | 371 CreateModuleObject(isolate, args[0], &thrower); |
377 if (!maybe_module_obj.ToHandle(&module_obj)) { | 372 if (!maybe_module_obj.ToHandle(&module_obj)) { |
378 DCHECK(thrower.error()); | 373 DCHECK(thrower.error()); |
379 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 374 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
380 return; | 375 return; |
381 } | 376 } |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
536 return; | 531 return; |
537 } | 532 } |
538 i::Handle<i::JSObject> memory_obj = | 533 i::Handle<i::JSObject> memory_obj = |
539 i::WasmMemoryObject::New(i_isolate, buffer, maximum); | 534 i::WasmMemoryObject::New(i_isolate, buffer, maximum); |
540 args.GetReturnValue().Set(Utils::ToLocal(memory_obj)); | 535 args.GetReturnValue().Set(Utils::ToLocal(memory_obj)); |
541 } | 536 } |
542 | 537 |
543 void WebAssemblyTableGetLength( | 538 void WebAssemblyTableGetLength( |
544 const v8::FunctionCallbackInfo<v8::Value>& args) { | 539 const v8::FunctionCallbackInfo<v8::Value>& args) { |
545 v8::Isolate* isolate = args.GetIsolate(); | 540 v8::Isolate* isolate = args.GetIsolate(); |
541 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | |
542 "WebAssembly.Table.length()"); | |
546 Local<Context> context = isolate->GetCurrentContext(); | 543 Local<Context> context = isolate->GetCurrentContext(); |
547 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 544 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
548 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 545 if (!BrandCheck(&thrower, Utils::OpenHandle(*args.This()), |
549 i::Handle<i::Symbol>(i_context->wasm_table_sym()), | 546 i::Handle<i::Symbol>(i_context->wasm_table_sym()), |
550 "Receiver is not a WebAssembly.Table")) { | 547 "Receiver is not a WebAssembly.Table")) { |
551 return; | 548 return; |
552 } | 549 } |
553 auto receiver = | 550 auto receiver = |
554 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); | 551 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); |
555 args.GetReturnValue().Set( | 552 args.GetReturnValue().Set( |
556 v8::Number::New(isolate, receiver->current_length())); | 553 v8::Number::New(isolate, receiver->current_length())); |
557 } | 554 } |
558 | 555 |
559 void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { | 556 void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { |
560 v8::Isolate* isolate = args.GetIsolate(); | 557 v8::Isolate* isolate = args.GetIsolate(); |
558 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | |
559 "WebAssembly.Table.grow()"); | |
561 Local<Context> context = isolate->GetCurrentContext(); | 560 Local<Context> context = isolate->GetCurrentContext(); |
562 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 561 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
563 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 562 if (!BrandCheck(&thrower, Utils::OpenHandle(*args.This()), |
564 i::Handle<i::Symbol>(i_context->wasm_table_sym()), | 563 i::Handle<i::Symbol>(i_context->wasm_table_sym()), |
565 "Receiver is not a WebAssembly.Table")) { | 564 "Receiver is not a WebAssembly.Table")) { |
566 return; | 565 return; |
567 } | 566 } |
568 | 567 |
569 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 568 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
570 auto receiver = | 569 auto receiver = |
571 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); | 570 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); |
572 i::Handle<i::FixedArray> old_array(receiver->functions(), i_isolate); | 571 i::Handle<i::FixedArray> old_array(receiver->functions(), i_isolate); |
573 int old_size = old_array->length(); | 572 int old_size = old_array->length(); |
574 int64_t new_size64 = 0; | 573 int64_t new_size64 = 0; |
575 if (args.Length() > 0 && !args[0]->IntegerValue(context).To(&new_size64)) { | 574 if (args.Length() > 0 && !args[0]->IntegerValue(context).To(&new_size64)) { |
576 return; | 575 return; |
577 } | 576 } |
578 new_size64 += old_size; | 577 new_size64 += old_size; |
579 | 578 |
580 int64_t max_size64 = receiver->maximum_length(); | 579 int64_t max_size64 = receiver->maximum_length(); |
581 if (max_size64 < 0 || | 580 if (max_size64 < 0 || |
582 max_size64 > static_cast<int64_t>(i::FLAG_wasm_max_table_size)) { | 581 max_size64 > static_cast<int64_t>(i::FLAG_wasm_max_table_size)) { |
583 max_size64 = i::FLAG_wasm_max_table_size; | 582 max_size64 = i::FLAG_wasm_max_table_size; |
584 } | 583 } |
585 | 584 |
586 if (new_size64 < old_size || new_size64 > max_size64) { | 585 if (new_size64 < old_size || new_size64 > max_size64) { |
587 v8::Local<v8::Value> e = v8::Exception::RangeError( | 586 thrower.RangeError(new_size64 < old_size ? "trying to shrink table" |
588 v8_str(isolate, new_size64 < old_size ? "trying to shrink table" | 587 : "maximum table size exceeded"); |
589 : "maximum table size exceeded")); | |
590 isolate->ThrowException(e); | |
591 return; | 588 return; |
592 } | 589 } |
593 | 590 |
594 int new_size = static_cast<int>(new_size64); | 591 int new_size = static_cast<int>(new_size64); |
595 i::WasmTableObject::Grow(i_isolate, receiver, | 592 i::WasmTableObject::Grow(i_isolate, receiver, |
596 static_cast<uint32_t>(new_size - old_size)); | 593 static_cast<uint32_t>(new_size - old_size)); |
597 | 594 |
598 if (new_size != old_size) { | 595 if (new_size != old_size) { |
599 i::Handle<i::FixedArray> new_array = | 596 i::Handle<i::FixedArray> new_array = |
600 i_isolate->factory()->NewFixedArray(new_size); | 597 i_isolate->factory()->NewFixedArray(new_size); |
601 for (int i = 0; i < old_size; ++i) new_array->set(i, old_array->get(i)); | 598 for (int i = 0; i < old_size; ++i) new_array->set(i, old_array->get(i)); |
602 i::Object* null = i_isolate->heap()->null_value(); | 599 i::Object* null = i_isolate->heap()->null_value(); |
603 for (int i = old_size; i < new_size; ++i) new_array->set(i, null); | 600 for (int i = old_size; i < new_size; ++i) new_array->set(i, null); |
604 receiver->set_functions(*new_array); | 601 receiver->set_functions(*new_array); |
605 } | 602 } |
606 | 603 |
607 // TODO(gdeepti): use weak links for instances | 604 // TODO(gdeepti): use weak links for instances |
608 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 605 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
609 return_value.Set(old_size); | 606 return_value.Set(old_size); |
610 } | 607 } |
611 | 608 |
612 void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) { | 609 void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) { |
613 v8::Isolate* isolate = args.GetIsolate(); | 610 v8::Isolate* isolate = args.GetIsolate(); |
611 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
612 ErrorThrower thrower(i_isolate, "WebAssembly.Table.get()"); | |
614 Local<Context> context = isolate->GetCurrentContext(); | 613 Local<Context> context = isolate->GetCurrentContext(); |
615 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 614 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
616 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 615 if (!BrandCheck(&thrower, Utils::OpenHandle(*args.This()), |
617 i::Handle<i::Symbol>(i_context->wasm_table_sym()), | 616 i::Handle<i::Symbol>(i_context->wasm_table_sym()), |
618 "Receiver is not a WebAssembly.Table")) { | 617 "Receiver is not a WebAssembly.Table")) { |
619 return; | 618 return; |
620 } | 619 } |
621 | 620 |
622 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
623 auto receiver = | 621 auto receiver = |
624 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); | 622 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); |
625 i::Handle<i::FixedArray> array(receiver->functions(), i_isolate); | 623 i::Handle<i::FixedArray> array(receiver->functions(), i_isolate); |
626 int i = 0; | 624 int i = 0; |
627 if (args.Length() > 0 && !args[0]->Int32Value(context).To(&i)) return; | 625 if (args.Length() > 0 && !args[0]->Int32Value(context).To(&i)) return; |
628 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 626 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
629 if (i < 0 || i >= array->length()) { | 627 if (i < 0 || i >= array->length()) { |
630 v8::Local<v8::Value> e = | 628 thrower.RangeError("index out of bounds"); |
631 v8::Exception::RangeError(v8_str(isolate, "index out of bounds")); | |
632 isolate->ThrowException(e); | |
633 return; | 629 return; |
634 } | 630 } |
635 | 631 |
636 i::Handle<i::Object> value(array->get(i), i_isolate); | 632 i::Handle<i::Object> value(array->get(i), i_isolate); |
637 return_value.Set(Utils::ToLocal(value)); | 633 return_value.Set(Utils::ToLocal(value)); |
638 } | 634 } |
639 | 635 |
640 void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) { | 636 void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) { |
641 v8::Isolate* isolate = args.GetIsolate(); | 637 v8::Isolate* isolate = args.GetIsolate(); |
642 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 638 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
639 ErrorThrower thrower(i_isolate, "WebAssembly.Table.set()"); | |
643 Local<Context> context = isolate->GetCurrentContext(); | 640 Local<Context> context = isolate->GetCurrentContext(); |
644 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 641 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
645 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 642 if (!BrandCheck(&thrower, Utils::OpenHandle(*args.This()), |
646 i::Handle<i::Symbol>(i_context->wasm_table_sym()), | 643 i::Handle<i::Symbol>(i_context->wasm_table_sym()), |
647 "Receiver is not a WebAssembly.Table")) { | 644 "Receiver is not a WebAssembly.Table")) { |
648 return; | 645 return; |
649 } | 646 } |
650 if (args.Length() < 2) { | 647 if (args.Length() < 2) { |
651 v8::Local<v8::Value> e = v8::Exception::TypeError( | 648 thrower.TypeError("Argument 1 must be null or a function"); |
652 v8_str(isolate, "Argument 1 must be null or a function")); | |
653 isolate->ThrowException(e); | |
654 return; | 649 return; |
655 } | 650 } |
656 i::Handle<i::Object> value = Utils::OpenHandle(*args[1]); | 651 i::Handle<i::Object> value = Utils::OpenHandle(*args[1]); |
657 if (!value->IsNull(i_isolate) && | 652 if (!value->IsNull(i_isolate) && |
658 (!value->IsJSFunction() || | 653 (!value->IsJSFunction() || |
659 i::Handle<i::JSFunction>::cast(value)->code()->kind() != | 654 i::Handle<i::JSFunction>::cast(value)->code()->kind() != |
660 i::Code::JS_TO_WASM_FUNCTION)) { | 655 i::Code::JS_TO_WASM_FUNCTION)) { |
661 v8::Local<v8::Value> e = v8::Exception::TypeError( | 656 thrower.TypeError("Argument 1 must be null or a WebAssembly function"); |
662 v8_str(isolate, "Argument 1 must be null or a WebAssembly function")); | |
663 isolate->ThrowException(e); | |
664 return; | 657 return; |
665 } | 658 } |
666 | 659 |
667 auto receiver = | 660 auto receiver = |
668 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); | 661 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); |
669 i::Handle<i::FixedArray> array(receiver->functions(), i_isolate); | 662 i::Handle<i::FixedArray> array(receiver->functions(), i_isolate); |
670 int i; | 663 int i; |
671 if (!args[0]->Int32Value(context).To(&i)) return; | 664 if (!args[0]->Int32Value(context).To(&i)) return; |
672 if (i < 0 || i >= array->length()) { | 665 if (i < 0 || i >= array->length()) { |
673 v8::Local<v8::Value> e = | 666 thrower.RangeError("index out of bounds"); |
674 v8::Exception::RangeError(v8_str(isolate, "index out of bounds")); | |
675 isolate->ThrowException(e); | |
676 return; | 667 return; |
677 } | 668 } |
678 | 669 |
679 i::Handle<i::FixedArray> dispatch_tables(receiver->dispatch_tables(), | 670 i::Handle<i::FixedArray> dispatch_tables(receiver->dispatch_tables(), |
680 i_isolate); | 671 i_isolate); |
681 if (value->IsNull(i_isolate)) { | 672 if (value->IsNull(i_isolate)) { |
682 i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i, | 673 i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i, |
683 i::Handle<i::JSFunction>::null()); | 674 i::Handle<i::JSFunction>::null()); |
684 } else { | 675 } else { |
685 i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i, | 676 i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i, |
686 i::Handle<i::JSFunction>::cast(value)); | 677 i::Handle<i::JSFunction>::cast(value)); |
687 } | 678 } |
688 | 679 |
689 i::Handle<i::FixedArray>::cast(array)->set(i, *value); | 680 i::Handle<i::FixedArray>::cast(array)->set(i, *value); |
690 } | 681 } |
691 | 682 |
692 void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { | 683 void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { |
693 v8::Isolate* isolate = args.GetIsolate(); | 684 v8::Isolate* isolate = args.GetIsolate(); |
685 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
686 ErrorThrower thrower(i_isolate, "WebAssembly.Memory.grow()"); | |
694 Local<Context> context = isolate->GetCurrentContext(); | 687 Local<Context> context = isolate->GetCurrentContext(); |
695 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 688 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
696 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 689 if (!BrandCheck(&thrower, Utils::OpenHandle(*args.This()), |
697 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), | 690 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), |
698 "Receiver is not a WebAssembly.Memory")) { | 691 "Receiver is not a WebAssembly.Memory")) { |
699 return; | 692 return; |
700 } | 693 } |
701 int64_t delta_size = 0; | 694 int64_t delta_size = 0; |
702 if (args.Length() < 1 || !args[0]->IntegerValue(context).To(&delta_size)) { | 695 if (args.Length() < 1 || !args[0]->IntegerValue(context).To(&delta_size)) { |
703 v8::Local<v8::Value> e = v8::Exception::TypeError( | 696 thrower.TypeError("Argument 0 required, must be numeric value of pages"); |
704 v8_str(isolate, "Argument 0 required, must be numeric value of pages")); | |
705 isolate->ThrowException(e); | |
706 return; | 697 return; |
707 } | 698 } |
708 i::Handle<i::WasmMemoryObject> receiver = | 699 i::Handle<i::WasmMemoryObject> receiver = |
709 i::Handle<i::WasmMemoryObject>::cast(Utils::OpenHandle(*args.This())); | 700 i::Handle<i::WasmMemoryObject>::cast(Utils::OpenHandle(*args.This())); |
710 int64_t max_size64 = receiver->maximum_pages(); | 701 int64_t max_size64 = receiver->maximum_pages(); |
711 if (max_size64 < 0 || | 702 if (max_size64 < 0 || |
712 max_size64 > static_cast<int64_t>(i::FLAG_wasm_max_mem_pages)) { | 703 max_size64 > static_cast<int64_t>(i::FLAG_wasm_max_mem_pages)) { |
713 max_size64 = i::FLAG_wasm_max_mem_pages; | 704 max_size64 = i::FLAG_wasm_max_mem_pages; |
714 } | 705 } |
715 i::Handle<i::JSArrayBuffer> old_buffer(receiver->buffer()); | 706 i::Handle<i::JSArrayBuffer> old_buffer(receiver->buffer()); |
716 uint32_t old_size = | 707 uint32_t old_size = |
717 old_buffer->byte_length()->Number() / i::wasm::kSpecMaxWasmMemoryPages; | 708 old_buffer->byte_length()->Number() / i::wasm::kSpecMaxWasmMemoryPages; |
718 int64_t new_size64 = old_size + delta_size; | 709 int64_t new_size64 = old_size + delta_size; |
719 if (delta_size < 0 || max_size64 < new_size64 || new_size64 < old_size) { | 710 if (delta_size < 0 || max_size64 < new_size64 || new_size64 < old_size) { |
720 v8::Local<v8::Value> e = v8::Exception::RangeError(v8_str( | 711 thrower.RangeError(new_size64 < old_size ? "trying to shrink memory" |
721 isolate, new_size64 < old_size ? "trying to shrink memory" | 712 : "maximum memory size exceeded"); |
722 : "maximum memory size exceeded")); | |
723 isolate->ThrowException(e); | |
724 return; | 713 return; |
725 } | 714 } |
726 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
727 int32_t ret = i::wasm::GrowWebAssemblyMemory( | 715 int32_t ret = i::wasm::GrowWebAssemblyMemory( |
728 i_isolate, receiver, static_cast<uint32_t>(delta_size)); | 716 i_isolate, receiver, static_cast<uint32_t>(delta_size)); |
729 if (ret == -1) { | 717 if (ret == -1) { |
730 v8::Local<v8::Value> e = v8::Exception::RangeError( | 718 thrower.RangeError("Unable to grow instance memory."); |
731 v8_str(isolate, "Unable to grow instance memory.")); | |
732 isolate->ThrowException(e); | |
733 return; | 719 return; |
734 } | 720 } |
735 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 721 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
736 return_value.Set(ret); | 722 return_value.Set(ret); |
737 } | 723 } |
738 | 724 |
739 void WebAssemblyMemoryGetBuffer( | 725 void WebAssemblyMemoryGetBuffer( |
740 const v8::FunctionCallbackInfo<v8::Value>& args) { | 726 const v8::FunctionCallbackInfo<v8::Value>& args) { |
741 v8::Isolate* isolate = args.GetIsolate(); | 727 v8::Isolate* isolate = args.GetIsolate(); |
728 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
729 ErrorThrower thrower(i_isolate, "WebAssembly.Memory.buffer"); | |
742 Local<Context> context = isolate->GetCurrentContext(); | 730 Local<Context> context = isolate->GetCurrentContext(); |
743 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 731 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
744 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 732 if (!BrandCheck(&thrower, Utils::OpenHandle(*args.This()), |
745 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), | 733 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), |
746 "Receiver is not a WebAssembly.Memory")) { | 734 "Receiver is not a WebAssembly.Memory")) { |
747 return; | 735 return; |
748 } | 736 } |
749 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
750 i::Handle<i::WasmMemoryObject> receiver = | 737 i::Handle<i::WasmMemoryObject> receiver = |
751 i::Handle<i::WasmMemoryObject>::cast(Utils::OpenHandle(*args.This())); | 738 i::Handle<i::WasmMemoryObject>::cast(Utils::OpenHandle(*args.This())); |
752 i::Handle<i::Object> buffer(receiver->buffer(), i_isolate); | 739 i::Handle<i::Object> buffer(receiver->buffer(), i_isolate); |
753 DCHECK(buffer->IsJSArrayBuffer()); | 740 DCHECK(buffer->IsJSArrayBuffer()); |
754 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 741 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
755 return_value.Set(Utils::ToLocal(buffer)); | 742 return_value.Set(Utils::ToLocal(buffer)); |
756 } | 743 } |
757 } // namespace | 744 } // namespace |
758 | 745 |
759 // TODO(titzer): we use the API to create the function template because the | 746 // TODO(titzer): we use the API to create the function template because the |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
944 Handle<JSFunction> link_error( | 931 Handle<JSFunction> link_error( |
945 isolate->native_context()->wasm_link_error_function()); | 932 isolate->native_context()->wasm_link_error_function()); |
946 JSObject::AddProperty(webassembly, isolate->factory()->LinkError_string(), | 933 JSObject::AddProperty(webassembly, isolate->factory()->LinkError_string(), |
947 link_error, attributes); | 934 link_error, attributes); |
948 Handle<JSFunction> runtime_error( | 935 Handle<JSFunction> runtime_error( |
949 isolate->native_context()->wasm_runtime_error_function()); | 936 isolate->native_context()->wasm_runtime_error_function()); |
950 JSObject::AddProperty(webassembly, isolate->factory()->RuntimeError_string(), | 937 JSObject::AddProperty(webassembly, isolate->factory()->RuntimeError_string(), |
951 runtime_error, attributes); | 938 runtime_error, attributes); |
952 } | 939 } |
953 | 940 |
954 static bool HasBrand(i::Handle<i::Object> value, i::Handle<i::Symbol> symbol) { | 941 static bool HasBrand(i::Handle<i::Object> value, i::Handle<i::Symbol> symbol) { |
rossberg
2017/01/25 09:47:34
Why is there another version of HasBrand here?
titzer
2017/01/25 09:54:33
Removed.
| |
955 if (value->IsJSObject()) { | 942 if (value->IsJSObject()) { |
956 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); | 943 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); |
957 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, symbol); | 944 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, symbol); |
958 if (has_brand.IsNothing()) return false; | 945 if (has_brand.IsNothing()) return false; |
959 if (has_brand.ToChecked()) return true; | 946 if (has_brand.ToChecked()) return true; |
960 } | 947 } |
961 return false; | 948 return false; |
962 } | 949 } |
963 | 950 |
964 bool WasmJs::IsWasmMemoryObject(Isolate* isolate, Handle<Object> value) { | 951 bool WasmJs::IsWasmMemoryObject(Isolate* isolate, Handle<Object> value) { |
965 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); | 952 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); |
966 return HasBrand(value, symbol); | 953 return HasBrand(value, symbol); |
967 } | 954 } |
968 | 955 |
969 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { | 956 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { |
970 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); | 957 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); |
971 return HasBrand(value, symbol); | 958 return HasBrand(value, symbol); |
972 } | 959 } |
973 } // namespace internal | 960 } // namespace internal |
974 } // namespace v8 | 961 } // namespace v8 |
OLD | NEW |