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. | |
443 Node* closure = GetFunctionClosure(); | 454 Node* closure = GetFunctionClosure(); |
Michael Starzinger
2015/02/17 10:34:37
nit: The closure is only needed in the case we bui
titzer
2015/02/17 10:44:16
Tried that, but nope. GetFunctionClosure() has a s
| |
444 Node* inner_context = BuildLocalFunctionContext(incoming_context, closure); | 455 bool ok; |
456 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | |
457 if (heap_slots > 0) { | |
458 // Push a new inner context scope for the function. | |
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) { |
Michael Starzinger
2015/02/17 10:34:37
It should be safe to also do this in the case of s
titzer
2015/02/17 10:44:16
Tried that too, but nope, the environment's contro
titzer
2015/02/17 11:24:36
Disregard previous comment.
| |
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 1202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2423 receiver_check.Then(); | 2455 receiver_check.Then(); |
2424 environment()->Push(BuildLoadGlobalProxy()); | 2456 environment()->Push(BuildLoadGlobalProxy()); |
2425 receiver_check.Else(); | 2457 receiver_check.Else(); |
2426 environment()->Push(receiver); | 2458 environment()->Push(receiver); |
2427 receiver_check.End(); | 2459 receiver_check.End(); |
2428 return environment()->Pop(); | 2460 return environment()->Pop(); |
2429 } | 2461 } |
2430 | 2462 |
2431 | 2463 |
2432 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, Node* closure) { | 2464 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, Node* closure) { |
2433 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | |
2434 if (heap_slots <= 0) return context; | |
2435 | |
2436 // Allocate a new local context. | 2465 // Allocate a new local context. |
2437 const Operator* op = javascript()->CreateFunctionContext(); | 2466 const Operator* op = javascript()->CreateFunctionContext(); |
2438 Node* local_context = NewNode(op, closure); | 2467 Node* local_context = NewNode(op, closure); |
2439 | 2468 |
2440 // Copy parameters into context if necessary. | 2469 // Copy parameters into context if necessary. |
2441 int num_parameters = info()->scope()->num_parameters(); | 2470 int num_parameters = info()->scope()->num_parameters(); |
2442 for (int i = 0; i < num_parameters; i++) { | 2471 for (int i = 0; i < num_parameters; i++) { |
2443 Variable* variable = info()->scope()->parameter(i); | 2472 Variable* variable = info()->scope()->parameter(i); |
2444 if (!variable->IsContextSlot()) continue; | 2473 if (!variable->IsContextSlot()) continue; |
2445 // Temporary parameter node. The parameter indices are shifted by 1 | 2474 // Temporary parameter node. The parameter indices are shifted by 1 |
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2999 if (exit_control() != NULL) { | 3028 if (exit_control() != NULL) { |
3000 exit = MergeControl(exit_control(), exit); | 3029 exit = MergeControl(exit_control(), exit); |
3001 } | 3030 } |
3002 environment()->MarkAsUnreachable(); | 3031 environment()->MarkAsUnreachable(); |
3003 set_exit_control(exit); | 3032 set_exit_control(exit); |
3004 } | 3033 } |
3005 | 3034 |
3006 | 3035 |
3007 void AstGraphBuilder::Environment::Merge(Environment* other) { | 3036 void AstGraphBuilder::Environment::Merge(Environment* other) { |
3008 DCHECK(values_.size() == other->values_.size()); | 3037 DCHECK(values_.size() == other->values_.size()); |
3038 DCHECK(contexts_.size() <= other->contexts_.size()); | |
3009 | 3039 |
3010 // Nothing to do if the other environment is dead. | 3040 // Nothing to do if the other environment is dead. |
3011 if (other->IsMarkedAsUnreachable()) return; | 3041 if (other->IsMarkedAsUnreachable()) return; |
3012 | 3042 |
3013 // Resurrect a dead environment by copying the contents of the other one and | 3043 // Resurrect a dead environment by copying the contents of the other one and |
3014 // placing a singleton merge as the new control dependency. | 3044 // placing a singleton merge as the new control dependency. |
3015 if (this->IsMarkedAsUnreachable()) { | 3045 if (this->IsMarkedAsUnreachable()) { |
3016 Node* other_control = other->control_dependency_; | 3046 Node* other_control = other->control_dependency_; |
3017 Node* inputs[] = {other_control}; | 3047 Node* inputs[] = {other_control}; |
3018 control_dependency_ = | 3048 control_dependency_ = |
(...skipping 13 matching lines...) Expand all Loading... | |
3032 // the current environment's effect dependency accordingly. | 3062 // the current environment's effect dependency accordingly. |
3033 Node* effect = builder_->MergeEffect(this->GetEffectDependency(), | 3063 Node* effect = builder_->MergeEffect(this->GetEffectDependency(), |
3034 other->GetEffectDependency(), control); | 3064 other->GetEffectDependency(), control); |
3035 UpdateEffectDependency(effect); | 3065 UpdateEffectDependency(effect); |
3036 | 3066 |
3037 // Introduce Phi nodes for values that have differing input at merge points, | 3067 // Introduce Phi nodes for values that have differing input at merge points, |
3038 // potentially extending an existing Phi node if possible. | 3068 // potentially extending an existing Phi node if possible. |
3039 for (int i = 0; i < static_cast<int>(values_.size()); ++i) { | 3069 for (int i = 0; i < static_cast<int>(values_.size()); ++i) { |
3040 values_[i] = builder_->MergeValue(values_[i], other->values_[i], control); | 3070 values_[i] = builder_->MergeValue(values_[i], other->values_[i], control); |
3041 } | 3071 } |
3072 for (int i = 0; i < static_cast<int>(contexts_.size()); ++i) { | |
3073 contexts_[i] = | |
3074 builder_->MergeValue(contexts_[i], other->contexts_[i], control); | |
3075 } | |
3042 } | 3076 } |
3043 | 3077 |
3044 | 3078 |
3045 void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned, | 3079 void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned, |
3046 bool is_osr) { | 3080 bool is_osr) { |
3047 int size = static_cast<int>(values()->size()); | 3081 int size = static_cast<int>(values()->size()); |
3048 | 3082 |
3049 Node* control = builder_->NewLoop(); | 3083 Node* control = builder_->NewLoop(); |
3050 if (assigned == nullptr) { | 3084 if (assigned == nullptr) { |
3051 // Assume that everything is updated in the loop. | 3085 // Assume that everything is updated in the loop. |
3052 for (int i = 0; i < size; ++i) { | 3086 for (int i = 0; i < size; ++i) { |
3053 Node* phi = builder_->NewPhi(1, values()->at(i), control); | 3087 values()->at(i) = builder_->NewPhi(1, values()->at(i), control); |
3054 values()->at(i) = phi; | |
3055 } | 3088 } |
3056 } else { | 3089 } else { |
3057 // Only build phis for those locals assigned in this loop. | 3090 // Only build phis for those locals assigned in this loop. |
3058 for (int i = 0; i < size; ++i) { | 3091 for (int i = 0; i < size; ++i) { |
3059 if (i < assigned->length() && !assigned->Contains(i)) continue; | 3092 if (i < assigned->length() && !assigned->Contains(i)) continue; |
3060 Node* phi = builder_->NewPhi(1, values()->at(i), control); | 3093 Node* phi = builder_->NewPhi(1, values()->at(i), control); |
3061 values()->at(i) = phi; | 3094 values()->at(i) = phi; |
3062 } | 3095 } |
3063 } | 3096 } |
3064 Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control); | 3097 Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control); |
3065 UpdateEffectDependency(effect); | 3098 UpdateEffectDependency(effect); |
3066 | 3099 |
3100 if (builder_->info()->is_osr()) { | |
3101 // Introduce phis for all context values in the case of an OSR graph. | |
3102 for (int i = 0; i < static_cast<int>(contexts()->size()); ++i) { | |
3103 Node* val = contexts()->at(i); | |
3104 if (!IrOpcode::IsConstantOpcode(val->opcode())) { | |
3105 contexts()->at(i) = builder_->NewPhi(1, val, control); | |
3106 } | |
3107 } | |
3108 } | |
3109 | |
3067 if (is_osr) { | 3110 if (is_osr) { |
3068 // Merge OSR values as inputs to the phis of the loop. | 3111 // Merge OSR values as inputs to the phis of the loop. |
3069 Graph* graph = builder_->graph(); | 3112 Graph* graph = builder_->graph(); |
3070 Node* osr_loop_entry = builder_->graph()->NewNode( | 3113 Node* osr_loop_entry = builder_->graph()->NewNode( |
3071 builder_->common()->OsrLoopEntry(), graph->start(), graph->start()); | 3114 builder_->common()->OsrLoopEntry(), graph->start(), graph->start()); |
3072 | 3115 |
3073 builder_->MergeControl(control, osr_loop_entry); | 3116 builder_->MergeControl(control, osr_loop_entry); |
3074 builder_->MergeEffect(effect, osr_loop_entry, control); | 3117 builder_->MergeEffect(effect, osr_loop_entry, control); |
3075 | 3118 |
3076 for (int i = 0; i < size; ++i) { | 3119 for (int i = 0; i < size; ++i) { |
3077 Node* val = values()->at(i); | 3120 Node* val = values()->at(i); |
3078 if (!IrOpcode::IsConstantOpcode(val->opcode())) { | 3121 if (!IrOpcode::IsConstantOpcode(val->opcode())) { |
3079 Node* osr_value = | 3122 Node* osr_value = |
3080 graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry); | 3123 graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry); |
3081 values()->at(i) = builder_->MergeValue(val, osr_value, control); | 3124 values()->at(i) = builder_->MergeValue(val, osr_value, control); |
3082 } | 3125 } |
3083 } | 3126 } |
3127 | |
3128 // Rename all the contexts in the environment. | |
3129 // The innermost context is the OSR value, and the outer contexts are | |
3130 // reconstructed by dynamically walking up the context chain. | |
3131 Node* osr_context = nullptr; | |
3132 const Operator* op = | |
3133 builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true); | |
3134 int last = static_cast<int>(contexts()->size() - 1); | |
3135 for (int i = last; i >= 0; i--) { | |
3136 Node* val = contexts()->at(i); | |
3137 if (!IrOpcode::IsConstantOpcode(val->opcode())) { | |
3138 osr_context = (i == last) ? builder_->NewCurrentContextOsrValue() | |
3139 : graph->NewNode(op, osr_context, osr_context, | |
3140 osr_loop_entry); | |
3141 contexts()->at(i) = builder_->MergeValue(val, osr_context, control); | |
3142 } else { | |
3143 osr_context = val; | |
3144 } | |
3145 } | |
3084 } | 3146 } |
3085 } | 3147 } |
3086 | 3148 |
3087 | 3149 |
3088 Node* AstGraphBuilder::NewPhi(int count, Node* input, Node* control) { | 3150 Node* AstGraphBuilder::NewPhi(int count, Node* input, Node* control) { |
3089 const Operator* phi_op = common()->Phi(kMachAnyTagged, count); | 3151 const Operator* phi_op = common()->Phi(kMachAnyTagged, count); |
3090 Node** buffer = EnsureInputBufferSize(count + 1); | 3152 Node** buffer = EnsureInputBufferSize(count + 1); |
3091 MemsetPointer(buffer, input, count); | 3153 MemsetPointer(buffer, input, count); |
3092 buffer[count] = control; | 3154 buffer[count] = control; |
3093 return graph()->NewNode(phi_op, count + 1, buffer, true); | 3155 return graph()->NewNode(phi_op, count + 1, buffer, true); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3163 Node* dead_node = graph()->NewNode(common()->Dead()); | 3225 Node* dead_node = graph()->NewNode(common()->Dead()); |
3164 dead_control_.set(dead_node); | 3226 dead_control_.set(dead_node); |
3165 return dead_node; | 3227 return dead_node; |
3166 } | 3228 } |
3167 return dead_control_.get(); | 3229 return dead_control_.get(); |
3168 } | 3230 } |
3169 | 3231 |
3170 } // namespace compiler | 3232 } // namespace compiler |
3171 } // namespace internal | 3233 } // namespace internal |
3172 } // namespace v8 | 3234 } // namespace v8 |
OLD | NEW |