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

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: Fixed todos. 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 6221 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698