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 3 // found in the LICENSE file. 4 5 #ifndef V8_COMPILER_AST_GRAPH_BUILDER_H_ 6 #define V8_COMPILER_AST_GRAPH_BUILDER_H_ 7 8 #include "src/ast/ast.h" 9 #include "src/compiler/js-graph.h" 10 #include "src/compiler/liveness-analyzer.h" 11 #include "src/compiler/state-values-utils.h" 12 13 namespace v8 { 14 namespace internal { 15 16 // Forward declarations. 17 class BitVector; 18 class CompilationInfo; 19 20 namespace compiler { 21 22 // Forward declarations. 23 class ControlBuilder; 24 class Graph; 25 class LoopAssignmentAnalysis; 26 class LoopBuilder; 27 class Node; 28 class TypeHintAnalysis; 29 30 31 // The AstGraphBuilder produces a high-level IR graph, based on an 32 // underlying AST. The produced graph can either be compiled into a 33 // stand-alone function or be wired into another graph for the purposes 34 // of function inlining. 35 class AstGraphBuilder : public AstVisitor { 36 public: 37 AstGraphBuilder(Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph, 38 LoopAssignmentAnalysis* loop_assignment = nullptr, 39 TypeHintAnalysis* type_hint_analysis = nullptr); 40 41 // Creates a graph by visiting the entire AST. 42 bool CreateGraph(bool stack_check = true); 43 44 // Helpers to create new control nodes. NewIfTrue()45 Node* NewIfTrue() { return NewNode(common()->IfTrue()); } NewIfFalse()46 Node* NewIfFalse() { return NewNode(common()->IfFalse()); } NewMerge()47 Node* NewMerge() { return NewNode(common()->Merge(1), true); } NewLoop()48 Node* NewLoop() { return NewNode(common()->Loop(1), true); } 49 Node* NewBranch(Node* condition, BranchHint hint = BranchHint::kNone) { 50 return NewNode(common()->Branch(hint), condition); 51 } 52 53 protected: 54 #define DECLARE_VISIT(type) void Visit##type(type* node) override; 55 // Visiting functions for AST nodes make this an AstVisitor. 56 AST_NODE_LIST(DECLARE_VISIT) 57 #undef DECLARE_VISIT 58 59 // Visiting function for declarations list is overridden. 60 void VisitDeclarations(ZoneList<Declaration*>* declarations) override; 61 62 private: 63 class AstContext; 64 class AstEffectContext; 65 class AstValueContext; 66 class AstTestContext; 67 class ContextScope; 68 class ControlScope; 69 class ControlScopeForBreakable; 70 class ControlScopeForIteration; 71 class ControlScopeForCatch; 72 class ControlScopeForFinally; 73 class Environment; 74 class FrameStateBeforeAndAfter; 75 friend class ControlBuilder; 76 77 Isolate* isolate_; 78 Zone* local_zone_; 79 CompilationInfo* info_; 80 JSGraph* jsgraph_; 81 Environment* environment_; 82 AstContext* ast_context_; 83 84 // List of global declarations for functions and variables. 85 ZoneVector<Handle<Object>> globals_; 86 87 // Stack of control scopes currently entered by the visitor. 88 ControlScope* execution_control_; 89 90 // Stack of context objects pushed onto the chain by the visitor. 91 ContextScope* execution_context_; 92 93 // Nodes representing values in the activation record. 94 SetOncePointer<Node> function_closure_; 95 SetOncePointer<Node> function_context_; 96 SetOncePointer<Node> new_target_; 97 98 // Tracks how many try-blocks are currently entered. 99 int try_catch_nesting_level_; 100 int try_nesting_level_; 101 102 // Temporary storage for building node input lists. 103 int input_buffer_size_; 104 Node** input_buffer_; 105 106 // Optimization to cache loaded feedback vector. 107 SetOncePointer<Node> feedback_vector_; 108 109 // Optimization to cache empty frame state. 110 SetOncePointer<Node> empty_frame_state_; 111 112 // Control nodes that exit the function body. 113 ZoneVector<Node*> exit_controls_; 114 115 // Result of loop assignment analysis performed before graph creation. 116 LoopAssignmentAnalysis* loop_assignment_analysis_; 117 118 // Result of type hint analysis performed before graph creation. 119 TypeHintAnalysis* type_hint_analysis_; 120 121 // Cache for StateValues nodes for frame states. 122 StateValuesCache state_values_cache_; 123 124 // Analyzer of local variable liveness. 125 LivenessAnalyzer liveness_analyzer_; 126 127 // Function info for frame state construction. 128 const FrameStateFunctionInfo* const frame_state_function_info_; 129 130 // Growth increment for the temporary buffer used to construct input lists to 131 // new nodes. 132 static const int kInputBufferSizeIncrement = 64; 133 local_zone()134 Zone* local_zone() const { return local_zone_; } environment()135 Environment* environment() const { return environment_; } ast_context()136 AstContext* ast_context() const { return ast_context_; } execution_control()137 ControlScope* execution_control() const { return execution_control_; } execution_context()138 ContextScope* execution_context() const { return execution_context_; } common()139 CommonOperatorBuilder* common() const { return jsgraph_->common(); } info()140 CompilationInfo* info() const { return info_; } isolate()141 Isolate* isolate() const { return isolate_; } 142 LanguageMode language_mode() const; jsgraph()143 JSGraph* jsgraph() { return jsgraph_; } graph()144 Graph* graph() { return jsgraph_->graph(); } graph_zone()145 Zone* graph_zone() { return graph()->zone(); } javascript()146 JSOperatorBuilder* javascript() { return jsgraph_->javascript(); } globals()147 ZoneVector<Handle<Object>>* globals() { return &globals_; } 148 Scope* current_scope() const; 149 Node* current_context() const; liveness_analyzer()150 LivenessAnalyzer* liveness_analyzer() { return &liveness_analyzer_; } frame_state_function_info()151 const FrameStateFunctionInfo* frame_state_function_info() const { 152 return frame_state_function_info_; 153 } 154 set_environment(Environment * env)155 void set_environment(Environment* env) { environment_ = env; } set_ast_context(AstContext * ctx)156 void set_ast_context(AstContext* ctx) { ast_context_ = ctx; } set_execution_control(ControlScope * ctrl)157 void set_execution_control(ControlScope* ctrl) { execution_control_ = ctrl; } set_execution_context(ContextScope * ctx)158 void set_execution_context(ContextScope* ctx) { execution_context_ = ctx; } 159 160 // Create the main graph body by visiting the AST. 161 void CreateGraphBody(bool stack_check); 162 163 // Get or create the node that represents the incoming function closure. 164 Node* GetFunctionClosureForContext(); 165 Node* GetFunctionClosure(); 166 167 // Get or create the node that represents the incoming function context. 168 Node* GetFunctionContext(); 169 170 // Get or create the node that represents the incoming new target value. 171 Node* GetNewTarget(); 172 173 // Get or create the node that represents the empty frame state. 174 Node* GetEmptyFrameState(); 175 176 // Node creation helpers. 177 Node* NewNode(const Operator* op, bool incomplete = false) { 178 return MakeNode(op, 0, static_cast<Node**>(nullptr), incomplete); 179 } 180 NewNode(const Operator * op,Node * n1)181 Node* NewNode(const Operator* op, Node* n1) { 182 return MakeNode(op, 1, &n1, false); 183 } 184 NewNode(const Operator * op,Node * n1,Node * n2)185 Node* NewNode(const Operator* op, Node* n1, Node* n2) { 186 Node* buffer[] = {n1, n2}; 187 return MakeNode(op, arraysize(buffer), buffer, false); 188 } 189 NewNode(const Operator * op,Node * n1,Node * n2,Node * n3)190 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) { 191 Node* buffer[] = {n1, n2, n3}; 192 return MakeNode(op, arraysize(buffer), buffer, false); 193 } 194 NewNode(const Operator * op,Node * n1,Node * n2,Node * n3,Node * n4)195 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) { 196 Node* buffer[] = {n1, n2, n3, n4}; 197 return MakeNode(op, arraysize(buffer), buffer, false); 198 } 199 NewNode(const Operator * op,Node * n1,Node * n2,Node * n3,Node * n4,Node * n5)200 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4, 201 Node* n5) { 202 Node* buffer[] = {n1, n2, n3, n4, n5}; 203 return MakeNode(op, arraysize(buffer), buffer, false); 204 } 205 NewNode(const Operator * op,Node * n1,Node * n2,Node * n3,Node * n4,Node * n5,Node * n6)206 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4, 207 Node* n5, Node* n6) { 208 Node* nodes[] = {n1, n2, n3, n4, n5, n6}; 209 return MakeNode(op, arraysize(nodes), nodes, false); 210 } 211 212 Node* NewNode(const Operator* op, int value_input_count, Node** value_inputs, 213 bool incomplete = false) { 214 return MakeNode(op, value_input_count, value_inputs, incomplete); 215 } 216 217 // Creates a new Phi node having {count} input values. 218 Node* NewPhi(int count, Node* input, Node* control); 219 Node* NewEffectPhi(int count, Node* input, Node* control); 220 221 // Helpers for merging control, effect or value dependencies. 222 Node* MergeControl(Node* control, Node* other); 223 Node* MergeEffect(Node* value, Node* other, Node* control); 224 Node* MergeValue(Node* value, Node* other, Node* control); 225 226 // The main node creation chokepoint. Adds context, frame state, effect, 227 // and control dependencies depending on the operator. 228 Node* MakeNode(const Operator* op, int value_input_count, Node** value_inputs, 229 bool incomplete); 230 231 // Helper to indicate a node exits the function body. 232 void UpdateControlDependencyToLeaveFunction(Node* exit); 233 234 // Prepare information for lazy deoptimization. This information is attached 235 // to the given node and the output value produced by the node is combined. 236 // Conceptually this frame state is "after" a given operation. 237 void PrepareFrameState(Node* node, BailoutId ast_id, 238 OutputFrameStateCombine framestate_combine = 239 OutputFrameStateCombine::Ignore()); 240 241 // Prepare information for eager deoptimization. This information is carried 242 // by dedicated {Checkpoint} nodes that are wired into the effect chain. 243 // Conceptually this frame state is "before" a given operation. 244 void PrepareEagerCheckpoint(BailoutId ast_id); 245 246 BitVector* GetVariablesAssignedInLoop(IterationStatement* stmt); 247 248 // Check if the given statement is an OSR entry. 249 // If so, record the stack height into the compilation and return {true}. 250 bool CheckOsrEntry(IterationStatement* stmt); 251 252 // Computes local variable liveness and replaces dead variables in 253 // frame states with the undefined values. 254 void ClearNonLiveSlotsInFrameStates(); 255 256 Node** EnsureInputBufferSize(int size); 257 258 // Named and keyed loads require a VectorSlotPair for successful lowering. 259 VectorSlotPair CreateVectorSlotPair(FeedbackVectorSlot slot) const; 260 261 // Determine which contexts need to be checked for extension objects that 262 // might shadow the optimistic declaration of dynamic lookup variables. 263 uint32_t ComputeBitsetForDynamicGlobal(Variable* variable); 264 uint32_t ComputeBitsetForDynamicContext(Variable* variable); 265 266 // =========================================================================== 267 // The following build methods all generate graph fragments and return one 268 // resulting node. The operand stack height remains the same, variables and 269 // other dependencies tracked by the environment might be mutated though. 270 271 // Builders to create local function, script and block contexts. 272 Node* BuildLocalActivationContext(Node* context); 273 Node* BuildLocalFunctionContext(Scope* scope); 274 Node* BuildLocalScriptContext(Scope* scope); 275 Node* BuildLocalBlockContext(Scope* scope); 276 277 // Builder to create an arguments object if it is used. 278 Node* BuildArgumentsObject(Variable* arguments); 279 280 // Builder to create an array of rest parameters if used 281 Node* BuildRestArgumentsArray(Variable* rest, int index); 282 283 // Builder that assigns to the {.this_function} internal variable if needed. 284 Node* BuildThisFunctionVariable(Variable* this_function_var); 285 286 // Builder that assigns to the {new.target} internal variable if needed. 287 Node* BuildNewTargetVariable(Variable* new_target_var); 288 289 // Builders for variable load and assignment. 290 Node* BuildVariableAssignment(Variable* variable, Node* value, 291 Token::Value op, const VectorSlotPair& slot, 292 BailoutId bailout_id, 293 OutputFrameStateCombine framestate_combine = 294 OutputFrameStateCombine::Ignore()); 295 Node* BuildVariableDelete(Variable* variable, BailoutId bailout_id, 296 OutputFrameStateCombine framestate_combine); 297 Node* BuildVariableLoad(Variable* variable, BailoutId bailout_id, 298 const VectorSlotPair& feedback, 299 OutputFrameStateCombine framestate_combine, 300 TypeofMode typeof_mode = NOT_INSIDE_TYPEOF); 301 302 // Builders for property loads and stores. 303 Node* BuildKeyedLoad(Node* receiver, Node* key, 304 const VectorSlotPair& feedback); 305 Node* BuildNamedLoad(Node* receiver, Handle<Name> name, 306 const VectorSlotPair& feedback); 307 Node* BuildKeyedStore(Node* receiver, Node* key, Node* value, 308 const VectorSlotPair& feedback); 309 Node* BuildNamedStore(Node* receiver, Handle<Name> name, Node* value, 310 const VectorSlotPair& feedback); 311 312 // Builders for super property loads and stores. 313 Node* BuildKeyedSuperStore(Node* receiver, Node* home_object, Node* key, 314 Node* value); 315 Node* BuildNamedSuperStore(Node* receiver, Node* home_object, 316 Handle<Name> name, Node* value); 317 Node* BuildNamedSuperLoad(Node* receiver, Node* home_object, 318 Handle<Name> name, const VectorSlotPair& feedback); 319 Node* BuildKeyedSuperLoad(Node* receiver, Node* home_object, Node* key, 320 const VectorSlotPair& feedback); 321 322 // Builders for global variable loads and stores. 323 Node* BuildGlobalLoad(Handle<Name> name, const VectorSlotPair& feedback, 324 TypeofMode typeof_mode); 325 Node* BuildGlobalStore(Handle<Name> name, Node* value, 326 const VectorSlotPair& feedback); 327 328 // Builders for dynamic variable loads and stores. 329 Node* BuildDynamicLoad(Handle<Name> name, TypeofMode typeof_mode); 330 Node* BuildDynamicStore(Handle<Name> name, Node* value); 331 332 // Builders for accessing the function context. 333 Node* BuildLoadGlobalObject(); 334 Node* BuildLoadNativeContextField(int index); 335 336 // Builders for automatic type conversion. 337 Node* BuildToBoolean(Node* input, TypeFeedbackId feedback_id); 338 Node* BuildToName(Node* input, BailoutId bailout_id); 339 Node* BuildToObject(Node* input, BailoutId bailout_id); 340 341 // Builder for adding the [[HomeObject]] to a value if the value came from a 342 // function literal and needs a home object. Do nothing otherwise. 343 Node* BuildSetHomeObject(Node* value, Node* home_object, 344 ObjectLiteralProperty* property, 345 int slot_number = 0); 346 347 // Builders for error reporting at runtime. 348 Node* BuildThrowError(Node* exception, BailoutId bailout_id); 349 Node* BuildThrowReferenceError(Variable* var, BailoutId bailout_id); 350 Node* BuildThrowConstAssignError(BailoutId bailout_id); 351 Node* BuildThrowStaticPrototypeError(BailoutId bailout_id); 352 Node* BuildThrowUnsupportedSuperError(BailoutId bailout_id); 353 354 // Builders for dynamic hole-checks at runtime. 355 Node* BuildHoleCheckThenThrow(Node* value, Variable* var, Node* not_hole, 356 BailoutId bailout_id); 357 Node* BuildHoleCheckElseThrow(Node* value, Variable* var, Node* for_hole, 358 BailoutId bailout_id); 359 360 // Builders for conditional errors. 361 Node* BuildThrowIfStaticPrototype(Node* name, BailoutId bailout_id); 362 363 // Builders for non-local control flow. 364 Node* BuildReturn(Node* return_value); 365 Node* BuildThrow(Node* exception_value); 366 367 // Builders for binary operations. 368 Node* BuildBinaryOp(Node* left, Node* right, Token::Value op, 369 TypeFeedbackId feedback_id); 370 371 // Process arguments to a call by popping {arity} elements off the operand 372 // stack and build a call node using the given call operator. 373 Node* ProcessArguments(const Operator* op, int arity); 374 375 // =========================================================================== 376 // The following build methods have the same contract as the above ones, but 377 // they can also return {nullptr} to indicate that no fragment was built. Note 378 // that these are optimizations, disabling any of them should still produce 379 // correct graphs. 380 381 // Optimization for variable load from global object. 382 Node* TryLoadGlobalConstant(Handle<Name> name); 383 384 // Optimization for variable load of dynamic lookup slot that is most likely 385 // to resolve to a global slot or context slot (inferred from scope chain). 386 Node* TryLoadDynamicVariable(Variable* variable, Handle<String> name, 387 BailoutId bailout_id, 388 const VectorSlotPair& feedback, 389 OutputFrameStateCombine combine, 390 TypeofMode typeof_mode); 391 392 // Optimizations for automatic type conversion. 393 Node* TryFastToBoolean(Node* input); 394 Node* TryFastToName(Node* input); 395 396 // =========================================================================== 397 // The following visitation methods all recursively visit a subtree of the 398 // underlying AST and extent the graph. The operand stack is mutated in a way 399 // consistent with other compilers: 400 // - Expressions pop operands and push result, depending on {AstContext}. 401 // - Statements keep the operand stack balanced. 402 403 // Visit statements. 404 void VisitIfNotNull(Statement* stmt); 405 void VisitInScope(Statement* stmt, Scope* scope, Node* context); 406 407 // Visit expressions. 408 void Visit(Expression* expr); 409 void VisitForTest(Expression* expr); 410 void VisitForEffect(Expression* expr); 411 void VisitForValue(Expression* expr); 412 void VisitForValueOrNull(Expression* expr); 413 void VisitForValueOrTheHole(Expression* expr); 414 void VisitForValues(ZoneList<Expression*>* exprs); 415 416 // Common for all IterationStatement bodies. 417 void VisitIterationBody(IterationStatement* stmt, LoopBuilder* loop); 418 419 // Dispatched from VisitCall. 420 void VisitCallSuper(Call* expr); 421 422 // Dispatched from VisitCallRuntime. 423 void VisitCallJSRuntime(CallRuntime* expr); 424 425 // Dispatched from VisitUnaryOperation. 426 void VisitDelete(UnaryOperation* expr); 427 void VisitVoid(UnaryOperation* expr); 428 void VisitTypeof(UnaryOperation* expr); 429 void VisitNot(UnaryOperation* expr); 430 431 // Dispatched from VisitTypeof, VisitLiteralCompareTypeof. 432 void VisitTypeofExpression(Expression* expr); 433 434 // Dispatched from VisitBinaryOperation. 435 void VisitComma(BinaryOperation* expr); 436 void VisitLogicalExpression(BinaryOperation* expr); 437 void VisitArithmeticExpression(BinaryOperation* expr); 438 439 // Dispatched from VisitCompareOperation. 440 void VisitLiteralCompareNil(CompareOperation* expr, Expression* sub_expr, 441 Node* nil_value); 442 void VisitLiteralCompareTypeof(CompareOperation* expr, Expression* sub_expr, 443 Handle<String> check); 444 445 // Dispatched from VisitForInStatement. 446 void VisitForInAssignment(Expression* expr, Node* value, 447 const VectorSlotPair& feedback, 448 BailoutId bailout_id_before, 449 BailoutId bailout_id_after); 450 451 // Dispatched from VisitObjectLiteral. 452 void VisitObjectLiteralAccessor(Node* home_object, 453 ObjectLiteralProperty* property); 454 455 // Dispatched from VisitClassLiteral. 456 void VisitClassLiteralContents(ClassLiteral* expr); 457 458 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); 459 DISALLOW_COPY_AND_ASSIGN(AstGraphBuilder); 460 }; 461 462 463 // The abstract execution environment for generated code consists of 464 // parameter variables, local variables and the operand stack. The 465 // environment will perform proper SSA-renaming of all tracked nodes 466 // at split and merge points in the control flow. Internally all the 467 // values are stored in one list using the following layout: 468 // 469 // [parameters (+receiver)] [locals] [operand stack] 470 // 471 class AstGraphBuilder::Environment : public ZoneObject { 472 public: 473 Environment(AstGraphBuilder* builder, Scope* scope, Node* control_dependency); 474 parameters_count()475 int parameters_count() const { return parameters_count_; } locals_count()476 int locals_count() const { return locals_count_; } context_chain_length()477 int context_chain_length() { return static_cast<int>(contexts_.size()); } stack_height()478 int stack_height() { 479 return static_cast<int>(values()->size()) - parameters_count_ - 480 locals_count_; 481 } 482 483 // Operations on parameter or local variables. 484 void Bind(Variable* variable, Node* node); 485 Node* Lookup(Variable* variable); 486 void MarkAllLocalsLive(); 487 488 // Raw operations on parameter variables. 489 void RawParameterBind(int index, Node* node); 490 Node* RawParameterLookup(int index); 491 492 // Operations on the context chain. Context()493 Node* Context() const { return contexts_.back(); } PushContext(Node * context)494 void PushContext(Node* context) { contexts()->push_back(context); } PopContext()495 void PopContext() { contexts()->pop_back(); } TrimContextChain(int trim_to_length)496 void TrimContextChain(int trim_to_length) { 497 contexts()->resize(trim_to_length); 498 } 499 500 // Operations on the operand stack. Push(Node * node)501 void Push(Node* node) { 502 values()->push_back(node); 503 } Top()504 Node* Top() { 505 DCHECK(stack_height() > 0); 506 return values()->back(); 507 } Pop()508 Node* Pop() { 509 DCHECK(stack_height() > 0); 510 Node* back = values()->back(); 511 values()->pop_back(); 512 return back; 513 } 514 515 // Direct mutations of the operand stack. Poke(int depth,Node * node)516 void Poke(int depth, Node* node) { 517 DCHECK(depth >= 0 && depth < stack_height()); 518 int index = static_cast<int>(values()->size()) - depth - 1; 519 values()->at(index) = node; 520 } Peek(int depth)521 Node* Peek(int depth) { 522 DCHECK(depth >= 0 && depth < stack_height()); 523 int index = static_cast<int>(values()->size()) - depth - 1; 524 return values()->at(index); 525 } Drop(int depth)526 void Drop(int depth) { 527 DCHECK(depth >= 0 && depth <= stack_height()); 528 values()->erase(values()->end() - depth, values()->end()); 529 } TrimStack(int trim_to_height)530 void TrimStack(int trim_to_height) { 531 int depth = stack_height() - trim_to_height; 532 DCHECK(depth >= 0 && depth <= stack_height()); 533 values()->erase(values()->end() - depth, values()->end()); 534 } 535 536 // Preserve a checkpoint of the environment for the IR graph. Any 537 // further mutation of the environment will not affect checkpoints. 538 Node* Checkpoint(BailoutId ast_id, OutputFrameStateCombine combine = 539 OutputFrameStateCombine::Ignore(), 540 bool node_has_exception = false); 541 542 // Control dependency tracked by this environment. GetControlDependency()543 Node* GetControlDependency() { return control_dependency_; } UpdateControlDependency(Node * dependency)544 void UpdateControlDependency(Node* dependency) { 545 control_dependency_ = dependency; 546 } 547 548 // Effect dependency tracked by this environment. GetEffectDependency()549 Node* GetEffectDependency() { return effect_dependency_; } UpdateEffectDependency(Node * dependency)550 void UpdateEffectDependency(Node* dependency) { 551 effect_dependency_ = dependency; 552 } 553 554 // Mark this environment as being unreachable. MarkAsUnreachable()555 void MarkAsUnreachable() { 556 UpdateControlDependency(builder()->jsgraph()->Dead()); 557 liveness_block_ = nullptr; 558 } IsMarkedAsUnreachable()559 bool IsMarkedAsUnreachable() { 560 return GetControlDependency()->opcode() == IrOpcode::kDead; 561 } 562 563 // Merge another environment into this one. 564 void Merge(Environment* other); 565 566 // Copies this environment at a control-flow split point. 567 Environment* CopyForConditional(); 568 569 // Copies this environment to a potentially unreachable control-flow point. 570 Environment* CopyAsUnreachable(); 571 572 // Copies this environment at a loop header control-flow point. 573 Environment* CopyForLoop(BitVector* assigned, bool is_osr = false); 574 575 private: 576 AstGraphBuilder* builder_; 577 int parameters_count_; 578 int locals_count_; 579 LivenessAnalyzerBlock* liveness_block_; 580 NodeVector values_; 581 NodeVector contexts_; 582 Node* control_dependency_; 583 Node* effect_dependency_; 584 Node* parameters_node_; 585 Node* locals_node_; 586 Node* stack_node_; 587 588 explicit Environment(Environment* copy, 589 LivenessAnalyzerBlock* liveness_block); 590 Environment* CopyAndShareLiveness(); 591 void UpdateStateValues(Node** state_values, int offset, int count); 592 void UpdateStateValuesWithCache(Node** state_values, int offset, int count); zone()593 Zone* zone() const { return builder_->local_zone(); } graph()594 Graph* graph() const { return builder_->graph(); } builder()595 AstGraphBuilder* builder() const { return builder_; } common()596 CommonOperatorBuilder* common() { return builder_->common(); } values()597 NodeVector* values() { return &values_; } contexts()598 NodeVector* contexts() { return &contexts_; } liveness_block()599 LivenessAnalyzerBlock* liveness_block() { return liveness_block_; } 600 bool IsLivenessAnalysisEnabled(); 601 bool IsLivenessBlockConsistent(); 602 603 // Prepare environment to be used as loop header. 604 void PrepareForLoop(BitVector* assigned, bool is_osr = false); 605 }; 606 607 } // namespace compiler 608 } // namespace internal 609 } // namespace v8 610 611 #endif // V8_COMPILER_AST_GRAPH_BUILDER_H_ 612