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