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