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 |