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 6221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6232 do_block->statements()->Add(get_value, zone); | 6232 do_block->statements()->Add(get_value, zone); |
| 6233 | 6233 |
| 6234 Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string()); | 6234 Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string()); |
| 6235 yield_star = factory->NewDoExpression(do_block, dot_result, nopos); | 6235 yield_star = factory->NewDoExpression(do_block, dot_result, nopos); |
| 6236 Rewriter::Rewrite(parser_, yield_star, avfactory); | 6236 Rewriter::Rewrite(parser_, yield_star, avfactory); |
| 6237 } | 6237 } |
| 6238 | 6238 |
| 6239 return yield_star; | 6239 return yield_star; |
| 6240 } | 6240 } |
| 6241 | 6241 |
| 6242 // Desugaring of (lhs) instanceof (rhs) | |
| 6243 // ==================== | |
|
rossberg
2016/02/12 14:11:31
Nit: underline all of it?
mvstanton
2016/02/18 02:12:17
Done.
| |
| 6244 // | |
| 6245 // We desugar instanceof into a load of property @@hasInstance on the rhs. | |
| 6246 // We end up with roughly the following code (O, C): | |
| 6247 // | |
| 6248 // do { | |
| 6249 // let O = lhs; | |
| 6250 // let C = rhs; | |
| 6251 // let result; | |
| 6252 // if (!IS_RECEIVER(C)) throw MakeTypeError(kNonObjectInInstanceOfCheck); | |
| 6253 // let handler = C[Symbol.hasInstance]; | |
| 6254 // if (handler === undefined) { | |
| 6255 // result = %ordinary_has_instance(C, O); | |
|
mvstanton
2016/02/18 02:12:17
I had to add an IS_CALLABLE check here, because %o
| |
| 6256 // } else { | |
| 6257 // if (!%IsCallable(handler)) { | |
|
rossberg
2016/02/12 14:11:32
Is this actually necessary? %_Call would throw the
mvstanton
2016/02/18 02:12:17
Indeed, I was able to remove it, thanks!
| |
| 6258 // throw MakeTypeError(kFoundNonCallableHasInstance); | |
| 6259 // } | |
| 6260 // result = !!(%_Call(handler, C, O)); | |
| 6261 // } | |
| 6262 // } | |
|
rossberg
2016/02/12 14:11:31
result; as the last statement?
mvstanton
2016/02/18 02:12:17
Done.
| |
| 6263 // | |
| 6264 Expression* ParserTraits::RewriteInstanceof(Expression* lhs, Expression* rhs, | |
| 6265 int pos) { | |
| 6266 const int nopos = RelocInfo::kNoPosition; | |
| 6267 | |
| 6268 auto factory = parser_->factory(); | |
| 6269 auto avfactory = parser_->ast_value_factory(); | |
| 6270 auto scope = parser_->scope_; | |
| 6271 auto zone = parser_->zone(); | |
| 6272 | |
| 6273 // let O = lhs; | |
| 6274 Variable* var_O = scope->NewTemporary(avfactory->empty_string()); | |
| 6275 Statement* get_O; | |
| 6276 { | |
| 6277 Expression* O_proxy = factory->NewVariableProxy(var_O); | |
| 6278 Expression* assignment = | |
| 6279 factory->NewAssignment(Token::ASSIGN, O_proxy, lhs, nopos); | |
| 6280 get_O = factory->NewExpressionStatement(assignment, nopos); | |
| 6281 } | |
| 6282 | |
| 6283 // let C = lhs; | |
| 6284 Variable* var_C = scope->NewTemporary(avfactory->empty_string()); | |
| 6285 Statement* get_C; | |
| 6286 { | |
| 6287 Expression* C_proxy = factory->NewVariableProxy(var_C); | |
| 6288 Expression* assignment = | |
| 6289 factory->NewAssignment(Token::ASSIGN, C_proxy, rhs, nopos); | |
| 6290 get_C = factory->NewExpressionStatement(assignment, nopos); | |
| 6291 } | |
| 6292 | |
| 6293 Statement* skip = factory->NewEmptyStatement(nopos); | |
|
rossberg
2016/02/12 14:11:31
It looks like you are using this AST node twice. T
mvstanton
2016/02/18 02:12:17
Done.
| |
| 6294 | |
| 6295 // if (!IS_RECEIVER(C)) throw MakeTypeError(kNonObjectInInstanceOfCheck); | |
| 6296 Statement* validate_C; | |
| 6297 { | |
| 6298 Expression* is_receiver_call; | |
| 6299 { | |
| 6300 auto args = new (zone) ZoneList<Expression*>(1, zone); | |
| 6301 args->Add(factory->NewVariableProxy(var_C), zone); | |
| 6302 is_receiver_call = | |
| 6303 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); | |
| 6304 } | |
| 6305 | |
| 6306 Statement* throw_call; | |
| 6307 { | |
| 6308 Expression* call = | |
| 6309 NewThrowTypeError(MessageTemplate::kNonObjectInInstanceOfCheck, | |
| 6310 avfactory->empty_string(), nopos); | |
| 6311 throw_call = factory->NewExpressionStatement(call, nopos); | |
| 6312 } | |
| 6313 | |
| 6314 validate_C = | |
| 6315 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); | |
| 6316 } | |
| 6317 | |
| 6318 Variable* var_result = scope->NewTemporary(avfactory->empty_string()); | |
|
rossberg
2016/02/12 14:11:32
Nit: you can probably reuse the same temporary for
mvstanton
2016/02/18 02:12:17
Done.
| |
| 6319 | |
| 6320 // let handler = C[Symbol.hasInstance]; | |
| 6321 Variable* var_handler = scope->NewTemporary(avfactory->empty_string()); | |
| 6322 Statement* initialize_handler; | |
| 6323 { | |
| 6324 Expression* hasInstance_symbol_literal = | |
| 6325 factory->NewSymbolLiteral("hasInstance_symbol", RelocInfo::kNoPosition); | |
| 6326 Expression* prop = factory->NewProperty(factory->NewVariableProxy(var_C), | |
| 6327 hasInstance_symbol_literal, pos); | |
| 6328 Expression* handler_proxy = factory->NewVariableProxy(var_handler); | |
| 6329 Expression* assignment = | |
| 6330 factory->NewAssignment(Token::ASSIGN, handler_proxy, prop, nopos); | |
| 6331 initialize_handler = factory->NewExpressionStatement(assignment, nopos); | |
| 6332 } | |
| 6333 | |
| 6334 // if (handler === undefined) { | |
| 6335 // result = %ordinary_has_instance(C, O); | |
| 6336 // } else { | |
| 6337 // result = !!%_Call(handler, C, O); | |
| 6338 // } | |
| 6339 Statement* call_handler; | |
| 6340 { | |
| 6341 Expression* condition = factory->NewCompareOperation( | |
| 6342 Token::EQ_STRICT, factory->NewVariableProxy(var_handler), | |
| 6343 factory->NewUndefinedLiteral(nopos), nopos); | |
| 6344 Statement* then_side; | |
| 6345 { | |
| 6346 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone); | |
| 6347 args->Add(factory->NewVariableProxy(var_C), zone); | |
| 6348 args->Add(factory->NewVariableProxy(var_O), zone); | |
| 6349 CallRuntime* call = factory->NewCallRuntime( | |
| 6350 Context::ORDINARY_HAS_INSTANCE_INDEX, args, pos); | |
| 6351 Expression* result_proxy = factory->NewVariableProxy(var_result); | |
| 6352 Expression* assignment = | |
| 6353 factory->NewAssignment(Token::ASSIGN, result_proxy, call, nopos); | |
| 6354 then_side = factory->NewExpressionStatement(assignment, nopos); | |
| 6355 } | |
| 6356 Statement* else_side; | |
| 6357 { | |
| 6358 Block* block = factory->NewBlock(nullptr, 2, true, nopos); | |
| 6359 | |
| 6360 // if (!%IsCallable(handler)) { | |
| 6361 // throw MakeTypeError(kFoundNonCallableHasInstance); | |
| 6362 // } | |
| 6363 Statement* validate_handler; | |
| 6364 { | |
| 6365 Expression* is_callable_call; | |
| 6366 { | |
| 6367 auto args = new (zone) ZoneList<Expression*>(1, zone); | |
| 6368 args->Add(factory->NewVariableProxy(var_handler), zone); | |
| 6369 is_callable_call = | |
| 6370 factory->NewCallRuntime(Runtime::kIsCallable, args, nopos); | |
| 6371 } | |
| 6372 | |
| 6373 Statement* throw_call; | |
| 6374 { | |
| 6375 Expression* call = | |
| 6376 NewThrowTypeError(MessageTemplate::kFoundNonCallableHasInstance, | |
| 6377 avfactory->empty_string(), nopos); | |
| 6378 throw_call = factory->NewExpressionStatement(call, nopos); | |
| 6379 } | |
| 6380 | |
| 6381 validate_handler = | |
| 6382 factory->NewIfStatement(is_callable_call, skip, throw_call, nopos); | |
| 6383 } | |
| 6384 | |
| 6385 auto args = new (zone) ZoneList<Expression*>(3, zone); | |
| 6386 args->Add(factory->NewVariableProxy(var_handler), zone); | |
| 6387 args->Add(factory->NewVariableProxy(var_C), zone); | |
| 6388 args->Add(factory->NewVariableProxy(var_O), zone); | |
| 6389 Expression* call = | |
| 6390 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos); | |
| 6391 Expression* inner_not = | |
| 6392 factory->NewUnaryOperation(Token::NOT, call, nopos); | |
| 6393 Expression* outer_not = | |
| 6394 factory->NewUnaryOperation(Token::NOT, inner_not, nopos); | |
| 6395 Expression* result_proxy = factory->NewVariableProxy(var_result); | |
| 6396 Expression* assignment = | |
| 6397 factory->NewAssignment(Token::ASSIGN, result_proxy, outer_not, nopos); | |
| 6398 Statement* assignment_return = | |
| 6399 factory->NewExpressionStatement(assignment, nopos); | |
| 6400 | |
| 6401 block->statements()->Add(validate_handler, zone); | |
| 6402 block->statements()->Add(assignment_return, zone); | |
| 6403 | |
| 6404 else_side = block; | |
| 6405 } | |
| 6406 call_handler = | |
| 6407 factory->NewIfStatement(condition, then_side, else_side, nopos); | |
| 6408 } | |
| 6409 | |
| 6410 // do { ... } | |
| 6411 DoExpression* instanceof; | |
| 6412 { | |
| 6413 Block* block = factory->NewBlock(nullptr, 5, true, nopos); | |
| 6414 block->statements()->Add(get_O, zone); | |
| 6415 block->statements()->Add(get_C, zone); | |
| 6416 block->statements()->Add(validate_C, zone); | |
| 6417 block->statements()->Add(initialize_handler, zone); | |
| 6418 block->statements()->Add(call_handler, zone); | |
| 6419 | |
| 6420 // Here is the desugared instanceof. | |
| 6421 instanceof = factory->NewDoExpression(block, var_result, nopos); | |
| 6422 Rewriter::Rewrite(parser_, instanceof, avfactory); | |
| 6423 } | |
| 6424 | |
| 6425 return instanceof; | |
| 6426 } | |
| 6242 | 6427 |
| 6243 void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, | 6428 void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, |
| 6244 Variable* iterator, | 6429 Variable* iterator, |
| 6245 Maybe<Variable*> input, | 6430 Maybe<Variable*> input, |
| 6246 Maybe<Variable*> output) { | 6431 Maybe<Variable*> output) { |
| 6247 const int nopos = RelocInfo::kNoPosition; | 6432 const int nopos = RelocInfo::kNoPosition; |
| 6248 auto factory = parser_->factory(); | 6433 auto factory = parser_->factory(); |
| 6249 auto avfactory = parser_->ast_value_factory(); | 6434 auto avfactory = parser_->ast_value_factory(); |
| 6250 auto scope = parser_->scope_; | 6435 auto scope = parser_->scope_; |
| 6251 auto zone = parser_->zone(); | 6436 auto zone = parser_->zone(); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6330 | 6515 |
| 6331 statements->Add(get_return, zone); | 6516 statements->Add(get_return, zone); |
| 6332 statements->Add(check_return, zone); | 6517 statements->Add(check_return, zone); |
| 6333 statements->Add(call_return, zone); | 6518 statements->Add(call_return, zone); |
| 6334 statements->Add(validate_output, zone); | 6519 statements->Add(validate_output, zone); |
| 6335 } | 6520 } |
| 6336 | 6521 |
| 6337 | 6522 |
| 6338 } // namespace internal | 6523 } // namespace internal |
| 6339 } // namespace v8 | 6524 } // namespace v8 |
| OLD | NEW |