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/js-type-feedback.h" | 10 #include "src/compiler/js-type-feedback.h" |
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
476 if (!function_closure_.is_set()) { | 476 if (!function_closure_.is_set()) { |
477 const Operator* op = common()->Parameter( | 477 const Operator* op = common()->Parameter( |
478 Linkage::kJSFunctionCallClosureParamIndex, "%closure"); | 478 Linkage::kJSFunctionCallClosureParamIndex, "%closure"); |
479 Node* node = NewNode(op, graph()->start()); | 479 Node* node = NewNode(op, graph()->start()); |
480 function_closure_.set(node); | 480 function_closure_.set(node); |
481 } | 481 } |
482 return function_closure_.get(); | 482 return function_closure_.get(); |
483 } | 483 } |
484 | 484 |
485 | 485 |
486 void AstGraphBuilder::CreateFunctionContext(bool constant_context) { | 486 Node* AstGraphBuilder::GetFunctionContext() { |
487 function_context_.set(constant_context | 487 if (!function_context_.is_set()) { |
488 ? jsgraph()->HeapConstant(info()->context()) | 488 const Operator* op = common()->Parameter( |
489 : NewOuterContextParam()); | 489 info()->num_parameters_including_this(), "%context"); |
490 Node* node = NewNode(op, graph()->start()); | |
491 function_context_.set(node); | |
492 } | |
493 return function_context_.get(); | |
490 } | 494 } |
491 | 495 |
492 | 496 |
493 Node* AstGraphBuilder::NewOuterContextParam() { | 497 bool AstGraphBuilder::CreateGraph(bool stack_check) { |
494 // Parameter (arity + 1) is special for the outer context of the function | |
495 const Operator* op = | |
496 common()->Parameter(info()->num_parameters_including_this(), "%context"); | |
497 return NewNode(op, graph()->start()); | |
498 } | |
499 | |
500 | |
501 Node* AstGraphBuilder::NewCurrentContextOsrValue() { | |
502 // TODO(titzer): use a real OSR value here; a parameter works by accident. | |
503 // Parameter (arity + 1) is special for the outer context of the function | |
504 const Operator* op = common()->Parameter( | |
505 info()->num_parameters_including_this(), "%osr-context"); | |
506 return NewNode(op, graph()->start()); | |
507 } | |
508 | |
509 | |
510 bool AstGraphBuilder::CreateGraph(bool constant_context, bool stack_check) { | |
511 Scope* scope = info()->scope(); | 498 Scope* scope = info()->scope(); |
512 DCHECK(graph() != NULL); | 499 DCHECK(graph() != NULL); |
513 | 500 |
514 // Set up the basic structure of the graph. | 501 // Set up the basic structure of the graph. |
515 int parameter_count = info()->num_parameters(); | 502 int parameter_count = info()->num_parameters(); |
516 graph()->SetStart(graph()->NewNode(common()->Start(parameter_count))); | 503 graph()->SetStart(graph()->NewNode(common()->Start(parameter_count))); |
517 | 504 |
518 // Initialize the top-level environment. | 505 // Initialize the top-level environment. |
519 Environment env(this, scope, graph()->start()); | 506 Environment env(this, scope, graph()->start()); |
520 set_environment(&env); | 507 set_environment(&env); |
521 | 508 |
522 if (info()->is_osr()) { | 509 if (info()->is_osr()) { |
523 // Use OSR normal entry as the start of the top-level environment. | 510 // Use OSR normal entry as the start of the top-level environment. |
524 // It will be replaced with {Dead} after typing and optimizations. | 511 // It will be replaced with {Dead} after typing and optimizations. |
525 NewNode(common()->OsrNormalEntry()); | 512 NewNode(common()->OsrNormalEntry()); |
526 } | 513 } |
527 | 514 |
528 // Initialize the incoming context. | 515 // Initialize the incoming context. |
529 CreateFunctionContext(constant_context); | 516 ContextScope incoming(this, scope, GetFunctionContext()); |
530 ContextScope incoming(this, scope, function_context_.get()); | |
531 | 517 |
532 // Initialize control scope. | 518 // Initialize control scope. |
533 ControlScope control(this); | 519 ControlScope control(this); |
534 | 520 |
535 // Build receiver check for sloppy mode if necessary. | 521 // Build receiver check for sloppy mode if necessary. |
536 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC? | 522 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC? |
537 Node* patched_receiver = nullptr; | 523 Node* patched_receiver = nullptr; |
538 if (scope->has_this_declaration()) { | 524 if (scope->has_this_declaration()) { |
539 Node* original_receiver = NewNode(common()->Parameter(0), graph()->start()); | 525 Node* original_receiver = NewNode(common()->Parameter(0), graph()->start()); |
540 patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver); | 526 patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver); |
541 if (scope->receiver()->IsStackAllocated()) { | 527 if (scope->receiver()->IsStackAllocated()) { |
542 env.Bind(scope->receiver(), patched_receiver); | 528 env.Bind(scope->receiver(), patched_receiver); |
543 } | 529 } |
544 } | 530 } |
545 | 531 |
546 // Build function context only if there are context allocated variables. | 532 // Build function context only if there are context allocated variables. |
547 if (info()->num_heap_slots() > 0) { | 533 if (info()->num_heap_slots() > 0) { |
548 // Push a new inner context scope for the function. | 534 // Push a new inner context scope for the function. |
549 Node* inner_context = | 535 Node* inner_context = |
550 BuildLocalFunctionContext(function_context_.get(), patched_receiver); | 536 BuildLocalFunctionContext(GetFunctionContext(), patched_receiver); |
551 ContextScope top_context(this, scope, inner_context); | 537 ContextScope top_context(this, scope, inner_context); |
552 CreateGraphBody(stack_check); | 538 CreateGraphBody(stack_check); |
553 } else { | 539 } else { |
554 // Simply use the outer function context in building the graph. | 540 // Simply use the outer function context in building the graph. |
555 CreateGraphBody(stack_check); | 541 CreateGraphBody(stack_check); |
556 } | 542 } |
557 | 543 |
558 // Finish the basic structure of the graph. | 544 // Finish the basic structure of the graph. |
559 DCHECK_NE(0u, exit_controls_.size()); | 545 DCHECK_NE(0u, exit_controls_.size()); |
560 int const input_count = static_cast<int>(exit_controls_.size()); | 546 int const input_count = static_cast<int>(exit_controls_.size()); |
(...skipping 3068 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3629 Node* global = BuildLoadGlobalObject(); | 3615 Node* global = BuildLoadGlobalObject(); |
3630 Node* builtins = | 3616 Node* builtins = |
3631 BuildLoadObjectField(global, JSGlobalObject::kBuiltinsOffset); | 3617 BuildLoadObjectField(global, JSGlobalObject::kBuiltinsOffset); |
3632 return builtins; | 3618 return builtins; |
3633 } | 3619 } |
3634 | 3620 |
3635 | 3621 |
3636 Node* AstGraphBuilder::BuildLoadGlobalObject() { | 3622 Node* AstGraphBuilder::BuildLoadGlobalObject() { |
3637 const Operator* load_op = | 3623 const Operator* load_op = |
3638 javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true); | 3624 javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true); |
3639 return NewNode(load_op, function_context_.get()); | 3625 return NewNode(load_op, GetFunctionContext()); |
3640 } | 3626 } |
3641 | 3627 |
3642 | 3628 |
3643 Node* AstGraphBuilder::BuildLoadGlobalProxy() { | 3629 Node* AstGraphBuilder::BuildLoadGlobalProxy() { |
3644 Node* global = BuildLoadGlobalObject(); | 3630 Node* global = BuildLoadGlobalObject(); |
3645 Node* proxy = | 3631 Node* proxy = |
3646 BuildLoadObjectField(global, JSGlobalObject::kGlobalProxyOffset); | 3632 BuildLoadObjectField(global, JSGlobalObject::kGlobalProxyOffset); |
3647 return proxy; | 3633 return proxy; |
3648 } | 3634 } |
3649 | 3635 |
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4056 // Connect the Loop node to end via a Terminate node. | 4042 // Connect the Loop node to end via a Terminate node. |
4057 Node* terminate = builder_->graph()->NewNode( | 4043 Node* terminate = builder_->graph()->NewNode( |
4058 builder_->common()->Terminate(), effect, control); | 4044 builder_->common()->Terminate(), effect, control); |
4059 builder_->exit_controls_.push_back(terminate); | 4045 builder_->exit_controls_.push_back(terminate); |
4060 } | 4046 } |
4061 | 4047 |
4062 if (builder_->info()->is_osr()) { | 4048 if (builder_->info()->is_osr()) { |
4063 // Introduce phis for all context values in the case of an OSR graph. | 4049 // Introduce phis for all context values in the case of an OSR graph. |
4064 for (int i = 0; i < static_cast<int>(contexts()->size()); ++i) { | 4050 for (int i = 0; i < static_cast<int>(contexts()->size()); ++i) { |
4065 Node* val = contexts()->at(i); | 4051 Node* val = contexts()->at(i); |
4066 if (!IrOpcode::IsConstantOpcode(val->opcode())) { | 4052 if (!IrOpcode::IsConstantOpcode(val->opcode()) && |
4053 (val != builder_->GetFunctionContext() || | |
4054 !builder_->info()->is_context_specializing())) { | |
4067 contexts()->at(i) = builder_->NewPhi(1, val, control); | 4055 contexts()->at(i) = builder_->NewPhi(1, val, control); |
4068 } | 4056 } |
4069 } | 4057 } |
4070 } | 4058 } |
4071 | 4059 |
4072 if (is_osr) { | 4060 if (is_osr) { |
4073 // Merge OSR values as inputs to the phis of the loop. | 4061 // Merge OSR values as inputs to the phis of the loop. |
4074 Graph* graph = builder_->graph(); | 4062 Graph* graph = builder_->graph(); |
4075 Node* osr_loop_entry = builder_->graph()->NewNode( | 4063 Node* osr_loop_entry = builder_->graph()->NewNode( |
4076 builder_->common()->OsrLoopEntry(), graph->start(), graph->start()); | 4064 builder_->common()->OsrLoopEntry(), graph->start(), graph->start()); |
4077 | 4065 |
4078 builder_->MergeControl(control, osr_loop_entry); | 4066 builder_->MergeControl(control, osr_loop_entry); |
4079 builder_->MergeEffect(effect, osr_loop_entry, control); | 4067 builder_->MergeEffect(effect, osr_loop_entry, control); |
4080 | 4068 |
4081 for (int i = 0; i < size; ++i) { | 4069 for (int i = 0; i < size; ++i) { |
4082 Node* val = values()->at(i); | 4070 Node* val = values()->at(i); |
4083 if (!IrOpcode::IsConstantOpcode(val->opcode())) { | 4071 if (!IrOpcode::IsConstantOpcode(val->opcode())) { |
4084 Node* osr_value = | 4072 Node* osr_value = |
4085 graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry); | 4073 graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry); |
4086 values()->at(i) = builder_->MergeValue(val, osr_value, control); | 4074 values()->at(i) = builder_->MergeValue(val, osr_value, control); |
4087 } | 4075 } |
4088 } | 4076 } |
4089 | 4077 |
4090 // Rename all the contexts in the environment. | 4078 // Rename all the contexts in the environment. |
4091 // The innermost context is the OSR value, and the outer contexts are | 4079 // The innermost context is the OSR value, and the outer contexts are |
4092 // reconstructed by dynamically walking up the context chain. | 4080 // reconstructed by dynamically walking up the context chain. |
4081 // TODO(titzer): use a real OSR value here; a parameter works by accident. | |
titzer
2015/07/03 09:28:17
To get rid of this TODO, we need a special OSR val
Michael Starzinger
2015/07/06 13:08:40
Done, see: https://codereview.chromium.org/1213043
| |
4082 Node* innermost_context = graph->NewNode( | |
4083 builder_->common()->Parameter( | |
4084 builder_->info()->num_parameters_including_this(), "%osr-context"), | |
4085 graph->start()); | |
4093 Node* osr_context = nullptr; | 4086 Node* osr_context = nullptr; |
4094 const Operator* op = | 4087 const Operator* op = |
4095 builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true); | 4088 builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true); |
4096 int last = static_cast<int>(contexts()->size() - 1); | 4089 int last = static_cast<int>(contexts()->size() - 1); |
4097 for (int i = last; i >= 0; i--) { | 4090 for (int i = last; i >= 0; i--) { |
4098 Node* val = contexts()->at(i); | 4091 Node* val = contexts()->at(i); |
4099 if (!IrOpcode::IsConstantOpcode(val->opcode())) { | 4092 if (!IrOpcode::IsConstantOpcode(val->opcode()) && |
4100 osr_context = (i == last) ? builder_->NewCurrentContextOsrValue() | 4093 (val != builder_->GetFunctionContext() || |
4094 !builder_->info()->is_context_specializing())) { | |
4095 osr_context = (i == last) ? innermost_context | |
4101 : graph->NewNode(op, osr_context, osr_context, | 4096 : graph->NewNode(op, osr_context, osr_context, |
4102 osr_loop_entry); | 4097 osr_loop_entry); |
4103 contexts()->at(i) = builder_->MergeValue(val, osr_context, control); | 4098 contexts()->at(i) = builder_->MergeValue(val, osr_context, control); |
4104 } else { | 4099 } else { |
4105 osr_context = val; | 4100 osr_context = val; |
4106 } | 4101 } |
4107 } | 4102 } |
4108 } | 4103 } |
4109 } | 4104 } |
4110 | 4105 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4177 // Phi does not exist yet, introduce one. | 4172 // Phi does not exist yet, introduce one. |
4178 value = NewPhi(inputs, value, control); | 4173 value = NewPhi(inputs, value, control); |
4179 value->ReplaceInput(inputs - 1, other); | 4174 value->ReplaceInput(inputs - 1, other); |
4180 } | 4175 } |
4181 return value; | 4176 return value; |
4182 } | 4177 } |
4183 | 4178 |
4184 } // namespace compiler | 4179 } // namespace compiler |
4185 } // namespace internal | 4180 } // namespace internal |
4186 } // namespace v8 | 4181 } // namespace v8 |
OLD | NEW |