Chromium Code Reviews| 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 "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
| 9 #include "src/ast/ast-expression-rewriter.h" | 9 #include "src/ast/ast-expression-rewriter.h" |
| 10 #include "src/ast/ast-expression-visitor.h" | 10 #include "src/ast/ast-expression-visitor.h" |
| (...skipping 5779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5790 } else { | 5790 } else { |
| 5791 DCHECK(value->IsClassLiteral()); | 5791 DCHECK(value->IsClassLiteral()); |
| 5792 auto class_literal = value->AsClassLiteral(); | 5792 auto class_literal = value->AsClassLiteral(); |
| 5793 if (class_literal->raw_name() == nullptr) { | 5793 if (class_literal->raw_name() == nullptr) { |
| 5794 class_literal->set_raw_name(name); | 5794 class_literal->set_raw_name(name); |
| 5795 } | 5795 } |
| 5796 } | 5796 } |
| 5797 } | 5797 } |
| 5798 | 5798 |
| 5799 | 5799 |
| 5800 // Desugaring of yield* | |
| 5801 // ==================== | |
| 5802 // | |
| 5803 // With the help of do-expressions and function.sent, we desugar yield* into a | |
| 5804 // loop containing a "raw" yield (a yield that doesn't wrap an iterator result | |
| 5805 // object around its argument). Concretely, "yield* iterable" turns into | |
| 5806 // roughly the following code: | |
| 5807 // | |
| 5808 // do { | |
| 5809 // const kNext = 0; | |
| 5810 // const kReturn = 1; | |
| 5811 // const kThrow = 2; | |
| 5812 // | |
| 5813 // let input = function.sent; | |
| 5814 // let mode = kNext; | |
| 5815 // let output = undefined; | |
| 5816 // | |
| 5817 // let iterator = iterable[Symbol.iterator](); | |
| 5818 // if (!IS_RECEIVER(iterator)) throw MakeTypeError(kSymbolIteratorInvalid); | |
| 5819 // | |
| 5820 // while (true) { | |
| 5821 // // From the generator to the iterator: | |
| 5822 // // Forward input according to resume mode and obtain output. | |
| 5823 // switch (mode) { | |
| 5824 // case kNext: | |
| 5825 // output = iterator.next(input); | |
| 5826 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); | |
| 5827 // break; | |
| 5828 // case kReturn: | |
| 5829 // let iteratorReturn = iterator.return; | |
| 5830 // if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return input; | |
| 5831 // output = %_Call(iteratorReturn, iterator, input); | |
| 5832 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); | |
| 5833 // break; | |
| 5834 // case kThrow: | |
| 5835 // let iteratorThrow = iterator.throw; | |
| 5836 // if (IS_NULL_OR_UNDEFINED(iteratorThrow)) { | |
| 5837 // IteratorClose(iterator); | |
| 5838 // throw MakeTypeError(kThrowMethodMissing); | |
| 5839 // } | |
| 5840 // output = %_Call(iteratorThrow, iterator, input); | |
| 5841 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); | |
| 5842 // break; | |
| 5843 // } | |
| 5844 // if (output.done) break; | |
| 5845 // | |
| 5846 // // From the generator to its user: | |
| 5847 // // Forward output, receive new input, and determine resume mode. | |
| 5848 // mode = kReturn; | |
| 5849 // try { | |
| 5850 // try { | |
| 5851 // RawYield(output); // See explanation above. | |
| 5852 // mode = kNext; | |
| 5853 // } catch (error) { | |
| 5854 // mode = kThrow; | |
| 5855 // } | |
| 5856 // } finally { | |
| 5857 // input = function.sent; | |
| 5858 // continue; | |
| 5859 // } | |
| 5860 // } | |
| 5861 // | |
| 5862 // output.value; | |
| 5863 // } | |
| 5864 // | |
| 5865 // IteratorClose(iterator) in the code above expands to the following: | |
| 5866 // | |
| 5867 // let iteratorReturn = iterator.return; | |
| 5868 // if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return; | |
| 5869 // let result = %_Call(iteratorReturn, iterator); | |
| 5870 // if (!IS_RECEIVER(result)) throw MakeTypeError(kIllegalInvocation); | |
| 5871 | |
| 5872 | |
| 5873 Expression* ParserTraits::RewriteYieldStar( | |
| 5874 Expression* generator, Expression* iterable, int pos) { | |
| 5875 | |
| 5876 const int nopos = RelocInfo::kNoPosition; | |
| 5877 | |
| 5878 auto factory = parser_->factory(); | |
| 5879 auto avfactory = parser_->ast_value_factory(); | |
| 5880 auto scope = parser_->scope_; | |
| 5881 auto zone = parser_->zone(); | |
| 5882 | |
| 5883 Statement* skip = factory->NewEmptyStatement(nopos); | |
| 5884 | |
| 5885 enum { kNext, kReturn, kThrow }; | |
|
Dan Ehrenberg
2016/02/04 11:40:32
This looks redundant with JSGeneratorObject::Resum
| |
| 5886 | |
| 5887 // Forward definition for break/continue statements. | |
| 5888 WhileStatement* loop = factory->NewWhileStatement(nullptr, nopos); | |
| 5889 | |
| 5890 | |
| 5891 // let input = undefined; | |
| 5892 Variable* var_input = scope->NewTemporary(avfactory->empty_string()); | |
| 5893 Statement* initialize_input; | |
| 5894 { | |
| 5895 Expression* input_proxy = factory->NewVariableProxy(var_input); | |
| 5896 Expression* assignment = factory->NewAssignment( | |
| 5897 Token::ASSIGN, input_proxy, factory->NewUndefinedLiteral(nopos), nopos); | |
| 5898 initialize_input = factory->NewExpressionStatement(assignment, nopos); | |
| 5899 } | |
| 5900 | |
| 5901 | |
| 5902 // let mode = kNext; | |
| 5903 Variable* var_mode = scope->NewTemporary(avfactory->empty_string()); | |
| 5904 Statement* initialize_mode; | |
| 5905 { | |
| 5906 Expression* mode_proxy = factory->NewVariableProxy(var_mode); | |
| 5907 Expression* knext = factory->NewSmiLiteral(kNext, nopos); | |
| 5908 Expression* assignment = | |
| 5909 factory->NewAssignment(Token::ASSIGN, mode_proxy, knext, nopos); | |
| 5910 initialize_mode = factory->NewExpressionStatement(assignment, nopos); | |
| 5911 } | |
| 5912 | |
| 5913 | |
| 5914 // let output = undefined; | |
| 5915 Variable* var_output = scope->NewTemporary(avfactory->empty_string()); | |
| 5916 Statement* initialize_output; | |
| 5917 { | |
| 5918 Expression* output_proxy = factory->NewVariableProxy(var_output); | |
| 5919 Expression* assignment = factory->NewAssignment( | |
| 5920 Token::ASSIGN, output_proxy, factory->NewUndefinedLiteral(nopos), | |
| 5921 nopos); | |
| 5922 initialize_output = factory->NewExpressionStatement(assignment, nopos); | |
| 5923 } | |
| 5924 | |
| 5925 | |
| 5926 // let iterator = iterable[Symbol.iterator]; | |
| 5927 Variable* var_iterator = scope->NewTemporary(avfactory->empty_string()); | |
| 5928 Statement* get_iterator; | |
| 5929 { | |
| 5930 Expression* iterator = GetIterator(iterable, factory, nopos); | |
| 5931 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator); | |
| 5932 Expression* assignment = factory->NewAssignment( | |
| 5933 Token::ASSIGN, iterator_proxy, iterator, nopos); | |
| 5934 get_iterator = factory->NewExpressionStatement(assignment, nopos); | |
| 5935 } | |
| 5936 | |
| 5937 | |
| 5938 // if (!IS_RECEIVER(iterator)) throw MakeTypeError(kSymbolIteratorInvalid); | |
| 5939 Statement* validate_iterator; | |
| 5940 { | |
| 5941 Expression* is_receiver_call; | |
| 5942 { | |
| 5943 auto args = new (zone) ZoneList<Expression*>(1, zone); | |
| 5944 args->Add(factory->NewVariableProxy(var_iterator), zone); | |
| 5945 is_receiver_call = | |
| 5946 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); | |
| 5947 } | |
| 5948 | |
| 5949 Statement* throw_call; | |
| 5950 { | |
| 5951 Expression* call = NewThrowTypeError( | |
| 5952 MessageTemplate::kSymbolIteratorInvalid, avfactory->empty_string(), | |
| 5953 nopos); | |
| 5954 throw_call = factory->NewExpressionStatement(call, nopos); | |
| 5955 } | |
| 5956 | |
| 5957 validate_iterator = | |
| 5958 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); | |
| 5959 } | |
| 5960 | |
| 5961 | |
| 5962 // output = iterator.next(input); | |
| 5963 Statement* call_next; | |
| 5964 { | |
| 5965 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator); | |
| 5966 Expression* literal = | |
| 5967 factory->NewStringLiteral(avfactory->next_string(), nopos); | |
| 5968 Expression* next_property = | |
| 5969 factory->NewProperty(iterator_proxy, literal, nopos); | |
| 5970 Expression* input_proxy = factory->NewVariableProxy(var_input); | |
| 5971 auto args = new (zone) ZoneList<Expression*>(1, zone); | |
| 5972 args->Add(input_proxy, zone); | |
| 5973 Expression* call = factory->NewCall(next_property, args, nopos); | |
| 5974 Expression* output_proxy = factory->NewVariableProxy(var_output); | |
| 5975 Expression* assignment = | |
| 5976 factory->NewAssignment(Token::ASSIGN, output_proxy, call, nopos); | |
| 5977 call_next = factory->NewExpressionStatement(assignment, nopos); | |
| 5978 } | |
| 5979 | |
| 5980 | |
| 5981 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); | |
| 5982 Statement* validate_next_output; | |
| 5983 { | |
| 5984 Expression* is_receiver_call; | |
| 5985 { | |
| 5986 auto args = new (zone) ZoneList<Expression*>(1, zone); | |
| 5987 args->Add(factory->NewVariableProxy(var_output), zone); | |
| 5988 is_receiver_call = | |
| 5989 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); | |
| 5990 } | |
| 5991 | |
| 5992 Statement* throw_call; | |
| 5993 { | |
| 5994 auto args = new (zone) ZoneList<Expression*>(1, zone); | |
| 5995 args->Add(factory->NewVariableProxy(var_output), zone); | |
| 5996 Expression* call = factory->NewCallRuntime( | |
| 5997 Runtime::kThrowIteratorResultNotAnObject, args, nopos); | |
| 5998 throw_call = factory->NewExpressionStatement(call, nopos); | |
| 5999 } | |
| 6000 | |
| 6001 validate_next_output = | |
| 6002 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); | |
| 6003 } | |
| 6004 | |
| 6005 | |
| 6006 // let iteratorReturn = iterator.return; | |
| 6007 Variable* var_fun = scope->NewTemporary(avfactory->empty_string()); | |
| 6008 Statement* get_return; | |
| 6009 { | |
| 6010 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator); | |
| 6011 Expression* literal = | |
| 6012 factory->NewStringLiteral(avfactory->return_string(), nopos); | |
| 6013 Expression* property = | |
| 6014 factory->NewProperty(iterator_proxy, literal, nopos); | |
| 6015 Expression* return_proxy = factory->NewVariableProxy(var_fun); | |
| 6016 Expression* assignment = factory->NewAssignment( | |
| 6017 Token::ASSIGN, return_proxy, property, nopos); | |
| 6018 get_return = factory->NewExpressionStatement(assignment, nopos); | |
| 6019 } | |
| 6020 | |
| 6021 | |
| 6022 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return input; | |
| 6023 Statement* check_return; | |
| 6024 { | |
| 6025 Expression* condition = factory->NewCompareOperation( | |
| 6026 Token::EQ, factory->NewVariableProxy(var_fun), | |
| 6027 factory->NewNullLiteral(nopos), nopos); | |
| 6028 Statement* return_input = factory->NewReturnStatement( | |
| 6029 factory->NewVariableProxy(var_input), nopos); | |
| 6030 check_return = | |
| 6031 factory->NewIfStatement(condition, return_input, skip, nopos); | |
| 6032 } | |
| 6033 | |
| 6034 | |
| 6035 // output = %_Call(iteratorReturn, iterator, input); | |
| 6036 Statement* call_return; | |
| 6037 { | |
| 6038 auto args = new (zone) ZoneList<Expression*>(3, zone); | |
| 6039 args->Add(factory->NewVariableProxy(var_fun), zone); | |
| 6040 args->Add(factory->NewVariableProxy(var_iterator), zone); | |
| 6041 args->Add(factory->NewVariableProxy(var_input), zone); | |
| 6042 Expression* call = | |
| 6043 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos); | |
| 6044 Expression* assignment = factory->NewAssignment( | |
| 6045 Token::ASSIGN, factory->NewVariableProxy(var_output), call, nopos); | |
| 6046 call_return = factory->NewExpressionStatement(assignment, nopos); | |
| 6047 } | |
| 6048 | |
| 6049 | |
| 6050 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); | |
| 6051 Statement* validate_return_output; | |
| 6052 { | |
| 6053 Expression* is_receiver_call; | |
| 6054 { | |
| 6055 auto args = new (zone) ZoneList<Expression*>(1, zone); | |
| 6056 args->Add(factory->NewVariableProxy(var_output), zone); | |
| 6057 is_receiver_call = | |
| 6058 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); | |
| 6059 } | |
| 6060 | |
| 6061 Statement* throw_call; | |
| 6062 { | |
| 6063 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(1, zone); | |
| 6064 args->Add(factory->NewVariableProxy(var_output), zone); | |
| 6065 Expression* call = factory->NewCallRuntime( | |
| 6066 Runtime::kThrowIteratorResultNotAnObject, args, nopos); | |
| 6067 throw_call = factory->NewExpressionStatement(call, nopos); | |
| 6068 } | |
| 6069 | |
| 6070 validate_return_output = | |
| 6071 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); | |
| 6072 } | |
| 6073 | |
| 6074 | |
| 6075 // let iteratorThrow = iterator.throw; | |
| 6076 Statement* get_throw; | |
| 6077 { | |
| 6078 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator); | |
| 6079 Expression* literal = | |
| 6080 factory->NewStringLiteral(avfactory->throw_string(), nopos); | |
| 6081 Expression* property = | |
| 6082 factory->NewProperty(iterator_proxy, literal, nopos); | |
| 6083 Expression* throw_proxy = factory->NewVariableProxy(var_fun); | |
| 6084 Expression* assignment = factory->NewAssignment( | |
| 6085 Token::ASSIGN, throw_proxy, property, nopos); | |
| 6086 get_throw = factory->NewExpressionStatement(assignment, nopos); | |
| 6087 } | |
| 6088 | |
| 6089 | |
| 6090 // if (IS_NULL_OR_UNDEFINED(iteratorThrow) { | |
| 6091 // IteratorClose(iterator); | |
| 6092 // throw MakeTypeError(kThrowMethodMissing); | |
| 6093 // } | |
| 6094 Statement* check_throw; | |
| 6095 { | |
| 6096 Expression* condition = factory->NewCompareOperation( | |
| 6097 Token::EQ, factory->NewVariableProxy(var_fun), | |
| 6098 factory->NewNullLiteral(nopos), nopos); | |
| 6099 | |
| 6100 Expression* call = NewThrowTypeError( | |
| 6101 MessageTemplate::kThrowMethodMissing, | |
| 6102 avfactory->empty_string(), nopos); | |
| 6103 Statement* throw_call = factory->NewExpressionStatement(call, nopos); | |
| 6104 | |
| 6105 Block* then = factory->NewBlock(nullptr, 4+1, false, nopos); | |
| 6106 BuildIteratorClose(then->statements(), var_iterator); | |
| 6107 then->statements()->Add(throw_call, zone); | |
| 6108 check_throw = | |
| 6109 factory->NewIfStatement(condition, then, skip, nopos); | |
| 6110 } | |
| 6111 | |
| 6112 | |
| 6113 // output = %_Call(iteratorThrow, iterator, input); | |
| 6114 Statement* call_throw; | |
| 6115 { | |
| 6116 auto args = new (zone) ZoneList<Expression*>(3, zone); | |
| 6117 args->Add(factory->NewVariableProxy(var_fun), zone); | |
| 6118 args->Add(factory->NewVariableProxy(var_iterator), zone); | |
| 6119 args->Add(factory->NewVariableProxy(var_input), zone); | |
| 6120 Expression* call = | |
| 6121 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos); | |
| 6122 Expression* assignment = factory->NewAssignment( | |
| 6123 Token::ASSIGN, factory->NewVariableProxy(var_output), call, nopos); | |
| 6124 call_throw = factory->NewExpressionStatement(assignment, nopos); | |
| 6125 } | |
| 6126 | |
| 6127 | |
| 6128 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); | |
| 6129 Statement* validate_throw_output; | |
| 6130 { | |
| 6131 Expression* is_receiver_call; | |
| 6132 { | |
| 6133 auto args = new (zone) ZoneList<Expression*>(1, zone); | |
| 6134 args->Add(factory->NewVariableProxy(var_output), zone); | |
| 6135 is_receiver_call = | |
| 6136 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); | |
| 6137 } | |
| 6138 | |
| 6139 Statement* throw_call; | |
| 6140 { | |
| 6141 auto args = new (zone) ZoneList<Expression*>(1, zone); | |
| 6142 args->Add(factory->NewVariableProxy(var_output), zone); | |
| 6143 Expression* call = factory->NewCallRuntime( | |
| 6144 Runtime::kThrowIteratorResultNotAnObject, args, nopos); | |
| 6145 throw_call = factory->NewExpressionStatement(call, nopos); | |
| 6146 } | |
| 6147 | |
| 6148 validate_throw_output = | |
| 6149 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); | |
| 6150 } | |
| 6151 | |
| 6152 | |
| 6153 // if (output.done) break; | |
| 6154 Statement* if_done; | |
| 6155 { | |
| 6156 Expression* output_proxy = factory->NewVariableProxy(var_output); | |
| 6157 Expression* literal = | |
| 6158 factory->NewStringLiteral(avfactory->done_string(), nopos); | |
| 6159 Expression* property = factory->NewProperty(output_proxy, literal, nopos); | |
| 6160 BreakStatement* break_loop = factory->NewBreakStatement(loop, nopos); | |
| 6161 if_done = factory->NewIfStatement(property, break_loop, skip, nopos); | |
| 6162 } | |
| 6163 | |
| 6164 | |
| 6165 // mode = kReturn; | |
| 6166 Statement* set_mode_return; | |
| 6167 { | |
| 6168 Expression* mode_proxy = factory->NewVariableProxy(var_mode); | |
| 6169 Expression* kreturn = factory->NewSmiLiteral(kReturn, nopos); | |
| 6170 Expression* assignment = | |
| 6171 factory->NewAssignment(Token::ASSIGN, mode_proxy, kreturn, nopos); | |
| 6172 set_mode_return = factory->NewExpressionStatement(assignment, nopos); | |
| 6173 } | |
| 6174 | |
| 6175 | |
| 6176 // RawYield(output); | |
| 6177 Statement* yield_output; | |
| 6178 { | |
| 6179 Expression* output_proxy = factory->NewVariableProxy(var_output); | |
| 6180 Yield* yield = factory->NewYield( | |
| 6181 generator, output_proxy, Yield::kInitial, nopos); | |
| 6182 yield_output = factory->NewExpressionStatement(yield, nopos); | |
| 6183 } | |
| 6184 | |
| 6185 | |
| 6186 // mode = kNext; | |
| 6187 Statement* set_mode_next; | |
| 6188 { | |
| 6189 Expression* mode_proxy = factory->NewVariableProxy(var_mode); | |
| 6190 Expression* knext = factory->NewSmiLiteral(kNext, nopos); | |
| 6191 Expression* assignment = | |
| 6192 factory->NewAssignment(Token::ASSIGN, mode_proxy, knext, nopos); | |
| 6193 set_mode_next = factory->NewExpressionStatement(assignment, nopos); | |
| 6194 } | |
| 6195 | |
| 6196 | |
| 6197 // mode = kThrow; | |
| 6198 Statement* set_mode_throw; | |
| 6199 { | |
| 6200 Expression* mode_proxy = factory->NewVariableProxy(var_mode); | |
| 6201 Expression* kthrow = factory->NewSmiLiteral(kThrow, nopos); | |
| 6202 Expression* assignment = | |
| 6203 factory->NewAssignment(Token::ASSIGN, mode_proxy, kthrow, nopos); | |
| 6204 set_mode_throw = factory->NewExpressionStatement(assignment, nopos); | |
| 6205 } | |
| 6206 | |
| 6207 | |
| 6208 // input = function.sent; | |
| 6209 Statement* get_input; | |
| 6210 { | |
| 6211 Expression* function_sent = FunctionSentExpression(scope, factory, nopos); | |
| 6212 Expression* input_proxy = factory->NewVariableProxy(var_input); | |
| 6213 Expression* assignment = factory->NewAssignment( | |
| 6214 Token::ASSIGN, input_proxy, function_sent, nopos); | |
| 6215 get_input = factory->NewExpressionStatement(assignment, nopos); | |
| 6216 } | |
| 6217 | |
| 6218 | |
| 6219 // output.value; | |
| 6220 Statement* get_value; | |
| 6221 { | |
| 6222 Expression* output_proxy = factory->NewVariableProxy(var_output); | |
| 6223 Expression* literal = | |
| 6224 factory->NewStringLiteral(avfactory->value_string(), nopos); | |
| 6225 Expression* property = factory->NewProperty(output_proxy, literal, nopos); | |
| 6226 get_value = factory->NewExpressionStatement(property, nopos); | |
| 6227 } | |
| 6228 | |
| 6229 | |
| 6230 // Now put things together. | |
| 6231 | |
| 6232 | |
| 6233 // try { ... } catch(e) { ... } | |
| 6234 Statement* try_catch; | |
| 6235 { | |
| 6236 Block* try_block = factory->NewBlock(nullptr, 2, false, nopos); | |
| 6237 try_block->statements()->Add(yield_output, zone); | |
| 6238 try_block->statements()->Add(set_mode_next, zone); | |
| 6239 | |
| 6240 Block* catch_block = factory->NewBlock(nullptr, 1, false, nopos); | |
| 6241 catch_block->statements()->Add(set_mode_throw, zone); | |
| 6242 | |
| 6243 Scope* catch_scope = NewScope(scope, CATCH_SCOPE); | |
| 6244 const AstRawString* name = avfactory->dot_catch_string(); | |
| 6245 Variable* catch_variable = | |
| 6246 catch_scope->DeclareLocal(name, VAR, kCreatedInitialized, | |
| 6247 Variable::NORMAL); | |
| 6248 | |
| 6249 try_catch = factory->NewTryCatchStatement( | |
| 6250 try_block, catch_scope, catch_variable, catch_block, nopos); | |
| 6251 } | |
| 6252 | |
| 6253 | |
| 6254 // try { ... } finally { ... } | |
| 6255 Statement* try_finally; | |
| 6256 { | |
| 6257 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos); | |
| 6258 try_block->statements()->Add(try_catch, zone); | |
| 6259 | |
| 6260 Block* finally = factory->NewBlock(nullptr, 2, false, nopos); | |
| 6261 finally->statements()->Add(get_input, zone); | |
| 6262 finally->statements()->Add( | |
| 6263 factory->NewContinueStatement(loop, nopos), zone); | |
| 6264 | |
| 6265 try_finally = factory->NewTryFinallyStatement(try_block, finally, nopos); | |
| 6266 } | |
| 6267 | |
| 6268 | |
| 6269 // switch (mode) { ... } | |
| 6270 SwitchStatement* switch_mode = factory->NewSwitchStatement(nullptr, nopos); | |
| 6271 { | |
| 6272 auto case_next = new (zone) ZoneList<Statement*>(3, zone); | |
| 6273 case_next->Add(call_next, zone); | |
| 6274 case_next->Add(validate_next_output, zone); | |
| 6275 case_next->Add(factory->NewBreakStatement(switch_mode, nopos), zone); | |
| 6276 | |
| 6277 auto case_return = new (zone) ZoneList<Statement*>(5, zone); | |
| 6278 case_return->Add(get_return, zone); | |
| 6279 case_return->Add(check_return, zone); | |
| 6280 case_return->Add(call_return, zone); | |
| 6281 case_return->Add(validate_return_output, zone); | |
| 6282 case_return->Add(factory->NewBreakStatement(switch_mode, nopos), zone); | |
| 6283 | |
| 6284 auto case_throw = new (zone) ZoneList<Statement*>(5, zone); | |
| 6285 case_throw->Add(get_throw, zone); | |
| 6286 case_throw->Add(check_throw, zone); | |
| 6287 case_throw->Add(call_throw, zone); | |
| 6288 case_throw->Add(validate_throw_output, zone); | |
| 6289 case_throw->Add(factory->NewBreakStatement(switch_mode, nopos), zone); | |
| 6290 | |
| 6291 auto cases = new (zone) ZoneList<CaseClause*>(3, zone); | |
| 6292 Expression* knext = factory->NewSmiLiteral(kNext, nopos); | |
| 6293 Expression* kreturn = factory->NewSmiLiteral(kReturn, nopos); | |
| 6294 Expression* kthrow = factory->NewSmiLiteral(kThrow, nopos); | |
| 6295 cases->Add(factory->NewCaseClause(knext, case_next, nopos), zone); | |
| 6296 cases->Add(factory->NewCaseClause(kreturn, case_return, nopos), zone); | |
| 6297 cases->Add(factory->NewCaseClause(kthrow, case_throw, nopos), zone); | |
| 6298 | |
| 6299 switch_mode->Initialize(factory->NewVariableProxy(var_mode), cases); | |
| 6300 } | |
| 6301 | |
| 6302 | |
| 6303 // while (true) { ... } | |
| 6304 // Already defined earlier: WhileStatement* loop = ... | |
| 6305 { | |
| 6306 Block* loop_body = factory->NewBlock(nullptr, 4, false, nopos); | |
| 6307 loop_body->statements()->Add(switch_mode, zone); | |
| 6308 loop_body->statements()->Add(if_done, zone); | |
| 6309 loop_body->statements()->Add(set_mode_return, zone); | |
| 6310 loop_body->statements()->Add(try_finally, zone); | |
| 6311 | |
| 6312 loop->Initialize(factory->NewBooleanLiteral(true, nopos), loop_body); | |
| 6313 } | |
| 6314 | |
| 6315 | |
| 6316 // do { ... } | |
| 6317 DoExpression* yield_star; | |
| 6318 { | |
| 6319 // The rewriter needs to process the get_value statement only, hence we | |
| 6320 // put the preceding statements into an init block. | |
| 6321 | |
| 6322 Block* do_block_ = factory->NewBlock(nullptr, 6, true, nopos); | |
| 6323 do_block_->statements()->Add(initialize_input, zone); | |
| 6324 do_block_->statements()->Add(initialize_mode, zone); | |
| 6325 do_block_->statements()->Add(initialize_output, zone); | |
| 6326 do_block_->statements()->Add(get_iterator, zone); | |
| 6327 do_block_->statements()->Add(validate_iterator, zone); | |
| 6328 do_block_->statements()->Add(loop, zone); | |
| 6329 | |
| 6330 Block* do_block = factory->NewBlock(nullptr, 2, false, nopos); | |
| 6331 do_block->statements()->Add(do_block_, zone); | |
| 6332 do_block->statements()->Add(get_value, zone); | |
| 6333 | |
| 6334 Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string()); | |
| 6335 yield_star = factory->NewDoExpression(do_block, dot_result, nopos); | |
| 6336 Rewriter::Rewrite(parser_, yield_star, avfactory); | |
| 6337 } | |
| 6338 | |
| 6339 return yield_star; | |
| 6340 } | |
| 6341 | |
| 6342 | |
| 6343 void ParserTraits::BuildIteratorClose( | |
| 6344 ZoneList<Statement*>* statements, Variable* iterator) { | |
| 6345 | |
| 6346 const int nopos = RelocInfo::kNoPosition; | |
| 6347 auto factory = parser_->factory(); | |
| 6348 auto avfactory = parser_->ast_value_factory(); | |
| 6349 auto scope = parser_->scope_; | |
| 6350 auto zone = parser_->zone(); | |
| 6351 Statement* skip = factory->NewEmptyStatement(nopos); | |
| 6352 | |
| 6353 // let iteratorReturn = iterator.return; | |
| 6354 Variable* var = scope->NewTemporary(avfactory->empty_string()); | |
| 6355 Statement* get_return; | |
| 6356 { | |
| 6357 Expression* iterator_proxy = factory->NewVariableProxy(iterator); | |
| 6358 Expression* literal = | |
| 6359 factory->NewStringLiteral(avfactory->return_string(), nopos); | |
| 6360 Expression* property = | |
| 6361 factory->NewProperty(iterator_proxy, literal, nopos); | |
| 6362 Expression* return_proxy = factory->NewVariableProxy(var); | |
| 6363 Expression* assignment = factory->NewAssignment( | |
| 6364 Token::ASSIGN, return_proxy, property, nopos); | |
| 6365 get_return = factory->NewExpressionStatement(assignment, nopos); | |
| 6366 } | |
| 6367 | |
| 6368 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return; | |
| 6369 Statement* check_return; | |
| 6370 { | |
| 6371 Expression* condition = factory->NewCompareOperation( | |
| 6372 Token::EQ, factory->NewVariableProxy(var), | |
| 6373 factory->NewNullLiteral(nopos), nopos); | |
| 6374 | |
| 6375 Statement* return_undefined = factory->NewReturnStatement( | |
| 6376 factory->NewUndefinedLiteral(nopos), nopos); | |
| 6377 | |
| 6378 check_return = | |
| 6379 factory->NewIfStatement(condition, return_undefined, skip, nopos); | |
| 6380 } | |
| 6381 | |
| 6382 // let result = %_Call(iteratorReturn, iterator); | |
| 6383 Statement* call_return; | |
| 6384 { | |
| 6385 auto args = new (zone) ZoneList<Expression*>(2, zone); | |
| 6386 args->Add(factory->NewVariableProxy(var), zone); | |
| 6387 args->Add(factory->NewVariableProxy(iterator), zone); | |
| 6388 Expression* call = | |
| 6389 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos); | |
| 6390 Expression* assignment = factory->NewAssignment( | |
| 6391 Token::ASSIGN, factory->NewVariableProxy(var), call, nopos); | |
| 6392 call_return = factory->NewExpressionStatement(assignment, nopos); | |
| 6393 } | |
| 6394 | |
| 6395 // if (!IS_RECEIVER(result)) %ThrowIterResultNotAnObject(result); | |
| 6396 Statement* validate_result; | |
| 6397 { | |
| 6398 Expression* is_receiver_call; | |
| 6399 { | |
| 6400 auto args = new (zone) ZoneList<Expression*>(1, zone); | |
| 6401 args->Add(factory->NewVariableProxy(var), zone); | |
| 6402 is_receiver_call = | |
| 6403 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); | |
| 6404 } | |
| 6405 | |
| 6406 Statement* throw_call; | |
| 6407 { | |
| 6408 auto args = new (zone) ZoneList<Expression*>(1, zone); | |
| 6409 args->Add(factory->NewVariableProxy(var), zone); | |
| 6410 Expression* call = factory->NewCallRuntime( | |
| 6411 Runtime::kThrowIteratorResultNotAnObject, args, nopos); | |
| 6412 throw_call = factory->NewExpressionStatement(call, nopos); | |
| 6413 } | |
| 6414 | |
| 6415 validate_result = | |
| 6416 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); | |
| 6417 } | |
| 6418 | |
| 6419 statements->Add(get_return, zone); | |
| 6420 statements->Add(check_return, zone); | |
| 6421 statements->Add(call_return, zone); | |
| 6422 statements->Add(validate_result, zone); | |
| 6423 } | |
| 6424 | |
| 6425 | |
| 5800 } // namespace internal | 6426 } // namespace internal |
| 5801 } // namespace v8 | 6427 } // namespace v8 |
| OLD | NEW |