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/linkage.h" | 10 #include "src/compiler/linkage.h" |
11 #include "src/compiler/machine-operator.h" | 11 #include "src/compiler/machine-operator.h" |
12 #include "src/compiler/node-matchers.h" | 12 #include "src/compiler/node-matchers.h" |
13 #include "src/compiler/node-properties.h" | 13 #include "src/compiler/node-properties.h" |
14 #include "src/compiler/operator-properties.h" | 14 #include "src/compiler/operator-properties.h" |
15 #include "src/full-codegen.h" | 15 #include "src/full-codegen.h" |
16 #include "src/parser.h" | 16 #include "src/parser.h" |
17 #include "src/scopes.h" | 17 #include "src/scopes.h" |
18 | 18 |
19 namespace v8 { | 19 namespace v8 { |
20 namespace internal { | 20 namespace internal { |
21 namespace compiler { | 21 namespace compiler { |
22 | 22 |
| 23 |
23 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, | 24 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, |
24 JSGraph* jsgraph, LoopAssignmentAnalysis* loop) | 25 JSGraph* jsgraph, LoopAssignmentAnalysis* loop) |
25 : StructuredGraphBuilder(jsgraph->isolate(), local_zone, jsgraph->graph(), | 26 : local_zone_(local_zone), |
26 jsgraph->common()), | |
27 info_(info), | 27 info_(info), |
28 jsgraph_(jsgraph), | 28 jsgraph_(jsgraph), |
| 29 environment_(nullptr), |
| 30 ast_context_(nullptr), |
29 globals_(0, local_zone), | 31 globals_(0, local_zone), |
30 breakable_(NULL), | 32 breakable_(nullptr), |
31 execution_context_(NULL), | 33 execution_context_(nullptr), |
| 34 input_buffer_size_(0), |
| 35 input_buffer_(nullptr), |
| 36 current_context_(nullptr), |
| 37 exit_control_(nullptr), |
32 loop_assignment_analysis_(loop) { | 38 loop_assignment_analysis_(loop) { |
33 InitializeAstVisitor(info->isolate(), local_zone); | 39 InitializeAstVisitor(info->isolate(), local_zone); |
34 } | 40 } |
35 | 41 |
36 | 42 |
37 Node* AstGraphBuilder::GetFunctionClosure() { | 43 Node* AstGraphBuilder::GetFunctionClosure() { |
38 if (!function_closure_.is_set()) { | 44 if (!function_closure_.is_set()) { |
39 const Operator* op = | 45 const Operator* op = |
40 common()->Parameter(Linkage::kJSFunctionCallClosureParamIndex); | 46 common()->Parameter(Linkage::kJSFunctionCallClosureParamIndex); |
41 Node* node = NewNode(op, graph()->start()); | 47 Node* node = NewNode(op, graph()->start()); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 Property* property = expr->AsProperty(); | 150 Property* property = expr->AsProperty(); |
145 DCHECK(expr->IsValidReferenceExpression()); | 151 DCHECK(expr->IsValidReferenceExpression()); |
146 LhsKind lhs_kind = | 152 LhsKind lhs_kind = |
147 (property == NULL) ? VARIABLE : (property->key()->IsPropertyName()) | 153 (property == NULL) ? VARIABLE : (property->key()->IsPropertyName()) |
148 ? NAMED_PROPERTY | 154 ? NAMED_PROPERTY |
149 : KEYED_PROPERTY; | 155 : KEYED_PROPERTY; |
150 return lhs_kind; | 156 return lhs_kind; |
151 } | 157 } |
152 | 158 |
153 | 159 |
154 StructuredGraphBuilder::Environment* AstGraphBuilder::CopyEnvironment( | |
155 StructuredGraphBuilder::Environment* env) { | |
156 return new (zone()) Environment(*reinterpret_cast<Environment*>(env)); | |
157 } | |
158 | |
159 | |
160 AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder, | 160 AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder, |
161 Scope* scope, | 161 Scope* scope, |
162 Node* control_dependency) | 162 Node* control_dependency) |
163 : StructuredGraphBuilder::Environment(builder, control_dependency), | 163 : builder_(builder), |
164 parameters_count_(scope->num_parameters() + 1), | 164 parameters_count_(scope->num_parameters() + 1), |
165 locals_count_(scope->num_stack_slots()), | 165 locals_count_(scope->num_stack_slots()), |
166 parameters_node_(NULL), | 166 values_(builder_->local_zone()), |
167 locals_node_(NULL), | 167 control_dependency_(control_dependency), |
168 stack_node_(NULL) { | 168 effect_dependency_(control_dependency), |
| 169 parameters_node_(nullptr), |
| 170 locals_node_(nullptr), |
| 171 stack_node_(nullptr) { |
169 DCHECK_EQ(scope->num_parameters() + 1, parameters_count()); | 172 DCHECK_EQ(scope->num_parameters() + 1, parameters_count()); |
170 | 173 |
171 // Bind the receiver variable. | 174 // Bind the receiver variable. |
172 Node* receiver = builder->graph()->NewNode(common()->Parameter(0), | 175 Node* receiver = builder->graph()->NewNode(common()->Parameter(0), |
173 builder->graph()->start()); | 176 builder->graph()->start()); |
174 values()->push_back(receiver); | 177 values()->push_back(receiver); |
175 | 178 |
176 // Bind all parameter variables. The parameter indices are shifted by 1 | 179 // Bind all parameter variables. The parameter indices are shifted by 1 |
177 // (receiver is parameter index -1 but environment index 0). | 180 // (receiver is parameter index -1 but environment index 0). |
178 for (int i = 0; i < scope->num_parameters(); ++i) { | 181 for (int i = 0; i < scope->num_parameters(); ++i) { |
179 Node* parameter = builder->graph()->NewNode(common()->Parameter(i + 1), | 182 Node* parameter = builder->graph()->NewNode(common()->Parameter(i + 1), |
180 builder->graph()->start()); | 183 builder->graph()->start()); |
181 values()->push_back(parameter); | 184 values()->push_back(parameter); |
182 } | 185 } |
183 | 186 |
184 // Bind all local variables to undefined. | 187 // Bind all local variables to undefined. |
185 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); | 188 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); |
186 values()->insert(values()->end(), locals_count(), undefined_constant); | 189 values()->insert(values()->end(), locals_count(), undefined_constant); |
187 } | 190 } |
188 | 191 |
189 | 192 |
190 AstGraphBuilder::Environment::Environment(const Environment& copy) | 193 AstGraphBuilder::Environment::Environment( |
191 : StructuredGraphBuilder::Environment( | 194 const AstGraphBuilder::Environment* copy) |
192 static_cast<StructuredGraphBuilder::Environment>(copy)), | 195 : builder_(copy->builder_), |
193 parameters_count_(copy.parameters_count_), | 196 parameters_count_(copy->parameters_count_), |
194 locals_count_(copy.locals_count_), | 197 locals_count_(copy->locals_count_), |
195 parameters_node_(copy.parameters_node_), | 198 values_(copy->zone()), |
196 locals_node_(copy.locals_node_), | 199 control_dependency_(copy->control_dependency_), |
197 stack_node_(copy.stack_node_) {} | 200 effect_dependency_(copy->effect_dependency_), |
| 201 parameters_node_(copy->parameters_node_), |
| 202 locals_node_(copy->locals_node_), |
| 203 stack_node_(copy->stack_node_) { |
| 204 const size_t kStackEstimate = 7; // optimum from experimentation! |
| 205 values_.reserve(copy->values_.size() + kStackEstimate); |
| 206 values_.insert(values_.begin(), copy->values_.begin(), copy->values_.end()); |
| 207 } |
198 | 208 |
199 | 209 |
200 void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values, | 210 void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values, |
201 int offset, int count) { | 211 int offset, int count) { |
202 bool should_update = false; | 212 bool should_update = false; |
203 Node** env_values = (count == 0) ? NULL : &values()->at(offset); | 213 Node** env_values = (count == 0) ? NULL : &values()->at(offset); |
204 if (*state_values == NULL || (*state_values)->InputCount() != count) { | 214 if (*state_values == NULL || (*state_values)->InputCount() != count) { |
205 should_update = true; | 215 should_update = true; |
206 } else { | 216 } else { |
207 DCHECK(static_cast<size_t>(offset + count) <= values()->size()); | 217 DCHECK(static_cast<size_t>(offset + count) <= values()->size()); |
(...skipping 14 matching lines...) Expand all Loading... |
222 Node* AstGraphBuilder::Environment::Checkpoint( | 232 Node* AstGraphBuilder::Environment::Checkpoint( |
223 BailoutId ast_id, OutputFrameStateCombine combine) { | 233 BailoutId ast_id, OutputFrameStateCombine combine) { |
224 UpdateStateValues(¶meters_node_, 0, parameters_count()); | 234 UpdateStateValues(¶meters_node_, 0, parameters_count()); |
225 UpdateStateValues(&locals_node_, parameters_count(), locals_count()); | 235 UpdateStateValues(&locals_node_, parameters_count(), locals_count()); |
226 UpdateStateValues(&stack_node_, parameters_count() + locals_count(), | 236 UpdateStateValues(&stack_node_, parameters_count() + locals_count(), |
227 stack_height()); | 237 stack_height()); |
228 | 238 |
229 const Operator* op = common()->FrameState(JS_FRAME, ast_id, combine); | 239 const Operator* op = common()->FrameState(JS_FRAME, ast_id, combine); |
230 | 240 |
231 return graph()->NewNode(op, parameters_node_, locals_node_, stack_node_, | 241 return graph()->NewNode(op, parameters_node_, locals_node_, stack_node_, |
232 GetContext(), | 242 builder()->current_context(), |
233 builder()->jsgraph()->UndefinedConstant()); | 243 builder()->jsgraph()->UndefinedConstant()); |
234 } | 244 } |
235 | 245 |
236 | 246 |
237 AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own, | 247 AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own, |
238 Expression::Context kind) | 248 Expression::Context kind) |
239 : kind_(kind), owner_(own), outer_(own->ast_context()) { | 249 : kind_(kind), owner_(own), outer_(own->ast_context()) { |
240 owner()->set_ast_context(this); // Push. | 250 owner()->set_ast_context(this); // Push. |
241 #ifdef DEBUG | 251 #ifdef DEBUG |
242 original_height_ = environment()->stack_height(); | 252 original_height_ = environment()->stack_height(); |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 compare_if.If(condition); | 521 compare_if.If(condition); |
512 compare_if.Then(); | 522 compare_if.Then(); |
513 Visit(stmt->then_statement()); | 523 Visit(stmt->then_statement()); |
514 compare_if.Else(); | 524 compare_if.Else(); |
515 Visit(stmt->else_statement()); | 525 Visit(stmt->else_statement()); |
516 compare_if.End(); | 526 compare_if.End(); |
517 } | 527 } |
518 | 528 |
519 | 529 |
520 void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { | 530 void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { |
521 StructuredGraphBuilder::Environment* env = environment()->CopyAsUnreachable(); | 531 Environment* env = environment()->CopyAsUnreachable(); |
522 breakable()->ContinueTarget(stmt->target()); | 532 breakable()->ContinueTarget(stmt->target()); |
523 set_environment(env); | 533 set_environment(env); |
524 } | 534 } |
525 | 535 |
526 | 536 |
527 void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { | 537 void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
528 StructuredGraphBuilder::Environment* env = environment()->CopyAsUnreachable(); | 538 Environment* env = environment()->CopyAsUnreachable(); |
529 breakable()->BreakTarget(stmt->target()); | 539 breakable()->BreakTarget(stmt->target()); |
530 set_environment(env); | 540 set_environment(env); |
531 } | 541 } |
532 | 542 |
533 | 543 |
534 void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 544 void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
535 VisitForValue(stmt->expression()); | 545 VisitForValue(stmt->expression()); |
536 Node* result = environment()->Pop(); | 546 Node* result = environment()->Pop(); |
537 Node* control = NewNode(common()->Return(), result); | 547 Node* control = NewNode(common()->Return(), result); |
538 UpdateControlDependencyToLeaveFunction(control); | 548 UpdateControlDependencyToLeaveFunction(control); |
(...skipping 1399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1938 } | 1948 } |
1939 Node* value = NewNode(op, arity, all); | 1949 Node* value = NewNode(op, arity, all); |
1940 return value; | 1950 return value; |
1941 } | 1951 } |
1942 | 1952 |
1943 | 1953 |
1944 Node* AstGraphBuilder::BuildPatchReceiverToGlobalProxy(Node* receiver) { | 1954 Node* AstGraphBuilder::BuildPatchReceiverToGlobalProxy(Node* receiver) { |
1945 // Sloppy mode functions and builtins need to replace the receiver with the | 1955 // Sloppy mode functions and builtins need to replace the receiver with the |
1946 // global proxy when called as functions (without an explicit receiver | 1956 // global proxy when called as functions (without an explicit receiver |
1947 // object). Otherwise there is nothing left to do here. | 1957 // object). Otherwise there is nothing left to do here. |
1948 if (info()->strict_mode() != SLOPPY || info()->is_native()) return receiver; | 1958 if (strict_mode() != SLOPPY || info()->is_native()) return receiver; |
1949 | 1959 |
1950 // There is no need to perform patching if the receiver is never used. Note | 1960 // There is no need to perform patching if the receiver is never used. Note |
1951 // that scope predicates are purely syntactical, a call to eval might still | 1961 // that scope predicates are purely syntactical, a call to eval might still |
1952 // inspect the receiver value. | 1962 // inspect the receiver value. |
1953 if (!info()->scope()->uses_this() && !info()->scope()->inner_uses_this() && | 1963 if (!info()->scope()->uses_this() && !info()->scope()->inner_uses_this() && |
1954 !info()->scope()->calls_sloppy_eval()) { | 1964 !info()->scope()->calls_sloppy_eval()) { |
1955 return receiver; | 1965 return receiver; |
1956 } | 1966 } |
1957 | 1967 |
1958 IfBuilder receiver_check(this); | 1968 IfBuilder receiver_check(this); |
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2432 } | 2442 } |
2433 } | 2443 } |
2434 | 2444 |
2435 | 2445 |
2436 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( | 2446 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( |
2437 IterationStatement* stmt) { | 2447 IterationStatement* stmt) { |
2438 if (loop_assignment_analysis_ == NULL) return NULL; | 2448 if (loop_assignment_analysis_ == NULL) return NULL; |
2439 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); | 2449 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); |
2440 } | 2450 } |
2441 | 2451 |
| 2452 |
| 2453 Node** AstGraphBuilder::EnsureInputBufferSize(int size) { |
| 2454 if (size > input_buffer_size_) { |
| 2455 size = size + kInputBufferSizeIncrement + input_buffer_size_; |
| 2456 input_buffer_ = local_zone()->NewArray<Node*>(size); |
| 2457 input_buffer_size_ = size; |
| 2458 } |
| 2459 return input_buffer_; |
| 2460 } |
| 2461 |
| 2462 |
| 2463 Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count, |
| 2464 Node** value_inputs, bool incomplete) { |
| 2465 DCHECK(op->ValueInputCount() == value_input_count); |
| 2466 |
| 2467 bool has_context = OperatorProperties::HasContextInput(op); |
| 2468 bool has_framestate = OperatorProperties::HasFrameStateInput(op); |
| 2469 bool has_control = op->ControlInputCount() == 1; |
| 2470 bool has_effect = op->EffectInputCount() == 1; |
| 2471 |
| 2472 DCHECK(op->ControlInputCount() < 2); |
| 2473 DCHECK(op->EffectInputCount() < 2); |
| 2474 |
| 2475 Node* result = NULL; |
| 2476 if (!has_context && !has_framestate && !has_control && !has_effect) { |
| 2477 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); |
| 2478 } else { |
| 2479 int input_count_with_deps = value_input_count; |
| 2480 if (has_context) ++input_count_with_deps; |
| 2481 if (has_framestate) ++input_count_with_deps; |
| 2482 if (has_control) ++input_count_with_deps; |
| 2483 if (has_effect) ++input_count_with_deps; |
| 2484 Node** buffer = EnsureInputBufferSize(input_count_with_deps); |
| 2485 memcpy(buffer, value_inputs, kPointerSize * value_input_count); |
| 2486 Node** current_input = buffer + value_input_count; |
| 2487 if (has_context) { |
| 2488 *current_input++ = current_context(); |
| 2489 } |
| 2490 if (has_framestate) { |
| 2491 // The frame state will be inserted later. Here we misuse |
| 2492 // the dead_control node as a sentinel to be later overwritten |
| 2493 // with the real frame state. |
| 2494 *current_input++ = dead_control(); |
| 2495 } |
| 2496 if (has_effect) { |
| 2497 *current_input++ = environment_->GetEffectDependency(); |
| 2498 } |
| 2499 if (has_control) { |
| 2500 *current_input++ = environment_->GetControlDependency(); |
| 2501 } |
| 2502 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); |
| 2503 if (has_effect) { |
| 2504 environment_->UpdateEffectDependency(result); |
| 2505 } |
| 2506 if (result->op()->ControlOutputCount() > 0 && |
| 2507 !environment()->IsMarkedAsUnreachable()) { |
| 2508 environment_->UpdateControlDependency(result); |
| 2509 } |
| 2510 } |
| 2511 |
| 2512 return result; |
| 2513 } |
| 2514 |
| 2515 |
| 2516 void AstGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { |
| 2517 if (environment()->IsMarkedAsUnreachable()) return; |
| 2518 if (exit_control() != NULL) { |
| 2519 exit = MergeControl(exit_control(), exit); |
| 2520 } |
| 2521 environment()->MarkAsUnreachable(); |
| 2522 set_exit_control(exit); |
| 2523 } |
| 2524 |
| 2525 |
| 2526 void AstGraphBuilder::Environment::Merge(Environment* other) { |
| 2527 DCHECK(values_.size() == other->values_.size()); |
| 2528 |
| 2529 // Nothing to do if the other environment is dead. |
| 2530 if (other->IsMarkedAsUnreachable()) return; |
| 2531 |
| 2532 // Resurrect a dead environment by copying the contents of the other one and |
| 2533 // placing a singleton merge as the new control dependency. |
| 2534 if (this->IsMarkedAsUnreachable()) { |
| 2535 Node* other_control = other->control_dependency_; |
| 2536 Node* inputs[] = {other_control}; |
| 2537 control_dependency_ = |
| 2538 graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true); |
| 2539 effect_dependency_ = other->effect_dependency_; |
| 2540 values_ = other->values_; |
| 2541 return; |
| 2542 } |
| 2543 |
| 2544 // Create a merge of the control dependencies of both environments and update |
| 2545 // the current environment's control dependency accordingly. |
| 2546 Node* control = builder_->MergeControl(this->GetControlDependency(), |
| 2547 other->GetControlDependency()); |
| 2548 UpdateControlDependency(control); |
| 2549 |
| 2550 // Create a merge of the effect dependencies of both environments and update |
| 2551 // the current environment's effect dependency accordingly. |
| 2552 Node* effect = builder_->MergeEffect(this->GetEffectDependency(), |
| 2553 other->GetEffectDependency(), control); |
| 2554 UpdateEffectDependency(effect); |
| 2555 |
| 2556 // Introduce Phi nodes for values that have differing input at merge points, |
| 2557 // potentially extending an existing Phi node if possible. |
| 2558 for (int i = 0; i < static_cast<int>(values_.size()); ++i) { |
| 2559 values_[i] = builder_->MergeValue(values_[i], other->values_[i], control); |
| 2560 } |
| 2561 } |
| 2562 |
| 2563 |
| 2564 void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned, |
| 2565 bool is_osr) { |
| 2566 int size = static_cast<int>(values()->size()); |
| 2567 |
| 2568 Node* control = builder_->NewLoop(); |
| 2569 if (assigned == nullptr) { |
| 2570 // Assume that everything is updated in the loop. |
| 2571 for (int i = 0; i < size; ++i) { |
| 2572 Node* phi = builder_->NewPhi(1, values()->at(i), control); |
| 2573 values()->at(i) = phi; |
| 2574 } |
| 2575 } else { |
| 2576 // Only build phis for those locals assigned in this loop. |
| 2577 for (int i = 0; i < size; ++i) { |
| 2578 if (i < assigned->length() && !assigned->Contains(i)) continue; |
| 2579 Node* phi = builder_->NewPhi(1, values()->at(i), control); |
| 2580 values()->at(i) = phi; |
| 2581 } |
| 2582 } |
| 2583 Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control); |
| 2584 UpdateEffectDependency(effect); |
| 2585 |
| 2586 if (is_osr) { |
| 2587 // Merge OSR values as inputs to the phis of the loop. |
| 2588 Graph* graph = builder_->graph(); |
| 2589 Node* osr_loop_entry = builder_->graph()->NewNode( |
| 2590 builder_->common()->OsrLoopEntry(), graph->start(), graph->start()); |
| 2591 |
| 2592 builder_->MergeControl(control, osr_loop_entry); |
| 2593 builder_->MergeEffect(effect, osr_loop_entry, control); |
| 2594 |
| 2595 for (int i = 0; i < size; ++i) { |
| 2596 Node* val = values()->at(i); |
| 2597 if (!IrOpcode::IsConstantOpcode(val->opcode())) { |
| 2598 Node* osr_value = |
| 2599 graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry); |
| 2600 values()->at(i) = builder_->MergeValue(val, osr_value, control); |
| 2601 } |
| 2602 } |
| 2603 } |
| 2604 } |
| 2605 |
| 2606 |
| 2607 Node* AstGraphBuilder::NewPhi(int count, Node* input, Node* control) { |
| 2608 const Operator* phi_op = common()->Phi(kMachAnyTagged, count); |
| 2609 Node** buffer = EnsureInputBufferSize(count + 1); |
| 2610 MemsetPointer(buffer, input, count); |
| 2611 buffer[count] = control; |
| 2612 return graph()->NewNode(phi_op, count + 1, buffer, true); |
| 2613 } |
| 2614 |
| 2615 |
| 2616 // TODO(mstarzinger): Revisit this once we have proper effect states. |
| 2617 Node* AstGraphBuilder::NewEffectPhi(int count, Node* input, Node* control) { |
| 2618 const Operator* phi_op = common()->EffectPhi(count); |
| 2619 Node** buffer = EnsureInputBufferSize(count + 1); |
| 2620 MemsetPointer(buffer, input, count); |
| 2621 buffer[count] = control; |
| 2622 return graph()->NewNode(phi_op, count + 1, buffer, true); |
| 2623 } |
| 2624 |
| 2625 |
| 2626 Node* AstGraphBuilder::MergeControl(Node* control, Node* other) { |
| 2627 int inputs = control->op()->ControlInputCount() + 1; |
| 2628 if (control->opcode() == IrOpcode::kLoop) { |
| 2629 // Control node for loop exists, add input. |
| 2630 const Operator* op = common()->Loop(inputs); |
| 2631 control->AppendInput(graph_zone(), other); |
| 2632 control->set_op(op); |
| 2633 } else if (control->opcode() == IrOpcode::kMerge) { |
| 2634 // Control node for merge exists, add input. |
| 2635 const Operator* op = common()->Merge(inputs); |
| 2636 control->AppendInput(graph_zone(), other); |
| 2637 control->set_op(op); |
| 2638 } else { |
| 2639 // Control node is a singleton, introduce a merge. |
| 2640 const Operator* op = common()->Merge(inputs); |
| 2641 Node* inputs[] = {control, other}; |
| 2642 control = graph()->NewNode(op, arraysize(inputs), inputs, true); |
| 2643 } |
| 2644 return control; |
| 2645 } |
| 2646 |
| 2647 |
| 2648 Node* AstGraphBuilder::MergeEffect(Node* value, Node* other, Node* control) { |
| 2649 int inputs = control->op()->ControlInputCount(); |
| 2650 if (value->opcode() == IrOpcode::kEffectPhi && |
| 2651 NodeProperties::GetControlInput(value) == control) { |
| 2652 // Phi already exists, add input. |
| 2653 value->set_op(common()->EffectPhi(inputs)); |
| 2654 value->InsertInput(graph_zone(), inputs - 1, other); |
| 2655 } else if (value != other) { |
| 2656 // Phi does not exist yet, introduce one. |
| 2657 value = NewEffectPhi(inputs, value, control); |
| 2658 value->ReplaceInput(inputs - 1, other); |
| 2659 } |
| 2660 return value; |
| 2661 } |
| 2662 |
| 2663 |
| 2664 Node* AstGraphBuilder::MergeValue(Node* value, Node* other, Node* control) { |
| 2665 int inputs = control->op()->ControlInputCount(); |
| 2666 if (value->opcode() == IrOpcode::kPhi && |
| 2667 NodeProperties::GetControlInput(value) == control) { |
| 2668 // Phi already exists, add input. |
| 2669 value->set_op(common()->Phi(kMachAnyTagged, inputs)); |
| 2670 value->InsertInput(graph_zone(), inputs - 1, other); |
| 2671 } else if (value != other) { |
| 2672 // Phi does not exist yet, introduce one. |
| 2673 value = NewPhi(inputs, value, control); |
| 2674 value->ReplaceInput(inputs - 1, other); |
| 2675 } |
| 2676 return value; |
| 2677 } |
| 2678 |
| 2679 |
| 2680 Node* AstGraphBuilder::dead_control() { |
| 2681 if (!dead_control_.is_set()) { |
| 2682 Node* dead_node = graph()->NewNode(common()->Dead()); |
| 2683 dead_control_.set(dead_node); |
| 2684 return dead_node; |
| 2685 } |
| 2686 return dead_control_.get(); |
| 2687 } |
| 2688 |
2442 } // namespace compiler | 2689 } // namespace compiler |
2443 } // namespace internal | 2690 } // namespace internal |
2444 } // namespace v8 | 2691 } // namespace v8 |
OLD | NEW |