1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_HYDROGEN_H_ 29 #define V8_HYDROGEN_H_ 30 31 #include "v8.h" 32 33 #include "allocation.h" 34 #include "ast.h" 35 #include "compiler.h" 36 #include "hydrogen-instructions.h" 37 #include "zone.h" 38 #include "scopes.h" 39 40 namespace v8 { 41 namespace internal { 42 43 // Forward declarations. 44 class BitVector; 45 class FunctionState; 46 class HEnvironment; 47 class HGraph; 48 class HLoopInformation; 49 class HOsrBuilder; 50 class HTracer; 51 class LAllocator; 52 class LChunk; 53 class LiveRange; 54 55 56 class HBasicBlock: public ZoneObject { 57 public: 58 explicit HBasicBlock(HGraph* graph); 59 virtual ~HBasicBlock() { } 60 61 // Simple accessors. 62 int block_id() const { return block_id_; } 63 void set_block_id(int id) { block_id_ = id; } 64 HGraph* graph() const { return graph_; } 65 Isolate* isolate() const; 66 const ZoneList<HPhi*>* phis() const { return &phis_; } 67 HInstruction* first() const { return first_; } 68 HInstruction* last() const { return last_; } 69 void set_last(HInstruction* instr) { last_ = instr; } 70 HControlInstruction* end() const { return end_; } 71 HLoopInformation* loop_information() const { return loop_information_; } 72 HLoopInformation* current_loop() const { 73 return IsLoopHeader() ? loop_information() 74 : (parent_loop_header() != NULL 75 ? parent_loop_header()->loop_information() : NULL); 76 } 77 const ZoneList<HBasicBlock*>* predecessors() const { return &predecessors_; } 78 bool HasPredecessor() const { return predecessors_.length() > 0; } 79 const ZoneList<HBasicBlock*>* dominated_blocks() const { 80 return &dominated_blocks_; 81 } 82 const ZoneList<int>* deleted_phis() const { 83 return &deleted_phis_; 84 } 85 void RecordDeletedPhi(int merge_index) { 86 deleted_phis_.Add(merge_index, zone()); 87 } 88 HBasicBlock* dominator() const { return dominator_; } 89 HEnvironment* last_environment() const { return last_environment_; } 90 int argument_count() const { return argument_count_; } 91 void set_argument_count(int count) { argument_count_ = count; } 92 int first_instruction_index() const { return first_instruction_index_; } 93 void set_first_instruction_index(int index) { 94 first_instruction_index_ = index; 95 } 96 int last_instruction_index() const { return last_instruction_index_; } 97 void set_last_instruction_index(int index) { 98 last_instruction_index_ = index; 99 } 100 bool is_osr_entry() { return is_osr_entry_; } 101 void set_osr_entry() { is_osr_entry_ = true; } 102 103 void AttachLoopInformation(); 104 void DetachLoopInformation(); 105 bool IsLoopHeader() const { return loop_information() != NULL; } 106 bool IsStartBlock() const { return block_id() == 0; } 107 void PostProcessLoopHeader(IterationStatement* stmt); 108 109 bool IsFinished() const { return end_ != NULL; } 110 void AddPhi(HPhi* phi); 111 void RemovePhi(HPhi* phi); 112 void AddInstruction(HInstruction* instr); 113 bool Dominates(HBasicBlock* other) const; 114 int LoopNestingDepth() const; 115 116 void SetInitialEnvironment(HEnvironment* env); 117 void ClearEnvironment() { 118 ASSERT(IsFinished()); 119 ASSERT(end()->SuccessorCount() == 0); 120 last_environment_ = NULL; 121 } 122 bool HasEnvironment() const { return last_environment_ != NULL; } 123 void UpdateEnvironment(HEnvironment* env); 124 HBasicBlock* parent_loop_header() const { return parent_loop_header_; } 125 126 void set_parent_loop_header(HBasicBlock* block) { 127 ASSERT(parent_loop_header_ == NULL); 128 parent_loop_header_ = block; 129 } 130 131 bool HasParentLoopHeader() const { return parent_loop_header_ != NULL; } 132 133 void SetJoinId(BailoutId ast_id); 134 135 void Finish(HControlInstruction* last); 136 void FinishExit(HControlInstruction* instruction); 137 void Goto(HBasicBlock* block, 138 FunctionState* state = NULL, 139 bool add_simulate = true); 140 void GotoNoSimulate(HBasicBlock* block) { 141 Goto(block, NULL, false); 142 } 143 144 int PredecessorIndexOf(HBasicBlock* predecessor) const; 145 HPhi* AddNewPhi(int merged_index); 146 HSimulate* AddNewSimulate(BailoutId ast_id, 147 RemovableSimulate removable = FIXED_SIMULATE) { 148 HSimulate* instr = CreateSimulate(ast_id, removable); 149 AddInstruction(instr); 150 return instr; 151 } 152 void AssignCommonDominator(HBasicBlock* other); 153 void AssignLoopSuccessorDominators(); 154 155 // Add the inlined function exit sequence, adding an HLeaveInlined 156 // instruction and updating the bailout environment. 157 void AddLeaveInlined(HValue* return_value, FunctionState* state); 158 159 // If a target block is tagged as an inline function return, all 160 // predecessors should contain the inlined exit sequence: 161 // 162 // LeaveInlined 163 // Simulate (caller's environment) 164 // Goto (target block) 165 bool IsInlineReturnTarget() const { return is_inline_return_target_; } 166 void MarkAsInlineReturnTarget(HBasicBlock* inlined_entry_block) { 167 is_inline_return_target_ = true; 168 inlined_entry_block_ = inlined_entry_block; 169 } 170 HBasicBlock* inlined_entry_block() { return inlined_entry_block_; } 171 172 bool IsDeoptimizing() const { return is_deoptimizing_; } 173 void MarkAsDeoptimizing() { is_deoptimizing_ = true; } 174 175 bool IsLoopSuccessorDominator() const { 176 return dominates_loop_successors_; 177 } 178 void MarkAsLoopSuccessorDominator() { 179 dominates_loop_successors_ = true; 180 } 181 182 inline Zone* zone() const; 183 184 #ifdef DEBUG 185 void Verify(); 186 #endif 187 188 private: 189 friend class HGraphBuilder; 190 191 void RegisterPredecessor(HBasicBlock* pred); 192 void AddDominatedBlock(HBasicBlock* block); 193 194 HSimulate* CreateSimulate(BailoutId ast_id, RemovableSimulate removable); 195 196 int block_id_; 197 HGraph* graph_; 198 ZoneList<HPhi*> phis_; 199 HInstruction* first_; 200 HInstruction* last_; 201 HControlInstruction* end_; 202 HLoopInformation* loop_information_; 203 ZoneList<HBasicBlock*> predecessors_; 204 HBasicBlock* dominator_; 205 ZoneList<HBasicBlock*> dominated_blocks_; 206 HEnvironment* last_environment_; 207 // Outgoing parameter count at block exit, set during lithium translation. 208 int argument_count_; 209 // Instruction indices into the lithium code stream. 210 int first_instruction_index_; 211 int last_instruction_index_; 212 ZoneList<int> deleted_phis_; 213 HBasicBlock* parent_loop_header_; 214 // For blocks marked as inline return target: the block with HEnterInlined. 215 HBasicBlock* inlined_entry_block_; 216 bool is_inline_return_target_ : 1; 217 bool is_deoptimizing_ : 1; 218 bool dominates_loop_successors_ : 1; 219 bool is_osr_entry_ : 1; 220 }; 221 222 223 class HPredecessorIterator BASE_EMBEDDED { 224 public: 225 explicit HPredecessorIterator(HBasicBlock* block) 226 : predecessor_list_(block->predecessors()), current_(0) { } 227 228 bool Done() { return current_ >= predecessor_list_->length(); } 229 HBasicBlock* Current() { return predecessor_list_->at(current_); } 230 void Advance() { current_++; } 231 232 private: 233 const ZoneList<HBasicBlock*>* predecessor_list_; 234 int current_; 235 }; 236 237 238 class HInstructionIterator BASE_EMBEDDED { 239 public: 240 explicit HInstructionIterator(HBasicBlock* block) 241 : instr_(block->first()) { 242 next_ = Done() ? NULL : instr_->next(); 243 } 244 245 inline bool Done() const { return instr_ == NULL; } 246 inline HInstruction* Current() { return instr_; } 247 inline void Advance() { 248 instr_ = next_; 249 next_ = Done() ? NULL : instr_->next(); 250 } 251 252 private: 253 HInstruction* instr_; 254 HInstruction* next_; 255 }; 256 257 258 class HLoopInformation: public ZoneObject { 259 public: 260 HLoopInformation(HBasicBlock* loop_header, Zone* zone) 261 : back_edges_(4, zone), 262 loop_header_(loop_header), 263 blocks_(8, zone), 264 stack_check_(NULL) { 265 blocks_.Add(loop_header, zone); 266 } 267 virtual ~HLoopInformation() {} 268 269 const ZoneList<HBasicBlock*>* back_edges() const { return &back_edges_; } 270 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; } 271 HBasicBlock* loop_header() const { return loop_header_; } 272 HBasicBlock* GetLastBackEdge() const; 273 void RegisterBackEdge(HBasicBlock* block); 274 275 HStackCheck* stack_check() const { return stack_check_; } 276 void set_stack_check(HStackCheck* stack_check) { 277 stack_check_ = stack_check; 278 } 279 280 bool IsNestedInThisLoop(HLoopInformation* other) { 281 while (other != NULL) { 282 if (other == this) { 283 return true; 284 } 285 other = other->parent_loop(); 286 } 287 return false; 288 } 289 HLoopInformation* parent_loop() { 290 HBasicBlock* parent_header = loop_header()->parent_loop_header(); 291 return parent_header != NULL ? parent_header->loop_information() : NULL; 292 } 293 294 private: 295 void AddBlock(HBasicBlock* block); 296 297 ZoneList<HBasicBlock*> back_edges_; 298 HBasicBlock* loop_header_; 299 ZoneList<HBasicBlock*> blocks_; 300 HStackCheck* stack_check_; 301 }; 302 303 304 class BoundsCheckTable; 305 class InductionVariableBlocksTable; 306 class HGraph: public ZoneObject { 307 public: 308 explicit HGraph(CompilationInfo* info); 309 310 Isolate* isolate() const { return isolate_; } 311 Zone* zone() const { return zone_; } 312 CompilationInfo* info() const { return info_; } 313 314 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; } 315 const ZoneList<HPhi*>* phi_list() const { return phi_list_; } 316 HBasicBlock* entry_block() const { return entry_block_; } 317 HEnvironment* start_environment() const { return start_environment_; } 318 319 void FinalizeUniqueValueIds(); 320 bool ProcessArgumentsObject(); 321 void OrderBlocks(); 322 void AssignDominators(); 323 void SetupInformativeDefinitions(); 324 void RestoreActualValues(); 325 326 // Returns false if there are phi-uses of the arguments-object 327 // which are not supported by the optimizing compiler. 328 bool CheckArgumentsPhiUses(); 329 330 // Returns false if there are phi-uses of an uninitialized const 331 // which are not supported by the optimizing compiler. 332 bool CheckConstPhiUses(); 333 334 void CollectPhis(); 335 336 void set_undefined_constant(HConstant* constant) { 337 undefined_constant_.set(constant); 338 } 339 HConstant* GetConstantUndefined() const { return undefined_constant_.get(); } 340 HConstant* GetConstant0(); 341 HConstant* GetConstant1(); 342 HConstant* GetConstantMinus1(); 343 HConstant* GetConstantTrue(); 344 HConstant* GetConstantFalse(); 345 HConstant* GetConstantHole(); 346 HConstant* GetConstantNull(); 347 HConstant* GetInvalidContext(); 348 349 bool IsStandardConstant(HConstant* constant); 350 351 HBasicBlock* CreateBasicBlock(); 352 HArgumentsObject* GetArgumentsObject() const { 353 return arguments_object_.get(); 354 } 355 356 void SetArgumentsObject(HArgumentsObject* object) { 357 arguments_object_.set(object); 358 } 359 360 int GetMaximumValueID() const { return values_.length(); } 361 int GetNextBlockID() { return next_block_id_++; } 362 int GetNextValueID(HValue* value) { 363 values_.Add(value, zone()); 364 return values_.length() - 1; 365 } 366 HValue* LookupValue(int id) const { 367 if (id >= 0 && id < values_.length()) return values_[id]; 368 return NULL; 369 } 370 371 bool Optimize(BailoutReason* bailout_reason); 372 373 #ifdef DEBUG 374 void Verify(bool do_full_verify) const; 375 #endif 376 377 bool has_osr() { 378 return osr_ != NULL; 379 } 380 381 void set_osr(HOsrBuilder* osr) { 382 osr_ = osr; 383 } 384 385 HOsrBuilder* osr() { 386 return osr_; 387 } 388 389 int update_type_change_checksum(int delta) { 390 type_change_checksum_ += delta; 391 return type_change_checksum_; 392 } 393 394 void update_maximum_environment_size(int environment_size) { 395 if (environment_size > maximum_environment_size_) { 396 maximum_environment_size_ = environment_size; 397 } 398 } 399 int maximum_environment_size() { return maximum_environment_size_; } 400 401 bool use_optimistic_licm() { 402 return use_optimistic_licm_; 403 } 404 405 void set_use_optimistic_licm(bool value) { 406 use_optimistic_licm_ = value; 407 } 408 409 bool has_soft_deoptimize() { 410 return has_soft_deoptimize_; 411 } 412 413 void set_has_soft_deoptimize(bool value) { 414 has_soft_deoptimize_ = value; 415 } 416 417 void MarkRecursive() { 418 is_recursive_ = true; 419 } 420 421 bool is_recursive() const { 422 return is_recursive_; 423 } 424 425 void MarkDependsOnEmptyArrayProtoElements() { 426 // Add map dependency if not already added. 427 if (depends_on_empty_array_proto_elements_) return; 428 isolate()->initial_object_prototype()->map()->AddDependentCompilationInfo( 429 DependentCode::kElementsCantBeAddedGroup, info()); 430 isolate()->initial_array_prototype()->map()->AddDependentCompilationInfo( 431 DependentCode::kElementsCantBeAddedGroup, info()); 432 depends_on_empty_array_proto_elements_ = true; 433 } 434 435 bool depends_on_empty_array_proto_elements() { 436 return depends_on_empty_array_proto_elements_; 437 } 438 439 bool has_uint32_instructions() { 440 ASSERT(uint32_instructions_ == NULL || !uint32_instructions_->is_empty()); 441 return uint32_instructions_ != NULL; 442 } 443 444 ZoneList<HInstruction*>* uint32_instructions() { 445 ASSERT(uint32_instructions_ == NULL || !uint32_instructions_->is_empty()); 446 return uint32_instructions_; 447 } 448 449 void RecordUint32Instruction(HInstruction* instr) { 450 ASSERT(uint32_instructions_ == NULL || !uint32_instructions_->is_empty()); 451 if (uint32_instructions_ == NULL) { 452 uint32_instructions_ = new(zone()) ZoneList<HInstruction*>(4, zone()); 453 } 454 uint32_instructions_->Add(instr, zone()); 455 } 456 457 void IncrementInNoSideEffectsScope() { no_side_effects_scope_count_++; } 458 void DecrementInNoSideEffectsScope() { no_side_effects_scope_count_--; } 459 bool IsInsideNoSideEffectsScope() { return no_side_effects_scope_count_ > 0; } 460 461 private: 462 HConstant* GetConstant(SetOncePointer<HConstant>* pointer, 463 int32_t integer_value); 464 465 template<class Phase> 466 void Run() { 467 Phase phase(this); 468 phase.Run(); 469 } 470 471 void CheckForBackEdge(HBasicBlock* block, HBasicBlock* successor); 472 void SetupInformativeDefinitionsInBlock(HBasicBlock* block); 473 void SetupInformativeDefinitionsRecursively(HBasicBlock* block); 474 void EliminateRedundantBoundsChecksUsingInductionVariables(); 475 476 Isolate* isolate_; 477 int next_block_id_; 478 HBasicBlock* entry_block_; 479 HEnvironment* start_environment_; 480 ZoneList<HBasicBlock*> blocks_; 481 ZoneList<HValue*> values_; 482 ZoneList<HPhi*>* phi_list_; 483 ZoneList<HInstruction*>* uint32_instructions_; 484 SetOncePointer<HConstant> undefined_constant_; 485 SetOncePointer<HConstant> constant_0_; 486 SetOncePointer<HConstant> constant_1_; 487 SetOncePointer<HConstant> constant_minus1_; 488 SetOncePointer<HConstant> constant_true_; 489 SetOncePointer<HConstant> constant_false_; 490 SetOncePointer<HConstant> constant_the_hole_; 491 SetOncePointer<HConstant> constant_null_; 492 SetOncePointer<HConstant> constant_invalid_context_; 493 SetOncePointer<HArgumentsObject> arguments_object_; 494 495 HOsrBuilder* osr_; 496 497 CompilationInfo* info_; 498 Zone* zone_; 499 500 bool is_recursive_; 501 bool use_optimistic_licm_; 502 bool has_soft_deoptimize_; 503 bool depends_on_empty_array_proto_elements_; 504 int type_change_checksum_; 505 int maximum_environment_size_; 506 int no_side_effects_scope_count_; 507 508 DISALLOW_COPY_AND_ASSIGN(HGraph); 509 }; 510 511 512 Zone* HBasicBlock::zone() const { return graph_->zone(); } 513 514 515 // Type of stack frame an environment might refer to. 516 enum FrameType { 517 JS_FUNCTION, 518 JS_CONSTRUCT, 519 JS_GETTER, 520 JS_SETTER, 521 ARGUMENTS_ADAPTOR, 522 STUB 523 }; 524 525 526 class HEnvironment: public ZoneObject { 527 public: 528 HEnvironment(HEnvironment* outer, 529 Scope* scope, 530 Handle<JSFunction> closure, 531 Zone* zone); 532 533 HEnvironment(Zone* zone, int parameter_count); 534 535 HEnvironment* arguments_environment() { 536 return outer()->frame_type() == ARGUMENTS_ADAPTOR ? outer() : this; 537 } 538 539 // Simple accessors. 540 Handle<JSFunction> closure() const { return closure_; } 541 const ZoneList<HValue*>* values() const { return &values_; } 542 const GrowableBitVector* assigned_variables() const { 543 return &assigned_variables_; 544 } 545 FrameType frame_type() const { return frame_type_; } 546 int parameter_count() const { return parameter_count_; } 547 int specials_count() const { return specials_count_; } 548 int local_count() const { return local_count_; } 549 HEnvironment* outer() const { return outer_; } 550 int pop_count() const { return pop_count_; } 551 int push_count() const { return push_count_; } 552 553 BailoutId ast_id() const { return ast_id_; } 554 void set_ast_id(BailoutId id) { ast_id_ = id; } 555 556 HEnterInlined* entry() const { return entry_; } 557 void set_entry(HEnterInlined* entry) { entry_ = entry; } 558 559 int length() const { return values_.length(); } 560 bool is_special_index(int i) const { 561 return i >= parameter_count() && i < parameter_count() + specials_count(); 562 } 563 564 int first_expression_index() const { 565 return parameter_count() + specials_count() + local_count(); 566 } 567 568 int first_local_index() const { 569 return parameter_count() + specials_count(); 570 } 571 572 void Bind(Variable* variable, HValue* value) { 573 Bind(IndexFor(variable), value); 574 } 575 576 void Bind(int index, HValue* value); 577 578 void BindContext(HValue* value) { 579 Bind(parameter_count(), value); 580 } 581 582 HValue* Lookup(Variable* variable) const { 583 return Lookup(IndexFor(variable)); 584 } 585 586 HValue* Lookup(int index) const { 587 HValue* result = values_[index]; 588 ASSERT(result != NULL); 589 return result; 590 } 591 592 HValue* context() const { 593 // Return first special. 594 return Lookup(parameter_count()); 595 } 596 597 void Push(HValue* value) { 598 ASSERT(value != NULL); 599 ++push_count_; 600 values_.Add(value, zone()); 601 } 602 603 HValue* Pop() { 604 ASSERT(!ExpressionStackIsEmpty()); 605 if (push_count_ > 0) { 606 --push_count_; 607 } else { 608 ++pop_count_; 609 } 610 return values_.RemoveLast(); 611 } 612 613 void Drop(int count); 614 615 HValue* Top() const { return ExpressionStackAt(0); } 616 617 bool ExpressionStackIsEmpty() const; 618 619 HValue* ExpressionStackAt(int index_from_top) const { 620 int index = length() - index_from_top - 1; 621 ASSERT(HasExpressionAt(index)); 622 return values_[index]; 623 } 624 625 void SetExpressionStackAt(int index_from_top, HValue* value); 626 627 HEnvironment* Copy() const; 628 HEnvironment* CopyWithoutHistory() const; 629 HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const; 630 631 // Create an "inlined version" of this environment, where the original 632 // environment is the outer environment but the top expression stack 633 // elements are moved to an inner environment as parameters. 634 HEnvironment* CopyForInlining(Handle<JSFunction> target, 635 int arguments, 636 FunctionLiteral* function, 637 HConstant* undefined, 638 InliningKind inlining_kind, 639 bool undefined_receiver) const; 640 641 static bool UseUndefinedReceiver(Handle<JSFunction> closure, 642 FunctionLiteral* function, 643 CallKind call_kind, 644 InliningKind inlining_kind) { 645 return (closure->shared()->native() || !function->is_classic_mode()) && 646 call_kind == CALL_AS_FUNCTION && inlining_kind != CONSTRUCT_CALL_RETURN; 647 } 648 649 HEnvironment* DiscardInlined(bool drop_extra) { 650 HEnvironment* outer = outer_; 651 while (outer->frame_type() != JS_FUNCTION) outer = outer->outer_; 652 if (drop_extra) outer->Drop(1); 653 return outer; 654 } 655 656 void AddIncomingEdge(HBasicBlock* block, HEnvironment* other); 657 658 void ClearHistory() { 659 pop_count_ = 0; 660 push_count_ = 0; 661 assigned_variables_.Clear(); 662 } 663 664 void SetValueAt(int index, HValue* value) { 665 ASSERT(index < length()); 666 values_[index] = value; 667 } 668 669 // Map a variable to an environment index. Parameter indices are shifted 670 // by 1 (receiver is parameter index -1 but environment index 0). 671 // Stack-allocated local indices are shifted by the number of parameters. 672 int IndexFor(Variable* variable) const { 673 ASSERT(variable->IsStackAllocated()); 674 int shift = variable->IsParameter() 675 ? 1 676 : parameter_count_ + specials_count_; 677 return variable->index() + shift; 678 } 679 680 bool is_local_index(int i) const { 681 return i >= first_local_index() && 682 i < first_expression_index(); 683 } 684 685 void PrintTo(StringStream* stream); 686 void PrintToStd(); 687 688 Zone* zone() const { return zone_; } 689 690 private: 691 HEnvironment(const HEnvironment* other, Zone* zone); 692 693 HEnvironment(HEnvironment* outer, 694 Handle<JSFunction> closure, 695 FrameType frame_type, 696 int arguments, 697 Zone* zone); 698 699 // Create an artificial stub environment (e.g. for argument adaptor or 700 // constructor stub). 701 HEnvironment* CreateStubEnvironment(HEnvironment* outer, 702 Handle<JSFunction> target, 703 FrameType frame_type, 704 int arguments) const; 705 706 // True if index is included in the expression stack part of the environment. 707 bool HasExpressionAt(int index) const; 708 709 void Initialize(int parameter_count, int local_count, int stack_height); 710 void Initialize(const HEnvironment* other); 711 712 Handle<JSFunction> closure_; 713 // Value array [parameters] [specials] [locals] [temporaries]. 714 ZoneList<HValue*> values_; 715 GrowableBitVector assigned_variables_; 716 FrameType frame_type_; 717 int parameter_count_; 718 int specials_count_; 719 int local_count_; 720 HEnvironment* outer_; 721 HEnterInlined* entry_; 722 int pop_count_; 723 int push_count_; 724 BailoutId ast_id_; 725 Zone* zone_; 726 }; 727 728 729 class HOptimizedGraphBuilder; 730 731 enum ArgumentsAllowedFlag { 732 ARGUMENTS_NOT_ALLOWED, 733 ARGUMENTS_ALLOWED 734 }; 735 736 737 class HIfContinuation; 738 739 // This class is not BASE_EMBEDDED because our inlining implementation uses 740 // new and delete. 741 class AstContext { 742 public: 743 bool IsEffect() const { return kind_ == Expression::kEffect; } 744 bool IsValue() const { return kind_ == Expression::kValue; } 745 bool IsTest() const { return kind_ == Expression::kTest; } 746 747 // 'Fill' this context with a hydrogen value. The value is assumed to 748 // have already been inserted in the instruction stream (or not need to 749 // be, e.g., HPhi). Call this function in tail position in the Visit 750 // functions for expressions. 751 virtual void ReturnValue(HValue* value) = 0; 752 753 // Add a hydrogen instruction to the instruction stream (recording an 754 // environment simulation if necessary) and then fill this context with 755 // the instruction as value. 756 virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id) = 0; 757 758 // Finishes the current basic block and materialize a boolean for 759 // value context, nothing for effect, generate a branch for test context. 760 // Call this function in tail position in the Visit functions for 761 // expressions. 762 virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id) = 0; 763 764 // Finishes the current basic block and materialize a boolean for 765 // value context, nothing for effect, generate a branch for test context. 766 // Call this function in tail position in the Visit functions for 767 // expressions that use an IfBuilder. 768 virtual void ReturnContinuation(HIfContinuation* continuation, 769 BailoutId ast_id) = 0; 770 771 void set_for_typeof(bool for_typeof) { for_typeof_ = for_typeof; } 772 bool is_for_typeof() { return for_typeof_; } 773 774 protected: 775 AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind); 776 virtual ~AstContext(); 777 778 HOptimizedGraphBuilder* owner() const { return owner_; } 779 780 inline Zone* zone() const; 781 782 // We want to be able to assert, in a context-specific way, that the stack 783 // height makes sense when the context is filled. 784 #ifdef DEBUG 785 int original_length_; 786 #endif 787 788 private: 789 HOptimizedGraphBuilder* owner_; 790 Expression::Context kind_; 791 AstContext* outer_; 792 bool for_typeof_; 793 }; 794 795 796 class EffectContext: public AstContext { 797 public: 798 explicit EffectContext(HOptimizedGraphBuilder* owner) 799 : AstContext(owner, Expression::kEffect) { 800 } 801 virtual ~EffectContext(); 802 803 virtual void ReturnValue(HValue* value); 804 virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id); 805 virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id); 806 virtual void ReturnContinuation(HIfContinuation* continuation, 807 BailoutId ast_id); 808 }; 809 810 811 class ValueContext: public AstContext { 812 public: 813 ValueContext(HOptimizedGraphBuilder* owner, ArgumentsAllowedFlag flag) 814 : AstContext(owner, Expression::kValue), flag_(flag) { 815 } 816 virtual ~ValueContext(); 817 818 virtual void ReturnValue(HValue* value); 819 virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id); 820 virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id); 821 virtual void ReturnContinuation(HIfContinuation* continuation, 822 BailoutId ast_id); 823 824 bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; } 825 826 private: 827 ArgumentsAllowedFlag flag_; 828 }; 829 830 831 class TestContext: public AstContext { 832 public: 833 TestContext(HOptimizedGraphBuilder* owner, 834 Expression* condition, 835 HBasicBlock* if_true, 836 HBasicBlock* if_false) 837 : AstContext(owner, Expression::kTest), 838 condition_(condition), 839 if_true_(if_true), 840 if_false_(if_false) { 841 } 842 843 virtual void ReturnValue(HValue* value); 844 virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id); 845 virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id); 846 virtual void ReturnContinuation(HIfContinuation* continuation, 847 BailoutId ast_id); 848 849 static TestContext* cast(AstContext* context) { 850 ASSERT(context->IsTest()); 851 return reinterpret_cast<TestContext*>(context); 852 } 853 854 Expression* condition() const { return condition_; } 855 HBasicBlock* if_true() const { return if_true_; } 856 HBasicBlock* if_false() const { return if_false_; } 857 858 private: 859 // Build the shared core part of the translation unpacking a value into 860 // control flow. 861 void BuildBranch(HValue* value); 862 863 Expression* condition_; 864 HBasicBlock* if_true_; 865 HBasicBlock* if_false_; 866 }; 867 868 869 class FunctionState { 870 public: 871 FunctionState(HOptimizedGraphBuilder* owner, 872 CompilationInfo* info, 873 InliningKind inlining_kind); 874 ~FunctionState(); 875 876 CompilationInfo* compilation_info() { return compilation_info_; } 877 AstContext* call_context() { return call_context_; } 878 InliningKind inlining_kind() const { return inlining_kind_; } 879 HBasicBlock* function_return() { return function_return_; } 880 TestContext* test_context() { return test_context_; } 881 void ClearInlinedTestContext() { 882 delete test_context_; 883 test_context_ = NULL; 884 } 885 886 FunctionState* outer() { return outer_; } 887 888 HEnterInlined* entry() { return entry_; } 889 void set_entry(HEnterInlined* entry) { entry_ = entry; } 890 891 HArgumentsObject* arguments_object() { return arguments_object_; } 892 void set_arguments_object(HArgumentsObject* arguments_object) { 893 arguments_object_ = arguments_object; 894 } 895 896 HArgumentsElements* arguments_elements() { return arguments_elements_; } 897 void set_arguments_elements(HArgumentsElements* arguments_elements) { 898 arguments_elements_ = arguments_elements; 899 } 900 901 bool arguments_pushed() { return arguments_elements() != NULL; } 902 903 private: 904 HOptimizedGraphBuilder* owner_; 905 906 CompilationInfo* compilation_info_; 907 908 // During function inlining, expression context of the call being 909 // inlined. NULL when not inlining. 910 AstContext* call_context_; 911 912 // The kind of call which is currently being inlined. 913 InliningKind inlining_kind_; 914 915 // When inlining in an effect or value context, this is the return block. 916 // It is NULL otherwise. When inlining in a test context, there are a 917 // pair of return blocks in the context. When not inlining, there is no 918 // local return point. 919 HBasicBlock* function_return_; 920 921 // When inlining a call in a test context, a context containing a pair of 922 // return blocks. NULL in all other cases. 923 TestContext* test_context_; 924 925 // When inlining HEnterInlined instruction corresponding to the function 926 // entry. 927 HEnterInlined* entry_; 928 929 HArgumentsObject* arguments_object_; 930 HArgumentsElements* arguments_elements_; 931 932 FunctionState* outer_; 933 }; 934 935 936 class HIfContinuation { 937 public: 938 HIfContinuation() { continuation_captured_ = false; } 939 ~HIfContinuation() { ASSERT(!continuation_captured_); } 940 941 void Capture(HBasicBlock* true_branch, 942 HBasicBlock* false_branch, 943 int position) { 944 ASSERT(!continuation_captured_); 945 true_branch_ = true_branch; 946 false_branch_ = false_branch; 947 position_ = position; 948 continuation_captured_ = true; 949 } 950 951 void Continue(HBasicBlock** true_branch, 952 HBasicBlock** false_branch, 953 int* position) { 954 ASSERT(continuation_captured_); 955 *true_branch = true_branch_; 956 *false_branch = false_branch_; 957 if (position != NULL) *position = position_; 958 continuation_captured_ = false; 959 } 960 961 bool IsTrueReachable() { return true_branch_ != NULL; } 962 bool IsFalseReachable() { return false_branch_ != NULL; } 963 bool TrueAndFalseReachable() { 964 return IsTrueReachable() || IsFalseReachable(); 965 } 966 967 bool continuation_captured_; 968 HBasicBlock* true_branch_; 969 HBasicBlock* false_branch_; 970 int position_; 971 }; 972 973 974 class HGraphBuilder { 975 public: 976 explicit HGraphBuilder(CompilationInfo* info) 977 : info_(info), 978 graph_(NULL), 979 current_block_(NULL) {} 980 virtual ~HGraphBuilder() {} 981 982 HBasicBlock* current_block() const { return current_block_; } 983 void set_current_block(HBasicBlock* block) { current_block_ = block; } 984 HEnvironment* environment() const { 985 return current_block()->last_environment(); 986 } 987 Zone* zone() const { return info_->zone(); } 988 HGraph* graph() const { return graph_; } 989 Isolate* isolate() const { return graph_->isolate(); } 990 CompilationInfo* top_info() { return info_; } 991 992 HGraph* CreateGraph(); 993 994 // Bailout environment manipulation. 995 void Push(HValue* value) { environment()->Push(value); } 996 HValue* Pop() { return environment()->Pop(); } 997 998 virtual HValue* context() = 0; 999 1000 // Adding instructions. 1001 HInstruction* AddInstruction(HInstruction* instr); 1002 1003 template<class I> 1004 HInstruction* NewUncasted() { return I::New(zone(), context()); } 1005 1006 template<class I> 1007 I* New() { return I::cast(NewUncasted<I>()); } 1008 1009 template<class I> 1010 HInstruction* AddUncasted() { return AddInstruction(NewUncasted<I>());} 1011 1012 template<class I> 1013 I* Add() { return I::cast(AddUncasted<I>());} 1014 1015 template<class I, class P1> 1016 HInstruction* NewUncasted(P1 p1) { 1017 return I::New(zone(), context(), p1); 1018 } 1019 1020 template<class I, class P1> 1021 I* New(P1 p1) { return I::cast(NewUncasted<I>(p1)); } 1022 1023 template<class I, class P1> 1024 HInstruction* AddUncasted(P1 p1) { 1025 HInstruction* result = AddInstruction(NewUncasted<I>(p1)); 1026 // Specializations must have their parameters properly casted 1027 // to avoid landing here. 1028 ASSERT(!result->IsReturn() && !result->IsSimulate() && 1029 !result->IsDeoptimize()); 1030 return result; 1031 } 1032 1033 template<class I, class P1> 1034 I* Add(P1 p1) { 1035 return I::cast(AddUncasted<I>(p1)); 1036 } 1037 1038 template<class I, class P1, class P2> 1039 HInstruction* NewUncasted(P1 p1, P2 p2) { 1040 return I::New(zone(), context(), p1, p2); 1041 } 1042 1043 template<class I, class P1, class P2> 1044 I* New(P1 p1, P2 p2) { 1045 return I::cast(NewUncasted<I>(p1, p2)); 1046 } 1047 1048 template<class I, class P1, class P2> 1049 HInstruction* AddUncasted(P1 p1, P2 p2) { 1050 HInstruction* result = AddInstruction(NewUncasted<I>(p1, p2)); 1051 // Specializations must have their parameters properly casted 1052 // to avoid landing here. 1053 ASSERT(!result->IsSimulate()); 1054 return result; 1055 } 1056 1057 template<class I, class P1, class P2> 1058 I* Add(P1 p1, P2 p2) { 1059 return static_cast<I*>(AddUncasted<I>(p1, p2)); 1060 } 1061 1062 template<class I, class P1, class P2, class P3> 1063 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3) { 1064 return I::New(zone(), context(), p1, p2, p3); 1065 } 1066 1067 template<class I, class P1, class P2, class P3> 1068 I* New(P1 p1, P2 p2, P3 p3) { 1069 return I::cast(NewUncasted<I>(p1, p2, p3)); 1070 } 1071 1072 template<class I, class P1, class P2, class P3> 1073 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3) { 1074 return AddInstruction(NewUncasted<I>(p1, p2, p3)); 1075 } 1076 1077 template<class I, class P1, class P2, class P3> 1078 I* Add(P1 p1, P2 p2, P3 p3) { 1079 return I::cast(AddUncasted<I>(p1, p2, p3)); 1080 } 1081 1082 template<class I, class P1, class P2, class P3, class P4> 1083 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4) { 1084 return I::New(zone(), context(), p1, p2, p3, p4); 1085 } 1086 1087 template<class I, class P1, class P2, class P3, class P4> 1088 I* New(P1 p1, P2 p2, P3 p3, P4 p4) { 1089 return I::cast(NewUncasted<I>(p1, p2, p3, p4)); 1090 } 1091 1092 template<class I, class P1, class P2, class P3, class P4> 1093 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4) { 1094 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4)); 1095 } 1096 1097 template<class I, class P1, class P2, class P3, class P4> 1098 I* Add(P1 p1, P2 p2, P3 p3, P4 p4) { 1099 return I::cast(AddUncasted<I>(p1, p2, p3, p4)); 1100 } 1101 1102 template<class I, class P1, class P2, class P3, class P4, class P5> 1103 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { 1104 return I::New(zone(), context(), p1, p2, p3, p4, p5); 1105 } 1106 1107 template<class I, class P1, class P2, class P3, class P4, class P5> 1108 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { 1109 return I::cast(NewUncasted<I>(p1, p2, p3, p4, p5)); 1110 } 1111 1112 template<class I, class P1, class P2, class P3, class P4, class P5> 1113 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { 1114 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5)); 1115 } 1116 1117 template<class I, class P1, class P2, class P3, class P4, class P5> 1118 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { 1119 return I::cast(AddUncasted<I>(p1, p2, p3, p4, p5)); 1120 } 1121 1122 template<class I, class P1, class P2, class P3, class P4, class P5, class P6> 1123 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { 1124 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6); 1125 } 1126 1127 template<class I, class P1, class P2, class P3, class P4, class P5, class P6> 1128 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { 1129 return I::cast(NewUncasted<I>(p1, p2, p3, p4, p5, p6)); 1130 } 1131 1132 template<class I, class P1, class P2, class P3, class P4, class P5, class P6> 1133 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { 1134 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6)); 1135 } 1136 1137 template<class I, class P1, class P2, class P3, class P4, class P5, class P6> 1138 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { 1139 return I::cast(AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6))); 1140 } 1141 1142 template<class I, class P1, class P2, class P3, class P4, 1143 class P5, class P6, class P7> 1144 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { 1145 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7); 1146 } 1147 1148 template<class I, class P1, class P2, class P3, class P4, 1149 class P5, class P6, class P7> 1150 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { 1151 return I::cast(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7)); 1152 } 1153 1154 template<class I, class P1, class P2, class P3, 1155 class P4, class P5, class P6, class P7> 1156 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { 1157 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7)); 1158 } 1159 1160 template<class I, class P1, class P2, class P3, 1161 class P4, class P5, class P6, class P7> 1162 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { 1163 return I::cast(AddInstruction(NewUncasted<I>(p1, p2, p3, p4, 1164 p5, p6, p7))); 1165 } 1166 1167 template<class I, class P1, class P2, class P3, class P4, 1168 class P5, class P6, class P7, class P8> 1169 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, 1170 P5 p5, P6 p6, P7 p7, P8 p8) { 1171 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8); 1172 } 1173 1174 template<class I, class P1, class P2, class P3, class P4, 1175 class P5, class P6, class P7, class P8> 1176 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) { 1177 return I::cast(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8)); 1178 } 1179 1180 template<class I, class P1, class P2, class P3, class P4, 1181 class P5, class P6, class P7, class P8> 1182 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, 1183 P5 p5, P6 p6, P7 p7, P8 p8) { 1184 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8)); 1185 } 1186 1187 template<class I, class P1, class P2, class P3, class P4, 1188 class P5, class P6, class P7, class P8> 1189 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) { 1190 return I::cast( 1191 AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8))); 1192 } 1193 1194 void AddSimulate(BailoutId id, RemovableSimulate removable = FIXED_SIMULATE); 1195 1196 protected: 1197 virtual bool BuildGraph() = 0; 1198 1199 HBasicBlock* CreateBasicBlock(HEnvironment* env); 1200 HBasicBlock* CreateLoopHeaderBlock(); 1201 1202 HValue* BuildCheckHeapObject(HValue* object); 1203 HValue* BuildCheckMap(HValue* obj, Handle<Map> map); 1204 HValue* BuildWrapReceiver(HValue* object, HValue* function); 1205 1206 // Building common constructs 1207 HValue* BuildCheckForCapacityGrow(HValue* object, 1208 HValue* elements, 1209 ElementsKind kind, 1210 HValue* length, 1211 HValue* key, 1212 bool is_js_array); 1213 1214 HValue* BuildCopyElementsOnWrite(HValue* object, 1215 HValue* elements, 1216 ElementsKind kind, 1217 HValue* length); 1218 1219 void BuildTransitionElementsKind(HValue* object, 1220 HValue* map, 1221 ElementsKind from_kind, 1222 ElementsKind to_kind, 1223 bool is_jsarray); 1224 1225 HInstruction* BuildUncheckedMonomorphicElementAccess( 1226 HValue* object, 1227 HValue* key, 1228 HValue* val, 1229 HCheckMaps* mapcheck, 1230 bool is_js_array, 1231 ElementsKind elements_kind, 1232 bool is_store, 1233 LoadKeyedHoleMode load_mode, 1234 KeyedAccessStoreMode store_mode); 1235 1236 HInstruction* AddExternalArrayElementAccess( 1237 HValue* external_elements, 1238 HValue* checked_key, 1239 HValue* val, 1240 HValue* dependency, 1241 ElementsKind elements_kind, 1242 bool is_store); 1243 1244 HInstruction* AddFastElementAccess( 1245 HValue* elements, 1246 HValue* checked_key, 1247 HValue* val, 1248 HValue* dependency, 1249 ElementsKind elements_kind, 1250 bool is_store, 1251 LoadKeyedHoleMode load_mode, 1252 KeyedAccessStoreMode store_mode); 1253 1254 HLoadNamedField* BuildLoadNamedField( 1255 HValue* object, 1256 HObjectAccess access, 1257 HValue* typecheck); 1258 HInstruction* BuildLoadStringLength(HValue* object, HValue* typecheck); 1259 HStoreNamedField* AddStoreMapConstant(HValue *object, Handle<Map>); 1260 HLoadNamedField* AddLoadElements(HValue *object, HValue *typecheck); 1261 HLoadNamedField* AddLoadFixedArrayLength(HValue *object); 1262 1263 HValue* AddLoadJSBuiltin(Builtins::JavaScript builtin); 1264 1265 HValue* TruncateToNumber(HValue* value, Handle<Type>* expected); 1266 1267 void PushAndAdd(HInstruction* instr); 1268 1269 void FinishExitWithHardDeoptimization(const char* reason, 1270 HBasicBlock* continuation); 1271 1272 void AddIncrementCounter(StatsCounter* counter, 1273 HValue* context); 1274 1275 class IfBuilder { 1276 public: 1277 explicit IfBuilder(HGraphBuilder* builder, 1278 int position = RelocInfo::kNoPosition); 1279 IfBuilder(HGraphBuilder* builder, 1280 HIfContinuation* continuation); 1281 1282 ~IfBuilder() { 1283 if (!finished_) End(); 1284 } 1285 1286 template<class Condition> 1287 HInstruction* If(HValue *p) { 1288 HControlInstruction* compare = new(zone()) Condition(p); 1289 AddCompare(compare); 1290 return compare; 1291 } 1292 1293 template<class Condition, class P2> 1294 HInstruction* If(HValue* p1, P2 p2) { 1295 HControlInstruction* compare = new(zone()) Condition(p1, p2); 1296 AddCompare(compare); 1297 return compare; 1298 } 1299 1300 template<class Condition, class P2, class P3> 1301 HInstruction* If(HValue* p1, P2 p2, P3 p3) { 1302 HControlInstruction* compare = new(zone()) Condition(p1, p2, p3); 1303 AddCompare(compare); 1304 return compare; 1305 } 1306 1307 template<class Condition, class P2> 1308 HInstruction* IfNot(HValue* p1, P2 p2) { 1309 HControlInstruction* compare = new(zone()) Condition(p1, p2); 1310 AddCompare(compare); 1311 HBasicBlock* block0 = compare->SuccessorAt(0); 1312 HBasicBlock* block1 = compare->SuccessorAt(1); 1313 compare->SetSuccessorAt(0, block1); 1314 compare->SetSuccessorAt(1, block0); 1315 return compare; 1316 } 1317 1318 template<class Condition, class P2, class P3> 1319 HInstruction* IfNot(HValue* p1, P2 p2, P3 p3) { 1320 HControlInstruction* compare = new(zone()) Condition(p1, p2, p3); 1321 AddCompare(compare); 1322 HBasicBlock* block0 = compare->SuccessorAt(0); 1323 HBasicBlock* block1 = compare->SuccessorAt(1); 1324 compare->SetSuccessorAt(0, block1); 1325 compare->SetSuccessorAt(1, block0); 1326 return compare; 1327 } 1328 1329 template<class Condition> 1330 HInstruction* OrIf(HValue *p) { 1331 Or(); 1332 return If<Condition>(p); 1333 } 1334 1335 template<class Condition, class P2> 1336 HInstruction* OrIf(HValue* p1, P2 p2) { 1337 Or(); 1338 return If<Condition>(p1, p2); 1339 } 1340 1341 template<class Condition, class P2, class P3> 1342 HInstruction* OrIf(HValue* p1, P2 p2, P3 p3) { 1343 Or(); 1344 return If<Condition>(p1, p2, p3); 1345 } 1346 1347 template<class Condition> 1348 HInstruction* AndIf(HValue *p) { 1349 And(); 1350 return If<Condition>(p); 1351 } 1352 1353 template<class Condition, class P2> 1354 HInstruction* AndIf(HValue* p1, P2 p2) { 1355 And(); 1356 return If<Condition>(p1, p2); 1357 } 1358 1359 template<class Condition, class P2, class P3> 1360 HInstruction* AndIf(HValue* p1, P2 p2, P3 p3) { 1361 And(); 1362 return If<Condition>(p1, p2, p3); 1363 } 1364 1365 void Or(); 1366 void And(); 1367 1368 void CaptureContinuation(HIfContinuation* continuation); 1369 1370 void Then(); 1371 void Else(); 1372 void End(); 1373 1374 void Deopt(const char* reason); 1375 void ElseDeopt(const char* reason) { 1376 Else(); 1377 Deopt(reason); 1378 } 1379 1380 void Return(HValue* value); 1381 1382 private: 1383 void AddCompare(HControlInstruction* compare); 1384 1385 Zone* zone() { return builder_->zone(); } 1386 1387 HGraphBuilder* builder_; 1388 int position_; 1389 bool finished_ : 1; 1390 bool deopt_then_ : 1; 1391 bool deopt_else_ : 1; 1392 bool did_then_ : 1; 1393 bool did_else_ : 1; 1394 bool did_and_ : 1; 1395 bool did_or_ : 1; 1396 bool captured_ : 1; 1397 bool needs_compare_ : 1; 1398 HBasicBlock* first_true_block_; 1399 HBasicBlock* last_true_block_; 1400 HBasicBlock* first_false_block_; 1401 HBasicBlock* split_edge_merge_block_; 1402 HBasicBlock* merge_block_; 1403 }; 1404 1405 class LoopBuilder { 1406 public: 1407 enum Direction { 1408 kPreIncrement, 1409 kPostIncrement, 1410 kPreDecrement, 1411 kPostDecrement 1412 }; 1413 1414 LoopBuilder(HGraphBuilder* builder, 1415 HValue* context, 1416 Direction direction); 1417 ~LoopBuilder() { 1418 ASSERT(finished_); 1419 } 1420 1421 HValue* BeginBody( 1422 HValue* initial, 1423 HValue* terminating, 1424 Token::Value token); 1425 void EndBody(); 1426 1427 private: 1428 Zone* zone() { return builder_->zone(); } 1429 1430 HGraphBuilder* builder_; 1431 HValue* context_; 1432 HInstruction* increment_; 1433 HPhi* phi_; 1434 HBasicBlock* header_block_; 1435 HBasicBlock* body_block_; 1436 HBasicBlock* exit_block_; 1437 Direction direction_; 1438 bool finished_; 1439 }; 1440 1441 HValue* BuildNewElementsCapacity(HValue* old_capacity); 1442 1443 void BuildNewSpaceArrayCheck(HValue* length, 1444 ElementsKind kind); 1445 1446 class JSArrayBuilder { 1447 public: 1448 JSArrayBuilder(HGraphBuilder* builder, 1449 ElementsKind kind, 1450 HValue* allocation_site_payload, 1451 HValue* constructor_function, 1452 AllocationSiteOverrideMode override_mode); 1453 1454 JSArrayBuilder(HGraphBuilder* builder, 1455 ElementsKind kind, 1456 HValue* constructor_function); 1457 1458 HValue* AllocateEmptyArray(); 1459 HValue* AllocateArray(HValue* capacity, HValue* length_field, 1460 bool fill_with_hole); 1461 HValue* GetElementsLocation() { return elements_location_; } 1462 1463 private: 1464 Zone* zone() const { return builder_->zone(); } 1465 int elements_size() const { 1466 return IsFastDoubleElementsKind(kind_) ? kDoubleSize : kPointerSize; 1467 } 1468 HGraphBuilder* builder() { return builder_; } 1469 HGraph* graph() { return builder_->graph(); } 1470 int initial_capacity() { 1471 STATIC_ASSERT(JSArray::kPreallocatedArrayElements > 0); 1472 return JSArray::kPreallocatedArrayElements; 1473 } 1474 1475 HValue* EmitMapCode(); 1476 HValue* EmitInternalMapCode(); 1477 HValue* EstablishEmptyArrayAllocationSize(); 1478 HValue* EstablishAllocationSize(HValue* length_node); 1479 HValue* AllocateArray(HValue* size_in_bytes, HValue* capacity, 1480 HValue* length_field, bool fill_with_hole); 1481 1482 HGraphBuilder* builder_; 1483 ElementsKind kind_; 1484 AllocationSiteMode mode_; 1485 HValue* allocation_site_payload_; 1486 HValue* constructor_function_; 1487 HInnerAllocatedObject* elements_location_; 1488 }; 1489 1490 HValue* BuildAllocateElements(ElementsKind kind, 1491 HValue* capacity); 1492 1493 void BuildInitializeElementsHeader(HValue* elements, 1494 ElementsKind kind, 1495 HValue* capacity); 1496 1497 HValue* BuildAllocateElementsAndInitializeElementsHeader(ElementsKind kind, 1498 HValue* capacity); 1499 1500 // array must have been allocated with enough room for 1501 // 1) the JSArray, 2) a AllocationMemento if mode requires it, 1502 // 3) a FixedArray or FixedDoubleArray. 1503 // A pointer to the Fixed(Double)Array is returned. 1504 HInnerAllocatedObject* BuildJSArrayHeader(HValue* array, 1505 HValue* array_map, 1506 AllocationSiteMode mode, 1507 ElementsKind elements_kind, 1508 HValue* allocation_site_payload, 1509 HValue* length_field); 1510 1511 HValue* BuildGrowElementsCapacity(HValue* object, 1512 HValue* elements, 1513 ElementsKind kind, 1514 ElementsKind new_kind, 1515 HValue* length, 1516 HValue* new_capacity); 1517 1518 void BuildFillElementsWithHole(HValue* elements, 1519 ElementsKind elements_kind, 1520 HValue* from, 1521 HValue* to); 1522 1523 void BuildCopyElements(HValue* from_elements, 1524 ElementsKind from_elements_kind, 1525 HValue* to_elements, 1526 ElementsKind to_elements_kind, 1527 HValue* length, 1528 HValue* capacity); 1529 1530 HValue* BuildCloneShallowArray(HValue* boilerplate, 1531 HValue* allocation_site, 1532 AllocationSiteMode mode, 1533 ElementsKind kind, 1534 int length); 1535 1536 void BuildCompareNil( 1537 HValue* value, 1538 Handle<Type> type, 1539 int position, 1540 HIfContinuation* continuation); 1541 1542 HValue* BuildCreateAllocationMemento(HValue* previous_object, 1543 int previous_object_size, 1544 HValue* payload); 1545 1546 void BuildConstantMapCheck(Handle<JSObject> constant, CompilationInfo* info); 1547 void BuildCheckPrototypeMaps(Handle<JSObject> prototype, 1548 Handle<JSObject> holder); 1549 1550 HInstruction* BuildGetNativeContext(); 1551 HInstruction* BuildGetArrayFunction(); 1552 1553 private: 1554 HGraphBuilder(); 1555 1556 void PadEnvironmentForContinuation(HBasicBlock* from, 1557 HBasicBlock* continuation); 1558 1559 CompilationInfo* info_; 1560 HGraph* graph_; 1561 HBasicBlock* current_block_; 1562 }; 1563 1564 1565 template<> 1566 inline HInstruction* HGraphBuilder::AddUncasted<HDeoptimize>( 1567 const char* reason, Deoptimizer::BailoutType type) { 1568 if (type == Deoptimizer::SOFT) { 1569 isolate()->counters()->soft_deopts_requested()->Increment(); 1570 if (FLAG_always_opt) return NULL; 1571 } 1572 if (current_block()->IsDeoptimizing()) return NULL; 1573 HDeoptimize* instr = New<HDeoptimize>(reason, type); 1574 AddInstruction(instr); 1575 if (type == Deoptimizer::SOFT) { 1576 isolate()->counters()->soft_deopts_inserted()->Increment(); 1577 graph()->set_has_soft_deoptimize(true); 1578 } 1579 current_block()->MarkAsDeoptimizing(); 1580 return instr; 1581 } 1582 1583 1584 template<> 1585 inline HDeoptimize* HGraphBuilder::Add<HDeoptimize>( 1586 const char* reason, Deoptimizer::BailoutType type) { 1587 return static_cast<HDeoptimize*>(AddUncasted<HDeoptimize>(reason, type)); 1588 } 1589 1590 1591 template<> 1592 inline HInstruction* HGraphBuilder::AddUncasted<HSimulate>( 1593 BailoutId id, 1594 RemovableSimulate removable) { 1595 HSimulate* instr = current_block()->CreateSimulate(id, removable); 1596 AddInstruction(instr); 1597 return instr; 1598 } 1599 1600 1601 template<> 1602 inline HInstruction* HGraphBuilder::NewUncasted<HLoadNamedField>( 1603 HValue* object, HObjectAccess access) { 1604 return NewUncasted<HLoadNamedField>(object, access, 1605 static_cast<HValue*>(NULL)); 1606 } 1607 1608 1609 template<> 1610 inline HInstruction* HGraphBuilder::AddUncasted<HLoadNamedField>( 1611 HValue* object, HObjectAccess access) { 1612 return AddUncasted<HLoadNamedField>(object, access, 1613 static_cast<HValue*>(NULL)); 1614 } 1615 1616 1617 template<> 1618 inline HInstruction* HGraphBuilder::AddUncasted<HSimulate>(BailoutId id) { 1619 return AddUncasted<HSimulate>(id, FIXED_SIMULATE); 1620 } 1621 1622 1623 template<> 1624 inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HValue* value) { 1625 int num_parameters = graph()->info()->num_parameters(); 1626 HValue* params = AddUncasted<HConstant>(num_parameters); 1627 HReturn* return_instruction = New<HReturn>(value, params); 1628 current_block()->FinishExit(return_instruction); 1629 return return_instruction; 1630 } 1631 1632 1633 template<> 1634 inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HConstant* value) { 1635 return AddUncasted<HReturn>(static_cast<HValue*>(value)); 1636 } 1637 1638 1639 template<> 1640 inline HInstruction* HGraphBuilder::NewUncasted<HContext>() { 1641 return HContext::New(zone()); 1642 } 1643 1644 1645 class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor { 1646 public: 1647 // A class encapsulating (lazily-allocated) break and continue blocks for 1648 // a breakable statement. Separated from BreakAndContinueScope so that it 1649 // can have a separate lifetime. 1650 class BreakAndContinueInfo BASE_EMBEDDED { 1651 public: 1652 explicit BreakAndContinueInfo(BreakableStatement* target, 1653 int drop_extra = 0) 1654 : target_(target), 1655 break_block_(NULL), 1656 continue_block_(NULL), 1657 drop_extra_(drop_extra) { 1658 } 1659 1660 BreakableStatement* target() { return target_; } 1661 HBasicBlock* break_block() { return break_block_; } 1662 void set_break_block(HBasicBlock* block) { break_block_ = block; } 1663 HBasicBlock* continue_block() { return continue_block_; } 1664 void set_continue_block(HBasicBlock* block) { continue_block_ = block; } 1665 int drop_extra() { return drop_extra_; } 1666 1667 private: 1668 BreakableStatement* target_; 1669 HBasicBlock* break_block_; 1670 HBasicBlock* continue_block_; 1671 int drop_extra_; 1672 }; 1673 1674 // A helper class to maintain a stack of current BreakAndContinueInfo 1675 // structures mirroring BreakableStatement nesting. 1676 class BreakAndContinueScope BASE_EMBEDDED { 1677 public: 1678 BreakAndContinueScope(BreakAndContinueInfo* info, 1679 HOptimizedGraphBuilder* owner) 1680 : info_(info), owner_(owner), next_(owner->break_scope()) { 1681 owner->set_break_scope(this); 1682 } 1683 1684 ~BreakAndContinueScope() { owner_->set_break_scope(next_); } 1685 1686 BreakAndContinueInfo* info() { return info_; } 1687 HOptimizedGraphBuilder* owner() { return owner_; } 1688 BreakAndContinueScope* next() { return next_; } 1689 1690 // Search the break stack for a break or continue target. 1691 enum BreakType { BREAK, CONTINUE }; 1692 HBasicBlock* Get(BreakableStatement* stmt, BreakType type, int* drop_extra); 1693 1694 private: 1695 BreakAndContinueInfo* info_; 1696 HOptimizedGraphBuilder* owner_; 1697 BreakAndContinueScope* next_; 1698 }; 1699 1700 explicit HOptimizedGraphBuilder(CompilationInfo* info); 1701 1702 virtual bool BuildGraph(); 1703 1704 // Simple accessors. 1705 BreakAndContinueScope* break_scope() const { return break_scope_; } 1706 void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; } 1707 1708 bool inline_bailout() { return inline_bailout_; } 1709 1710 HValue* context() { return environment()->context(); } 1711 1712 void Bailout(BailoutReason reason); 1713 1714 HBasicBlock* CreateJoin(HBasicBlock* first, 1715 HBasicBlock* second, 1716 BailoutId join_id); 1717 1718 FunctionState* function_state() const { return function_state_; } 1719 1720 void VisitDeclarations(ZoneList<Declaration*>* declarations); 1721 1722 void* operator new(size_t size, Zone* zone) { 1723 return zone->New(static_cast<int>(size)); 1724 } 1725 void operator delete(void* pointer, Zone* zone) { } 1726 void operator delete(void* pointer) { } 1727 1728 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); 1729 1730 private: 1731 // Type of a member function that generates inline code for a native function. 1732 typedef void (HOptimizedGraphBuilder::*InlineFunctionGenerator) 1733 (CallRuntime* call); 1734 1735 // Forward declarations for inner scope classes. 1736 class SubgraphScope; 1737 1738 static const InlineFunctionGenerator kInlineFunctionGenerators[]; 1739 1740 static const int kMaxCallPolymorphism = 4; 1741 static const int kMaxLoadPolymorphism = 4; 1742 static const int kMaxStorePolymorphism = 4; 1743 1744 // Even in the 'unlimited' case we have to have some limit in order not to 1745 // overflow the stack. 1746 static const int kUnlimitedMaxInlinedSourceSize = 100000; 1747 static const int kUnlimitedMaxInlinedNodes = 10000; 1748 static const int kUnlimitedMaxInlinedNodesCumulative = 10000; 1749 1750 // Maximum depth and total number of elements and properties for literal 1751 // graphs to be considered for fast deep-copying. 1752 static const int kMaxFastLiteralDepth = 3; 1753 static const int kMaxFastLiteralProperties = 8; 1754 1755 // Simple accessors. 1756 void set_function_state(FunctionState* state) { function_state_ = state; } 1757 1758 AstContext* ast_context() const { return ast_context_; } 1759 void set_ast_context(AstContext* context) { ast_context_ = context; } 1760 1761 // Accessors forwarded to the function state. 1762 CompilationInfo* current_info() const { 1763 return function_state()->compilation_info(); 1764 } 1765 AstContext* call_context() const { 1766 return function_state()->call_context(); 1767 } 1768 HBasicBlock* function_return() const { 1769 return function_state()->function_return(); 1770 } 1771 TestContext* inlined_test_context() const { 1772 return function_state()->test_context(); 1773 } 1774 void ClearInlinedTestContext() { 1775 function_state()->ClearInlinedTestContext(); 1776 } 1777 StrictModeFlag function_strict_mode_flag() { 1778 return function_state()->compilation_info()->is_classic_mode() 1779 ? kNonStrictMode : kStrictMode; 1780 } 1781 1782 // Generators for inline runtime functions. 1783 #define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize) \ 1784 void Generate##Name(CallRuntime* call); 1785 1786 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION) 1787 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION) 1788 #undef INLINE_FUNCTION_GENERATOR_DECLARATION 1789 1790 void VisitDelete(UnaryOperation* expr); 1791 void VisitVoid(UnaryOperation* expr); 1792 void VisitTypeof(UnaryOperation* expr); 1793 void VisitNot(UnaryOperation* expr); 1794 1795 void VisitComma(BinaryOperation* expr); 1796 void VisitLogicalExpression(BinaryOperation* expr); 1797 void VisitArithmeticExpression(BinaryOperation* expr); 1798 1799 bool PreProcessOsrEntry(IterationStatement* statement); 1800 void VisitLoopBody(IterationStatement* stmt, 1801 HBasicBlock* loop_entry, 1802 BreakAndContinueInfo* break_info); 1803 1804 // Create a back edge in the flow graph. body_exit is the predecessor 1805 // block and loop_entry is the successor block. loop_successor is the 1806 // block where control flow exits the loop normally (e.g., via failure of 1807 // the condition) and break_block is the block where control flow breaks 1808 // from the loop. All blocks except loop_entry can be NULL. The return 1809 // value is the new successor block which is the join of loop_successor 1810 // and break_block, or NULL. 1811 HBasicBlock* CreateLoop(IterationStatement* statement, 1812 HBasicBlock* loop_entry, 1813 HBasicBlock* body_exit, 1814 HBasicBlock* loop_successor, 1815 HBasicBlock* break_block); 1816 1817 HBasicBlock* JoinContinue(IterationStatement* statement, 1818 HBasicBlock* exit_block, 1819 HBasicBlock* continue_block); 1820 1821 HValue* Top() const { return environment()->Top(); } 1822 void Drop(int n) { environment()->Drop(n); } 1823 void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); } 1824 bool IsEligibleForEnvironmentLivenessAnalysis(Variable* var, 1825 int index, 1826 HValue* value, 1827 HEnvironment* env) { 1828 if (!FLAG_analyze_environment_liveness) return false; 1829 // |this| and |arguments| are always live; zapping parameters isn't 1830 // safe because function.arguments can inspect them at any time. 1831 return !var->is_this() && 1832 !var->is_arguments() && 1833 !value->IsArgumentsObject() && 1834 env->is_local_index(index); 1835 } 1836 void BindIfLive(Variable* var, HValue* value) { 1837 HEnvironment* env = environment(); 1838 int index = env->IndexFor(var); 1839 env->Bind(index, value); 1840 if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) { 1841 HEnvironmentMarker* bind = 1842 new(zone()) HEnvironmentMarker(HEnvironmentMarker::BIND, index); 1843 AddInstruction(bind); 1844 #ifdef DEBUG 1845 bind->set_closure(env->closure()); 1846 #endif 1847 } 1848 } 1849 HValue* LookupAndMakeLive(Variable* var) { 1850 HEnvironment* env = environment(); 1851 int index = env->IndexFor(var); 1852 HValue* value = env->Lookup(index); 1853 if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) { 1854 HEnvironmentMarker* lookup = 1855 new(zone()) HEnvironmentMarker(HEnvironmentMarker::LOOKUP, index); 1856 AddInstruction(lookup); 1857 #ifdef DEBUG 1858 lookup->set_closure(env->closure()); 1859 #endif 1860 } 1861 return value; 1862 } 1863 1864 // The value of the arguments object is allowed in some but not most value 1865 // contexts. (It's allowed in all effect contexts and disallowed in all 1866 // test contexts.) 1867 void VisitForValue(Expression* expr, 1868 ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED); 1869 void VisitForTypeOf(Expression* expr); 1870 void VisitForEffect(Expression* expr); 1871 void VisitForControl(Expression* expr, 1872 HBasicBlock* true_block, 1873 HBasicBlock* false_block); 1874 1875 // Visit an argument subexpression and emit a push to the outgoing arguments. 1876 void VisitArgument(Expression* expr); 1877 1878 void VisitArgumentList(ZoneList<Expression*>* arguments); 1879 1880 // Visit a list of expressions from left to right, each in a value context. 1881 void VisitExpressions(ZoneList<Expression*>* exprs); 1882 1883 // Remove the arguments from the bailout environment and emit instructions 1884 // to push them as outgoing parameters. 1885 template <class Instruction> HInstruction* PreProcessCall(Instruction* call); 1886 1887 void SetUpScope(Scope* scope); 1888 virtual void VisitStatements(ZoneList<Statement*>* statements); 1889 1890 #define DECLARE_VISIT(type) virtual void Visit##type(type* node); 1891 AST_NODE_LIST(DECLARE_VISIT) 1892 #undef DECLARE_VISIT 1893 1894 // Helpers for flow graph construction. 1895 enum GlobalPropertyAccess { 1896 kUseCell, 1897 kUseGeneric 1898 }; 1899 GlobalPropertyAccess LookupGlobalProperty(Variable* var, 1900 LookupResult* lookup, 1901 bool is_store); 1902 1903 void EnsureArgumentsArePushedForAccess(); 1904 bool TryArgumentsAccess(Property* expr); 1905 1906 // Try to optimize fun.apply(receiver, arguments) pattern. 1907 bool TryCallApply(Call* expr); 1908 1909 int InliningAstSize(Handle<JSFunction> target); 1910 bool TryInline(CallKind call_kind, 1911 Handle<JSFunction> target, 1912 int arguments_count, 1913 HValue* implicit_return_value, 1914 BailoutId ast_id, 1915 BailoutId return_id, 1916 InliningKind inlining_kind); 1917 1918 bool TryInlineCall(Call* expr, bool drop_extra = false); 1919 bool TryInlineConstruct(CallNew* expr, HValue* implicit_return_value); 1920 bool TryInlineGetter(Handle<JSFunction> getter, Property* prop); 1921 bool TryInlineSetter(Handle<JSFunction> setter, 1922 BailoutId id, 1923 BailoutId assignment_id, 1924 HValue* implicit_return_value); 1925 bool TryInlineApply(Handle<JSFunction> function, 1926 Call* expr, 1927 int arguments_count); 1928 bool TryInlineBuiltinMethodCall(Call* expr, 1929 HValue* receiver, 1930 Handle<Map> receiver_map, 1931 CheckType check_type); 1932 bool TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra); 1933 1934 // If --trace-inlining, print a line of the inlining trace. Inlining 1935 // succeeded if the reason string is NULL and failed if there is a 1936 // non-NULL reason string. 1937 void TraceInline(Handle<JSFunction> target, 1938 Handle<JSFunction> caller, 1939 const char* failure_reason); 1940 1941 void HandleGlobalVariableAssignment(Variable* var, 1942 HValue* value, 1943 int position, 1944 BailoutId ast_id); 1945 1946 void HandlePropertyAssignment(Assignment* expr); 1947 void HandleCompoundAssignment(Assignment* expr); 1948 void HandlePolymorphicLoadNamedField(Property* expr, 1949 HValue* object, 1950 SmallMapList* types, 1951 Handle<String> name); 1952 HInstruction* TryLoadPolymorphicAsMonomorphic(Property* expr, 1953 HValue* object, 1954 SmallMapList* types, 1955 Handle<String> name); 1956 void HandlePolymorphicStoreNamedField(int position, 1957 BailoutId assignment_id, 1958 HValue* object, 1959 HValue* value, 1960 HValue* result, 1961 SmallMapList* types, 1962 Handle<String> name); 1963 bool TryStorePolymorphicAsMonomorphic(int position, 1964 BailoutId assignment_id, 1965 HValue* object, 1966 HValue* value, 1967 HValue* result, 1968 SmallMapList* types, 1969 Handle<String> name); 1970 void HandlePolymorphicCallNamed(Call* expr, 1971 HValue* receiver, 1972 SmallMapList* types, 1973 Handle<String> name); 1974 bool TryCallPolymorphicAsMonomorphic(Call* expr, 1975 HValue* receiver, 1976 SmallMapList* types, 1977 Handle<String> name); 1978 void HandleLiteralCompareTypeof(CompareOperation* expr, 1979 Expression* sub_expr, 1980 Handle<String> check); 1981 void HandleLiteralCompareNil(CompareOperation* expr, 1982 Expression* sub_expr, 1983 NilValue nil); 1984 1985 HInstruction* BuildStringCharCodeAt(HValue* string, 1986 HValue* index); 1987 HInstruction* BuildBinaryOperation(BinaryOperation* expr, 1988 HValue* left, 1989 HValue* right); 1990 HInstruction* BuildIncrement(bool returns_original_input, 1991 CountOperation* expr); 1992 HInstruction* BuildLoadKeyedGeneric(HValue* object, 1993 HValue* key); 1994 1995 HInstruction* TryBuildConsolidatedElementLoad(HValue* object, 1996 HValue* key, 1997 HValue* val, 1998 SmallMapList* maps); 1999 2000 HInstruction* BuildMonomorphicElementAccess(HValue* object, 2001 HValue* key, 2002 HValue* val, 2003 HValue* dependency, 2004 Handle<Map> map, 2005 bool is_store, 2006 KeyedAccessStoreMode store_mode); 2007 2008 HValue* HandlePolymorphicElementAccess(HValue* object, 2009 HValue* key, 2010 HValue* val, 2011 Expression* prop, 2012 BailoutId ast_id, 2013 int position, 2014 bool is_store, 2015 KeyedAccessStoreMode store_mode, 2016 bool* has_side_effects); 2017 2018 HValue* HandleKeyedElementAccess(HValue* obj, 2019 HValue* key, 2020 HValue* val, 2021 Expression* expr, 2022 BailoutId ast_id, 2023 int position, 2024 bool is_store, 2025 bool* has_side_effects); 2026 2027 HInstruction* BuildLoadNamedGeneric(HValue* object, 2028 Handle<String> name, 2029 Property* expr); 2030 HInstruction* BuildCallGetter(HValue* object, 2031 Handle<Map> map, 2032 Handle<JSFunction> getter, 2033 Handle<JSObject> holder); 2034 HInstruction* BuildLoadNamedMonomorphic(HValue* object, 2035 Handle<String> name, 2036 Property* expr, 2037 Handle<Map> map); 2038 2039 HCheckMaps* AddCheckMap(HValue* object, Handle<Map> map); 2040 2041 void BuildStoreNamed(Expression* expression, 2042 BailoutId id, 2043 int position, 2044 BailoutId assignment_id, 2045 Property* prop, 2046 HValue* object, 2047 HValue* store_value, 2048 HValue* result_value); 2049 2050 HInstruction* BuildStoreNamedField(HValue* object, 2051 Handle<String> name, 2052 HValue* value, 2053 Handle<Map> map, 2054 LookupResult* lookup); 2055 HInstruction* BuildStoreNamedGeneric(HValue* object, 2056 Handle<String> name, 2057 HValue* value); 2058 HInstruction* BuildStoreNamedMonomorphic(HValue* object, 2059 Handle<String> name, 2060 HValue* value, 2061 Handle<Map> map); 2062 HInstruction* BuildStoreKeyedGeneric(HValue* object, 2063 HValue* key, 2064 HValue* value); 2065 2066 HValue* BuildContextChainWalk(Variable* var); 2067 2068 HInstruction* BuildThisFunction(); 2069 2070 HInstruction* BuildFastLiteral(HValue* context, 2071 Handle<JSObject> boilerplate_object, 2072 Handle<JSObject> original_boilerplate_object, 2073 Handle<Object> allocation_site, 2074 int data_size, 2075 int pointer_size, 2076 AllocationSiteMode mode); 2077 2078 void BuildEmitDeepCopy(Handle<JSObject> boilerplat_object, 2079 Handle<JSObject> object, 2080 Handle<Object> allocation_site, 2081 HInstruction* target, 2082 int* offset, 2083 HInstruction* data_target, 2084 int* data_offset, 2085 AllocationSiteMode mode); 2086 2087 MUST_USE_RESULT HValue* BuildEmitObjectHeader( 2088 Handle<JSObject> boilerplat_object, 2089 HInstruction* target, 2090 HInstruction* data_target, 2091 int object_offset, 2092 int elements_offset, 2093 int elements_size); 2094 2095 void BuildEmitInObjectProperties(Handle<JSObject> boilerplate_object, 2096 Handle<JSObject> original_boilerplate_object, 2097 HValue* object_properties, 2098 HInstruction* target, 2099 int* offset, 2100 HInstruction* data_target, 2101 int* data_offset); 2102 2103 void BuildEmitElements(Handle<FixedArrayBase> elements, 2104 Handle<FixedArrayBase> original_elements, 2105 ElementsKind kind, 2106 HValue* object_elements, 2107 HInstruction* target, 2108 int* offset, 2109 HInstruction* data_target, 2110 int* data_offset); 2111 2112 void BuildEmitFixedDoubleArray(Handle<FixedArrayBase> elements, 2113 ElementsKind kind, 2114 HValue* object_elements); 2115 2116 void BuildEmitFixedArray(Handle<FixedArrayBase> elements, 2117 Handle<FixedArrayBase> original_elements, 2118 ElementsKind kind, 2119 HValue* object_elements, 2120 HInstruction* target, 2121 int* offset, 2122 HInstruction* data_target, 2123 int* data_offset); 2124 2125 void AddCheckPrototypeMaps(Handle<JSObject> holder, 2126 Handle<Map> receiver_map); 2127 2128 void AddCheckConstantFunction(Handle<JSObject> holder, 2129 HValue* receiver, 2130 Handle<Map> receiver_map); 2131 2132 bool MatchRotateRight(HValue* left, 2133 HValue* right, 2134 HValue** operand, 2135 HValue** shift_amount); 2136 2137 // The translation state of the currently-being-translated function. 2138 FunctionState* function_state_; 2139 2140 // The base of the function state stack. 2141 FunctionState initial_function_state_; 2142 2143 // Expression context of the currently visited subexpression. NULL when 2144 // visiting statements. 2145 AstContext* ast_context_; 2146 2147 // A stack of breakable statements entered. 2148 BreakAndContinueScope* break_scope_; 2149 2150 int inlined_count_; 2151 ZoneList<Handle<Object> > globals_; 2152 2153 bool inline_bailout_; 2154 2155 HOsrBuilder* osr_; 2156 2157 friend class FunctionState; // Pushes and pops the state stack. 2158 friend class AstContext; // Pushes and pops the AST context stack. 2159 friend class KeyedLoadFastElementStub; 2160 friend class HOsrBuilder; 2161 2162 DISALLOW_COPY_AND_ASSIGN(HOptimizedGraphBuilder); 2163 }; 2164 2165 2166 Zone* AstContext::zone() const { return owner_->zone(); } 2167 2168 2169 class HStatistics: public Malloced { 2170 public: 2171 HStatistics() 2172 : timing_(5), 2173 names_(5), 2174 sizes_(5), 2175 create_graph_(0), 2176 optimize_graph_(0), 2177 generate_code_(0), 2178 total_size_(0), 2179 full_code_gen_(0), 2180 source_size_(0) { } 2181 2182 void Initialize(CompilationInfo* info); 2183 void Print(); 2184 void SaveTiming(const char* name, int64_t ticks, unsigned size); 2185 2186 void IncrementFullCodeGen(int64_t full_code_gen) { 2187 full_code_gen_ += full_code_gen; 2188 } 2189 2190 void IncrementSubtotals(int64_t create_graph, 2191 int64_t optimize_graph, 2192 int64_t generate_code) { 2193 create_graph_ += create_graph; 2194 optimize_graph_ += optimize_graph; 2195 generate_code_ += generate_code; 2196 } 2197 2198 private: 2199 List<int64_t> timing_; 2200 List<const char*> names_; 2201 List<unsigned> sizes_; 2202 int64_t create_graph_; 2203 int64_t optimize_graph_; 2204 int64_t generate_code_; 2205 unsigned total_size_; 2206 int64_t full_code_gen_; 2207 double source_size_; 2208 }; 2209 2210 2211 class HPhase : public CompilationPhase { 2212 public: 2213 HPhase(const char* name, HGraph* graph) 2214 : CompilationPhase(name, graph->info()), 2215 graph_(graph) { } 2216 ~HPhase(); 2217 2218 protected: 2219 HGraph* graph() const { return graph_; } 2220 2221 private: 2222 HGraph* graph_; 2223 2224 DISALLOW_COPY_AND_ASSIGN(HPhase); 2225 }; 2226 2227 2228 class HTracer: public Malloced { 2229 public: 2230 explicit HTracer(int isolate_id) 2231 : trace_(&string_allocator_), indent_(0) { 2232 if (FLAG_trace_hydrogen_file == NULL) { 2233 OS::SNPrintF(filename_, 2234 "hydrogen-%d-%d.cfg", 2235 OS::GetCurrentProcessId(), 2236 isolate_id); 2237 } else { 2238 OS::StrNCpy(filename_, FLAG_trace_hydrogen_file, filename_.length()); 2239 } 2240 WriteChars(filename_.start(), "", 0, false); 2241 } 2242 2243 void TraceCompilation(CompilationInfo* info); 2244 void TraceHydrogen(const char* name, HGraph* graph); 2245 void TraceLithium(const char* name, LChunk* chunk); 2246 void TraceLiveRanges(const char* name, LAllocator* allocator); 2247 2248 private: 2249 class Tag BASE_EMBEDDED { 2250 public: 2251 Tag(HTracer* tracer, const char* name) { 2252 name_ = name; 2253 tracer_ = tracer; 2254 tracer->PrintIndent(); 2255 tracer->trace_.Add("begin_%s\n", name); 2256 tracer->indent_++; 2257 } 2258 2259 ~Tag() { 2260 tracer_->indent_--; 2261 tracer_->PrintIndent(); 2262 tracer_->trace_.Add("end_%s\n", name_); 2263 ASSERT(tracer_->indent_ >= 0); 2264 tracer_->FlushToFile(); 2265 } 2266 2267 private: 2268 HTracer* tracer_; 2269 const char* name_; 2270 }; 2271 2272 void TraceLiveRange(LiveRange* range, const char* type, Zone* zone); 2273 void Trace(const char* name, HGraph* graph, LChunk* chunk); 2274 void FlushToFile(); 2275 2276 void PrintEmptyProperty(const char* name) { 2277 PrintIndent(); 2278 trace_.Add("%s\n", name); 2279 } 2280 2281 void PrintStringProperty(const char* name, const char* value) { 2282 PrintIndent(); 2283 trace_.Add("%s \"%s\"\n", name, value); 2284 } 2285 2286 void PrintLongProperty(const char* name, int64_t value) { 2287 PrintIndent(); 2288 trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000)); 2289 } 2290 2291 void PrintBlockProperty(const char* name, int block_id) { 2292 PrintIndent(); 2293 trace_.Add("%s \"B%d\"\n", name, block_id); 2294 } 2295 2296 void PrintIntProperty(const char* name, int value) { 2297 PrintIndent(); 2298 trace_.Add("%s %d\n", name, value); 2299 } 2300 2301 void PrintIndent() { 2302 for (int i = 0; i < indent_; i++) { 2303 trace_.Add(" "); 2304 } 2305 } 2306 2307 EmbeddedVector<char, 64> filename_; 2308 HeapStringAllocator string_allocator_; 2309 StringStream trace_; 2310 int indent_; 2311 }; 2312 2313 2314 class NoObservableSideEffectsScope { 2315 public: 2316 explicit NoObservableSideEffectsScope(HGraphBuilder* builder) : 2317 builder_(builder) { 2318 builder_->graph()->IncrementInNoSideEffectsScope(); 2319 } 2320 ~NoObservableSideEffectsScope() { 2321 builder_->graph()->DecrementInNoSideEffectsScope(); 2322 } 2323 2324 private: 2325 HGraphBuilder* builder_; 2326 }; 2327 2328 2329 } } // namespace v8::internal 2330 2331 #endif // V8_HYDROGEN_H_ 2332