Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(127)

Side by Side Diff: src/parsing/parser.cc

Issue 1692713005: ES6: Desugaring of instanceof to support @@hasInstance (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@blah
Patch Set: REBASE plus comment response. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 6274 matching lines...) Expand 10 before | Expand all | Expand 10 after
6285 do_block->statements()->Add(get_value, zone); 6285 do_block->statements()->Add(get_value, zone);
6286 6286
6287 Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string()); 6287 Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string());
6288 yield_star = factory->NewDoExpression(do_block, dot_result, nopos); 6288 yield_star = factory->NewDoExpression(do_block, dot_result, nopos);
6289 Rewriter::Rewrite(parser_, yield_star, avfactory); 6289 Rewriter::Rewrite(parser_, yield_star, avfactory);
6290 } 6290 }
6291 6291
6292 return yield_star; 6292 return yield_star;
6293 } 6293 }
6294 6294
6295 // Desugaring of (lhs) instanceof (rhs)
6296 // ====================================
6297 //
6298 // We desugar instanceof into a load of property @@hasInstance on the rhs.
6299 // We end up with roughly the following code (O, C):
6300 //
6301 // do {
6302 // let O = lhs;
6303 // let C = rhs;
6304 // if (!IS_RECEIVER(C)) throw MakeTypeError(kNonObjectInInstanceOfCheck);
6305 // let handler_result = C[Symbol.hasInstance];
6306 // if (handler_result === undefined) {
6307 // if (!IS_CALLABLE(C)) {
6308 // throw MakeTypeError(kCalledNonCallableInstanceOf);
6309 // }
6310 // handler_result = %ordinary_has_instance(C, O);
6311 // } else {
6312 // handler_result = !!(%_Call(handler_result, C, O));
6313 // }
6314 // handler_result;
6315 // }
6316 //
6317 Expression* ParserTraits::RewriteInstanceof(Expression* lhs, Expression* rhs,
6318 int pos) {
6319 const int nopos = RelocInfo::kNoPosition;
6320
6321 auto factory = parser_->factory();
6322 auto avfactory = parser_->ast_value_factory();
6323 auto scope = parser_->scope_;
6324 auto zone = parser_->zone();
6325
6326 // let O = lhs;
6327 Variable* var_O = scope->NewTemporary(avfactory->empty_string());
6328 Statement* get_O;
6329 {
6330 Expression* O_proxy = factory->NewVariableProxy(var_O);
6331 Expression* assignment =
6332 factory->NewAssignment(Token::ASSIGN, O_proxy, lhs, nopos);
6333 get_O = factory->NewExpressionStatement(assignment, nopos);
6334 }
6335
6336 // let C = lhs;
6337 Variable* var_C = scope->NewTemporary(avfactory->empty_string());
6338 Statement* get_C;
6339 {
6340 Expression* C_proxy = factory->NewVariableProxy(var_C);
6341 Expression* assignment =
6342 factory->NewAssignment(Token::ASSIGN, C_proxy, rhs, nopos);
6343 get_C = factory->NewExpressionStatement(assignment, nopos);
6344 }
6345
6346 // if (!IS_RECEIVER(C)) throw MakeTypeError(kNonObjectInInstanceOfCheck);
6347 Statement* validate_C;
6348 {
6349 auto args = new (zone) ZoneList<Expression*>(1, zone);
6350 args->Add(factory->NewVariableProxy(var_C), zone);
6351 Expression* is_receiver_call =
6352 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
6353 Expression* call =
6354 NewThrowTypeError(MessageTemplate::kNonObjectInInstanceOfCheck,
6355 avfactory->empty_string(), nopos);
6356 Statement* throw_call = factory->NewExpressionStatement(call, nopos);
6357
6358 validate_C =
6359 factory->NewIfStatement(is_receiver_call,
6360 factory->NewEmptyStatement(nopos),
6361 throw_call,
6362 nopos);
6363 }
6364
6365 // let handler_result = C[Symbol.hasInstance];
6366 Variable* var_handler_result = scope->NewTemporary(avfactory->empty_string());
6367 Statement* initialize_handler;
6368 {
6369 Expression* hasInstance_symbol_literal =
6370 factory->NewSymbolLiteral("hasInstance_symbol", RelocInfo::kNoPosition);
6371 Expression* prop = factory->NewProperty(factory->NewVariableProxy(var_C),
6372 hasInstance_symbol_literal, pos);
6373 Expression* handler_proxy = factory->NewVariableProxy(var_handler_result);
6374 Expression* assignment =
6375 factory->NewAssignment(Token::ASSIGN, handler_proxy, prop, nopos);
6376 initialize_handler = factory->NewExpressionStatement(assignment, nopos);
6377 }
6378
6379 // if (handler_result === undefined) {
6380 // if (!IS_CALLABLE(C)) {
6381 // throw MakeTypeError(kCalledNonCallableInstanceOf);
6382 // }
6383 // result = %ordinary_has_instance(C, O);
6384 // } else {
6385 // handler_result = !!%_Call(handler_result, C, O);
6386 // }
6387 Statement* call_handler;
6388 {
6389 Expression* condition = factory->NewCompareOperation(
6390 Token::EQ_STRICT, factory->NewVariableProxy(var_handler_result),
6391 factory->NewUndefinedLiteral(nopos), nopos);
6392
6393 Block* then_side = factory->NewBlock(nullptr, 2, false, nopos);
6394 {
6395 Expression* throw_expr =
6396 NewThrowTypeError(MessageTemplate::kCalledNonCallableInstanceOf,
6397 avfactory->empty_string(), nopos);
6398 Statement* validate_C = CheckCallable(var_C, throw_expr);
6399 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone);
6400 args->Add(factory->NewVariableProxy(var_C), zone);
6401 args->Add(factory->NewVariableProxy(var_O), zone);
6402 CallRuntime* call = factory->NewCallRuntime(
6403 Context::ORDINARY_HAS_INSTANCE_INDEX, args, pos);
6404 Expression* result_proxy = factory->NewVariableProxy(var_handler_result);
6405 Expression* assignment =
6406 factory->NewAssignment(Token::ASSIGN, result_proxy, call, nopos);
6407 Statement* assignment_return =
6408 factory->NewExpressionStatement(assignment, nopos);
6409
6410 then_side->statements()->Add(validate_C, zone);
6411 then_side->statements()->Add(assignment_return, zone);
6412 }
6413
6414 Statement* else_side;
6415 {
6416 auto args = new (zone) ZoneList<Expression*>(3, zone);
6417 args->Add(factory->NewVariableProxy(var_handler_result), zone);
6418 args->Add(factory->NewVariableProxy(var_C), zone);
6419 args->Add(factory->NewVariableProxy(var_O), zone);
6420 Expression* call =
6421 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
6422 Expression* inner_not =
6423 factory->NewUnaryOperation(Token::NOT, call, nopos);
6424 Expression* outer_not =
6425 factory->NewUnaryOperation(Token::NOT, inner_not, nopos);
6426 Expression* result_proxy = factory->NewVariableProxy(var_handler_result);
6427 Expression* assignment =
6428 factory->NewAssignment(Token::ASSIGN, result_proxy, outer_not, nopos);
6429
6430 else_side = factory->NewExpressionStatement(assignment, nopos);
6431 }
6432 call_handler =
6433 factory->NewIfStatement(condition, then_side, else_side, nopos);
6434 }
6435
6436 // do { ... }
6437 DoExpression* instanceof;
6438 {
6439 Block* block = factory->NewBlock(nullptr, 5, true, nopos);
6440 block->statements()->Add(get_O, zone);
6441 block->statements()->Add(get_C, zone);
6442 block->statements()->Add(validate_C, zone);
6443 block->statements()->Add(initialize_handler, zone);
6444 block->statements()->Add(call_handler, zone);
6445
6446 // Here is the desugared instanceof.
6447 instanceof = factory->NewDoExpression(block, var_handler_result, nopos);
6448 Rewriter::Rewrite(parser_, instanceof, avfactory);
6449 }
6450
6451 return instanceof;
6452 }
6453
6454 Statement* ParserTraits::CheckCallable(Variable* var, Expression* error) {
6455 auto factory = parser_->factory();
6456 auto avfactory = parser_->ast_value_factory();
6457 const int nopos = RelocInfo::kNoPosition;
6458 Statement* validate_var;
6459 {
6460 Expression* type_of = factory->NewUnaryOperation(
6461 Token::TYPEOF, factory->NewVariableProxy(var), nopos);
6462 Expression* function_literal =
6463 factory->NewStringLiteral(avfactory->function_string(), nopos);
6464 Expression* condition = factory->NewCompareOperation(
6465 Token::EQ_STRICT, type_of, function_literal, nopos);
6466
6467 Statement* throw_call = factory->NewExpressionStatement(error, nopos);
6468
6469 validate_var = factory->NewIfStatement(
6470 condition, factory->NewEmptyStatement(nopos), throw_call, nopos);
6471 }
6472 return validate_var;
6473 }
6295 6474
6296 void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, 6475 void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements,
6297 Variable* iterator, 6476 Variable* iterator,
6298 Expression* input, 6477 Expression* input,
6299 Variable* var_output) { 6478 Variable* var_output) {
6300 // 6479 //
6301 // This function adds four statements to [statements], corresponding to the 6480 // This function adds four statements to [statements], corresponding to the
6302 // following code: 6481 // following code:
6303 // 6482 //
6304 // let iteratorReturn = iterator.return; 6483 // let iteratorReturn = iterator.return;
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
6433 Expression* assignment = factory->NewAssignment( 6612 Expression* assignment = factory->NewAssignment(
6434 Token::ASSIGN, return_proxy, property, nopos); 6613 Token::ASSIGN, return_proxy, property, nopos);
6435 get_return = factory->NewExpressionStatement(assignment, nopos); 6614 get_return = factory->NewExpressionStatement(assignment, nopos);
6436 } 6615 }
6437 6616
6438 // if (!IS_CALLABLE(iteratorReturn)) { 6617 // if (!IS_CALLABLE(iteratorReturn)) {
6439 // throw MakeTypeError(kReturnMethodNotCallable); 6618 // throw MakeTypeError(kReturnMethodNotCallable);
6440 // } 6619 // }
6441 Statement* check_return_callable; 6620 Statement* check_return_callable;
6442 { 6621 {
6443 Expression* type_of = factory->NewUnaryOperation( 6622 Expression* throw_expr = NewThrowTypeError(
6444 Token::TYPEOF, factory->NewVariableProxy(var_return), nopos);
6445 Expression* function_literal = factory->NewStringLiteral(
6446 avfactory->function_string(), nopos);
6447 Expression* condition = factory->NewCompareOperation(
6448 Token::EQ_STRICT, type_of, function_literal, nopos);
6449
6450 Expression* call = NewThrowTypeError(
6451 MessageTemplate::kReturnMethodNotCallable, 6623 MessageTemplate::kReturnMethodNotCallable,
6452 avfactory->empty_string(), nopos); 6624 avfactory->empty_string(), nopos);
6453 Statement* throw_call = factory->NewExpressionStatement(call, nopos); 6625 check_return_callable = CheckCallable(var_return, throw_expr);
6454
6455 check_return_callable = factory->NewIfStatement(
6456 condition, factory->NewEmptyStatement(nopos), throw_call, nopos);
6457 } 6626 }
6458 6627
6459 // output = %_Call(iteratorReturn, iterator); 6628 // output = %_Call(iteratorReturn, iterator);
6460 Statement* call_return; 6629 Statement* call_return;
6461 { 6630 {
6462 auto args = new (zone) ZoneList<Expression*>(2, zone); 6631 auto args = new (zone) ZoneList<Expression*>(2, zone);
6463 args->Add(factory->NewVariableProxy(var_return), zone); 6632 args->Add(factory->NewVariableProxy(var_return), zone);
6464 args->Add(factory->NewVariableProxy(iterator), zone); 6633 args->Add(factory->NewVariableProxy(iterator), zone);
6465 Expression* call = 6634 Expression* call =
6466 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos); 6635 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
6731 new_body->statements()->Add(loop->body(), zone); 6900 new_body->statements()->Add(loop->body(), zone);
6732 new_body->statements()->Add(set_completion_normal, zone); 6901 new_body->statements()->Add(set_completion_normal, zone);
6733 6902
6734 loop->set_body(new_body); 6903 loop->set_body(new_body);
6735 return final_loop; 6904 return final_loop;
6736 } 6905 }
6737 6906
6738 6907
6739 } // namespace internal 6908 } // namespace internal
6740 } // namespace v8 6909 } // namespace v8
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698