| 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/bit-vector.h" | |
| 8 #include "src/compiler.h" | |
| 9 #include "src/compiler/graph-visualizer.h" | |
| 10 #include "src/compiler/node.h" | |
| 11 #include "src/compiler/node-properties.h" | |
| 12 #include "src/compiler/operator-properties.h" | |
| 13 | |
| 14 namespace v8 { | |
| 15 namespace internal { | |
| 16 namespace compiler { | |
| 17 | |
| 18 | |
| 19 StructuredGraphBuilder::StructuredGraphBuilder(Isolate* isolate, | |
| 20 Zone* local_zone, Graph* graph, | |
| 21 CommonOperatorBuilder* common) | |
| 22 : GraphBuilder(isolate, graph), | |
| 23 common_(common), | |
| 24 environment_(NULL), | |
| 25 local_zone_(local_zone), | |
| 26 input_buffer_size_(0), | |
| 27 input_buffer_(NULL), | |
| 28 current_context_(NULL), | |
| 29 exit_control_(NULL) { | |
| 30 EnsureInputBufferSize(kInputBufferSizeIncrement); | |
| 31 } | |
| 32 | |
| 33 | |
| 34 Node** StructuredGraphBuilder::EnsureInputBufferSize(int size) { | |
| 35 if (size > input_buffer_size_) { | |
| 36 size += kInputBufferSizeIncrement; | |
| 37 input_buffer_ = local_zone()->NewArray<Node*>(size); | |
| 38 } | |
| 39 return input_buffer_; | |
| 40 } | |
| 41 | |
| 42 | |
| 43 Node* StructuredGraphBuilder::MakeNode(const Operator* op, | |
| 44 int value_input_count, | |
| 45 Node** value_inputs, bool incomplete) { | |
| 46 DCHECK(op->ValueInputCount() == value_input_count); | |
| 47 | |
| 48 bool has_context = OperatorProperties::HasContextInput(op); | |
| 49 bool has_framestate = OperatorProperties::HasFrameStateInput(op); | |
| 50 bool has_control = op->ControlInputCount() == 1; | |
| 51 bool has_effect = op->EffectInputCount() == 1; | |
| 52 | |
| 53 DCHECK(op->ControlInputCount() < 2); | |
| 54 DCHECK(op->EffectInputCount() < 2); | |
| 55 | |
| 56 Node* result = NULL; | |
| 57 if (!has_context && !has_framestate && !has_control && !has_effect) { | |
| 58 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); | |
| 59 } else { | |
| 60 int input_count_with_deps = value_input_count; | |
| 61 if (has_context) ++input_count_with_deps; | |
| 62 if (has_framestate) ++input_count_with_deps; | |
| 63 if (has_control) ++input_count_with_deps; | |
| 64 if (has_effect) ++input_count_with_deps; | |
| 65 Node** buffer = EnsureInputBufferSize(input_count_with_deps); | |
| 66 memcpy(buffer, value_inputs, kPointerSize * value_input_count); | |
| 67 Node** current_input = buffer + value_input_count; | |
| 68 if (has_context) { | |
| 69 *current_input++ = current_context(); | |
| 70 } | |
| 71 if (has_framestate) { | |
| 72 // The frame state will be inserted later. Here we misuse | |
| 73 // the dead_control node as a sentinel to be later overwritten | |
| 74 // with the real frame state. | |
| 75 *current_input++ = dead_control(); | |
| 76 } | |
| 77 if (has_effect) { | |
| 78 *current_input++ = environment_->GetEffectDependency(); | |
| 79 } | |
| 80 if (has_control) { | |
| 81 *current_input++ = environment_->GetControlDependency(); | |
| 82 } | |
| 83 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); | |
| 84 if (has_effect) { | |
| 85 environment_->UpdateEffectDependency(result); | |
| 86 } | |
| 87 if (result->op()->ControlOutputCount() > 0 && | |
| 88 !environment()->IsMarkedAsUnreachable()) { | |
| 89 environment_->UpdateControlDependency(result); | |
| 90 } | |
| 91 } | |
| 92 | |
| 93 return result; | |
| 94 } | |
| 95 | |
| 96 | |
| 97 void StructuredGraphBuilder::UpdateControlDependencyToLeaveFunction( | |
| 98 Node* exit) { | |
| 99 if (environment()->IsMarkedAsUnreachable()) return; | |
| 100 if (exit_control() != NULL) { | |
| 101 exit = MergeControl(exit_control(), exit); | |
| 102 } | |
| 103 environment()->MarkAsUnreachable(); | |
| 104 set_exit_control(exit); | |
| 105 } | |
| 106 | |
| 107 | |
| 108 StructuredGraphBuilder::Environment* StructuredGraphBuilder::CopyEnvironment( | |
| 109 Environment* env) { | |
| 110 return new (local_zone()) Environment(*env); | |
| 111 } | |
| 112 | |
| 113 | |
| 114 StructuredGraphBuilder::Environment::Environment( | |
| 115 StructuredGraphBuilder* builder, Node* control_dependency) | |
| 116 : builder_(builder), | |
| 117 control_dependency_(control_dependency), | |
| 118 effect_dependency_(control_dependency), | |
| 119 values_(zone()) {} | |
| 120 | |
| 121 | |
| 122 StructuredGraphBuilder::Environment::Environment(const Environment& copy) | |
| 123 : builder_(copy.builder()), | |
| 124 control_dependency_(copy.control_dependency_), | |
| 125 effect_dependency_(copy.effect_dependency_), | |
| 126 values_(copy.zone()) { | |
| 127 const size_t kStackEstimate = 7; // optimum from experimentation! | |
| 128 values_.reserve(copy.values_.size() + kStackEstimate); | |
| 129 values_.insert(values_.begin(), copy.values_.begin(), copy.values_.end()); | |
| 130 } | |
| 131 | |
| 132 | |
| 133 void StructuredGraphBuilder::Environment::Merge(Environment* other) { | |
| 134 DCHECK(values_.size() == other->values_.size()); | |
| 135 | |
| 136 // Nothing to do if the other environment is dead. | |
| 137 if (other->IsMarkedAsUnreachable()) return; | |
| 138 | |
| 139 // Resurrect a dead environment by copying the contents of the other one and | |
| 140 // placing a singleton merge as the new control dependency. | |
| 141 if (this->IsMarkedAsUnreachable()) { | |
| 142 Node* other_control = other->control_dependency_; | |
| 143 Node* inputs[] = {other_control}; | |
| 144 control_dependency_ = | |
| 145 graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true); | |
| 146 effect_dependency_ = other->effect_dependency_; | |
| 147 values_ = other->values_; | |
| 148 return; | |
| 149 } | |
| 150 | |
| 151 // Create a merge of the control dependencies of both environments and update | |
| 152 // the current environment's control dependency accordingly. | |
| 153 Node* control = builder_->MergeControl(this->GetControlDependency(), | |
| 154 other->GetControlDependency()); | |
| 155 UpdateControlDependency(control); | |
| 156 | |
| 157 // Create a merge of the effect dependencies of both environments and update | |
| 158 // the current environment's effect dependency accordingly. | |
| 159 Node* effect = builder_->MergeEffect(this->GetEffectDependency(), | |
| 160 other->GetEffectDependency(), control); | |
| 161 UpdateEffectDependency(effect); | |
| 162 | |
| 163 // Introduce Phi nodes for values that have differing input at merge points, | |
| 164 // potentially extending an existing Phi node if possible. | |
| 165 for (int i = 0; i < static_cast<int>(values_.size()); ++i) { | |
| 166 values_[i] = builder_->MergeValue(values_[i], other->values_[i], control); | |
| 167 } | |
| 168 } | |
| 169 | |
| 170 | |
| 171 void StructuredGraphBuilder::Environment::PrepareForLoop(BitVector* assigned, | |
| 172 bool is_osr) { | |
| 173 int size = static_cast<int>(values()->size()); | |
| 174 | |
| 175 Node* control = builder_->NewLoop(); | |
| 176 if (assigned == nullptr) { | |
| 177 // Assume that everything is updated in the loop. | |
| 178 for (int i = 0; i < size; ++i) { | |
| 179 Node* phi = builder_->NewPhi(1, values()->at(i), control); | |
| 180 values()->at(i) = phi; | |
| 181 } | |
| 182 } else { | |
| 183 // Only build phis for those locals assigned in this loop. | |
| 184 for (int i = 0; i < size; ++i) { | |
| 185 if (i < assigned->length() && !assigned->Contains(i)) continue; | |
| 186 Node* phi = builder_->NewPhi(1, values()->at(i), control); | |
| 187 values()->at(i) = phi; | |
| 188 } | |
| 189 } | |
| 190 Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control); | |
| 191 UpdateEffectDependency(effect); | |
| 192 | |
| 193 if (is_osr) { | |
| 194 // Merge OSR values as inputs to the phis of the loop. | |
| 195 Graph* graph = builder_->graph(); | |
| 196 Node* osr_loop_entry = builder_->graph()->NewNode( | |
| 197 builder_->common()->OsrLoopEntry(), graph->start(), graph->start()); | |
| 198 | |
| 199 builder_->MergeControl(control, osr_loop_entry); | |
| 200 builder_->MergeEffect(effect, osr_loop_entry, control); | |
| 201 | |
| 202 for (int i = 0; i < size; ++i) { | |
| 203 Node* val = values()->at(i); | |
| 204 if (!IrOpcode::IsConstantOpcode(val->opcode())) { | |
| 205 Node* osr_value = | |
| 206 graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry); | |
| 207 values()->at(i) = builder_->MergeValue(val, osr_value, control); | |
| 208 } | |
| 209 } | |
| 210 } | |
| 211 } | |
| 212 | |
| 213 | |
| 214 Node* StructuredGraphBuilder::NewPhi(int count, Node* input, Node* control) { | |
| 215 const Operator* phi_op = common()->Phi(kMachAnyTagged, count); | |
| 216 Node** buffer = EnsureInputBufferSize(count + 1); | |
| 217 MemsetPointer(buffer, input, count); | |
| 218 buffer[count] = control; | |
| 219 return graph()->NewNode(phi_op, count + 1, buffer, true); | |
| 220 } | |
| 221 | |
| 222 | |
| 223 // TODO(mstarzinger): Revisit this once we have proper effect states. | |
| 224 Node* StructuredGraphBuilder::NewEffectPhi(int count, Node* input, | |
| 225 Node* control) { | |
| 226 const Operator* phi_op = common()->EffectPhi(count); | |
| 227 Node** buffer = EnsureInputBufferSize(count + 1); | |
| 228 MemsetPointer(buffer, input, count); | |
| 229 buffer[count] = control; | |
| 230 return graph()->NewNode(phi_op, count + 1, buffer, true); | |
| 231 } | |
| 232 | |
| 233 | |
| 234 Node* StructuredGraphBuilder::MergeControl(Node* control, Node* other) { | |
| 235 int inputs = control->op()->ControlInputCount() + 1; | |
| 236 if (control->opcode() == IrOpcode::kLoop) { | |
| 237 // Control node for loop exists, add input. | |
| 238 const Operator* op = common()->Loop(inputs); | |
| 239 control->AppendInput(graph_zone(), other); | |
| 240 control->set_op(op); | |
| 241 } else if (control->opcode() == IrOpcode::kMerge) { | |
| 242 // Control node for merge exists, add input. | |
| 243 const Operator* op = common()->Merge(inputs); | |
| 244 control->AppendInput(graph_zone(), other); | |
| 245 control->set_op(op); | |
| 246 } else { | |
| 247 // Control node is a singleton, introduce a merge. | |
| 248 const Operator* op = common()->Merge(inputs); | |
| 249 Node* inputs[] = {control, other}; | |
| 250 control = graph()->NewNode(op, arraysize(inputs), inputs, true); | |
| 251 } | |
| 252 return control; | |
| 253 } | |
| 254 | |
| 255 | |
| 256 Node* StructuredGraphBuilder::MergeEffect(Node* value, Node* other, | |
| 257 Node* control) { | |
| 258 int inputs = control->op()->ControlInputCount(); | |
| 259 if (value->opcode() == IrOpcode::kEffectPhi && | |
| 260 NodeProperties::GetControlInput(value) == control) { | |
| 261 // Phi already exists, add input. | |
| 262 value->set_op(common()->EffectPhi(inputs)); | |
| 263 value->InsertInput(graph_zone(), inputs - 1, other); | |
| 264 } else if (value != other) { | |
| 265 // Phi does not exist yet, introduce one. | |
| 266 value = NewEffectPhi(inputs, value, control); | |
| 267 value->ReplaceInput(inputs - 1, other); | |
| 268 } | |
| 269 return value; | |
| 270 } | |
| 271 | |
| 272 | |
| 273 Node* StructuredGraphBuilder::MergeValue(Node* value, Node* other, | |
| 274 Node* control) { | |
| 275 int inputs = control->op()->ControlInputCount(); | |
| 276 if (value->opcode() == IrOpcode::kPhi && | |
| 277 NodeProperties::GetControlInput(value) == control) { | |
| 278 // Phi already exists, add input. | |
| 279 value->set_op(common()->Phi(kMachAnyTagged, inputs)); | |
| 280 value->InsertInput(graph_zone(), inputs - 1, other); | |
| 281 } else if (value != other) { | |
| 282 // Phi does not exist yet, introduce one. | |
| 283 value = NewPhi(inputs, value, control); | |
| 284 value->ReplaceInput(inputs - 1, other); | |
| 285 } | |
| 286 return value; | |
| 287 } | |
| 288 | |
| 289 | |
| 290 Node* StructuredGraphBuilder::dead_control() { | |
| 291 if (!dead_control_.is_set()) { | |
| 292 Node* dead_node = graph()->NewNode(common_->Dead()); | |
| 293 dead_control_.set(dead_node); | |
| 294 return dead_node; | |
| 295 } | |
| 296 return dead_control_.get(); | |
| 297 } | |
| 298 } | |
| 299 } | |
| 300 } // namespace v8::internal::compiler | |
| OLD | NEW |