| 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 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 DCHECK(thrower.error()); | 347 DCHECK(thrower.error()); |
| 348 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 348 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
| 349 } else { | 349 } else { |
| 350 DCHECK(!thrower.error()); | 350 DCHECK(!thrower.error()); |
| 351 resolver->Resolve(context, instance.ToLocalChecked()); | 351 resolver->Resolve(context, instance.ToLocalChecked()); |
| 352 } | 352 } |
| 353 } | 353 } |
| 354 | 354 |
| 355 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, | 355 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, |
| 356 Local<Context> context, Local<v8::Object> object, | 356 Local<Context> context, Local<v8::Object> object, |
| 357 Local<String> property, int* result, int lower_bound, | 357 Local<String> property, int* result, |
| 358 int upper_bound) { | 358 int64_t lower_bound, uint64_t upper_bound) { |
| 359 v8::MaybeLocal<v8::Value> maybe = object->Get(context, property); | 359 v8::MaybeLocal<v8::Value> maybe = object->Get(context, property); |
| 360 v8::Local<v8::Value> value; | 360 v8::Local<v8::Value> value; |
| 361 if (maybe.ToLocal(&value)) { | 361 if (maybe.ToLocal(&value)) { |
| 362 int64_t number; | 362 int64_t number; |
| 363 if (!value->IntegerValue(context).To(&number)) return false; | 363 if (!value->IntegerValue(context).To(&number)) return false; |
| 364 if (number < static_cast<int64_t>(lower_bound)) { | 364 if (number < lower_bound) { |
| 365 thrower->RangeError("Property value %" PRId64 | 365 thrower->RangeError("Property value %" PRId64 |
| 366 " is below the lower bound %d", | 366 " is below the lower bound %" PRIx64, |
| 367 number, lower_bound); | 367 number, lower_bound); |
| 368 return false; | 368 return false; |
| 369 } | 369 } |
| 370 if (number > static_cast<int64_t>(upper_bound)) { | 370 if (number > static_cast<int64_t>(upper_bound)) { |
| 371 thrower->RangeError("Property value %" PRId64 | 371 thrower->RangeError("Property value %" PRId64 |
| 372 " is above the upper bound %d", | 372 " is above the upper bound %" PRIu64, |
| 373 number, upper_bound); | 373 number, upper_bound); |
| 374 return false; | 374 return false; |
| 375 } | 375 } |
| 376 *result = static_cast<int>(number); | 376 *result = static_cast<int>(number); |
| 377 return true; | 377 return true; |
| 378 } | 378 } |
| 379 return false; | 379 return false; |
| 380 } | 380 } |
| 381 | 381 |
| 382 const int max_table_size = 1 << 26; | |
| 383 | |
| 384 void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) { | 382 void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 385 v8::Isolate* isolate = args.GetIsolate(); | 383 v8::Isolate* isolate = args.GetIsolate(); |
| 386 HandleScope scope(isolate); | 384 HandleScope scope(isolate); |
| 387 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | 385 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), |
| 388 "WebAssembly.Module()"); | 386 "WebAssembly.Module()"); |
| 389 if (args.Length() < 1 || !args[0]->IsObject()) { | 387 if (args.Length() < 1 || !args[0]->IsObject()) { |
| 390 thrower.TypeError("Argument 0 must be a table descriptor"); | 388 thrower.TypeError("Argument 0 must be a table descriptor"); |
| 391 return; | 389 return; |
| 392 } | 390 } |
| 393 Local<Context> context = isolate->GetCurrentContext(); | 391 Local<Context> context = isolate->GetCurrentContext(); |
| 394 Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked(); | 392 Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked(); |
| 395 // The descriptor's 'element'. | 393 // The descriptor's 'element'. |
| 396 { | 394 { |
| 397 v8::MaybeLocal<v8::Value> maybe = | 395 v8::MaybeLocal<v8::Value> maybe = |
| 398 descriptor->Get(context, v8_str(isolate, "element")); | 396 descriptor->Get(context, v8_str(isolate, "element")); |
| 399 v8::Local<v8::Value> value; | 397 v8::Local<v8::Value> value; |
| 400 if (!maybe.ToLocal(&value)) return; | 398 if (!maybe.ToLocal(&value)) return; |
| 401 v8::Local<v8::String> string; | 399 v8::Local<v8::String> string; |
| 402 if (!value->ToString(context).ToLocal(&string)) return; | 400 if (!value->ToString(context).ToLocal(&string)) return; |
| 403 bool equal; | 401 bool equal; |
| 404 if (!string->Equals(context, v8_str(isolate, "anyfunc")).To(&equal)) return; | 402 if (!string->Equals(context, v8_str(isolate, "anyfunc")).To(&equal)) return; |
| 405 if (!equal) { | 403 if (!equal) { |
| 406 thrower.TypeError("Descriptor property 'element' must be 'anyfunc'"); | 404 thrower.TypeError("Descriptor property 'element' must be 'anyfunc'"); |
| 407 return; | 405 return; |
| 408 } | 406 } |
| 409 } | 407 } |
| 410 // The descriptor's 'initial'. | 408 // The descriptor's 'initial'. |
| 411 int initial; | 409 int initial = 0; |
| 412 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, | 410 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, |
| 413 v8_str(isolate, "initial"), &initial, 0, | 411 v8_str(isolate, "initial"), &initial, 0, |
| 414 max_table_size)) { | 412 i::wasm::kV8MaxWasmTableSize)) { |
| 415 return; | 413 return; |
| 416 } | 414 } |
| 417 // The descriptor's 'maximum'. | 415 // The descriptor's 'maximum'. |
| 418 int maximum = 0; | 416 int maximum = -1; |
| 419 Local<String> maximum_key = v8_str(isolate, "maximum"); | 417 Local<String> maximum_key = v8_str(isolate, "maximum"); |
| 420 Maybe<bool> has_maximum = descriptor->Has(context, maximum_key); | 418 Maybe<bool> has_maximum = descriptor->Has(context, maximum_key); |
| 421 | 419 |
| 422 if (has_maximum.IsNothing()) { | 420 if (!has_maximum.IsNothing() && has_maximum.FromJust()) { |
| 423 // There has been an exception, just return. | |
| 424 return; | |
| 425 } | |
| 426 if (has_maximum.FromJust()) { | |
| 427 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key, | 421 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key, |
| 428 &maximum, initial, max_table_size)) { | 422 &maximum, initial, |
| 423 i::wasm::kSpecMaxWasmTableSize)) { |
| 429 return; | 424 return; |
| 430 } | 425 } |
| 431 } else { | |
| 432 maximum = static_cast<int>(i::wasm::kV8MaxWasmTableSize); | |
| 433 } | 426 } |
| 434 | 427 |
| 435 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 428 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 436 i::Handle<i::FixedArray> fixed_array; | 429 i::Handle<i::FixedArray> fixed_array; |
| 437 i::Handle<i::JSObject> table_obj = | 430 i::Handle<i::JSObject> table_obj = |
| 438 i::WasmTableObject::New(i_isolate, initial, maximum, &fixed_array); | 431 i::WasmTableObject::New(i_isolate, initial, maximum, &fixed_array); |
| 439 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 432 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
| 440 return_value.Set(Utils::ToLocal(table_obj)); | 433 return_value.Set(Utils::ToLocal(table_obj)); |
| 441 } | 434 } |
| 442 | 435 |
| 443 void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) { | 436 void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 444 v8::Isolate* isolate = args.GetIsolate(); | 437 v8::Isolate* isolate = args.GetIsolate(); |
| 445 HandleScope scope(isolate); | 438 HandleScope scope(isolate); |
| 446 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | 439 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), |
| 447 "WebAssembly.Memory()"); | 440 "WebAssembly.Memory()"); |
| 448 if (args.Length() < 1 || !args[0]->IsObject()) { | 441 if (args.Length() < 1 || !args[0]->IsObject()) { |
| 449 thrower.TypeError("Argument 0 must be a memory descriptor"); | 442 thrower.TypeError("Argument 0 must be a memory descriptor"); |
| 450 return; | 443 return; |
| 451 } | 444 } |
| 452 Local<Context> context = isolate->GetCurrentContext(); | 445 Local<Context> context = isolate->GetCurrentContext(); |
| 453 Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked(); | 446 Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked(); |
| 454 // The descriptor's 'initial'. | 447 // The descriptor's 'initial'. |
| 455 int initial; | 448 int initial = 0; |
| 456 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, | 449 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, |
| 457 v8_str(isolate, "initial"), &initial, 0, 65536)) { | 450 v8_str(isolate, "initial"), &initial, 0, |
| 451 i::wasm::kV8MaxWasmMemoryPages)) { |
| 458 return; | 452 return; |
| 459 } | 453 } |
| 460 // The descriptor's 'maximum'. | 454 // The descriptor's 'maximum'. |
| 461 int maximum = 0; | 455 int maximum = -1; |
| 462 Local<String> maximum_key = v8_str(isolate, "maximum"); | 456 Local<String> maximum_key = v8_str(isolate, "maximum"); |
| 463 Maybe<bool> has_maximum = descriptor->Has(context, maximum_key); | 457 Maybe<bool> has_maximum = descriptor->Has(context, maximum_key); |
| 464 | 458 |
| 465 if (has_maximum.IsNothing()) { | 459 if (!has_maximum.IsNothing() && has_maximum.FromJust()) { |
| 466 // There has been an exception, just return. | |
| 467 return; | |
| 468 } | |
| 469 if (has_maximum.FromJust()) { | |
| 470 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key, | 460 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key, |
| 471 &maximum, initial, 65536)) { | 461 &maximum, initial, |
| 462 i::wasm::kSpecMaxWasmMemoryPages)) { |
| 472 return; | 463 return; |
| 473 } | 464 } |
| 474 } | 465 } |
| 475 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 466 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 476 size_t size = static_cast<size_t>(i::wasm::WasmModule::kPageSize) * | 467 size_t size = static_cast<size_t>(i::wasm::WasmModule::kPageSize) * |
| 477 static_cast<size_t>(initial); | 468 static_cast<size_t>(initial); |
| 478 i::Handle<i::JSArrayBuffer> buffer = | 469 i::Handle<i::JSArrayBuffer> buffer = |
| 479 i::wasm::NewArrayBuffer(i_isolate, size, i::FLAG_wasm_guard_pages); | 470 i::wasm::NewArrayBuffer(i_isolate, size, i::FLAG_wasm_guard_pages); |
| 480 if (buffer.is_null()) { | 471 if (buffer.is_null()) { |
| 481 thrower.RangeError("could not allocate memory"); | 472 thrower.RangeError("could not allocate memory"); |
| 482 return; | 473 return; |
| 483 } | 474 } |
| 484 i::Handle<i::JSObject> memory_obj = i::WasmMemoryObject::New( | 475 i::Handle<i::JSObject> memory_obj = |
| 485 i_isolate, buffer, has_maximum.FromJust() ? maximum : -1); | 476 i::WasmMemoryObject::New(i_isolate, buffer, maximum); |
| 486 args.GetReturnValue().Set(Utils::ToLocal(memory_obj)); | 477 args.GetReturnValue().Set(Utils::ToLocal(memory_obj)); |
| 487 } | 478 } |
| 488 | 479 |
| 489 void WebAssemblyTableGetLength( | 480 void WebAssemblyTableGetLength( |
| 490 const v8::FunctionCallbackInfo<v8::Value>& args) { | 481 const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 491 v8::Isolate* isolate = args.GetIsolate(); | 482 v8::Isolate* isolate = args.GetIsolate(); |
| 492 Local<Context> context = isolate->GetCurrentContext(); | 483 Local<Context> context = isolate->GetCurrentContext(); |
| 493 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 484 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
| 494 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 485 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), |
| 495 i::Handle<i::Symbol>(i_context->wasm_table_sym()), | 486 i::Handle<i::Symbol>(i_context->wasm_table_sym()), |
| (...skipping 20 matching lines...) Expand all Loading... |
| 516 auto receiver = | 507 auto receiver = |
| 517 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); | 508 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); |
| 518 i::Handle<i::FixedArray> old_array(receiver->functions(), i_isolate); | 509 i::Handle<i::FixedArray> old_array(receiver->functions(), i_isolate); |
| 519 int old_size = old_array->length(); | 510 int old_size = old_array->length(); |
| 520 int64_t new_size64 = 0; | 511 int64_t new_size64 = 0; |
| 521 if (args.Length() > 0 && !args[0]->IntegerValue(context).To(&new_size64)) { | 512 if (args.Length() > 0 && !args[0]->IntegerValue(context).To(&new_size64)) { |
| 522 return; | 513 return; |
| 523 } | 514 } |
| 524 new_size64 += old_size; | 515 new_size64 += old_size; |
| 525 | 516 |
| 526 if (new_size64 < old_size || new_size64 > receiver->maximum_length()) { | 517 int64_t max_size64 = receiver->maximum_length(); |
| 518 if (max_size64 < 0 || |
| 519 max_size64 > static_cast<int64_t>(i::wasm::kV8MaxWasmTableSize)) { |
| 520 max_size64 = i::wasm::kV8MaxWasmTableSize; |
| 521 } |
| 522 |
| 523 if (new_size64 < old_size || new_size64 > max_size64) { |
| 527 v8::Local<v8::Value> e = v8::Exception::RangeError( | 524 v8::Local<v8::Value> e = v8::Exception::RangeError( |
| 528 v8_str(isolate, new_size64 < old_size ? "trying to shrink table" | 525 v8_str(isolate, new_size64 < old_size ? "trying to shrink table" |
| 529 : "maximum table size exceeded")); | 526 : "maximum table size exceeded")); |
| 530 isolate->ThrowException(e); | 527 isolate->ThrowException(e); |
| 531 return; | 528 return; |
| 532 } | 529 } |
| 533 | 530 |
| 534 int new_size = static_cast<int>(new_size64); | 531 int new_size = static_cast<int>(new_size64); |
| 535 i::WasmTableObject::Grow(i_isolate, receiver, | 532 i::WasmTableObject::Grow(i_isolate, receiver, |
| 536 static_cast<uint32_t>(new_size - old_size)); | 533 static_cast<uint32_t>(new_size - old_size)); |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 887 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); | 884 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); |
| 888 return HasBrand(value, symbol); | 885 return HasBrand(value, symbol); |
| 889 } | 886 } |
| 890 | 887 |
| 891 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { | 888 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { |
| 892 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); | 889 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); |
| 893 return HasBrand(value, symbol); | 890 return HasBrand(value, symbol); |
| 894 } | 891 } |
| 895 } // namespace internal | 892 } // namespace internal |
| 896 } // namespace v8 | 893 } // namespace v8 |
| OLD | NEW |