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 6270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6281 do_block->statements()->Add(get_value, zone); | 6281 do_block->statements()->Add(get_value, zone); |
| 6282 | 6282 |
| 6283 Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string()); | 6283 Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string()); |
| 6284 yield_star = factory->NewDoExpression(do_block, dot_result, nopos); | 6284 yield_star = factory->NewDoExpression(do_block, dot_result, nopos); |
| 6285 Rewriter::Rewrite(parser_, yield_star, avfactory); | 6285 Rewriter::Rewrite(parser_, yield_star, avfactory); |
| 6286 } | 6286 } |
| 6287 | 6287 |
| 6288 return yield_star; | 6288 return yield_star; |
| 6289 } | 6289 } |
| 6290 | 6290 |
| 6291 // Desugaring of (lhs) instanceof (rhs) | |
| 6292 // ==================================== | |
| 6293 // | |
| 6294 // We desugar instanceof into a load of property @@hasInstance on the rhs. | |
| 6295 // We end up with roughly the following code (O, C): | |
| 6296 // | |
| 6297 // do { | |
| 6298 // let O = lhs; | |
| 6299 // let C = rhs; | |
| 6300 // if (!IS_RECEIVER(C)) throw MakeTypeError(kNonObjectInInstanceOfCheck); | |
| 6301 // let handler_result = C[Symbol.hasInstance]; | |
| 6302 // if (handler_result === undefined) { | |
| 6303 // if (!IS_CALLABLE(C)) { | |
| 6304 // throw MakeTypeError(kCalledNonCallableInstanceOf); | |
| 6305 // } | |
| 6306 // handler_result = %ordinary_has_instance(C, O); | |
| 6307 // } else { | |
| 6308 // handler_result = !!(%_Call(handler_result, C, O)); | |
| 6309 // } | |
| 6310 // handler_result; | |
| 6311 // } | |
| 6312 // | |
| 6313 Expression* ParserTraits::RewriteInstanceof(Expression* lhs, Expression* rhs, | |
| 6314 int pos) { | |
| 6315 const int nopos = RelocInfo::kNoPosition; | |
| 6316 | |
| 6317 auto factory = parser_->factory(); | |
| 6318 auto avfactory = parser_->ast_value_factory(); | |
| 6319 auto scope = parser_->scope_; | |
| 6320 auto zone = parser_->zone(); | |
| 6321 | |
| 6322 // let O = lhs; | |
| 6323 Variable* var_O = scope->NewTemporary(avfactory->empty_string()); | |
| 6324 Statement* get_O; | |
| 6325 { | |
| 6326 Expression* O_proxy = factory->NewVariableProxy(var_O); | |
| 6327 Expression* assignment = | |
| 6328 factory->NewAssignment(Token::ASSIGN, O_proxy, lhs, nopos); | |
| 6329 get_O = factory->NewExpressionStatement(assignment, nopos); | |
| 6330 } | |
| 6331 | |
| 6332 // let C = lhs; | |
| 6333 Variable* var_C = scope->NewTemporary(avfactory->empty_string()); | |
| 6334 Statement* get_C; | |
| 6335 { | |
| 6336 Expression* C_proxy = factory->NewVariableProxy(var_C); | |
| 6337 Expression* assignment = | |
| 6338 factory->NewAssignment(Token::ASSIGN, C_proxy, rhs, nopos); | |
| 6339 get_C = factory->NewExpressionStatement(assignment, nopos); | |
| 6340 } | |
| 6341 | |
| 6342 // if (!IS_RECEIVER(C)) throw MakeTypeError(kNonObjectInInstanceOfCheck); | |
| 6343 Statement* validate_C; | |
| 6344 { | |
| 6345 auto args = new (zone) ZoneList<Expression*>(1, zone); | |
| 6346 args->Add(factory->NewVariableProxy(var_C), zone); | |
| 6347 Expression* is_receiver_call = | |
| 6348 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); | |
| 6349 Expression* call = | |
| 6350 NewThrowTypeError(MessageTemplate::kNonObjectInInstanceOfCheck, | |
| 6351 avfactory->empty_string(), nopos); | |
| 6352 Statement* throw_call = factory->NewExpressionStatement(call, nopos); | |
| 6353 | |
| 6354 validate_C = | |
| 6355 factory->NewIfStatement(is_receiver_call, | |
| 6356 factory->NewEmptyStatement(nopos), | |
| 6357 throw_call, | |
| 6358 nopos); | |
| 6359 } | |
| 6360 | |
| 6361 // let handler_result = C[Symbol.hasInstance]; | |
| 6362 Variable* var_handler_result = scope->NewTemporary(avfactory->empty_string()); | |
| 6363 Statement* initialize_handler; | |
| 6364 { | |
| 6365 Expression* hasInstance_symbol_literal = | |
| 6366 factory->NewSymbolLiteral("hasInstance_symbol", RelocInfo::kNoPosition); | |
| 6367 Expression* prop = factory->NewProperty(factory->NewVariableProxy(var_C), | |
| 6368 hasInstance_symbol_literal, pos); | |
| 6369 Expression* handler_proxy = factory->NewVariableProxy(var_handler_result); | |
| 6370 Expression* assignment = | |
| 6371 factory->NewAssignment(Token::ASSIGN, handler_proxy, prop, nopos); | |
| 6372 initialize_handler = factory->NewExpressionStatement(assignment, nopos); | |
| 6373 } | |
| 6374 | |
| 6375 // if (handler_result === undefined) { | |
| 6376 // if (!IS_CALLABLE(C)) { | |
| 6377 // throw MakeTypeError(kCalledNonCallableInstanceOf); | |
| 6378 // } | |
| 6379 // result = %ordinary_has_instance(C, O); | |
| 6380 // } else { | |
| 6381 // handler_result = !!%_Call(handler_result, C, O); | |
| 6382 // } | |
| 6383 Statement* call_handler; | |
| 6384 { | |
| 6385 Expression* condition = factory->NewCompareOperation( | |
| 6386 Token::EQ_STRICT, factory->NewVariableProxy(var_handler_result), | |
| 6387 factory->NewUndefinedLiteral(nopos), nopos); | |
| 6388 | |
| 6389 Block* then_side = factory->NewBlock(nullptr, 2, false, nopos); | |
| 6390 { | |
| 6391 Expression* throw_expr = | |
| 6392 NewThrowTypeError(MessageTemplate::kCalledNonCallableInstanceOf, | |
| 6393 avfactory->empty_string(), nopos); | |
| 6394 Statement* validate_C = CheckCallable(var_C, throw_expr); | |
| 6395 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone); | |
| 6396 args->Add(factory->NewVariableProxy(var_C), zone); | |
| 6397 args->Add(factory->NewVariableProxy(var_O), zone); | |
| 6398 CallRuntime* call = factory->NewCallRuntime( | |
| 6399 Context::ORDINARY_HAS_INSTANCE_INDEX, args, pos); | |
| 6400 Expression* result_proxy = factory->NewVariableProxy(var_handler_result); | |
| 6401 Expression* assignment = | |
| 6402 factory->NewAssignment(Token::ASSIGN, result_proxy, call, nopos); | |
| 6403 Statement* assignment_return = | |
| 6404 factory->NewExpressionStatement(assignment, nopos); | |
| 6405 | |
| 6406 then_side->statements()->Add(validate_C, zone); | |
| 6407 then_side->statements()->Add(assignment_return, zone); | |
| 6408 } | |
| 6409 | |
| 6410 Statement* else_side; | |
| 6411 { | |
| 6412 auto args = new (zone) ZoneList<Expression*>(3, zone); | |
| 6413 args->Add(factory->NewVariableProxy(var_handler_result), zone); | |
| 6414 args->Add(factory->NewVariableProxy(var_C), zone); | |
| 6415 args->Add(factory->NewVariableProxy(var_O), zone); | |
| 6416 Expression* call = | |
| 6417 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos); | |
| 6418 Expression* inner_not = | |
| 6419 factory->NewUnaryOperation(Token::NOT, call, nopos); | |
| 6420 Expression* outer_not = | |
| 6421 factory->NewUnaryOperation(Token::NOT, inner_not, nopos); | |
| 6422 Expression* result_proxy = factory->NewVariableProxy(var_handler_result); | |
| 6423 Expression* assignment = | |
| 6424 factory->NewAssignment(Token::ASSIGN, result_proxy, outer_not, nopos); | |
| 6425 | |
| 6426 else_side = factory->NewExpressionStatement(assignment, nopos); | |
| 6427 } | |
| 6428 call_handler = | |
| 6429 factory->NewIfStatement(condition, then_side, else_side, nopos); | |
| 6430 } | |
| 6431 | |
| 6432 // do { ... } | |
| 6433 DoExpression* instanceof; | |
| 6434 { | |
| 6435 Block* block = factory->NewBlock(nullptr, 5, true, nopos); | |
| 6436 block->statements()->Add(get_O, zone); | |
| 6437 block->statements()->Add(get_C, zone); | |
| 6438 block->statements()->Add(validate_C, zone); | |
| 6439 block->statements()->Add(initialize_handler, zone); | |
| 6440 block->statements()->Add(call_handler, zone); | |
| 6441 | |
| 6442 // Here is the desugared instanceof. | |
| 6443 instanceof = factory->NewDoExpression(block, var_handler_result, nopos); | |
| 6444 Rewriter::Rewrite(parser_, instanceof, avfactory); | |
| 6445 } | |
| 6446 | |
| 6447 return instanceof; | |
| 6448 } | |
| 6449 | |
| 6450 Statement* ParserTraits::CheckCallable(Variable* var, Expression* error) { | |
|
rossberg
2016/02/19 12:19:00
Given that my CL has landed, can you now change Fi
mvstanton
2016/02/19 18:15:59
Done.
| |
| 6451 auto factory = parser_->factory(); | |
| 6452 auto avfactory = parser_->ast_value_factory(); | |
| 6453 const int nopos = RelocInfo::kNoPosition; | |
| 6454 Statement* validate_var; | |
| 6455 { | |
| 6456 Expression* type_of = factory->NewUnaryOperation( | |
| 6457 Token::TYPEOF, factory->NewVariableProxy(var), nopos); | |
| 6458 Expression* function_literal = | |
| 6459 factory->NewStringLiteral(avfactory->function_string(), nopos); | |
| 6460 Expression* condition = factory->NewCompareOperation( | |
| 6461 Token::EQ_STRICT, type_of, function_literal, nopos); | |
| 6462 | |
| 6463 Statement* throw_call = factory->NewExpressionStatement(error, nopos); | |
| 6464 | |
| 6465 validate_var = factory->NewIfStatement( | |
| 6466 condition, factory->NewEmptyStatement(nopos), throw_call, nopos); | |
| 6467 } | |
| 6468 return validate_var; | |
| 6469 } | |
| 6291 | 6470 |
| 6292 void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, | 6471 void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, |
| 6293 Variable* iterator, | 6472 Variable* iterator, |
| 6294 Expression* input, | 6473 Expression* input, |
| 6295 Variable* var_output) { | 6474 Variable* var_output) { |
| 6296 // | 6475 // |
| 6297 // This function adds four statements to [statements], corresponding to the | 6476 // This function adds four statements to [statements], corresponding to the |
| 6298 // following code: | 6477 // following code: |
| 6299 // | 6478 // |
| 6300 // let iteratorReturn = iterator.return; | 6479 // let iteratorReturn = iterator.return; |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6727 new_body->statements()->Add(loop->body(), zone); | 6906 new_body->statements()->Add(loop->body(), zone); |
| 6728 new_body->statements()->Add(set_completion_normal, zone); | 6907 new_body->statements()->Add(set_completion_normal, zone); |
| 6729 | 6908 |
| 6730 loop->set_body(new_body); | 6909 loop->set_body(new_body); |
| 6731 return final_loop; | 6910 return final_loop; |
| 6732 } | 6911 } |
| 6733 | 6912 |
| 6734 | 6913 |
| 6735 } // namespace internal | 6914 } // namespace internal |
| 6736 } // namespace v8 | 6915 } // namespace v8 |
| OLD | NEW |