| 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 | 
|---|