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/parsing/parser.h" | 5 #include "src/parsing/parser.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/ast/ast-expression-rewriter.h" | 10 #include "src/ast/ast-expression-rewriter.h" |
(...skipping 3664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3675 } else { | 3675 } else { |
3676 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); | 3676 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); |
3677 running_hash = StringHasher::ComputeRunningHash(running_hash, data, | 3677 running_hash = StringHasher::ComputeRunningHash(running_hash, data, |
3678 raw_string->length()); | 3678 raw_string->length()); |
3679 } | 3679 } |
3680 } | 3680 } |
3681 | 3681 |
3682 return running_hash; | 3682 return running_hash; |
3683 } | 3683 } |
3684 | 3684 |
3685 namespace { | |
3686 | |
3687 bool OnlyLastArgIsSpread(ZoneList<Expression*>* args) { | |
3688 for (int i = 0; i < args->length() - 1; i++) { | |
3689 if (args->at(i)->IsSpread()) { | |
3690 return false; | |
3691 } | |
3692 } | |
3693 return args->at(args->length() - 1)->IsSpread(); | |
3694 } | |
3695 | |
3696 } // namespace | |
3697 | |
3698 ZoneList<Expression*>* Parser::PrepareSpreadArguments( | 3685 ZoneList<Expression*>* Parser::PrepareSpreadArguments( |
3699 ZoneList<Expression*>* list) { | 3686 ZoneList<Expression*>* list) { |
3700 // Here we only deal with multiple arguments where the spread is not at the | 3687 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); |
3701 // end, or there are multiple spreads. | 3688 if (list->length() == 1) { |
3702 DCHECK_GT(list->length(), 1); | 3689 // Spread-call with single spread argument produces an InternalArray |
3703 DCHECK(!OnlyLastArgIsSpread(list)); | 3690 // containing the values from the array. |
| 3691 // |
| 3692 // Function is called or constructed with the produced array of arguments |
| 3693 // |
| 3694 // EG: Apply(Func, Spread(spread0)) |
| 3695 ZoneList<Expression*>* spread_list = |
| 3696 new (zone()) ZoneList<Expression*>(0, zone()); |
| 3697 spread_list->Add(list->at(0)->AsSpread()->expression(), zone()); |
| 3698 args->Add(factory()->NewCallRuntime(Runtime::kSpreadIterablePrepare, |
| 3699 spread_list, kNoSourcePosition), |
| 3700 zone()); |
| 3701 return args; |
| 3702 } else { |
| 3703 // Spread-call with multiple arguments produces array literals for each |
| 3704 // sequences of unspread arguments, and converts each spread iterable to |
| 3705 // an Internal array. Finally, all of these produced arrays are flattened |
| 3706 // into a single InternalArray, containing the arguments for the call. |
| 3707 // |
| 3708 // EG: Apply(Func, Flatten([unspread0, unspread1], Spread(spread0), |
| 3709 // Spread(spread1), [unspread2, unspread3])) |
| 3710 int i = 0; |
| 3711 int n = list->length(); |
| 3712 while (i < n) { |
| 3713 if (!list->at(i)->IsSpread()) { |
| 3714 ZoneList<Expression*>* unspread = |
| 3715 new (zone()) ZoneList<Expression*>(1, zone()); |
3704 | 3716 |
3705 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); | 3717 // Push array of unspread parameters |
3706 // Spread-call with multiple arguments produces array literals for each | 3718 while (i < n && !list->at(i)->IsSpread()) { |
3707 // sequences of unspread arguments, and converts each spread iterable to | 3719 unspread->Add(list->at(i++), zone()); |
3708 // an Internal array. Finally, all of these produced arrays are flattened | 3720 } |
3709 // into a single InternalArray, containing the arguments for the call. | 3721 int literal_index = function_state_->NextMaterializedLiteralIndex(); |
3710 // | 3722 args->Add(factory()->NewArrayLiteral(unspread, literal_index, |
3711 // EG: Apply(Func, Flatten([unspread0, unspread1], Spread(spread0), | 3723 kNoSourcePosition), |
3712 // Spread(spread1), [unspread2, unspread3])) | 3724 zone()); |
3713 int i = 0; | 3725 |
3714 int n = list->length(); | 3726 if (i == n) break; |
3715 while (i < n) { | 3727 } |
3716 if (!list->at(i)->IsSpread()) { | 3728 |
3717 ZoneList<Expression*>* unspread = | 3729 // Push eagerly spread argument |
| 3730 ZoneList<Expression*>* spread_list = |
3718 new (zone()) ZoneList<Expression*>(1, zone()); | 3731 new (zone()) ZoneList<Expression*>(1, zone()); |
3719 | 3732 spread_list->Add(list->at(i++)->AsSpread()->expression(), zone()); |
3720 // Push array of unspread parameters | 3733 args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX, |
3721 while (i < n && !list->at(i)->IsSpread()) { | 3734 spread_list, kNoSourcePosition), |
3722 unspread->Add(list->at(i++), zone()); | |
3723 } | |
3724 int literal_index = function_state_->NextMaterializedLiteralIndex(); | |
3725 args->Add(factory()->NewArrayLiteral(unspread, literal_index, | |
3726 kNoSourcePosition), | |
3727 zone()); | 3735 zone()); |
3728 | |
3729 if (i == n) break; | |
3730 } | 3736 } |
3731 | 3737 |
3732 // Push eagerly spread argument | 3738 list = new (zone()) ZoneList<Expression*>(1, zone()); |
3733 ZoneList<Expression*>* spread_list = | 3739 list->Add(factory()->NewCallRuntime(Context::SPREAD_ARGUMENTS_INDEX, args, |
3734 new (zone()) ZoneList<Expression*>(1, zone()); | 3740 kNoSourcePosition), |
3735 spread_list->Add(list->at(i++)->AsSpread()->expression(), zone()); | |
3736 args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX, | |
3737 spread_list, kNoSourcePosition), | |
3738 zone()); | 3741 zone()); |
| 3742 return list; |
3739 } | 3743 } |
3740 | 3744 UNREACHABLE(); |
3741 list = new (zone()) ZoneList<Expression*>(1, zone()); | |
3742 list->Add(factory()->NewCallRuntime(Context::SPREAD_ARGUMENTS_INDEX, args, | |
3743 kNoSourcePosition), | |
3744 zone()); | |
3745 return list; | |
3746 } | 3745 } |
3747 | 3746 |
3748 Expression* Parser::SpreadCall(Expression* function, | 3747 Expression* Parser::SpreadCall(Expression* function, |
3749 ZoneList<Expression*>* args, int pos, | 3748 ZoneList<Expression*>* args, int pos) { |
3750 Call::PossiblyEval is_possibly_eval) { | |
3751 // Handle these cases in BytecodeGenerator. | |
3752 if (OnlyLastArgIsSpread(args)) { | |
3753 if (function->IsSuperCallReference()) { | |
3754 function = NewSuperCallReference(pos); | |
3755 } | |
3756 return factory()->NewCall(function, args, pos); | |
3757 } | |
3758 | |
3759 if (function->IsSuperCallReference()) { | 3749 if (function->IsSuperCallReference()) { |
3760 // Super calls | 3750 // Super calls |
3761 // $super_constructor = %_GetSuperConstructor(<this-function>) | 3751 // $super_constructor = %_GetSuperConstructor(<this-function>) |
3762 // %reflect_construct($super_constructor, args, new.target) | 3752 // %reflect_construct($super_constructor, args, new.target) |
3763 | 3753 |
| 3754 bool only_last_arg_is_spread = false; |
| 3755 for (int i = 0; i < args->length(); i++) { |
| 3756 if (args->at(i)->IsSpread()) { |
| 3757 if (i == args->length() - 1) { |
| 3758 only_last_arg_is_spread = true; |
| 3759 } |
| 3760 break; |
| 3761 } |
| 3762 } |
| 3763 |
| 3764 if (only_last_arg_is_spread) { |
| 3765 // Handle in BytecodeGenerator. |
| 3766 Expression* super_call_ref = NewSuperCallReference(pos); |
| 3767 return factory()->NewCall(super_call_ref, args, pos); |
| 3768 } |
3764 args = PrepareSpreadArguments(args); | 3769 args = PrepareSpreadArguments(args); |
3765 ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone()); | 3770 ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone()); |
3766 tmp->Add(function->AsSuperCallReference()->this_function_var(), zone()); | 3771 tmp->Add(function->AsSuperCallReference()->this_function_var(), zone()); |
3767 Expression* super_constructor = factory()->NewCallRuntime( | 3772 Expression* super_constructor = factory()->NewCallRuntime( |
3768 Runtime::kInlineGetSuperConstructor, tmp, pos); | 3773 Runtime::kInlineGetSuperConstructor, tmp, pos); |
3769 args->InsertAt(0, super_constructor, zone()); | 3774 args->InsertAt(0, super_constructor, zone()); |
3770 args->Add(function->AsSuperCallReference()->new_target_var(), zone()); | 3775 args->Add(function->AsSuperCallReference()->new_target_var(), zone()); |
3771 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, | 3776 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, |
3772 pos); | 3777 pos); |
3773 } else { | 3778 } else { |
(...skipping 21 matching lines...) Expand all Loading... |
3795 args->InsertAt(0, function, zone()); | 3800 args->InsertAt(0, function, zone()); |
3796 args->InsertAt(1, factory()->NewUndefinedLiteral(kNoSourcePosition), | 3801 args->InsertAt(1, factory()->NewUndefinedLiteral(kNoSourcePosition), |
3797 zone()); | 3802 zone()); |
3798 } | 3803 } |
3799 return factory()->NewCallRuntime(Context::REFLECT_APPLY_INDEX, args, pos); | 3804 return factory()->NewCallRuntime(Context::REFLECT_APPLY_INDEX, args, pos); |
3800 } | 3805 } |
3801 } | 3806 } |
3802 | 3807 |
3803 Expression* Parser::SpreadCallNew(Expression* function, | 3808 Expression* Parser::SpreadCallNew(Expression* function, |
3804 ZoneList<Expression*>* args, int pos) { | 3809 ZoneList<Expression*>* args, int pos) { |
3805 if (OnlyLastArgIsSpread(args)) { | |
3806 // Handle in BytecodeGenerator. | |
3807 return factory()->NewCallNew(function, args, pos); | |
3808 } | |
3809 args = PrepareSpreadArguments(args); | 3810 args = PrepareSpreadArguments(args); |
3810 args->InsertAt(0, function, zone()); | 3811 args->InsertAt(0, function, zone()); |
3811 | 3812 |
3812 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos); | 3813 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos); |
3813 } | 3814 } |
3814 | 3815 |
3815 | 3816 |
3816 void Parser::SetLanguageMode(Scope* scope, LanguageMode mode) { | 3817 void Parser::SetLanguageMode(Scope* scope, LanguageMode mode) { |
3817 v8::Isolate::UseCounterFeature feature; | 3818 v8::Isolate::UseCounterFeature feature; |
3818 if (is_sloppy(mode)) | 3819 if (is_sloppy(mode)) |
(...skipping 1296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5115 | 5116 |
5116 return final_loop; | 5117 return final_loop; |
5117 } | 5118 } |
5118 | 5119 |
5119 #undef CHECK_OK | 5120 #undef CHECK_OK |
5120 #undef CHECK_OK_VOID | 5121 #undef CHECK_OK_VOID |
5121 #undef CHECK_FAILED | 5122 #undef CHECK_FAILED |
5122 | 5123 |
5123 } // namespace internal | 5124 } // namespace internal |
5124 } // namespace v8 | 5125 } // namespace v8 |
OLD | NEW |