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 |