Chromium Code Reviews| 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 |