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 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/isolate-inl.h" | 8 #include "src/isolate-inl.h" |
9 #include "src/lookup.h" | 9 #include "src/lookup.h" |
10 #include "src/messages.h" | 10 #include "src/messages.h" |
11 | 11 |
12 namespace v8 { | 12 namespace v8 { |
13 namespace internal { | 13 namespace internal { |
14 | 14 |
15 | 15 |
16 namespace { | 16 namespace { |
17 | 17 |
18 class InvokeScope { | 18 class InvokeScope { |
19 public: | 19 public: |
20 explicit InvokeScope(Isolate* isolate) | 20 explicit InvokeScope(Isolate* isolate) : save_context_(isolate) {} |
21 : isolate_(isolate), save_context_(isolate) {} | |
22 ~InvokeScope() { | 21 ~InvokeScope() { |
23 bool has_exception = isolate_->has_pending_exception(); | 22 Isolate* isolate = save_context_.isolate(); |
| 23 bool has_exception = isolate->has_pending_exception(); |
24 if (has_exception) { | 24 if (has_exception) { |
25 isolate_->ReportPendingMessages(); | 25 isolate->ReportPendingMessages(); |
26 } else { | 26 } else { |
27 isolate_->clear_pending_message(); | 27 isolate->clear_pending_message(); |
28 } | 28 } |
29 } | 29 } |
30 | 30 |
31 private: | 31 private: |
32 Isolate* isolate_; | |
33 SaveContext save_context_; | 32 SaveContext save_context_; |
34 }; | 33 }; |
35 | 34 |
36 MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, | 35 enum class CacheCheck { kCheck, kSkip }; |
37 Handle<ObjectTemplateInfo> data, | |
38 Handle<JSReceiver> new_target, | |
39 bool is_hidden_prototype); | |
40 | 36 |
41 MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate, | 37 MaybeHandle<JSObject> InstantiateObject( |
42 Handle<FunctionTemplateInfo> data, | 38 Isolate* isolate, Handle<ObjectTemplateInfo> data, |
43 Handle<Name> name = Handle<Name>()); | 39 Handle<JSReceiver> new_target, CacheCheck cache_check = CacheCheck::kCheck, |
| 40 bool is_hidden_prototype = false); |
44 | 41 |
| 42 MaybeHandle<JSFunction> InstantiateFunction( |
| 43 Isolate* isolate, Handle<FunctionTemplateInfo> data, |
| 44 CacheCheck cache_check = CacheCheck::kCheck, |
| 45 Handle<Name> name = Handle<Name>()); |
45 | 46 |
46 MaybeHandle<Object> Instantiate(Isolate* isolate, Handle<Object> data, | 47 MaybeHandle<Object> Instantiate(Isolate* isolate, Handle<Object> data, |
47 Handle<Name> name = Handle<Name>()) { | 48 Handle<Name> name = Handle<Name>()) { |
48 if (data->IsFunctionTemplateInfo()) { | 49 if (data->IsFunctionTemplateInfo()) { |
49 return InstantiateFunction(isolate, | 50 return InstantiateFunction(isolate, |
50 Handle<FunctionTemplateInfo>::cast(data), name); | 51 Handle<FunctionTemplateInfo>::cast(data), |
| 52 CacheCheck::kCheck, name); |
51 } else if (data->IsObjectTemplateInfo()) { | 53 } else if (data->IsObjectTemplateInfo()) { |
52 return InstantiateObject(isolate, Handle<ObjectTemplateInfo>::cast(data), | 54 return InstantiateObject(isolate, Handle<ObjectTemplateInfo>::cast(data), |
53 Handle<JSReceiver>(), false); | 55 Handle<JSReceiver>()); |
54 } else { | 56 } else { |
55 return data; | 57 return data; |
56 } | 58 } |
57 } | 59 } |
58 | 60 |
59 MaybeHandle<Object> DefineAccessorProperty( | 61 MaybeHandle<Object> DefineAccessorProperty( |
60 Isolate* isolate, Handle<JSObject> object, Handle<Name> name, | 62 Isolate* isolate, Handle<JSObject> object, Handle<Name> name, |
61 Handle<Object> getter, Handle<Object> setter, PropertyAttributes attributes, | 63 Handle<Object> getter, Handle<Object> setter, PropertyAttributes attributes, |
62 bool force_instantiate) { | 64 bool force_instantiate) { |
63 DCHECK(!getter->IsFunctionTemplateInfo() || | 65 DCHECK(!getter->IsFunctionTemplateInfo() || |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 DisallowHeapAllocation no_gc; | 333 DisallowHeapAllocation no_gc; |
332 | 334 |
333 if (!new_target->IsJSFunction()) return false; | 335 if (!new_target->IsJSFunction()) return false; |
334 JSFunction* fun = JSFunction::cast(new_target); | 336 JSFunction* fun = JSFunction::cast(new_target); |
335 if (fun->shared()->function_data() != info->constructor()) return false; | 337 if (fun->shared()->function_data() != info->constructor()) return false; |
336 if (info->immutable_proto()) return false; | 338 if (info->immutable_proto()) return false; |
337 return fun->context()->native_context() != | 339 return fun->context()->native_context() != |
338 isolate->context()->native_context(); | 340 isolate->context()->native_context(); |
339 } | 341 } |
340 | 342 |
| 343 MaybeHandle<JSObject> InstantiateObjectWithInvokeScope( |
| 344 Isolate* isolate, Handle<ObjectTemplateInfo> info, |
| 345 Handle<JSReceiver> new_target) { |
| 346 InvokeScope invoke_scope(isolate); |
| 347 return InstantiateObject(isolate, info, new_target, CacheCheck::kSkip); |
| 348 } |
| 349 |
341 MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, | 350 MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, |
342 Handle<ObjectTemplateInfo> info, | 351 Handle<ObjectTemplateInfo> info, |
343 Handle<JSReceiver> new_target, | 352 Handle<JSReceiver> new_target, |
| 353 CacheCheck cache_check, |
344 bool is_hidden_prototype) { | 354 bool is_hidden_prototype) { |
345 Handle<JSFunction> constructor; | 355 Handle<JSFunction> constructor; |
346 int serial_number = Smi::cast(info->serial_number())->value(); | 356 int serial_number = Smi::cast(info->serial_number())->value(); |
347 if (!new_target.is_null()) { | 357 if (!new_target.is_null()) { |
348 if (IsSimpleInstantiation(isolate, *info, *new_target)) { | 358 if (IsSimpleInstantiation(isolate, *info, *new_target)) { |
349 constructor = Handle<JSFunction>::cast(new_target); | 359 constructor = Handle<JSFunction>::cast(new_target); |
350 } else { | 360 } else { |
351 // Disable caching for subclass instantiation. | 361 // Disable caching for subclass instantiation. |
352 serial_number = 0; | 362 serial_number = 0; |
353 } | 363 } |
354 } | 364 } |
355 // Fast path. | 365 // Fast path. |
356 Handle<JSObject> result; | 366 Handle<JSObject> result; |
357 if (serial_number) { | 367 if (serial_number && cache_check == CacheCheck::kCheck) { |
358 if (ProbeInstantiationsCache(isolate, serial_number).ToHandle(&result)) { | 368 if (ProbeInstantiationsCache(isolate, serial_number).ToHandle(&result)) { |
359 return isolate->factory()->CopyJSObject(result); | 369 return isolate->factory()->CopyJSObject(result); |
360 } | 370 } |
361 } | 371 } |
362 | 372 |
363 if (constructor.is_null()) { | 373 if (constructor.is_null()) { |
364 Object* maybe_constructor_info = info->constructor(); | 374 Object* maybe_constructor_info = info->constructor(); |
365 if (maybe_constructor_info->IsUndefined(isolate)) { | 375 if (maybe_constructor_info->IsUndefined(isolate)) { |
366 constructor = isolate->object_function(); | 376 constructor = isolate->object_function(); |
367 } else { | 377 } else { |
(...skipping 13 matching lines...) Expand all Loading... |
381 | 391 |
382 Handle<JSObject> object; | 392 Handle<JSObject> object; |
383 ASSIGN_RETURN_ON_EXCEPTION(isolate, object, | 393 ASSIGN_RETURN_ON_EXCEPTION(isolate, object, |
384 JSObject::New(constructor, new_target), JSObject); | 394 JSObject::New(constructor, new_target), JSObject); |
385 ASSIGN_RETURN_ON_EXCEPTION( | 395 ASSIGN_RETURN_ON_EXCEPTION( |
386 isolate, result, | 396 isolate, result, |
387 ConfigureInstance(isolate, object, info, is_hidden_prototype), JSObject); | 397 ConfigureInstance(isolate, object, info, is_hidden_prototype), JSObject); |
388 if (info->immutable_proto()) { | 398 if (info->immutable_proto()) { |
389 JSObject::SetImmutableProto(object); | 399 JSObject::SetImmutableProto(object); |
390 } | 400 } |
391 // TODO(dcarney): is this necessary? | |
392 JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject"); | 401 JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject"); |
393 | 402 |
394 if (serial_number) { | 403 if (serial_number) { |
395 CacheTemplateInstantiation(isolate, serial_number, result); | 404 CacheTemplateInstantiation(isolate, serial_number, result); |
396 result = isolate->factory()->CopyJSObject(result); | 405 result = isolate->factory()->CopyJSObject(result); |
397 } | 406 } |
398 return result; | 407 return result; |
399 } | 408 } |
400 | 409 |
| 410 MaybeHandle<JSFunction> InstantiateFunctionWithInvokeScope( |
| 411 Isolate* isolate, Handle<FunctionTemplateInfo> info) { |
| 412 InvokeScope invoke_scope(isolate); |
| 413 return InstantiateFunction(isolate, info, CacheCheck::kSkip); |
| 414 } |
401 | 415 |
402 MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate, | 416 MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate, |
403 Handle<FunctionTemplateInfo> data, | 417 Handle<FunctionTemplateInfo> data, |
| 418 CacheCheck cache_check, |
404 Handle<Name> name) { | 419 Handle<Name> name) { |
405 int serial_number = Smi::cast(data->serial_number())->value(); | 420 int serial_number = Smi::cast(data->serial_number())->value(); |
406 if (serial_number) { | 421 if (serial_number && cache_check == CacheCheck::kCheck) { |
407 Handle<JSObject> result; | 422 Handle<JSObject> result; |
408 if (ProbeInstantiationsCache(isolate, serial_number).ToHandle(&result)) { | 423 if (ProbeInstantiationsCache(isolate, serial_number).ToHandle(&result)) { |
409 return Handle<JSFunction>::cast(result); | 424 return Handle<JSFunction>::cast(result); |
410 } | 425 } |
411 } | 426 } |
412 Handle<JSObject> prototype; | 427 Handle<JSObject> prototype; |
413 if (!data->remove_prototype()) { | 428 if (!data->remove_prototype()) { |
414 Object* prototype_templ = data->prototype_template(); | 429 Object* prototype_templ = data->prototype_template(); |
415 if (prototype_templ->IsUndefined(isolate)) { | 430 if (prototype_templ->IsUndefined(isolate)) { |
416 prototype = isolate->factory()->NewJSObject(isolate->object_function()); | 431 prototype = isolate->factory()->NewJSObject(isolate->object_function()); |
417 } else { | 432 } else { |
418 ASSIGN_RETURN_ON_EXCEPTION( | 433 ASSIGN_RETURN_ON_EXCEPTION( |
419 isolate, prototype, | 434 isolate, prototype, |
420 InstantiateObject( | 435 InstantiateObject( |
421 isolate, | 436 isolate, |
422 handle(ObjectTemplateInfo::cast(prototype_templ), isolate), | 437 handle(ObjectTemplateInfo::cast(prototype_templ), isolate), |
423 Handle<JSReceiver>(), data->hidden_prototype()), | 438 Handle<JSReceiver>(), CacheCheck::kCheck, |
| 439 data->hidden_prototype()), |
424 JSFunction); | 440 JSFunction); |
425 } | 441 } |
426 Object* parent = data->parent_template(); | 442 Object* parent = data->parent_template(); |
427 if (!parent->IsUndefined(isolate)) { | 443 if (!parent->IsUndefined(isolate)) { |
428 // Enter a new scope. Recursion could otherwise create a lot of handles. | 444 // Enter a new scope. Recursion could otherwise create a lot of handles. |
429 HandleScope scope(isolate); | 445 HandleScope scope(isolate); |
430 Handle<JSFunction> parent_instance; | 446 Handle<JSFunction> parent_instance; |
431 ASSIGN_RETURN_ON_EXCEPTION( | 447 ASSIGN_RETURN_ON_EXCEPTION( |
432 isolate, parent_instance, | 448 isolate, parent_instance, |
433 InstantiateFunction( | 449 InstantiateFunction( |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 data[i].is_null() | 498 data[i].is_null() |
483 ? Handle<Object>::cast(isolate->factory()->undefined_value()) | 499 ? Handle<Object>::cast(isolate->factory()->undefined_value()) |
484 : data[i]; | 500 : data[i]; |
485 list = TemplateList::Add(isolate, list, value); | 501 list = TemplateList::Add(isolate, list, value); |
486 } | 502 } |
487 templ->set_property_list(*list); | 503 templ->set_property_list(*list); |
488 } | 504 } |
489 | 505 |
490 } // namespace | 506 } // namespace |
491 | 507 |
492 | |
493 MaybeHandle<JSFunction> ApiNatives::InstantiateFunction( | 508 MaybeHandle<JSFunction> ApiNatives::InstantiateFunction( |
494 Handle<FunctionTemplateInfo> data) { | 509 Handle<FunctionTemplateInfo> info) { |
495 Isolate* isolate = data->GetIsolate(); | 510 Isolate* isolate = info->GetIsolate(); |
496 InvokeScope invoke_scope(isolate); | 511 int serial_number = Smi::cast(info->serial_number())->value(); |
497 return ::v8::internal::InstantiateFunction(isolate, data); | 512 if (serial_number) { |
| 513 Handle<JSObject> result; |
| 514 if (ProbeInstantiationsCache(isolate, serial_number).ToHandle(&result)) { |
| 515 return Handle<JSFunction>::cast(result); |
| 516 } |
| 517 } |
| 518 return InstantiateFunctionWithInvokeScope(isolate, info); |
498 } | 519 } |
499 | 520 |
500 MaybeHandle<JSObject> ApiNatives::InstantiateObject( | 521 MaybeHandle<JSObject> ApiNatives::InstantiateObject( |
501 Handle<ObjectTemplateInfo> data, Handle<JSReceiver> new_target) { | 522 Handle<ObjectTemplateInfo> info, Handle<JSReceiver> new_target) { |
502 Isolate* isolate = data->GetIsolate(); | 523 Isolate* isolate = info->GetIsolate(); |
503 InvokeScope invoke_scope(isolate); | 524 int serial_number = Smi::cast(info->serial_number())->value(); |
504 return ::v8::internal::InstantiateObject(isolate, data, new_target, false); | 525 if (serial_number && !new_target.is_null() && |
| 526 IsSimpleInstantiation(isolate, *info, *new_target)) { |
| 527 // Fast path. |
| 528 Handle<JSObject> result; |
| 529 if (ProbeInstantiationsCache(isolate, serial_number).ToHandle(&result)) { |
| 530 return isolate->factory()->CopyJSObject(result); |
| 531 } |
| 532 } |
| 533 return InstantiateObjectWithInvokeScope(isolate, info, new_target); |
505 } | 534 } |
506 | 535 |
507 MaybeHandle<JSObject> ApiNatives::InstantiateRemoteObject( | 536 MaybeHandle<JSObject> ApiNatives::InstantiateRemoteObject( |
508 Handle<ObjectTemplateInfo> data) { | 537 Handle<ObjectTemplateInfo> data) { |
509 Isolate* isolate = data->GetIsolate(); | 538 Isolate* isolate = data->GetIsolate(); |
510 InvokeScope invoke_scope(isolate); | 539 InvokeScope invoke_scope(isolate); |
511 | 540 |
512 Handle<FunctionTemplateInfo> constructor( | 541 Handle<FunctionTemplateInfo> constructor( |
513 FunctionTemplateInfo::cast(data->constructor())); | 542 FunctionTemplateInfo::cast(data->constructor())); |
514 Handle<SharedFunctionInfo> shared = | 543 Handle<SharedFunctionInfo> shared = |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
683 if (!obj->instance_call_handler()->IsUndefined(isolate)) { | 712 if (!obj->instance_call_handler()->IsUndefined(isolate)) { |
684 map->set_is_callable(); | 713 map->set_is_callable(); |
685 map->set_is_constructor(true); | 714 map->set_is_constructor(true); |
686 } | 715 } |
687 | 716 |
688 return result; | 717 return result; |
689 } | 718 } |
690 | 719 |
691 } // namespace internal | 720 } // namespace internal |
692 } // namespace v8 | 721 } // namespace v8 |
OLD | NEW |