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

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: Code comments. 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
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 6273 matching lines...) Expand 10 before | Expand all | Expand 10 after
6284 do_block->statements()->Add(get_value, zone); 6284 do_block->statements()->Add(get_value, zone);
6285 6285
6286 Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string()); 6286 Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string());
6287 yield_star = factory->NewDoExpression(do_block, dot_result, nopos); 6287 yield_star = factory->NewDoExpression(do_block, dot_result, nopos);
6288 Rewriter::Rewrite(parser_, yield_star, avfactory); 6288 Rewriter::Rewrite(parser_, yield_star, avfactory);
6289 } 6289 }
6290 6290
6291 return yield_star; 6291 return yield_star;
6292 } 6292 }
6293 6293
6294 // Desugaring of (lhs) instanceof (rhs)
6295 // ====================================
6296 //
6297 // We desugar instanceof into a load of property @@hasInstance on the rhs.
6298 // We end up with roughly the following code (O, C):
6299 //
6300 // do {
6301 // let O = lhs;
6302 // let C = rhs;
6303 // if (!IS_RECEIVER(C)) throw MakeTypeError(kNonObjectInInstanceOfCheck);
6304 // let handler_result = C[Symbol.hasInstance];
6305 // if (handler_result === undefined) {
6306 // if (!IS_CALLABLE(C)) {
6307 // throw MakeTypeError(kCalledNonCallableInstanceOf);
6308 // }
6309 // handler_result = %ordinary_has_instance(C, O);
6310 // } else {
6311 // handler_result = !!(%_Call(handler_result, C, O));
6312 // }
6313 // handler_result;
6314 // }
6315 //
6316 Expression* ParserTraits::RewriteInstanceof(Expression* lhs, Expression* rhs,
6317 int pos) {
6318 const int nopos = RelocInfo::kNoPosition;
6319
6320 auto factory = parser_->factory();
6321 auto avfactory = parser_->ast_value_factory();
6322 auto scope = parser_->scope_;
6323 auto zone = parser_->zone();
6324
6325 // let O = lhs;
6326 Variable* var_O = scope->NewTemporary(avfactory->empty_string());
6327 Statement* get_O;
6328 {
6329 Expression* O_proxy = factory->NewVariableProxy(var_O);
6330 Expression* assignment =
6331 factory->NewAssignment(Token::ASSIGN, O_proxy, lhs, nopos);
6332 get_O = factory->NewExpressionStatement(assignment, nopos);
6333 }
6334
6335 // let C = lhs;
6336 Variable* var_C = scope->NewTemporary(avfactory->empty_string());
6337 Statement* get_C;
6338 {
6339 Expression* C_proxy = factory->NewVariableProxy(var_C);
6340 Expression* assignment =
6341 factory->NewAssignment(Token::ASSIGN, C_proxy, rhs, nopos);
6342 get_C = factory->NewExpressionStatement(assignment, nopos);
6343 }
6344
6345 // if (!IS_RECEIVER(C)) throw MakeTypeError(kNonObjectInInstanceOfCheck);
6346 Statement* validate_C;
6347 {
6348 auto args = new (zone) ZoneList<Expression*>(1, zone);
6349 args->Add(factory->NewVariableProxy(var_C), zone);
6350 Expression* is_receiver_call =
6351 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
6352 Expression* call =
6353 NewThrowTypeError(MessageTemplate::kNonObjectInInstanceOfCheck,
6354 avfactory->empty_string(), nopos);
6355 Statement* throw_call = factory->NewExpressionStatement(call, nopos);
6356
6357 validate_C =
6358 factory->NewIfStatement(is_receiver_call,
6359 factory->NewEmptyStatement(nopos),
6360 throw_call,
6361 nopos);
6362 }
6363
6364 // let handler_result = C[Symbol.hasInstance];
6365 Variable* var_handler_result = scope->NewTemporary(avfactory->empty_string());
6366 Statement* initialize_handler;
6367 {
6368 Expression* hasInstance_symbol_literal =
6369 factory->NewSymbolLiteral("hasInstance_symbol", RelocInfo::kNoPosition);
6370 Expression* prop = factory->NewProperty(factory->NewVariableProxy(var_C),
6371 hasInstance_symbol_literal, pos);
6372 Expression* handler_proxy = factory->NewVariableProxy(var_handler_result);
6373 Expression* assignment =
6374 factory->NewAssignment(Token::ASSIGN, handler_proxy, prop, nopos);
6375 initialize_handler = factory->NewExpressionStatement(assignment, nopos);
6376 }
6377
6378 // if (handler_result === undefined) {
6379 // if (!IS_CALLABLE(C)) {
6380 // throw MakeTypeError(kCalledNonCallableInstanceOf);
6381 // }
6382 // result = %ordinary_has_instance(C, O);
6383 // } else {
6384 // handler_result = !!%_Call(handler_result, C, O);
6385 // }
6386 Statement* call_handler;
6387 {
6388 Expression* condition = factory->NewCompareOperation(
6389 Token::EQ_STRICT, factory->NewVariableProxy(var_handler_result),
6390 factory->NewUndefinedLiteral(nopos), nopos);
6391
6392 Block* then_side = factory->NewBlock(nullptr, 2, false, nopos);
6393 {
6394 Expression* throw_expr =
6395 NewThrowTypeError(MessageTemplate::kCalledNonCallableInstanceOf,
6396 avfactory->empty_string(), nopos);
6397 Statement* validate_C = CheckCallable(var_C, throw_expr);
6398 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone);
6399 args->Add(factory->NewVariableProxy(var_C), zone);
6400 args->Add(factory->NewVariableProxy(var_O), zone);
6401 CallRuntime* call = factory->NewCallRuntime(
6402 Context::ORDINARY_HAS_INSTANCE_INDEX, args, pos);
6403 Expression* result_proxy = factory->NewVariableProxy(var_handler_result);
6404 Expression* assignment =
6405 factory->NewAssignment(Token::ASSIGN, result_proxy, call, nopos);
6406 Statement* assignment_return =
6407 factory->NewExpressionStatement(assignment, nopos);
6408
6409 then_side->statements()->Add(validate_C, zone);
6410 then_side->statements()->Add(assignment_return, zone);
6411 }
6412
6413 Statement* else_side;
6414 {
6415 auto args = new (zone) ZoneList<Expression*>(3, zone);
6416 args->Add(factory->NewVariableProxy(var_handler_result), zone);
6417 args->Add(factory->NewVariableProxy(var_C), zone);
6418 args->Add(factory->NewVariableProxy(var_O), zone);
6419 Expression* call =
6420 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
6421 Expression* inner_not =
6422 factory->NewUnaryOperation(Token::NOT, call, nopos);
6423 Expression* outer_not =
6424 factory->NewUnaryOperation(Token::NOT, inner_not, nopos);
6425 Expression* result_proxy = factory->NewVariableProxy(var_handler_result);
6426 Expression* assignment =
6427 factory->NewAssignment(Token::ASSIGN, result_proxy, outer_not, nopos);
6428
6429 else_side = factory->NewExpressionStatement(assignment, nopos);
6430 }
6431 call_handler =
6432 factory->NewIfStatement(condition, then_side, else_side, nopos);
6433 }
6434
6435 // do { ... }
6436 DoExpression* instanceof;
6437 {
6438 Block* block = factory->NewBlock(nullptr, 5, true, nopos);
6439 block->statements()->Add(get_O, zone);
6440 block->statements()->Add(get_C, zone);
6441 block->statements()->Add(validate_C, zone);
6442 block->statements()->Add(initialize_handler, zone);
6443 block->statements()->Add(call_handler, zone);
6444
6445 // Here is the desugared instanceof.
6446 instanceof = factory->NewDoExpression(block, var_handler_result, nopos);
6447 Rewriter::Rewrite(parser_, instanceof, avfactory);
6448 }
6449
6450 return instanceof;
6451 }
6452
6453 Statement* ParserTraits::CheckCallable(Variable* var, Expression* error) {
6454 auto factory = parser_->factory();
6455 auto avfactory = parser_->ast_value_factory();
6456 const int nopos = RelocInfo::kNoPosition;
6457 Statement* validate_var;
6458 {
6459 Expression* type_of = factory->NewUnaryOperation(
6460 Token::TYPEOF, factory->NewVariableProxy(var), nopos);
6461 Expression* function_literal =
6462 factory->NewStringLiteral(avfactory->function_string(), nopos);
6463 Expression* condition = factory->NewCompareOperation(
6464 Token::EQ_STRICT, type_of, function_literal, nopos);
6465
6466 Statement* throw_call = factory->NewExpressionStatement(error, nopos);
6467
6468 validate_var = factory->NewIfStatement(
6469 condition, factory->NewEmptyStatement(nopos), throw_call, nopos);
6470 }
6471 return validate_var;
6472 }
6294 6473
6295 void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, 6474 void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements,
6296 Variable* iterator, 6475 Variable* iterator,
6297 Maybe<Variable*> input, 6476 Maybe<Variable*> input,
6298 Maybe<Variable*> output) { 6477 Maybe<Variable*> output) {
6299 const int nopos = RelocInfo::kNoPosition; 6478 const int nopos = RelocInfo::kNoPosition;
6300 auto factory = parser_->factory(); 6479 auto factory = parser_->factory();
6301 auto avfactory = parser_->ast_value_factory(); 6480 auto avfactory = parser_->ast_value_factory();
6302 auto scope = parser_->scope_; 6481 auto scope = parser_->scope_;
6303 auto zone = parser_->zone(); 6482 auto zone = parser_->zone();
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
6382 6561
6383 statements->Add(get_return, zone); 6562 statements->Add(get_return, zone);
6384 statements->Add(check_return, zone); 6563 statements->Add(check_return, zone);
6385 statements->Add(call_return, zone); 6564 statements->Add(call_return, zone);
6386 statements->Add(validate_output, zone); 6565 statements->Add(validate_output, zone);
6387 } 6566 }
6388 6567
6389 6568
6390 } // namespace internal 6569 } // namespace internal
6391 } // namespace v8 6570 } // namespace v8
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | src/runtime/runtime-function.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698