| 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 |