OLD | NEW |
(Empty) | |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "src/compiler/graph-builder.h" |
| 6 |
| 7 #include "src/compiler.h" |
| 8 #include "src/compiler/generic-graph.h" |
| 9 #include "src/compiler/generic-node.h" |
| 10 #include "src/compiler/generic-node-inl.h" |
| 11 #include "src/compiler/graph-visualizer.h" |
| 12 #include "src/compiler/node-properties.h" |
| 13 #include "src/compiler/node-properties-inl.h" |
| 14 #include "src/compiler/operator-properties.h" |
| 15 #include "src/compiler/operator-properties-inl.h" |
| 16 |
| 17 namespace v8 { |
| 18 namespace internal { |
| 19 namespace compiler { |
| 20 |
| 21 |
| 22 StructuredGraphBuilder::StructuredGraphBuilder(Graph* graph, |
| 23 CommonOperatorBuilder* common) |
| 24 : GraphBuilder(graph), |
| 25 common_(common), |
| 26 environment_(NULL), |
| 27 current_context_(NULL), |
| 28 exit_control_(NULL) {} |
| 29 |
| 30 |
| 31 Node* StructuredGraphBuilder::MakeNode(Operator* op, int value_input_count, |
| 32 Node** value_inputs) { |
| 33 bool has_context = OperatorProperties::HasContextInput(op); |
| 34 bool has_control = OperatorProperties::GetControlInputCount(op) == 1; |
| 35 bool has_effect = OperatorProperties::GetEffectInputCount(op) == 1; |
| 36 |
| 37 ASSERT(OperatorProperties::GetControlInputCount(op) < 2); |
| 38 ASSERT(OperatorProperties::GetEffectInputCount(op) < 2); |
| 39 |
| 40 Node* result = NULL; |
| 41 if (!has_context && !has_control && !has_effect) { |
| 42 result = graph()->NewNode(op, value_input_count, value_inputs); |
| 43 } else { |
| 44 int input_count_with_deps = value_input_count; |
| 45 if (has_context) ++input_count_with_deps; |
| 46 if (has_control) ++input_count_with_deps; |
| 47 if (has_effect) ++input_count_with_deps; |
| 48 void* raw_buffer = alloca(kPointerSize * input_count_with_deps); |
| 49 Node** buffer = reinterpret_cast<Node**>(raw_buffer); |
| 50 memcpy(buffer, value_inputs, kPointerSize * value_input_count); |
| 51 Node** current_input = buffer + value_input_count; |
| 52 if (has_context) { |
| 53 *current_input++ = current_context(); |
| 54 } |
| 55 if (has_effect) { |
| 56 *current_input++ = environment_->GetEffectDependency(); |
| 57 } |
| 58 if (has_control) { |
| 59 *current_input++ = GetControlDependency(); |
| 60 } |
| 61 result = graph()->NewNode(op, input_count_with_deps, buffer); |
| 62 if (has_effect) { |
| 63 environment_->UpdateEffectDependency(result); |
| 64 } |
| 65 if (NodeProperties::HasControlOutput(result) && |
| 66 !environment_internal()->IsMarkedAsUnreachable()) { |
| 67 UpdateControlDependency(result); |
| 68 } |
| 69 } |
| 70 |
| 71 return result; |
| 72 } |
| 73 |
| 74 |
| 75 Node* StructuredGraphBuilder::GetControlDependency() { |
| 76 return environment_->GetControlDependency(); |
| 77 } |
| 78 |
| 79 |
| 80 void StructuredGraphBuilder::UpdateControlDependency(Node* new_control) { |
| 81 environment_->UpdateControlDependency(new_control); |
| 82 } |
| 83 |
| 84 |
| 85 void StructuredGraphBuilder::UpdateControlDependencyToLeaveFunction( |
| 86 Node* exit) { |
| 87 if (environment_internal()->IsMarkedAsUnreachable()) return; |
| 88 if (exit_control() != NULL) { |
| 89 exit = MergeControl(exit_control(), exit); |
| 90 } |
| 91 environment_internal()->MarkAsUnreachable(); |
| 92 set_exit_control(exit); |
| 93 } |
| 94 |
| 95 |
| 96 StructuredGraphBuilder::Environment* StructuredGraphBuilder::CopyEnvironment( |
| 97 Environment* env) { |
| 98 return new (zone()) Environment(*env); |
| 99 } |
| 100 |
| 101 |
| 102 StructuredGraphBuilder::Environment::Environment( |
| 103 StructuredGraphBuilder* builder, Node* control_dependency) |
| 104 : builder_(builder), |
| 105 control_dependency_(control_dependency), |
| 106 effect_dependency_(control_dependency), |
| 107 values_(NodeVector::allocator_type(zone())) {} |
| 108 |
| 109 |
| 110 StructuredGraphBuilder::Environment::Environment(const Environment& copy) |
| 111 : builder_(copy.builder()), |
| 112 control_dependency_(copy.control_dependency_), |
| 113 effect_dependency_(copy.effect_dependency_), |
| 114 values_(copy.values_) {} |
| 115 |
| 116 |
| 117 void StructuredGraphBuilder::Environment::Merge(Environment* other) { |
| 118 ASSERT(values_.size() == other->values_.size()); |
| 119 |
| 120 // Nothing to do if the other environment is dead. |
| 121 if (other->IsMarkedAsUnreachable()) return; |
| 122 |
| 123 // Resurrect a dead environment by copying the contents of the other one and |
| 124 // placing a singleton merge as the new control dependency. |
| 125 if (this->IsMarkedAsUnreachable()) { |
| 126 Node* other_control = other->control_dependency_; |
| 127 control_dependency_ = graph()->NewNode(common()->Merge(1), other_control); |
| 128 effect_dependency_ = other->effect_dependency_; |
| 129 values_ = other->values_; |
| 130 return; |
| 131 } |
| 132 |
| 133 // Create a merge of the control dependencies of both environments and update |
| 134 // the current environment's control dependency accordingly. |
| 135 Node* control = builder_->MergeControl(this->GetControlDependency(), |
| 136 other->GetControlDependency()); |
| 137 UpdateControlDependency(control); |
| 138 |
| 139 // Create a merge of the effect dependencies of both environments and update |
| 140 // the current environment's effect dependency accordingly. |
| 141 Node* effect = builder_->MergeEffect(this->GetEffectDependency(), |
| 142 other->GetEffectDependency(), control); |
| 143 UpdateEffectDependency(effect); |
| 144 |
| 145 // Introduce Phi nodes for values that have differing input at merge points, |
| 146 // potentially extending an existing Phi node if possible. |
| 147 for (int i = 0; i < static_cast<int>(values_.size()); ++i) { |
| 148 if (values_[i] == NULL) continue; |
| 149 values_[i] = builder_->MergeValue(values_[i], other->values_[i], control); |
| 150 } |
| 151 } |
| 152 |
| 153 |
| 154 void StructuredGraphBuilder::Environment::PrepareForLoop() { |
| 155 Node* control = GetControlDependency(); |
| 156 for (int i = 0; i < static_cast<int>(values()->size()); ++i) { |
| 157 if (values()->at(i) == NULL) continue; |
| 158 Node* phi = builder_->NewPhi(1, values()->at(i), control); |
| 159 values()->at(i) = phi; |
| 160 } |
| 161 Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control); |
| 162 UpdateEffectDependency(effect); |
| 163 } |
| 164 |
| 165 |
| 166 Node* StructuredGraphBuilder::NewPhi(int count, Node* input, Node* control) { |
| 167 Operator* phi_op = common()->Phi(count); |
| 168 void* raw_buffer = alloca(kPointerSize * (count + 1)); |
| 169 Node** buffer = reinterpret_cast<Node**>(raw_buffer); |
| 170 MemsetPointer(buffer, input, count); |
| 171 buffer[count] = control; |
| 172 return graph()->NewNode(phi_op, count + 1, buffer); |
| 173 } |
| 174 |
| 175 |
| 176 // TODO(mstarzinger): Revisit this once we have proper effect states. |
| 177 Node* StructuredGraphBuilder::NewEffectPhi(int count, Node* input, |
| 178 Node* control) { |
| 179 Operator* phi_op = common()->EffectPhi(count); |
| 180 void* raw_buffer = alloca(kPointerSize * (count + 1)); |
| 181 Node** buffer = reinterpret_cast<Node**>(raw_buffer); |
| 182 MemsetPointer(buffer, input, count); |
| 183 buffer[count] = control; |
| 184 return graph()->NewNode(phi_op, count + 1, buffer); |
| 185 } |
| 186 |
| 187 |
| 188 Node* StructuredGraphBuilder::MergeControl(Node* control, Node* other) { |
| 189 int inputs = NodeProperties::GetControlInputCount(control) + 1; |
| 190 if (control->opcode() == IrOpcode::kLoop) { |
| 191 // Control node for loop exists, add input. |
| 192 Operator* op = common()->Loop(inputs); |
| 193 control->AppendInput(zone(), other); |
| 194 control->set_op(op); |
| 195 } else if (control->opcode() == IrOpcode::kMerge) { |
| 196 // Control node for merge exists, add input. |
| 197 Operator* op = common()->Merge(inputs); |
| 198 control->AppendInput(zone(), other); |
| 199 control->set_op(op); |
| 200 } else { |
| 201 // Control node is a singleton, introduce a merge. |
| 202 Operator* op = common()->Merge(inputs); |
| 203 control = graph()->NewNode(op, control, other); |
| 204 } |
| 205 return control; |
| 206 } |
| 207 |
| 208 |
| 209 Node* StructuredGraphBuilder::MergeEffect(Node* value, Node* other, |
| 210 Node* control) { |
| 211 int inputs = NodeProperties::GetControlInputCount(control); |
| 212 if (value->opcode() == IrOpcode::kEffectPhi && |
| 213 NodeProperties::GetControlInput(value) == control) { |
| 214 // Phi already exists, add input. |
| 215 value->set_op(common()->EffectPhi(inputs)); |
| 216 value->InsertInput(zone(), inputs - 1, other); |
| 217 } else if (value != other) { |
| 218 // Phi does not exist yet, introduce one. |
| 219 value = NewEffectPhi(inputs, value, control); |
| 220 value->ReplaceInput(inputs - 1, other); |
| 221 } |
| 222 return value; |
| 223 } |
| 224 |
| 225 |
| 226 Node* StructuredGraphBuilder::MergeValue(Node* value, Node* other, |
| 227 Node* control) { |
| 228 int inputs = NodeProperties::GetControlInputCount(control); |
| 229 if (value->opcode() == IrOpcode::kPhi && |
| 230 NodeProperties::GetControlInput(value) == control) { |
| 231 // Phi already exists, add input. |
| 232 value->set_op(common()->Phi(inputs)); |
| 233 value->InsertInput(zone(), inputs - 1, other); |
| 234 } else if (value != other) { |
| 235 // Phi does not exist yet, introduce one. |
| 236 value = NewPhi(inputs, value, control); |
| 237 value->ReplaceInput(inputs - 1, other); |
| 238 } |
| 239 return value; |
| 240 } |
| 241 |
| 242 |
| 243 Node* StructuredGraphBuilder::dead_control() { |
| 244 if (!dead_control_.is_set()) { |
| 245 Node* dead_node = graph()->NewNode(common_->Dead()); |
| 246 dead_control_.set(dead_node); |
| 247 return dead_node; |
| 248 } |
| 249 return dead_control_.get(); |
| 250 } |
| 251 } |
| 252 } |
| 253 } // namespace v8::internal::compiler |
OLD | NEW |