OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/builtins.h" | 5 #include "src/builtins.h" |
6 | 6 |
7 #include "src/api-arguments.h" | 7 #include "src/api-arguments.h" |
8 #include "src/api-natives.h" | 8 #include "src/api-natives.h" |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/base/once.h" | 10 #include "src/base/once.h" |
(...skipping 4458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4469 isolate, NewTypeError(MessageTemplate::kStrictPoisonPill)); | 4469 isolate, NewTypeError(MessageTemplate::kStrictPoisonPill)); |
4470 } | 4470 } |
4471 | 4471 |
4472 | 4472 |
4473 // ----------------------------------------------------------------------------- | 4473 // ----------------------------------------------------------------------------- |
4474 // | 4474 // |
4475 | 4475 |
4476 | 4476 |
4477 namespace { | 4477 namespace { |
4478 | 4478 |
4479 template <bool is_construct> | |
4480 MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper( | 4479 MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper( |
4481 Isolate* isolate, BuiltinArguments<BuiltinExtraArguments::kTarget> args) { | 4480 Isolate* isolate, |
| 4481 BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget> args) { |
4482 HandleScope scope(isolate); | 4482 HandleScope scope(isolate); |
4483 Handle<HeapObject> function = args.target<HeapObject>(); | 4483 Handle<HeapObject> function = args.target<HeapObject>(); |
| 4484 Handle<HeapObject> new_target = args.new_target(); |
| 4485 bool is_construct = !new_target->IsUndefined(); |
4484 Handle<JSReceiver> receiver; | 4486 Handle<JSReceiver> receiver; |
4485 | 4487 |
4486 DCHECK(function->IsFunctionTemplateInfo() || | 4488 DCHECK(function->IsFunctionTemplateInfo() || |
4487 Handle<JSFunction>::cast(function)->shared()->IsApiFunction()); | 4489 Handle<JSFunction>::cast(function)->shared()->IsApiFunction()); |
4488 | 4490 |
4489 Handle<FunctionTemplateInfo> fun_data = | 4491 Handle<FunctionTemplateInfo> fun_data = |
4490 function->IsFunctionTemplateInfo() | 4492 function->IsFunctionTemplateInfo() |
4491 ? Handle<FunctionTemplateInfo>::cast(function) | 4493 ? Handle<FunctionTemplateInfo>::cast(function) |
4492 : handle(JSFunction::cast(*function)->shared()->get_api_func_data()); | 4494 : handle(JSFunction::cast(*function)->shared()->get_api_func_data()); |
4493 if (is_construct) { | 4495 if (is_construct) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4533 DCHECK(raw_call_data->IsCallHandlerInfo()); | 4535 DCHECK(raw_call_data->IsCallHandlerInfo()); |
4534 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data); | 4536 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data); |
4535 Object* callback_obj = call_data->callback(); | 4537 Object* callback_obj = call_data->callback(); |
4536 v8::FunctionCallback callback = | 4538 v8::FunctionCallback callback = |
4537 v8::ToCData<v8::FunctionCallback>(callback_obj); | 4539 v8::ToCData<v8::FunctionCallback>(callback_obj); |
4538 Object* data_obj = call_data->data(); | 4540 Object* data_obj = call_data->data(); |
4539 | 4541 |
4540 LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver()))); | 4542 LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver()))); |
4541 DCHECK(raw_holder->IsJSObject()); | 4543 DCHECK(raw_holder->IsJSObject()); |
4542 | 4544 |
4543 FunctionCallbackArguments custom(isolate, | 4545 FunctionCallbackArguments custom(isolate, data_obj, *function, raw_holder, |
4544 data_obj, | 4546 *new_target, &args[0] - 1, |
4545 *function, | 4547 args.length() - 1); |
4546 raw_holder, | |
4547 &args[0] - 1, | |
4548 args.length() - 1, | |
4549 is_construct); | |
4550 | 4548 |
4551 Handle<Object> result = custom.Call(callback); | 4549 Handle<Object> result = custom.Call(callback); |
4552 if (result.is_null()) result = isolate->factory()->undefined_value(); | 4550 if (result.is_null()) result = isolate->factory()->undefined_value(); |
4553 | 4551 |
4554 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 4552 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
4555 if (!is_construct || result->IsJSObject()) { | 4553 if (!is_construct || result->IsJSObject()) { |
4556 return scope.CloseAndEscape(result); | 4554 return scope.CloseAndEscape(result); |
4557 } | 4555 } |
4558 } | 4556 } |
4559 | 4557 |
4560 return scope.CloseAndEscape(receiver); | 4558 return scope.CloseAndEscape(receiver); |
4561 } | 4559 } |
4562 | 4560 |
4563 } // namespace | 4561 } // namespace |
4564 | 4562 |
4565 | 4563 |
4566 BUILTIN(HandleApiCall) { | 4564 BUILTIN(HandleApiCall) { |
4567 HandleScope scope(isolate); | 4565 HandleScope scope(isolate); |
4568 Handle<Object> result; | 4566 Handle<Object> result; |
4569 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | 4567 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
4570 HandleApiCallHelper<false>(isolate, args)); | 4568 HandleApiCallHelper(isolate, args)); |
4571 return *result; | 4569 return *result; |
4572 } | 4570 } |
4573 | 4571 |
4574 | 4572 |
4575 BUILTIN(HandleApiCallConstruct) { | |
4576 HandleScope scope(isolate); | |
4577 Handle<Object> result; | |
4578 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | |
4579 HandleApiCallHelper<true>(isolate, args)); | |
4580 return *result; | |
4581 } | |
4582 | |
4583 Handle<Code> Builtins::CallFunction(ConvertReceiverMode mode, | 4573 Handle<Code> Builtins::CallFunction(ConvertReceiverMode mode, |
4584 TailCallMode tail_call_mode) { | 4574 TailCallMode tail_call_mode) { |
4585 switch (tail_call_mode) { | 4575 switch (tail_call_mode) { |
4586 case TailCallMode::kDisallow: | 4576 case TailCallMode::kDisallow: |
4587 switch (mode) { | 4577 switch (mode) { |
4588 case ConvertReceiverMode::kNullOrUndefined: | 4578 case ConvertReceiverMode::kNullOrUndefined: |
4589 return CallFunction_ReceiverIsNullOrUndefined(); | 4579 return CallFunction_ReceiverIsNullOrUndefined(); |
4590 case ConvertReceiverMode::kNotNullOrUndefined: | 4580 case ConvertReceiverMode::kNotNullOrUndefined: |
4591 return CallFunction_ReceiverIsNotNullOrUndefined(); | 4581 return CallFunction_ReceiverIsNotNullOrUndefined(); |
4592 case ConvertReceiverMode::kAny: | 4582 case ConvertReceiverMode::kAny: |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4654 case TailCallMode::kAllow: | 4644 case TailCallMode::kAllow: |
4655 return InterpreterPushArgsAndTailCall(); | 4645 return InterpreterPushArgsAndTailCall(); |
4656 } | 4646 } |
4657 UNREACHABLE(); | 4647 UNREACHABLE(); |
4658 return Handle<Code>::null(); | 4648 return Handle<Code>::null(); |
4659 } | 4649 } |
4660 | 4650 |
4661 namespace { | 4651 namespace { |
4662 | 4652 |
4663 class RelocatableArguments | 4653 class RelocatableArguments |
4664 : public BuiltinArguments<BuiltinExtraArguments::kTarget>, | 4654 : public BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>, |
4665 public Relocatable { | 4655 public Relocatable { |
4666 public: | 4656 public: |
4667 RelocatableArguments(Isolate* isolate, int length, Object** arguments) | 4657 RelocatableArguments(Isolate* isolate, int length, Object** arguments) |
4668 : BuiltinArguments<BuiltinExtraArguments::kTarget>(length, arguments), | 4658 : BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>(length, |
| 4659 arguments), |
4669 Relocatable(isolate) {} | 4660 Relocatable(isolate) {} |
4670 | 4661 |
4671 virtual inline void IterateInstance(ObjectVisitor* v) { | 4662 virtual inline void IterateInstance(ObjectVisitor* v) { |
4672 if (length() == 0) return; | 4663 if (length() == 0) return; |
4673 v->VisitPointers(lowest_address(), highest_address() + 1); | 4664 v->VisitPointers(lowest_address(), highest_address() + 1); |
4674 } | 4665 } |
4675 | 4666 |
4676 private: | 4667 private: |
4677 DISALLOW_COPY_AND_ASSIGN(RelocatableArguments); | 4668 DISALLOW_COPY_AND_ASSIGN(RelocatableArguments); |
4678 }; | 4669 }; |
(...skipping 11 matching lines...) Expand all Loading... |
4690 if (function->IsFunctionTemplateInfo() || | 4681 if (function->IsFunctionTemplateInfo() || |
4691 is_sloppy(JSFunction::cast(*function)->shared()->language_mode())) { | 4682 is_sloppy(JSFunction::cast(*function)->shared()->language_mode())) { |
4692 if (receiver->IsUndefined() || receiver->IsNull()) { | 4683 if (receiver->IsUndefined() || receiver->IsNull()) { |
4693 receiver = handle(isolate->global_proxy(), isolate); | 4684 receiver = handle(isolate->global_proxy(), isolate); |
4694 } else { | 4685 } else { |
4695 ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver, | 4686 ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver, |
4696 Object::ToObject(isolate, receiver), Object); | 4687 Object::ToObject(isolate, receiver), Object); |
4697 } | 4688 } |
4698 } | 4689 } |
4699 } | 4690 } |
4700 // Construct BuiltinArguments object: function, arguments reversed, receiver. | 4691 // Construct BuiltinArguments object: |
| 4692 // new target, function, arguments reversed, receiver. |
4701 const int kBufferSize = 32; | 4693 const int kBufferSize = 32; |
4702 Object* small_argv[kBufferSize]; | 4694 Object* small_argv[kBufferSize]; |
4703 Object** argv; | 4695 Object** argv; |
4704 if (argc + 2 <= kBufferSize) { | 4696 if (argc + 3 <= kBufferSize) { |
4705 argv = small_argv; | 4697 argv = small_argv; |
4706 } else { | 4698 } else { |
4707 argv = new Object* [argc + 2]; | 4699 argv = new Object*[argc + 3]; |
4708 } | 4700 } |
4709 argv[argc + 1] = *receiver; | 4701 argv[argc + 2] = *receiver; |
4710 for (int i = 0; i < argc; ++i) { | 4702 for (int i = 0; i < argc; ++i) { |
4711 argv[argc - i] = *args[i]; | 4703 argv[argc - i + 1] = *args[i]; |
4712 } | 4704 } |
4713 argv[0] = *function; | 4705 argv[1] = *function; |
| 4706 argv[0] = isolate->heap()->undefined_value(); // new target |
4714 MaybeHandle<Object> result; | 4707 MaybeHandle<Object> result; |
4715 { | 4708 { |
4716 RelocatableArguments arguments(isolate, argc + 2, &argv[argc + 1]); | 4709 RelocatableArguments arguments(isolate, argc + 3, &argv[argc] + 2); |
4717 result = HandleApiCallHelper<false>(isolate, arguments); | 4710 result = HandleApiCallHelper(isolate, arguments); |
4718 } | 4711 } |
4719 if (argv != small_argv) { | 4712 if (argv != small_argv) { |
4720 delete[] argv; | 4713 delete[] argv; |
4721 } | 4714 } |
4722 return result; | 4715 return result; |
4723 } | 4716 } |
4724 | 4717 |
4725 | 4718 |
4726 // Helper function to handle calls to non-function objects created through the | 4719 // Helper function to handle calls to non-function objects created through the |
4727 // API. The object can be called as either a constructor (using new) or just as | 4720 // API. The object can be called as either a constructor (using new) or just as |
4728 // a function (without new). | 4721 // a function (without new). |
4729 MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor( | 4722 MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor( |
4730 Isolate* isolate, bool is_construct_call, | 4723 Isolate* isolate, bool is_construct_call, |
4731 BuiltinArguments<BuiltinExtraArguments::kNone> args) { | 4724 BuiltinArguments<BuiltinExtraArguments::kNone> args) { |
4732 Handle<Object> receiver = args.receiver(); | 4725 Handle<Object> receiver = args.receiver(); |
4733 | 4726 |
4734 // Get the object called. | 4727 // Get the object called. |
4735 JSObject* obj = JSObject::cast(*receiver); | 4728 JSObject* obj = JSObject::cast(*receiver); |
4736 | 4729 |
| 4730 // Set the new target. |
| 4731 HeapObject* new_target; |
| 4732 if (is_construct_call) { |
| 4733 // TODO(adamk): This should be passed through in args instead of |
| 4734 // being patched in here. We need to set a non-undefined value |
| 4735 // for v8::FunctionCallbackInfo::IsConstructCall() to get the |
| 4736 // right answer. |
| 4737 new_target = obj; |
| 4738 } else { |
| 4739 new_target = isolate->heap()->undefined_value(); |
| 4740 } |
| 4741 |
4737 // Get the invocation callback from the function descriptor that was | 4742 // Get the invocation callback from the function descriptor that was |
4738 // used to create the called object. | 4743 // used to create the called object. |
4739 DCHECK(obj->map()->is_callable()); | 4744 DCHECK(obj->map()->is_callable()); |
4740 JSFunction* constructor = JSFunction::cast(obj->map()->GetConstructor()); | 4745 JSFunction* constructor = JSFunction::cast(obj->map()->GetConstructor()); |
4741 // TODO(ishell): turn this back to a DCHECK. | 4746 // TODO(ishell): turn this back to a DCHECK. |
4742 CHECK(constructor->shared()->IsApiFunction()); | 4747 CHECK(constructor->shared()->IsApiFunction()); |
4743 Object* handler = | 4748 Object* handler = |
4744 constructor->shared()->get_api_func_data()->instance_call_handler(); | 4749 constructor->shared()->get_api_func_data()->instance_call_handler(); |
4745 DCHECK(!handler->IsUndefined()); | 4750 DCHECK(!handler->IsUndefined()); |
4746 // TODO(ishell): remove this debugging code. | 4751 // TODO(ishell): remove this debugging code. |
4747 CHECK(handler->IsCallHandlerInfo()); | 4752 CHECK(handler->IsCallHandlerInfo()); |
4748 CallHandlerInfo* call_data = CallHandlerInfo::cast(handler); | 4753 CallHandlerInfo* call_data = CallHandlerInfo::cast(handler); |
4749 Object* callback_obj = call_data->callback(); | 4754 Object* callback_obj = call_data->callback(); |
4750 v8::FunctionCallback callback = | 4755 v8::FunctionCallback callback = |
4751 v8::ToCData<v8::FunctionCallback>(callback_obj); | 4756 v8::ToCData<v8::FunctionCallback>(callback_obj); |
4752 | 4757 |
4753 // Get the data for the call and perform the callback. | 4758 // Get the data for the call and perform the callback. |
4754 Object* result; | 4759 Object* result; |
4755 { | 4760 { |
4756 HandleScope scope(isolate); | 4761 HandleScope scope(isolate); |
4757 LOG(isolate, ApiObjectAccess("call non-function", obj)); | 4762 LOG(isolate, ApiObjectAccess("call non-function", obj)); |
4758 | 4763 |
4759 FunctionCallbackArguments custom(isolate, | 4764 FunctionCallbackArguments custom(isolate, call_data->data(), constructor, |
4760 call_data->data(), | 4765 obj, new_target, &args[0] - 1, |
4761 constructor, | 4766 args.length() - 1); |
4762 obj, | |
4763 &args[0] - 1, | |
4764 args.length() - 1, | |
4765 is_construct_call); | |
4766 Handle<Object> result_handle = custom.Call(callback); | 4767 Handle<Object> result_handle = custom.Call(callback); |
4767 if (result_handle.is_null()) { | 4768 if (result_handle.is_null()) { |
4768 result = isolate->heap()->undefined_value(); | 4769 result = isolate->heap()->undefined_value(); |
4769 } else { | 4770 } else { |
4770 result = *result_handle; | 4771 result = *result_handle; |
4771 } | 4772 } |
4772 } | 4773 } |
4773 // Check for exceptions and return result. | 4774 // Check for exceptions and return result. |
4774 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); | 4775 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |
4775 return result; | 4776 return result; |
(...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5346 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T) | 5347 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T) |
5347 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 5348 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
5348 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 5349 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
5349 #undef DEFINE_BUILTIN_ACCESSOR_C | 5350 #undef DEFINE_BUILTIN_ACCESSOR_C |
5350 #undef DEFINE_BUILTIN_ACCESSOR_A | 5351 #undef DEFINE_BUILTIN_ACCESSOR_A |
5351 #undef DEFINE_BUILTIN_ACCESSOR_T | 5352 #undef DEFINE_BUILTIN_ACCESSOR_T |
5352 #undef DEFINE_BUILTIN_ACCESSOR_H | 5353 #undef DEFINE_BUILTIN_ACCESSOR_H |
5353 | 5354 |
5354 } // namespace internal | 5355 } // namespace internal |
5355 } // namespace v8 | 5356 } // namespace v8 |
OLD | NEW |