| 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 // Parameter (arity + 1) is special for the outer context of the function |
| 489 : NewOuterContextParam()); | 489 const Operator* op = common()->Parameter( |
| 490 info()->num_parameters_including_this(), "%context"); |
| 491 Node* node = NewNode(op, graph()->start()); |
| 492 function_context_.set(node); |
| 493 } |
| 494 return function_context_.get(); |
| 490 } | 495 } |
| 491 | 496 |
| 492 | 497 |
| 493 Node* AstGraphBuilder::NewOuterContextParam() { | 498 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 bool AstGraphBuilder::CreateGraph(bool constant_context, bool stack_check) { | |
| 502 Scope* scope = info()->scope(); | 499 Scope* scope = info()->scope(); |
| 503 DCHECK(graph() != NULL); | 500 DCHECK(graph() != NULL); |
| 504 | 501 |
| 505 // Set up the basic structure of the graph. Outputs for {Start} are the formal | 502 // Set up the basic structure of the graph. Outputs for {Start} are the formal |
| 506 // parameters (including the receiver) plus context and closure. | 503 // parameters (including the receiver) plus context and closure. |
| 507 int actual_parameter_count = info()->num_parameters_including_this() + 2; | 504 int actual_parameter_count = info()->num_parameters_including_this() + 2; |
| 508 graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count))); | 505 graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count))); |
| 509 | 506 |
| 510 // Initialize the top-level environment. | 507 // Initialize the top-level environment. |
| 511 Environment env(this, scope, graph()->start()); | 508 Environment env(this, scope, graph()->start()); |
| 512 set_environment(&env); | 509 set_environment(&env); |
| 513 | 510 |
| 514 if (info()->is_osr()) { | 511 if (info()->is_osr()) { |
| 515 // Use OSR normal entry as the start of the top-level environment. | 512 // Use OSR normal entry as the start of the top-level environment. |
| 516 // It will be replaced with {Dead} after typing and optimizations. | 513 // It will be replaced with {Dead} after typing and optimizations. |
| 517 NewNode(common()->OsrNormalEntry()); | 514 NewNode(common()->OsrNormalEntry()); |
| 518 } | 515 } |
| 519 | 516 |
| 520 // Initialize the incoming context. | 517 // Initialize the incoming context. |
| 521 CreateFunctionContext(constant_context); | 518 ContextScope incoming(this, scope, GetFunctionContext()); |
| 522 ContextScope incoming(this, scope, function_context_.get()); | |
| 523 | 519 |
| 524 // Initialize control scope. | 520 // Initialize control scope. |
| 525 ControlScope control(this); | 521 ControlScope control(this); |
| 526 | 522 |
| 527 // Build receiver check for sloppy mode if necessary. | 523 // Build receiver check for sloppy mode if necessary. |
| 528 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC? | 524 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC? |
| 529 if (scope->has_this_declaration()) { | 525 if (scope->has_this_declaration()) { |
| 530 Node* original_receiver = env.RawParameterLookup(0); | 526 Node* original_receiver = env.RawParameterLookup(0); |
| 531 Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver); | 527 Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver); |
| 532 env.RawParameterBind(0, patched_receiver); | 528 env.RawParameterBind(0, patched_receiver); |
| 533 } | 529 } |
| 534 | 530 |
| 535 // Build function context only if there are context allocated variables. | 531 // Build function context only if there are context allocated variables. |
| 536 if (info()->num_heap_slots() > 0) { | 532 if (info()->num_heap_slots() > 0) { |
| 537 // Push a new inner context scope for the function. | 533 // Push a new inner context scope for the function. |
| 538 Node* inner_context = BuildLocalFunctionContext(function_context_.get()); | 534 Node* inner_context = BuildLocalFunctionContext(GetFunctionContext()); |
| 539 ContextScope top_context(this, scope, inner_context); | 535 ContextScope top_context(this, scope, inner_context); |
| 540 CreateGraphBody(stack_check); | 536 CreateGraphBody(stack_check); |
| 541 } else { | 537 } else { |
| 542 // Simply use the outer function context in building the graph. | 538 // Simply use the outer function context in building the graph. |
| 543 CreateGraphBody(stack_check); | 539 CreateGraphBody(stack_check); |
| 544 } | 540 } |
| 545 | 541 |
| 546 // Finish the basic structure of the graph. | 542 // Finish the basic structure of the graph. |
| 547 DCHECK_NE(0u, exit_controls_.size()); | 543 DCHECK_NE(0u, exit_controls_.size()); |
| 548 int const input_count = static_cast<int>(exit_controls_.size()); | 544 int const input_count = static_cast<int>(exit_controls_.size()); |
| (...skipping 3075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3624 Node* global = BuildLoadGlobalObject(); | 3620 Node* global = BuildLoadGlobalObject(); |
| 3625 Node* builtins = | 3621 Node* builtins = |
| 3626 BuildLoadObjectField(global, JSGlobalObject::kBuiltinsOffset); | 3622 BuildLoadObjectField(global, JSGlobalObject::kBuiltinsOffset); |
| 3627 return builtins; | 3623 return builtins; |
| 3628 } | 3624 } |
| 3629 | 3625 |
| 3630 | 3626 |
| 3631 Node* AstGraphBuilder::BuildLoadGlobalObject() { | 3627 Node* AstGraphBuilder::BuildLoadGlobalObject() { |
| 3632 const Operator* load_op = | 3628 const Operator* load_op = |
| 3633 javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true); | 3629 javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true); |
| 3634 return NewNode(load_op, function_context_.get()); | 3630 return NewNode(load_op, GetFunctionContext()); |
| 3635 } | 3631 } |
| 3636 | 3632 |
| 3637 | 3633 |
| 3638 Node* AstGraphBuilder::BuildLoadGlobalProxy() { | 3634 Node* AstGraphBuilder::BuildLoadGlobalProxy() { |
| 3639 Node* global = BuildLoadGlobalObject(); | 3635 Node* global = BuildLoadGlobalObject(); |
| 3640 Node* proxy = | 3636 Node* proxy = |
| 3641 BuildLoadObjectField(global, JSGlobalObject::kGlobalProxyOffset); | 3637 BuildLoadObjectField(global, JSGlobalObject::kGlobalProxyOffset); |
| 3642 return proxy; | 3638 return proxy; |
| 3643 } | 3639 } |
| 3644 | 3640 |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4049 // Connect the loop to end via Terminate if it's not marked as unreachable. | 4045 // Connect the loop to end via Terminate if it's not marked as unreachable. |
| 4050 if (!IsMarkedAsUnreachable()) { | 4046 if (!IsMarkedAsUnreachable()) { |
| 4051 // Connect the Loop node to end via a Terminate node. | 4047 // Connect the Loop node to end via a Terminate node. |
| 4052 Node* terminate = builder_->graph()->NewNode( | 4048 Node* terminate = builder_->graph()->NewNode( |
| 4053 builder_->common()->Terminate(), effect, control); | 4049 builder_->common()->Terminate(), effect, control); |
| 4054 builder_->exit_controls_.push_back(terminate); | 4050 builder_->exit_controls_.push_back(terminate); |
| 4055 } | 4051 } |
| 4056 | 4052 |
| 4057 if (builder_->info()->is_osr()) { | 4053 if (builder_->info()->is_osr()) { |
| 4058 // Introduce phis for all context values in the case of an OSR graph. | 4054 // Introduce phis for all context values in the case of an OSR graph. |
| 4059 for (int i = 0; i < static_cast<int>(contexts()->size()); ++i) { | 4055 for (size_t i = 0; i < contexts()->size(); ++i) { |
| 4060 Node* val = contexts()->at(i); | 4056 Node* context = contexts()->at(i); |
| 4061 if (!IrOpcode::IsConstantOpcode(val->opcode())) { | 4057 contexts()->at(i) = builder_->NewPhi(1, context, control); |
| 4062 contexts()->at(i) = builder_->NewPhi(1, val, control); | |
| 4063 } | |
| 4064 } | 4058 } |
| 4065 } | 4059 } |
| 4066 | 4060 |
| 4067 if (is_osr) { | 4061 if (is_osr) { |
| 4068 // Merge OSR values as inputs to the phis of the loop. | 4062 // Merge OSR values as inputs to the phis of the loop. |
| 4069 Graph* graph = builder_->graph(); | 4063 Graph* graph = builder_->graph(); |
| 4070 Node* osr_loop_entry = builder_->graph()->NewNode( | 4064 Node* osr_loop_entry = builder_->graph()->NewNode( |
| 4071 builder_->common()->OsrLoopEntry(), graph->start(), graph->start()); | 4065 builder_->common()->OsrLoopEntry(), graph->start(), graph->start()); |
| 4072 | 4066 |
| 4073 builder_->MergeControl(control, osr_loop_entry); | 4067 builder_->MergeControl(control, osr_loop_entry); |
| 4074 builder_->MergeEffect(effect, osr_loop_entry, control); | 4068 builder_->MergeEffect(effect, osr_loop_entry, control); |
| 4075 | 4069 |
| 4076 for (int i = 0; i < size; ++i) { | 4070 for (int i = 0; i < size; ++i) { |
| 4077 Node* val = values()->at(i); | 4071 Node* value = values()->at(i); |
| 4078 if (!IrOpcode::IsConstantOpcode(val->opcode())) { | 4072 Node* osr_value = |
| 4079 Node* osr_value = | 4073 graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry); |
| 4080 graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry); | 4074 values()->at(i) = builder_->MergeValue(value, osr_value, control); |
| 4081 values()->at(i) = builder_->MergeValue(val, osr_value, control); | |
| 4082 } | |
| 4083 } | 4075 } |
| 4084 | 4076 |
| 4085 // Rename all the contexts in the environment. | 4077 // Rename all the contexts in the environment. |
| 4086 // The innermost context is the OSR value, and the outer contexts are | 4078 // The innermost context is the OSR value, and the outer contexts are |
| 4087 // reconstructed by dynamically walking up the context chain. | 4079 // reconstructed by dynamically walking up the context chain. |
| 4088 Node* osr_context = nullptr; | 4080 Node* osr_context = nullptr; |
| 4089 const Operator* op = | 4081 const Operator* op = |
| 4090 builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true); | 4082 builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true); |
| 4091 const Operator* op_inner = | 4083 const Operator* op_inner = |
| 4092 builder_->common()->OsrValue(Linkage::kOsrContextSpillSlotIndex); | 4084 builder_->common()->OsrValue(Linkage::kOsrContextSpillSlotIndex); |
| 4093 int last = static_cast<int>(contexts()->size() - 1); | 4085 int last = static_cast<int>(contexts()->size() - 1); |
| 4094 for (int i = last; i >= 0; i--) { | 4086 for (int i = last; i >= 0; i--) { |
| 4095 Node* val = contexts()->at(i); | 4087 Node* context = contexts()->at(i); |
| 4096 if (!IrOpcode::IsConstantOpcode(val->opcode())) { | 4088 osr_context = (i == last) ? graph->NewNode(op_inner, osr_loop_entry) |
| 4097 osr_context = (i == last) ? graph->NewNode(op_inner, osr_loop_entry) | 4089 : graph->NewNode(op, osr_context, osr_context, |
| 4098 : graph->NewNode(op, osr_context, osr_context, | 4090 osr_loop_entry); |
| 4099 osr_loop_entry); | 4091 contexts()->at(i) = builder_->MergeValue(context, osr_context, control); |
| 4100 contexts()->at(i) = builder_->MergeValue(val, osr_context, control); | |
| 4101 } else { | |
| 4102 osr_context = val; | |
| 4103 } | |
| 4104 } | 4092 } |
| 4105 } | 4093 } |
| 4106 } | 4094 } |
| 4107 | 4095 |
| 4108 | 4096 |
| 4109 Node* AstGraphBuilder::NewPhi(int count, Node* input, Node* control) { | 4097 Node* AstGraphBuilder::NewPhi(int count, Node* input, Node* control) { |
| 4110 const Operator* phi_op = common()->Phi(kMachAnyTagged, count); | 4098 const Operator* phi_op = common()->Phi(kMachAnyTagged, count); |
| 4111 Node** buffer = EnsureInputBufferSize(count + 1); | 4099 Node** buffer = EnsureInputBufferSize(count + 1); |
| 4112 MemsetPointer(buffer, input, count); | 4100 MemsetPointer(buffer, input, count); |
| 4113 buffer[count] = control; | 4101 buffer[count] = control; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4174 // Phi does not exist yet, introduce one. | 4162 // Phi does not exist yet, introduce one. |
| 4175 value = NewPhi(inputs, value, control); | 4163 value = NewPhi(inputs, value, control); |
| 4176 value->ReplaceInput(inputs - 1, other); | 4164 value->ReplaceInput(inputs - 1, other); |
| 4177 } | 4165 } |
| 4178 return value; | 4166 return value; |
| 4179 } | 4167 } |
| 4180 | 4168 |
| 4181 } // namespace compiler | 4169 } // namespace compiler |
| 4182 } // namespace internal | 4170 } // namespace internal |
| 4183 } // namespace v8 | 4171 } // namespace v8 |
| OLD | NEW |