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 3674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3685 } else { | 3685 } else { |
3686 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); | 3686 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); |
3687 running_hash = StringHasher::ComputeRunningHash(running_hash, data, | 3687 running_hash = StringHasher::ComputeRunningHash(running_hash, data, |
3688 raw_string->length()); | 3688 raw_string->length()); |
3689 } | 3689 } |
3690 } | 3690 } |
3691 | 3691 |
3692 return running_hash; | 3692 return running_hash; |
3693 } | 3693 } |
3694 | 3694 |
| 3695 namespace { |
| 3696 |
| 3697 bool OnlyLastArgIsSpread(ZoneList<Expression*>* args) { |
| 3698 for (int i = 0; i < args->length() - 1; i++) { |
| 3699 if (args->at(i)->IsSpread()) { |
| 3700 return false; |
| 3701 } |
| 3702 } |
| 3703 return args->at(args->length() - 1)->IsSpread(); |
| 3704 } |
| 3705 |
| 3706 } // namespace |
| 3707 |
3695 ZoneList<Expression*>* Parser::PrepareSpreadArguments( | 3708 ZoneList<Expression*>* Parser::PrepareSpreadArguments( |
3696 ZoneList<Expression*>* list) { | 3709 ZoneList<Expression*>* list) { |
| 3710 // Here we only deal with multiple arguments where the spread is not at the |
| 3711 // end, or there are multiple spreads. |
| 3712 DCHECK_GT(list->length(), 1); |
| 3713 DCHECK(!OnlyLastArgIsSpread(list)); |
| 3714 |
3697 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); | 3715 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); |
3698 if (list->length() == 1) { | 3716 // Spread-call with multiple arguments produces array literals for each |
3699 // Spread-call with single spread argument produces an InternalArray | 3717 // sequences of unspread arguments, and converts each spread iterable to |
3700 // containing the values from the array. | 3718 // an Internal array. Finally, all of these produced arrays are flattened |
3701 // | 3719 // into a single InternalArray, containing the arguments for the call. |
3702 // Function is called or constructed with the produced array of arguments | 3720 // |
3703 // | 3721 // EG: Apply(Func, Flatten([unspread0, unspread1], Spread(spread0), |
3704 // EG: Apply(Func, Spread(spread0)) | 3722 // Spread(spread1), [unspread2, unspread3])) |
| 3723 int i = 0; |
| 3724 int n = list->length(); |
| 3725 while (i < n) { |
| 3726 if (!list->at(i)->IsSpread()) { |
| 3727 ZoneList<Expression*>* unspread = |
| 3728 new (zone()) ZoneList<Expression*>(1, zone()); |
| 3729 |
| 3730 // Push array of unspread parameters |
| 3731 while (i < n && !list->at(i)->IsSpread()) { |
| 3732 unspread->Add(list->at(i++), zone()); |
| 3733 } |
| 3734 int literal_index = function_state_->NextMaterializedLiteralIndex(); |
| 3735 args->Add(factory()->NewArrayLiteral(unspread, literal_index, |
| 3736 kNoSourcePosition), |
| 3737 zone()); |
| 3738 |
| 3739 if (i == n) break; |
| 3740 } |
| 3741 |
| 3742 // Push eagerly spread argument |
3705 ZoneList<Expression*>* spread_list = | 3743 ZoneList<Expression*>* spread_list = |
3706 new (zone()) ZoneList<Expression*>(0, zone()); | 3744 new (zone()) ZoneList<Expression*>(1, zone()); |
3707 spread_list->Add(list->at(0)->AsSpread()->expression(), zone()); | 3745 spread_list->Add(list->at(i++)->AsSpread()->expression(), zone()); |
3708 args->Add(factory()->NewCallRuntime(Runtime::kSpreadIterablePrepare, | 3746 args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX, |
3709 spread_list, kNoSourcePosition), | 3747 spread_list, kNoSourcePosition), |
3710 zone()); | 3748 zone()); |
3711 return args; | 3749 } |
3712 } else { | |
3713 // Spread-call with multiple arguments produces array literals for each | |
3714 // sequences of unspread arguments, and converts each spread iterable to | |
3715 // an Internal array. Finally, all of these produced arrays are flattened | |
3716 // into a single InternalArray, containing the arguments for the call. | |
3717 // | |
3718 // EG: Apply(Func, Flatten([unspread0, unspread1], Spread(spread0), | |
3719 // Spread(spread1), [unspread2, unspread3])) | |
3720 int i = 0; | |
3721 int n = list->length(); | |
3722 while (i < n) { | |
3723 if (!list->at(i)->IsSpread()) { | |
3724 ZoneList<Expression*>* unspread = | |
3725 new (zone()) ZoneList<Expression*>(1, zone()); | |
3726 | 3750 |
3727 // Push array of unspread parameters | 3751 list = new (zone()) ZoneList<Expression*>(1, zone()); |
3728 while (i < n && !list->at(i)->IsSpread()) { | 3752 list->Add(factory()->NewCallRuntime(Context::SPREAD_ARGUMENTS_INDEX, args, |
3729 unspread->Add(list->at(i++), zone()); | 3753 kNoSourcePosition), |
3730 } | 3754 zone()); |
3731 int literal_index = function_state_->NextMaterializedLiteralIndex(); | 3755 return list; |
3732 args->Add(factory()->NewArrayLiteral(unspread, literal_index, | |
3733 kNoSourcePosition), | |
3734 zone()); | |
3735 | |
3736 if (i == n) break; | |
3737 } | |
3738 | |
3739 // Push eagerly spread argument | |
3740 ZoneList<Expression*>* spread_list = | |
3741 new (zone()) ZoneList<Expression*>(1, zone()); | |
3742 spread_list->Add(list->at(i++)->AsSpread()->expression(), zone()); | |
3743 args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX, | |
3744 spread_list, kNoSourcePosition), | |
3745 zone()); | |
3746 } | |
3747 | |
3748 list = new (zone()) ZoneList<Expression*>(1, zone()); | |
3749 list->Add(factory()->NewCallRuntime(Context::SPREAD_ARGUMENTS_INDEX, args, | |
3750 kNoSourcePosition), | |
3751 zone()); | |
3752 return list; | |
3753 } | |
3754 UNREACHABLE(); | |
3755 } | 3756 } |
3756 | 3757 |
3757 Expression* Parser::SpreadCall(Expression* function, | 3758 Expression* Parser::SpreadCall(Expression* function, |
3758 ZoneList<Expression*>* args, int pos) { | 3759 ZoneList<Expression*>* args, int pos, |
| 3760 Call::PossiblyEval is_possibly_eval) { |
| 3761 // Handle these cases in BytecodeGenerator. |
| 3762 if (OnlyLastArgIsSpread(args)) { |
| 3763 if (function->IsSuperCallReference()) { |
| 3764 function = NewSuperCallReference(pos); |
| 3765 } |
| 3766 return factory()->NewCall(function, args, pos); |
| 3767 } |
| 3768 |
3759 if (function->IsSuperCallReference()) { | 3769 if (function->IsSuperCallReference()) { |
3760 // Super calls | 3770 // Super calls |
3761 // $super_constructor = %_GetSuperConstructor(<this-function>) | 3771 // $super_constructor = %_GetSuperConstructor(<this-function>) |
3762 // %reflect_construct($super_constructor, args, new.target) | 3772 // %reflect_construct($super_constructor, args, new.target) |
3763 | 3773 |
3764 bool only_last_arg_is_spread = false; | |
3765 for (int i = 0; i < args->length(); i++) { | |
3766 if (args->at(i)->IsSpread()) { | |
3767 if (i == args->length() - 1) { | |
3768 only_last_arg_is_spread = true; | |
3769 } | |
3770 break; | |
3771 } | |
3772 } | |
3773 | |
3774 if (only_last_arg_is_spread) { | |
3775 // Handle in BytecodeGenerator. | |
3776 Expression* super_call_ref = NewSuperCallReference(pos); | |
3777 return factory()->NewCall(super_call_ref, args, pos); | |
3778 } | |
3779 args = PrepareSpreadArguments(args); | 3774 args = PrepareSpreadArguments(args); |
3780 ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone()); | 3775 ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone()); |
3781 tmp->Add(function->AsSuperCallReference()->this_function_var(), zone()); | 3776 tmp->Add(function->AsSuperCallReference()->this_function_var(), zone()); |
3782 Expression* super_constructor = factory()->NewCallRuntime( | 3777 Expression* super_constructor = factory()->NewCallRuntime( |
3783 Runtime::kInlineGetSuperConstructor, tmp, pos); | 3778 Runtime::kInlineGetSuperConstructor, tmp, pos); |
3784 args->InsertAt(0, super_constructor, zone()); | 3779 args->InsertAt(0, super_constructor, zone()); |
3785 args->Add(function->AsSuperCallReference()->new_target_var(), zone()); | 3780 args->Add(function->AsSuperCallReference()->new_target_var(), zone()); |
3786 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, | 3781 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, |
3787 pos); | 3782 pos); |
3788 } else { | 3783 } else { |
(...skipping 21 matching lines...) Expand all Loading... |
3810 args->InsertAt(0, function, zone()); | 3805 args->InsertAt(0, function, zone()); |
3811 args->InsertAt(1, factory()->NewUndefinedLiteral(kNoSourcePosition), | 3806 args->InsertAt(1, factory()->NewUndefinedLiteral(kNoSourcePosition), |
3812 zone()); | 3807 zone()); |
3813 } | 3808 } |
3814 return factory()->NewCallRuntime(Context::REFLECT_APPLY_INDEX, args, pos); | 3809 return factory()->NewCallRuntime(Context::REFLECT_APPLY_INDEX, args, pos); |
3815 } | 3810 } |
3816 } | 3811 } |
3817 | 3812 |
3818 Expression* Parser::SpreadCallNew(Expression* function, | 3813 Expression* Parser::SpreadCallNew(Expression* function, |
3819 ZoneList<Expression*>* args, int pos) { | 3814 ZoneList<Expression*>* args, int pos) { |
| 3815 if (OnlyLastArgIsSpread(args)) { |
| 3816 // Handle in BytecodeGenerator. |
| 3817 return factory()->NewCallNew(function, args, pos); |
| 3818 } |
3820 args = PrepareSpreadArguments(args); | 3819 args = PrepareSpreadArguments(args); |
3821 args->InsertAt(0, function, zone()); | 3820 args->InsertAt(0, function, zone()); |
3822 | 3821 |
3823 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos); | 3822 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos); |
3824 } | 3823 } |
3825 | 3824 |
3826 | 3825 |
3827 void Parser::SetLanguageMode(Scope* scope, LanguageMode mode) { | 3826 void Parser::SetLanguageMode(Scope* scope, LanguageMode mode) { |
3828 v8::Isolate::UseCounterFeature feature; | 3827 v8::Isolate::UseCounterFeature feature; |
3829 if (is_sloppy(mode)) | 3828 if (is_sloppy(mode)) |
(...skipping 1299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5129 | 5128 |
5130 return final_loop; | 5129 return final_loop; |
5131 } | 5130 } |
5132 | 5131 |
5133 #undef CHECK_OK | 5132 #undef CHECK_OK |
5134 #undef CHECK_OK_VOID | 5133 #undef CHECK_OK_VOID |
5135 #undef CHECK_FAILED | 5134 #undef CHECK_FAILED |
5136 | 5135 |
5137 } // namespace internal | 5136 } // namespace internal |
5138 } // namespace v8 | 5137 } // namespace v8 |
OLD | NEW |