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 loop_assignment_analysis_(loop), | |
30 environment_(nullptr), | |
31 ast_context_(nullptr), | |
29 globals_(0, local_zone), | 32 globals_(0, local_zone), |
30 breakable_(NULL), | 33 breakable_(nullptr), |
31 execution_context_(NULL), | 34 execution_context_(nullptr), |
32 loop_assignment_analysis_(loop) { | 35 input_buffer_size_(0), |
36 input_buffer_(nullptr), | |
37 current_context_(nullptr), | |
38 exit_control_(nullptr) { | |
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()); |
42 function_closure_.set(node); | 48 function_closure_.set(node); |
(...skipping 101 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 303 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 AstGraphBuilder::Environment* env = environment()->CopyAsUnreachable(); |
Michael Starzinger
2015/02/02 18:08:23
nit: Just drop the prefix.
titzer
2015/02/02 18:26:47
Done.
| |
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 AstGraphBuilder::Environment* env = environment()->CopyAsUnreachable(); |
Michael Starzinger
2015/02/02 18:08:23
nit: Just drop the prefix.
titzer
2015/02/02 18:26:47
Done.
| |
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 |