| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/compiler/ast-graph-builder.h" | 5 #include "src/compiler/ast-graph-builder.h" |
| 6 | 6 |
| 7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
| 8 #include "src/compiler/ast-loop-assignment-analyzer.h" | 8 #include "src/compiler/ast-loop-assignment-analyzer.h" |
| 9 #include "src/compiler/control-builders.h" | 9 #include "src/compiler/control-builders.h" |
| 10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 | 102 |
| 103 // Scoped class tracking context objects created by the visitor. Represents | 103 // Scoped class tracking context objects created by the visitor. Represents |
| 104 // mutations of the context chain within the function body and allows to | 104 // mutations of the context chain within the function body and allows to |
| 105 // change the current {scope} and {context} during visitation. | 105 // change the current {scope} and {context} during visitation. |
| 106 class AstGraphBuilder::ContextScope BASE_EMBEDDED { | 106 class AstGraphBuilder::ContextScope BASE_EMBEDDED { |
| 107 public: | 107 public: |
| 108 ContextScope(AstGraphBuilder* builder, Scope* scope, Node* context) | 108 ContextScope(AstGraphBuilder* builder, Scope* scope, Node* context) |
| 109 : builder_(builder), | 109 : builder_(builder), |
| 110 outer_(builder->execution_context()), | 110 outer_(builder->execution_context()), |
| 111 scope_(scope), | 111 scope_(scope), |
| 112 context_(context) { | 112 depth_(builder_->environment()->ContextStackDepth()) { |
| 113 builder_->set_execution_context(this); // Push. | 113 builder_->environment()->PushContext(context); // Push. |
| 114 builder_->set_execution_context(this); |
| 114 } | 115 } |
| 115 | 116 |
| 116 ~ContextScope() { | 117 ~ContextScope() { |
| 117 builder_->set_execution_context(outer_); // Pop. | 118 builder_->set_execution_context(outer_); // Pop. |
| 119 builder_->environment()->PopContext(); |
| 120 CHECK_EQ(depth_, builder_->environment()->ContextStackDepth()); |
| 118 } | 121 } |
| 119 | 122 |
| 120 // Current scope during visitation. | 123 // Current scope during visitation. |
| 121 Scope* scope() const { return scope_; } | 124 Scope* scope() const { return scope_; } |
| 122 // Current context node during visitation. | |
| 123 Node* context() const { return context_; } | |
| 124 | 125 |
| 125 private: | 126 private: |
| 126 AstGraphBuilder* builder_; | 127 AstGraphBuilder* builder_; |
| 127 ContextScope* outer_; | 128 ContextScope* outer_; |
| 128 Scope* scope_; | 129 Scope* scope_; |
| 129 Node* context_; | 130 int depth_; |
| 130 }; | 131 }; |
| 131 | 132 |
| 132 | 133 |
| 133 // Scoped class tracking control statements entered by the visitor. There are | 134 // Scoped class tracking control statements entered by the visitor. There are |
| 134 // different types of statements participating in this stack to properly track | 135 // different types of statements participating in this stack to properly track |
| 135 // local as well as non-local control flow: | 136 // local as well as non-local control flow: |
| 136 // - IterationStatement : Allows proper 'break' and 'continue' behavior. | 137 // - IterationStatement : Allows proper 'break' and 'continue' behavior. |
| 137 // - BreakableStatement : Allows 'break' from block and switch statements. | 138 // - BreakableStatement : Allows 'break' from block and switch statements. |
| 138 // - TryCatchStatement : Intercepts 'throw' and implicit exceptional edges. | 139 // - TryCatchStatement : Intercepts 'throw' and implicit exceptional edges. |
| 139 // - TryFinallyStatement: Intercepts 'break', 'continue', 'throw' and 'return'. | 140 // - TryFinallyStatement: Intercepts 'break', 'continue', 'throw' and 'return'. |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, | 372 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, |
| 372 JSGraph* jsgraph, LoopAssignmentAnalysis* loop) | 373 JSGraph* jsgraph, LoopAssignmentAnalysis* loop) |
| 373 : local_zone_(local_zone), | 374 : local_zone_(local_zone), |
| 374 info_(info), | 375 info_(info), |
| 375 jsgraph_(jsgraph), | 376 jsgraph_(jsgraph), |
| 376 environment_(nullptr), | 377 environment_(nullptr), |
| 377 ast_context_(nullptr), | 378 ast_context_(nullptr), |
| 378 globals_(0, local_zone), | 379 globals_(0, local_zone), |
| 379 execution_control_(nullptr), | 380 execution_control_(nullptr), |
| 380 execution_context_(nullptr), | 381 execution_context_(nullptr), |
| 382 function_context_(nullptr), |
| 381 input_buffer_size_(0), | 383 input_buffer_size_(0), |
| 382 input_buffer_(nullptr), | 384 input_buffer_(nullptr), |
| 383 exit_control_(nullptr), | 385 exit_control_(nullptr), |
| 384 loop_assignment_analysis_(loop) { | 386 loop_assignment_analysis_(loop) { |
| 385 InitializeAstVisitor(info->isolate(), local_zone); | 387 InitializeAstVisitor(info->isolate(), local_zone); |
| 386 } | 388 } |
| 387 | 389 |
| 388 | 390 |
| 389 Node* AstGraphBuilder::GetFunctionClosure() { | 391 Node* AstGraphBuilder::GetFunctionClosure() { |
| 390 if (!function_closure_.is_set()) { | 392 if (!function_closure_.is_set()) { |
| 391 const Operator* op = | 393 const Operator* op = |
| 392 common()->Parameter(Linkage::kJSFunctionCallClosureParamIndex); | 394 common()->Parameter(Linkage::kJSFunctionCallClosureParamIndex); |
| 393 Node* node = NewNode(op, graph()->start()); | 395 Node* node = NewNode(op, graph()->start()); |
| 394 function_closure_.set(node); | 396 function_closure_.set(node); |
| 395 } | 397 } |
| 396 return function_closure_.get(); | 398 return function_closure_.get(); |
| 397 } | 399 } |
| 398 | 400 |
| 399 | 401 |
| 400 Node* AstGraphBuilder::GetFunctionContext() { | 402 Node* AstGraphBuilder::GetFunctionContext() { |
| 401 if (!function_context_.is_set()) { | 403 DCHECK(function_context_ != nullptr); |
| 402 // Parameter (arity + 1) is special for the outer context of the function | 404 return function_context_; |
| 403 const Operator* op = common()->Parameter(info()->num_parameters() + 1); | |
| 404 Node* node = NewNode(op, graph()->start()); | |
| 405 function_context_.set(node); | |
| 406 } | |
| 407 return function_context_.get(); | |
| 408 } | 405 } |
| 409 | 406 |
| 410 | 407 |
| 408 Node* AstGraphBuilder::NewOuterContextParam() { |
| 409 // Parameter (arity + 1) is special for the outer context of the function |
| 410 const Operator* op = common()->Parameter(info()->num_parameters() + 1); |
| 411 return NewNode(op, graph()->start()); |
| 412 } |
| 413 |
| 414 |
| 415 Node* AstGraphBuilder::NewCurrentContextOsrValue() { |
| 416 // TODO(titzer): use a real OSR value here; a parameter works by accident. |
| 417 // Parameter (arity + 1) is special for the outer context of the function |
| 418 const Operator* op = common()->Parameter(info()->num_parameters() + 1); |
| 419 return NewNode(op, graph()->start()); |
| 420 } |
| 421 |
| 422 |
| 411 bool AstGraphBuilder::CreateGraph() { | 423 bool AstGraphBuilder::CreateGraph() { |
| 412 Scope* scope = info()->scope(); | 424 Scope* scope = info()->scope(); |
| 413 DCHECK(graph() != NULL); | 425 DCHECK(graph() != NULL); |
| 414 | 426 |
| 415 // Set up the basic structure of the graph. | 427 // Set up the basic structure of the graph. |
| 416 int parameter_count = info()->num_parameters(); | 428 int parameter_count = info()->num_parameters(); |
| 417 graph()->SetStart(graph()->NewNode(common()->Start(parameter_count))); | 429 graph()->SetStart(graph()->NewNode(common()->Start(parameter_count))); |
| 418 | 430 |
| 419 // Initialize control scope. | 431 // Initialize control scope. |
| 420 ControlScope control(this, 0); | 432 ControlScope control(this, 0); |
| 421 | 433 |
| 422 // Initialize the top-level environment. | 434 // Initialize the top-level environment. |
| 423 Environment env(this, scope, graph()->start()); | 435 Environment env(this, scope, graph()->start()); |
| 424 set_environment(&env); | 436 set_environment(&env); |
| 425 | 437 |
| 426 if (info()->is_osr()) { | 438 if (info()->is_osr()) { |
| 427 // Use OSR normal entry as the start of the top-level environment. | 439 // Use OSR normal entry as the start of the top-level environment. |
| 428 // It will be replaced with {Dead} after typing and optimizations. | 440 // It will be replaced with {Dead} after typing and optimizations. |
| 429 NewNode(common()->OsrNormalEntry()); | 441 NewNode(common()->OsrNormalEntry()); |
| 430 } | 442 } |
| 431 | 443 |
| 432 // Initialize the incoming context. | 444 // Initialize the incoming context. |
| 433 Node* incoming_context = GetFunctionContext(); | 445 function_context_ = NewOuterContextParam(); |
| 434 ContextScope incoming(this, scope, incoming_context); | 446 ContextScope incoming(this, scope, function_context_); |
| 435 | 447 |
| 436 // Build receiver check for sloppy mode if necessary. | 448 // Build receiver check for sloppy mode if necessary. |
| 437 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC? | 449 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC? |
| 438 Node* original_receiver = env.Lookup(scope->receiver()); | 450 Node* original_receiver = env.Lookup(scope->receiver()); |
| 439 Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver); | 451 Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver); |
| 440 env.Bind(scope->receiver(), patched_receiver); | 452 env.Bind(scope->receiver(), patched_receiver); |
| 441 | 453 |
| 442 // Build node to initialize local function context. | 454 bool ok; |
| 443 Node* closure = GetFunctionClosure(); | 455 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 444 Node* inner_context = BuildLocalFunctionContext(incoming_context, closure); | 456 if (heap_slots > 0) { |
| 457 // Push a new inner context scope for the function. |
| 458 Node* closure = GetFunctionClosure(); |
| 459 Node* inner_context = BuildLocalFunctionContext(function_context_, closure); |
| 460 ContextScope top_context(this, scope, inner_context); |
| 461 ok = CreateGraphBody(); |
| 462 } else { |
| 463 // Simply use the outer function context in building the graph. |
| 464 ok = CreateGraphBody(); |
| 465 } |
| 445 | 466 |
| 446 // Push top-level function context for the function body. | 467 // Finish the basic structure of the graph. |
| 447 ContextScope top_context(this, scope, inner_context); | 468 if (ok) { |
| 469 environment()->UpdateControlDependency(exit_control()); |
| 470 graph()->SetEnd(NewNode(common()->End())); |
| 471 } |
| 448 | 472 |
| 473 return ok; |
| 474 } |
| 475 |
| 476 |
| 477 bool AstGraphBuilder::CreateGraphBody() { |
| 478 Scope* scope = info()->scope(); |
| 449 // Build the arguments object if it is used. | 479 // Build the arguments object if it is used. |
| 450 BuildArgumentsObject(scope->arguments()); | 480 BuildArgumentsObject(scope->arguments()); |
| 451 | 481 |
| 452 // Build rest arguments array if it is used. | 482 // Build rest arguments array if it is used. |
| 453 int rest_index; | 483 int rest_index; |
| 454 Variable* rest_parameter = scope->rest_parameter(&rest_index); | 484 Variable* rest_parameter = scope->rest_parameter(&rest_index); |
| 455 BuildRestArgumentsArray(rest_parameter, rest_index); | 485 BuildRestArgumentsArray(rest_parameter, rest_index); |
| 456 | 486 |
| 457 // Emit tracing call if requested to do so. | 487 // Emit tracing call if requested to do so. |
| 458 if (FLAG_trace) { | 488 if (FLAG_trace) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 478 // Emit tracing call if requested to do so. | 508 // Emit tracing call if requested to do so. |
| 479 if (FLAG_trace) { | 509 if (FLAG_trace) { |
| 480 // TODO(mstarzinger): Only traces implicit return. | 510 // TODO(mstarzinger): Only traces implicit return. |
| 481 Node* return_value = jsgraph()->UndefinedConstant(); | 511 Node* return_value = jsgraph()->UndefinedConstant(); |
| 482 NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value); | 512 NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value); |
| 483 } | 513 } |
| 484 | 514 |
| 485 // Return 'undefined' in case we can fall off the end. | 515 // Return 'undefined' in case we can fall off the end. |
| 486 BuildReturn(jsgraph()->UndefinedConstant()); | 516 BuildReturn(jsgraph()->UndefinedConstant()); |
| 487 | 517 |
| 488 // Finish the basic structure of the graph. | |
| 489 environment()->UpdateControlDependency(exit_control()); | |
| 490 graph()->SetEnd(NewNode(common()->End())); | |
| 491 | |
| 492 return true; | 518 return true; |
| 493 } | 519 } |
| 494 | 520 |
| 495 | 521 |
| 496 // Left-hand side can only be a property, a global or a variable slot. | 522 // Left-hand side can only be a property, a global or a variable slot. |
| 497 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 523 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 498 | 524 |
| 499 | 525 |
| 500 // Determine the left-hand side kind of an assignment. | 526 // Determine the left-hand side kind of an assignment. |
| 501 static LhsKind DetermineLhsKind(Expression* expr) { | 527 static LhsKind DetermineLhsKind(Expression* expr) { |
| 502 Property* property = expr->AsProperty(); | 528 Property* property = expr->AsProperty(); |
| 503 DCHECK(expr->IsValidReferenceExpression()); | 529 DCHECK(expr->IsValidReferenceExpression()); |
| 504 LhsKind lhs_kind = | 530 LhsKind lhs_kind = |
| 505 (property == NULL) ? VARIABLE : (property->key()->IsPropertyName()) | 531 (property == NULL) ? VARIABLE : (property->key()->IsPropertyName()) |
| 506 ? NAMED_PROPERTY | 532 ? NAMED_PROPERTY |
| 507 : KEYED_PROPERTY; | 533 : KEYED_PROPERTY; |
| 508 return lhs_kind; | 534 return lhs_kind; |
| 509 } | 535 } |
| 510 | 536 |
| 511 | 537 |
| 512 AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder, | 538 AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder, |
| 513 Scope* scope, | 539 Scope* scope, |
| 514 Node* control_dependency) | 540 Node* control_dependency) |
| 515 : builder_(builder), | 541 : builder_(builder), |
| 516 parameters_count_(scope->num_parameters() + 1), | 542 parameters_count_(scope->num_parameters() + 1), |
| 517 locals_count_(scope->num_stack_slots()), | 543 locals_count_(scope->num_stack_slots()), |
| 518 values_(builder_->local_zone()), | 544 values_(builder_->local_zone()), |
| 545 contexts_(builder_->local_zone()), |
| 519 control_dependency_(control_dependency), | 546 control_dependency_(control_dependency), |
| 520 effect_dependency_(control_dependency), | 547 effect_dependency_(control_dependency), |
| 521 parameters_node_(nullptr), | 548 parameters_node_(nullptr), |
| 522 locals_node_(nullptr), | 549 locals_node_(nullptr), |
| 523 stack_node_(nullptr) { | 550 stack_node_(nullptr) { |
| 524 DCHECK_EQ(scope->num_parameters() + 1, parameters_count()); | 551 DCHECK_EQ(scope->num_parameters() + 1, parameters_count()); |
| 525 | 552 |
| 526 // Bind the receiver variable. | 553 // Bind the receiver variable. |
| 527 Node* receiver = builder->graph()->NewNode(common()->Parameter(0), | 554 Node* receiver = builder->graph()->NewNode(common()->Parameter(0), |
| 528 builder->graph()->start()); | 555 builder->graph()->start()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 541 values()->insert(values()->end(), locals_count(), undefined_constant); | 568 values()->insert(values()->end(), locals_count(), undefined_constant); |
| 542 } | 569 } |
| 543 | 570 |
| 544 | 571 |
| 545 AstGraphBuilder::Environment::Environment( | 572 AstGraphBuilder::Environment::Environment( |
| 546 const AstGraphBuilder::Environment* copy) | 573 const AstGraphBuilder::Environment* copy) |
| 547 : builder_(copy->builder_), | 574 : builder_(copy->builder_), |
| 548 parameters_count_(copy->parameters_count_), | 575 parameters_count_(copy->parameters_count_), |
| 549 locals_count_(copy->locals_count_), | 576 locals_count_(copy->locals_count_), |
| 550 values_(copy->zone()), | 577 values_(copy->zone()), |
| 578 contexts_(copy->zone()), |
| 551 control_dependency_(copy->control_dependency_), | 579 control_dependency_(copy->control_dependency_), |
| 552 effect_dependency_(copy->effect_dependency_), | 580 effect_dependency_(copy->effect_dependency_), |
| 553 parameters_node_(copy->parameters_node_), | 581 parameters_node_(copy->parameters_node_), |
| 554 locals_node_(copy->locals_node_), | 582 locals_node_(copy->locals_node_), |
| 555 stack_node_(copy->stack_node_) { | 583 stack_node_(copy->stack_node_) { |
| 556 const size_t kStackEstimate = 7; // optimum from experimentation! | 584 const size_t kStackEstimate = 7; // optimum from experimentation! |
| 557 values_.reserve(copy->values_.size() + kStackEstimate); | 585 values_.reserve(copy->values_.size() + kStackEstimate); |
| 558 values_.insert(values_.begin(), copy->values_.begin(), copy->values_.end()); | 586 values_.insert(values_.begin(), copy->values_.begin(), copy->values_.end()); |
| 587 contexts_.reserve(copy->contexts_.size()); |
| 588 contexts_.insert(contexts_.begin(), copy->contexts_.begin(), |
| 589 copy->contexts_.end()); |
| 559 } | 590 } |
| 560 | 591 |
| 561 | 592 |
| 562 void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values, | 593 void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values, |
| 563 int offset, int count) { | 594 int offset, int count) { |
| 564 bool should_update = false; | 595 bool should_update = false; |
| 565 Node** env_values = (count == 0) ? NULL : &values()->at(offset); | 596 Node** env_values = (count == 0) ? NULL : &values()->at(offset); |
| 566 if (*state_values == NULL || (*state_values)->InputCount() != count) { | 597 if (*state_values == NULL || (*state_values)->InputCount() != count) { |
| 567 should_update = true; | 598 should_update = true; |
| 568 } else { | 599 } else { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 return environment()->Pop(); | 684 return environment()->Pop(); |
| 654 } | 685 } |
| 655 | 686 |
| 656 | 687 |
| 657 Scope* AstGraphBuilder::current_scope() const { | 688 Scope* AstGraphBuilder::current_scope() const { |
| 658 return execution_context_->scope(); | 689 return execution_context_->scope(); |
| 659 } | 690 } |
| 660 | 691 |
| 661 | 692 |
| 662 Node* AstGraphBuilder::current_context() const { | 693 Node* AstGraphBuilder::current_context() const { |
| 663 return execution_context_->context(); | 694 return environment()->Context(); |
| 664 } | 695 } |
| 665 | 696 |
| 666 | 697 |
| 667 void AstGraphBuilder::ControlScope::PerformCommand(Command command, | 698 void AstGraphBuilder::ControlScope::PerformCommand(Command command, |
| 668 Statement* target, | 699 Statement* target, |
| 669 Node* value) { | 700 Node* value) { |
| 670 Environment* env = environment()->CopyAsUnreachable(); | 701 Environment* env = environment()->CopyAsUnreachable(); |
| 671 ControlScope* current = this; | 702 ControlScope* current = this; |
| 672 while (current != NULL) { | 703 while (current != NULL) { |
| 673 if (current->Execute(command, target, value)) break; | 704 if (current->Execute(command, target, value)) break; |
| (...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1196 Visit(stmt->try_block()); | 1227 Visit(stmt->try_block()); |
| 1197 } | 1228 } |
| 1198 try_control.EndTry(); | 1229 try_control.EndTry(); |
| 1199 | 1230 |
| 1200 // Create a catch scope that binds the exception. | 1231 // Create a catch scope that binds the exception. |
| 1201 Node* exception = try_control.GetExceptionNode(); | 1232 Node* exception = try_control.GetExceptionNode(); |
| 1202 Unique<String> name = MakeUnique(stmt->variable()->name()); | 1233 Unique<String> name = MakeUnique(stmt->variable()->name()); |
| 1203 const Operator* op = javascript()->CreateCatchContext(name); | 1234 const Operator* op = javascript()->CreateCatchContext(name); |
| 1204 Node* context = NewNode(op, exception, GetFunctionClosure()); | 1235 Node* context = NewNode(op, exception, GetFunctionClosure()); |
| 1205 PrepareFrameState(context, BailoutId::None()); | 1236 PrepareFrameState(context, BailoutId::None()); |
| 1206 ContextScope scope(this, stmt->scope(), context); | 1237 { |
| 1207 DCHECK(stmt->scope()->declarations()->is_empty()); | 1238 ContextScope scope(this, stmt->scope(), context); |
| 1208 | 1239 DCHECK(stmt->scope()->declarations()->is_empty()); |
| 1209 // Evaluate the catch-block. | 1240 // Evaluate the catch-block. |
| 1210 Visit(stmt->catch_block()); | 1241 Visit(stmt->catch_block()); |
| 1242 } |
| 1211 try_control.EndCatch(); | 1243 try_control.EndCatch(); |
| 1212 | 1244 |
| 1213 // TODO(mstarzinger): Remove bailout once everything works. | 1245 // TODO(mstarzinger): Remove bailout once everything works. |
| 1214 if (!FLAG_turbo_exceptions) SetStackOverflow(); | 1246 if (!FLAG_turbo_exceptions) SetStackOverflow(); |
| 1215 } | 1247 } |
| 1216 | 1248 |
| 1217 | 1249 |
| 1218 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 1250 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
| 1219 TryFinallyBuilder try_control(this); | 1251 TryFinallyBuilder try_control(this); |
| 1220 | 1252 |
| (...skipping 1188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2409 receiver_check.Then(); | 2441 receiver_check.Then(); |
| 2410 environment()->Push(BuildLoadGlobalProxy()); | 2442 environment()->Push(BuildLoadGlobalProxy()); |
| 2411 receiver_check.Else(); | 2443 receiver_check.Else(); |
| 2412 environment()->Push(receiver); | 2444 environment()->Push(receiver); |
| 2413 receiver_check.End(); | 2445 receiver_check.End(); |
| 2414 return environment()->Pop(); | 2446 return environment()->Pop(); |
| 2415 } | 2447 } |
| 2416 | 2448 |
| 2417 | 2449 |
| 2418 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, Node* closure) { | 2450 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, Node* closure) { |
| 2419 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | |
| 2420 if (heap_slots <= 0) return context; | |
| 2421 | |
| 2422 // Allocate a new local context. | 2451 // Allocate a new local context. |
| 2423 const Operator* op = javascript()->CreateFunctionContext(); | 2452 const Operator* op = javascript()->CreateFunctionContext(); |
| 2424 Node* local_context = NewNode(op, closure); | 2453 Node* local_context = NewNode(op, closure); |
| 2425 | 2454 |
| 2426 // Copy parameters into context if necessary. | 2455 // Copy parameters into context if necessary. |
| 2427 int num_parameters = info()->scope()->num_parameters(); | 2456 int num_parameters = info()->scope()->num_parameters(); |
| 2428 for (int i = 0; i < num_parameters; i++) { | 2457 for (int i = 0; i < num_parameters; i++) { |
| 2429 Variable* variable = info()->scope()->parameter(i); | 2458 Variable* variable = info()->scope()->parameter(i); |
| 2430 if (!variable->IsContextSlot()) continue; | 2459 if (!variable->IsContextSlot()) continue; |
| 2431 // Temporary parameter node. The parameter indices are shifted by 1 | 2460 // Temporary parameter node. The parameter indices are shifted by 1 |
| (...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2996 if (exit_control() != NULL) { | 3025 if (exit_control() != NULL) { |
| 2997 exit = MergeControl(exit_control(), exit); | 3026 exit = MergeControl(exit_control(), exit); |
| 2998 } | 3027 } |
| 2999 environment()->MarkAsUnreachable(); | 3028 environment()->MarkAsUnreachable(); |
| 3000 set_exit_control(exit); | 3029 set_exit_control(exit); |
| 3001 } | 3030 } |
| 3002 | 3031 |
| 3003 | 3032 |
| 3004 void AstGraphBuilder::Environment::Merge(Environment* other) { | 3033 void AstGraphBuilder::Environment::Merge(Environment* other) { |
| 3005 DCHECK(values_.size() == other->values_.size()); | 3034 DCHECK(values_.size() == other->values_.size()); |
| 3035 DCHECK(contexts_.size() <= other->contexts_.size()); |
| 3006 | 3036 |
| 3007 // Nothing to do if the other environment is dead. | 3037 // Nothing to do if the other environment is dead. |
| 3008 if (other->IsMarkedAsUnreachable()) return; | 3038 if (other->IsMarkedAsUnreachable()) return; |
| 3009 | 3039 |
| 3010 // Resurrect a dead environment by copying the contents of the other one and | 3040 // Resurrect a dead environment by copying the contents of the other one and |
| 3011 // placing a singleton merge as the new control dependency. | 3041 // placing a singleton merge as the new control dependency. |
| 3012 if (this->IsMarkedAsUnreachable()) { | 3042 if (this->IsMarkedAsUnreachable()) { |
| 3013 Node* other_control = other->control_dependency_; | 3043 Node* other_control = other->control_dependency_; |
| 3014 Node* inputs[] = {other_control}; | 3044 Node* inputs[] = {other_control}; |
| 3015 control_dependency_ = | 3045 control_dependency_ = |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3029 // the current environment's effect dependency accordingly. | 3059 // the current environment's effect dependency accordingly. |
| 3030 Node* effect = builder_->MergeEffect(this->GetEffectDependency(), | 3060 Node* effect = builder_->MergeEffect(this->GetEffectDependency(), |
| 3031 other->GetEffectDependency(), control); | 3061 other->GetEffectDependency(), control); |
| 3032 UpdateEffectDependency(effect); | 3062 UpdateEffectDependency(effect); |
| 3033 | 3063 |
| 3034 // Introduce Phi nodes for values that have differing input at merge points, | 3064 // Introduce Phi nodes for values that have differing input at merge points, |
| 3035 // potentially extending an existing Phi node if possible. | 3065 // potentially extending an existing Phi node if possible. |
| 3036 for (int i = 0; i < static_cast<int>(values_.size()); ++i) { | 3066 for (int i = 0; i < static_cast<int>(values_.size()); ++i) { |
| 3037 values_[i] = builder_->MergeValue(values_[i], other->values_[i], control); | 3067 values_[i] = builder_->MergeValue(values_[i], other->values_[i], control); |
| 3038 } | 3068 } |
| 3069 for (int i = 0; i < static_cast<int>(contexts_.size()); ++i) { |
| 3070 contexts_[i] = |
| 3071 builder_->MergeValue(contexts_[i], other->contexts_[i], control); |
| 3072 } |
| 3039 } | 3073 } |
| 3040 | 3074 |
| 3041 | 3075 |
| 3042 void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned, | 3076 void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned, |
| 3043 bool is_osr) { | 3077 bool is_osr) { |
| 3044 int size = static_cast<int>(values()->size()); | 3078 int size = static_cast<int>(values()->size()); |
| 3045 | 3079 |
| 3046 Node* control = builder_->NewLoop(); | 3080 Node* control = builder_->NewLoop(); |
| 3047 if (assigned == nullptr) { | 3081 if (assigned == nullptr) { |
| 3048 // Assume that everything is updated in the loop. | 3082 // Assume that everything is updated in the loop. |
| 3049 for (int i = 0; i < size; ++i) { | 3083 for (int i = 0; i < size; ++i) { |
| 3050 Node* phi = builder_->NewPhi(1, values()->at(i), control); | 3084 values()->at(i) = builder_->NewPhi(1, values()->at(i), control); |
| 3051 values()->at(i) = phi; | |
| 3052 } | 3085 } |
| 3053 } else { | 3086 } else { |
| 3054 // Only build phis for those locals assigned in this loop. | 3087 // Only build phis for those locals assigned in this loop. |
| 3055 for (int i = 0; i < size; ++i) { | 3088 for (int i = 0; i < size; ++i) { |
| 3056 if (i < assigned->length() && !assigned->Contains(i)) continue; | 3089 if (i < assigned->length() && !assigned->Contains(i)) continue; |
| 3057 Node* phi = builder_->NewPhi(1, values()->at(i), control); | 3090 Node* phi = builder_->NewPhi(1, values()->at(i), control); |
| 3058 values()->at(i) = phi; | 3091 values()->at(i) = phi; |
| 3059 } | 3092 } |
| 3060 } | 3093 } |
| 3061 Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control); | 3094 Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control); |
| 3062 UpdateEffectDependency(effect); | 3095 UpdateEffectDependency(effect); |
| 3063 | 3096 |
| 3097 if (builder_->info()->is_osr()) { |
| 3098 // Introduce phis for all context values in the case of an OSR graph. |
| 3099 for (int i = 0; i < static_cast<int>(contexts()->size()); ++i) { |
| 3100 Node* val = contexts()->at(i); |
| 3101 if (!IrOpcode::IsConstantOpcode(val->opcode())) { |
| 3102 contexts()->at(i) = builder_->NewPhi(1, val, control); |
| 3103 } |
| 3104 } |
| 3105 } |
| 3106 |
| 3064 if (is_osr) { | 3107 if (is_osr) { |
| 3065 // Merge OSR values as inputs to the phis of the loop. | 3108 // Merge OSR values as inputs to the phis of the loop. |
| 3066 Graph* graph = builder_->graph(); | 3109 Graph* graph = builder_->graph(); |
| 3067 Node* osr_loop_entry = builder_->graph()->NewNode( | 3110 Node* osr_loop_entry = builder_->graph()->NewNode( |
| 3068 builder_->common()->OsrLoopEntry(), graph->start(), graph->start()); | 3111 builder_->common()->OsrLoopEntry(), graph->start(), graph->start()); |
| 3069 | 3112 |
| 3070 builder_->MergeControl(control, osr_loop_entry); | 3113 builder_->MergeControl(control, osr_loop_entry); |
| 3071 builder_->MergeEffect(effect, osr_loop_entry, control); | 3114 builder_->MergeEffect(effect, osr_loop_entry, control); |
| 3072 | 3115 |
| 3073 for (int i = 0; i < size; ++i) { | 3116 for (int i = 0; i < size; ++i) { |
| 3074 Node* val = values()->at(i); | 3117 Node* val = values()->at(i); |
| 3075 if (!IrOpcode::IsConstantOpcode(val->opcode())) { | 3118 if (!IrOpcode::IsConstantOpcode(val->opcode())) { |
| 3076 Node* osr_value = | 3119 Node* osr_value = |
| 3077 graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry); | 3120 graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry); |
| 3078 values()->at(i) = builder_->MergeValue(val, osr_value, control); | 3121 values()->at(i) = builder_->MergeValue(val, osr_value, control); |
| 3079 } | 3122 } |
| 3080 } | 3123 } |
| 3124 |
| 3125 // Rename all the contexts in the environment. |
| 3126 // The innermost context is the OSR value, and the outer contexts are |
| 3127 // reconstructed by dynamically walking up the context chain. |
| 3128 Node* osr_context = nullptr; |
| 3129 const Operator* op = |
| 3130 builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true); |
| 3131 int last = static_cast<int>(contexts()->size() - 1); |
| 3132 for (int i = last; i >= 0; i--) { |
| 3133 Node* val = contexts()->at(i); |
| 3134 if (!IrOpcode::IsConstantOpcode(val->opcode())) { |
| 3135 osr_context = (i == last) ? builder_->NewCurrentContextOsrValue() |
| 3136 : graph->NewNode(op, osr_context, osr_context, |
| 3137 osr_loop_entry); |
| 3138 contexts()->at(i) = builder_->MergeValue(val, osr_context, control); |
| 3139 } else { |
| 3140 osr_context = val; |
| 3141 } |
| 3142 } |
| 3081 } | 3143 } |
| 3082 } | 3144 } |
| 3083 | 3145 |
| 3084 | 3146 |
| 3085 Node* AstGraphBuilder::NewPhi(int count, Node* input, Node* control) { | 3147 Node* AstGraphBuilder::NewPhi(int count, Node* input, Node* control) { |
| 3086 const Operator* phi_op = common()->Phi(kMachAnyTagged, count); | 3148 const Operator* phi_op = common()->Phi(kMachAnyTagged, count); |
| 3087 Node** buffer = EnsureInputBufferSize(count + 1); | 3149 Node** buffer = EnsureInputBufferSize(count + 1); |
| 3088 MemsetPointer(buffer, input, count); | 3150 MemsetPointer(buffer, input, count); |
| 3089 buffer[count] = control; | 3151 buffer[count] = control; |
| 3090 return graph()->NewNode(phi_op, count + 1, buffer, true); | 3152 return graph()->NewNode(phi_op, count + 1, buffer, true); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3150 // Phi does not exist yet, introduce one. | 3212 // Phi does not exist yet, introduce one. |
| 3151 value = NewPhi(inputs, value, control); | 3213 value = NewPhi(inputs, value, control); |
| 3152 value->ReplaceInput(inputs - 1, other); | 3214 value->ReplaceInput(inputs - 1, other); |
| 3153 } | 3215 } |
| 3154 return value; | 3216 return value; |
| 3155 } | 3217 } |
| 3156 | 3218 |
| 3157 } // namespace compiler | 3219 } // namespace compiler |
| 3158 } // namespace internal | 3220 } // namespace internal |
| 3159 } // namespace v8 | 3221 } // namespace v8 |
| OLD | NEW |