1 // Copyright 2012 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_HYDROGEN_H_ 6 #define V8_HYDROGEN_H_ 7 8 #include "src/v8.h" 9 10 #include "src/accessors.h" 11 #include "src/allocation.h" 12 #include "src/ast.h" 13 #include "src/bailout-reason.h" 14 #include "src/compiler.h" 15 #include "src/hydrogen-instructions.h" 16 #include "src/scopes.h" 17 #include "src/zone.h" 18 19 namespace v8 { 20 namespace internal { 21 22 // Forward declarations. 23 class BitVector; 24 class FunctionState; 25 class HEnvironment; 26 class HGraph; 27 class HLoopInformation; 28 class HOsrBuilder; 29 class HTracer; 30 class LAllocator; 31 class LChunk; 32 class LiveRange; 33 34 35 class HBasicBlock FINAL : public ZoneObject { 36 public: 37 explicit HBasicBlock(HGraph* graph); 38 ~HBasicBlock() { } 39 40 // Simple accessors. 41 int block_id() const { return block_id_; } 42 void set_block_id(int id) { block_id_ = id; } 43 HGraph* graph() const { return graph_; } 44 Isolate* isolate() const; 45 const ZoneList<HPhi*>* phis() const { return &phis_; } 46 HInstruction* first() const { return first_; } 47 HInstruction* last() const { return last_; } 48 void set_last(HInstruction* instr) { last_ = instr; } 49 HControlInstruction* end() const { return end_; } 50 HLoopInformation* loop_information() const { return loop_information_; } 51 HLoopInformation* current_loop() const { 52 return IsLoopHeader() ? loop_information() 53 : (parent_loop_header() != NULL 54 ? parent_loop_header()->loop_information() : NULL); 55 } 56 const ZoneList<HBasicBlock*>* predecessors() const { return &predecessors_; } 57 bool HasPredecessor() const { return predecessors_.length() > 0; } 58 const ZoneList<HBasicBlock*>* dominated_blocks() const { 59 return &dominated_blocks_; 60 } 61 const ZoneList<int>* deleted_phis() const { 62 return &deleted_phis_; 63 } 64 void RecordDeletedPhi(int merge_index) { 65 deleted_phis_.Add(merge_index, zone()); 66 } 67 HBasicBlock* dominator() const { return dominator_; } 68 HEnvironment* last_environment() const { return last_environment_; } 69 int argument_count() const { return argument_count_; } 70 void set_argument_count(int count) { argument_count_ = count; } 71 int first_instruction_index() const { return first_instruction_index_; } 72 void set_first_instruction_index(int index) { 73 first_instruction_index_ = index; 74 } 75 int last_instruction_index() const { return last_instruction_index_; } 76 void set_last_instruction_index(int index) { 77 last_instruction_index_ = index; 78 } 79 bool is_osr_entry() { return is_osr_entry_; } 80 void set_osr_entry() { is_osr_entry_ = true; } 81 82 void AttachLoopInformation(); 83 void DetachLoopInformation(); 84 bool IsLoopHeader() const { return loop_information() != NULL; } 85 bool IsStartBlock() const { return block_id() == 0; } 86 void PostProcessLoopHeader(IterationStatement* stmt); 87 88 bool IsFinished() const { return end_ != NULL; } 89 void AddPhi(HPhi* phi); 90 void RemovePhi(HPhi* phi); 91 void AddInstruction(HInstruction* instr, HSourcePosition position); 92 bool Dominates(HBasicBlock* other) const; 93 bool EqualToOrDominates(HBasicBlock* other) const; 94 int LoopNestingDepth() const; 95 96 void SetInitialEnvironment(HEnvironment* env); 97 void ClearEnvironment() { 98 DCHECK(IsFinished()); 99 DCHECK(end()->SuccessorCount() == 0); 100 last_environment_ = NULL; 101 } 102 bool HasEnvironment() const { return last_environment_ != NULL; } 103 void UpdateEnvironment(HEnvironment* env); 104 HBasicBlock* parent_loop_header() const { return parent_loop_header_; } 105 106 void set_parent_loop_header(HBasicBlock* block) { 107 DCHECK(parent_loop_header_ == NULL); 108 parent_loop_header_ = block; 109 } 110 111 bool HasParentLoopHeader() const { return parent_loop_header_ != NULL; } 112 113 void SetJoinId(BailoutId ast_id); 114 115 int PredecessorIndexOf(HBasicBlock* predecessor) const; 116 HPhi* AddNewPhi(int merged_index); 117 HSimulate* AddNewSimulate(BailoutId ast_id, 118 HSourcePosition position, 119 RemovableSimulate removable = FIXED_SIMULATE) { 120 HSimulate* instr = CreateSimulate(ast_id, removable); 121 AddInstruction(instr, position); 122 return instr; 123 } 124 void AssignCommonDominator(HBasicBlock* other); 125 void AssignLoopSuccessorDominators(); 126 127 // If a target block is tagged as an inline function return, all 128 // predecessors should contain the inlined exit sequence: 129 // 130 // LeaveInlined 131 // Simulate (caller's environment) 132 // Goto (target block) 133 bool IsInlineReturnTarget() const { return is_inline_return_target_; } 134 void MarkAsInlineReturnTarget(HBasicBlock* inlined_entry_block) { 135 is_inline_return_target_ = true; 136 inlined_entry_block_ = inlined_entry_block; 137 } 138 HBasicBlock* inlined_entry_block() { return inlined_entry_block_; } 139 140 bool IsDeoptimizing() const { 141 return end() != NULL && end()->IsDeoptimize(); 142 } 143 144 void MarkUnreachable(); 145 bool IsUnreachable() const { return !is_reachable_; } 146 bool IsReachable() const { return is_reachable_; } 147 148 bool IsLoopSuccessorDominator() const { 149 return dominates_loop_successors_; 150 } 151 void MarkAsLoopSuccessorDominator() { 152 dominates_loop_successors_ = true; 153 } 154 155 bool IsOrdered() const { return is_ordered_; } 156 void MarkAsOrdered() { is_ordered_ = true; } 157 158 void MarkSuccEdgeUnreachable(int succ); 159 160 inline Zone* zone() const; 161 162 #ifdef DEBUG 163 void Verify(); 164 #endif 165 166 protected: 167 friend class HGraphBuilder; 168 169 HSimulate* CreateSimulate(BailoutId ast_id, RemovableSimulate removable); 170 void Finish(HControlInstruction* last, HSourcePosition position); 171 void FinishExit(HControlInstruction* instruction, HSourcePosition position); 172 void Goto(HBasicBlock* block, 173 HSourcePosition position, 174 FunctionState* state = NULL, 175 bool add_simulate = true); 176 void GotoNoSimulate(HBasicBlock* block, HSourcePosition position) { 177 Goto(block, position, NULL, false); 178 } 179 180 // Add the inlined function exit sequence, adding an HLeaveInlined 181 // instruction and updating the bailout environment. 182 void AddLeaveInlined(HValue* return_value, 183 FunctionState* state, 184 HSourcePosition position); 185 186 private: 187 void RegisterPredecessor(HBasicBlock* pred); 188 void AddDominatedBlock(HBasicBlock* block); 189 190 int block_id_; 191 HGraph* graph_; 192 ZoneList<HPhi*> phis_; 193 HInstruction* first_; 194 HInstruction* last_; 195 HControlInstruction* end_; 196 HLoopInformation* loop_information_; 197 ZoneList<HBasicBlock*> predecessors_; 198 HBasicBlock* dominator_; 199 ZoneList<HBasicBlock*> dominated_blocks_; 200 HEnvironment* last_environment_; 201 // Outgoing parameter count at block exit, set during lithium translation. 202 int argument_count_; 203 // Instruction indices into the lithium code stream. 204 int first_instruction_index_; 205 int last_instruction_index_; 206 ZoneList<int> deleted_phis_; 207 HBasicBlock* parent_loop_header_; 208 // For blocks marked as inline return target: the block with HEnterInlined. 209 HBasicBlock* inlined_entry_block_; 210 bool is_inline_return_target_ : 1; 211 bool is_reachable_ : 1; 212 bool dominates_loop_successors_ : 1; 213 bool is_osr_entry_ : 1; 214 bool is_ordered_ : 1; 215 }; 216 217 218 OStream& operator<<(OStream& os, const HBasicBlock& b); 219 220 221 class HPredecessorIterator FINAL BASE_EMBEDDED { 222 public: 223 explicit HPredecessorIterator(HBasicBlock* block) 224 : predecessor_list_(block->predecessors()), current_(0) { } 225 226 bool Done() { return current_ >= predecessor_list_->length(); } 227 HBasicBlock* Current() { return predecessor_list_->at(current_); } 228 void Advance() { current_++; } 229 230 private: 231 const ZoneList<HBasicBlock*>* predecessor_list_; 232 int current_; 233 }; 234 235 236 class HInstructionIterator FINAL BASE_EMBEDDED { 237 public: 238 explicit HInstructionIterator(HBasicBlock* block) 239 : instr_(block->first()) { 240 next_ = Done() ? NULL : instr_->next(); 241 } 242 243 inline bool Done() const { return instr_ == NULL; } 244 inline HInstruction* Current() { return instr_; } 245 inline void Advance() { 246 instr_ = next_; 247 next_ = Done() ? NULL : instr_->next(); 248 } 249 250 private: 251 HInstruction* instr_; 252 HInstruction* next_; 253 }; 254 255 256 class HLoopInformation FINAL : public ZoneObject { 257 public: 258 HLoopInformation(HBasicBlock* loop_header, Zone* zone) 259 : back_edges_(4, zone), 260 loop_header_(loop_header), 261 blocks_(8, zone), 262 stack_check_(NULL) { 263 blocks_.Add(loop_header, zone); 264 } 265 ~HLoopInformation() {} 266 267 const ZoneList<HBasicBlock*>* back_edges() const { return &back_edges_; } 268 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; } 269 HBasicBlock* loop_header() const { return loop_header_; } 270 HBasicBlock* GetLastBackEdge() const; 271 void RegisterBackEdge(HBasicBlock* block); 272 273 HStackCheck* stack_check() const { return stack_check_; } 274 void set_stack_check(HStackCheck* stack_check) { 275 stack_check_ = stack_check; 276 } 277 278 bool IsNestedInThisLoop(HLoopInformation* other) { 279 while (other != NULL) { 280 if (other == this) { 281 return true; 282 } 283 other = other->parent_loop(); 284 } 285 return false; 286 } 287 HLoopInformation* parent_loop() { 288 HBasicBlock* parent_header = loop_header()->parent_loop_header(); 289 return parent_header != NULL ? parent_header->loop_information() : NULL; 290 } 291 292 private: 293 void AddBlock(HBasicBlock* block); 294 295 ZoneList<HBasicBlock*> back_edges_; 296 HBasicBlock* loop_header_; 297 ZoneList<HBasicBlock*> blocks_; 298 HStackCheck* stack_check_; 299 }; 300 301 302 class BoundsCheckTable; 303 class InductionVariableBlocksTable; 304 class HGraph FINAL : public ZoneObject { 305 public: 306 explicit HGraph(CompilationInfo* info); 307 308 Isolate* isolate() const { return isolate_; } 309 Zone* zone() const { return zone_; } 310 CompilationInfo* info() const { return info_; } 311 312 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; } 313 const ZoneList<HPhi*>* phi_list() const { return phi_list_; } 314 HBasicBlock* entry_block() const { return entry_block_; } 315 HEnvironment* start_environment() const { return start_environment_; } 316 317 void FinalizeUniqueness(); 318 bool ProcessArgumentsObject(); 319 void OrderBlocks(); 320 void AssignDominators(); 321 void RestoreActualValues(); 322 323 // Returns false if there are phi-uses of the arguments-object 324 // which are not supported by the optimizing compiler. 325 bool CheckArgumentsPhiUses(); 326 327 // Returns false if there are phi-uses of an uninitialized const 328 // which are not supported by the optimizing compiler. 329 bool CheckConstPhiUses(); 330 331 void CollectPhis(); 332 333 HConstant* GetConstantUndefined(); 334 HConstant* GetConstant0(); 335 HConstant* GetConstant1(); 336 HConstant* GetConstantMinus1(); 337 HConstant* GetConstantTrue(); 338 HConstant* GetConstantFalse(); 339 HConstant* GetConstantHole(); 340 HConstant* GetConstantNull(); 341 HConstant* GetInvalidContext(); 342 343 bool IsConstantUndefined(HConstant* constant); 344 bool IsConstant0(HConstant* constant); 345 bool IsConstant1(HConstant* constant); 346 bool IsConstantMinus1(HConstant* constant); 347 bool IsConstantTrue(HConstant* constant); 348 bool IsConstantFalse(HConstant* constant); 349 bool IsConstantHole(HConstant* constant); 350 bool IsConstantNull(HConstant* constant); 351 bool IsStandardConstant(HConstant* constant); 352 353 HBasicBlock* CreateBasicBlock(); 354 HArgumentsObject* GetArgumentsObject() const { 355 return arguments_object_.get(); 356 } 357 358 void SetArgumentsObject(HArgumentsObject* object) { 359 arguments_object_.set(object); 360 } 361 362 int GetMaximumValueID() const { return values_.length(); } 363 int GetNextBlockID() { return next_block_id_++; } 364 int GetNextValueID(HValue* value) { 365 DCHECK(!disallow_adding_new_values_); 366 values_.Add(value, zone()); 367 return values_.length() - 1; 368 } 369 HValue* LookupValue(int id) const { 370 if (id >= 0 && id < values_.length()) return values_[id]; 371 return NULL; 372 } 373 void DisallowAddingNewValues() { 374 disallow_adding_new_values_ = true; 375 } 376 377 bool Optimize(BailoutReason* bailout_reason); 378 379 #ifdef DEBUG 380 void Verify(bool do_full_verify) const; 381 #endif 382 383 bool has_osr() { 384 return osr_ != NULL; 385 } 386 387 void set_osr(HOsrBuilder* osr) { 388 osr_ = osr; 389 } 390 391 HOsrBuilder* osr() { 392 return osr_; 393 } 394 395 int update_type_change_checksum(int delta) { 396 type_change_checksum_ += delta; 397 return type_change_checksum_; 398 } 399 400 void update_maximum_environment_size(int environment_size) { 401 if (environment_size > maximum_environment_size_) { 402 maximum_environment_size_ = environment_size; 403 } 404 } 405 int maximum_environment_size() { return maximum_environment_size_; } 406 407 bool use_optimistic_licm() { 408 return use_optimistic_licm_; 409 } 410 411 void set_use_optimistic_licm(bool value) { 412 use_optimistic_licm_ = value; 413 } 414 415 void MarkRecursive() { 416 is_recursive_ = true; 417 } 418 419 bool is_recursive() const { 420 return is_recursive_; 421 } 422 423 void MarkDependsOnEmptyArrayProtoElements() { 424 // Add map dependency if not already added. 425 if (depends_on_empty_array_proto_elements_) return; 426 Map::AddDependentCompilationInfo( 427 handle(isolate()->initial_object_prototype()->map()), 428 DependentCode::kElementsCantBeAddedGroup, info()); 429 Map::AddDependentCompilationInfo( 430 handle(isolate()->initial_array_prototype()->map()), 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 DCHECK(uint32_instructions_ == NULL || !uint32_instructions_->is_empty()); 441 return uint32_instructions_ != NULL; 442 } 443 444 ZoneList<HInstruction*>* uint32_instructions() { 445 DCHECK(uint32_instructions_ == NULL || !uint32_instructions_->is_empty()); 446 return uint32_instructions_; 447 } 448 449 void RecordUint32Instruction(HInstruction* instr) { 450 DCHECK(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 // If we are tracking source positions then this function assigns a unique 462 // identifier to each inlining and dumps function source if it was inlined 463 // for the first time during the current optimization. 464 int TraceInlinedFunction(Handle<SharedFunctionInfo> shared, 465 HSourcePosition position); 466 467 // Converts given HSourcePosition to the absolute offset from the start of 468 // the corresponding script. 469 int SourcePositionToScriptPosition(HSourcePosition position); 470 471 private: 472 HConstant* ReinsertConstantIfNecessary(HConstant* constant); 473 HConstant* GetConstant(SetOncePointer<HConstant>* pointer, 474 int32_t integer_value); 475 476 template<class Phase> 477 void Run() { 478 Phase phase(this); 479 phase.Run(); 480 } 481 482 void EliminateRedundantBoundsChecksUsingInductionVariables(); 483 484 Isolate* isolate_; 485 int next_block_id_; 486 HBasicBlock* entry_block_; 487 HEnvironment* start_environment_; 488 ZoneList<HBasicBlock*> blocks_; 489 ZoneList<HValue*> values_; 490 ZoneList<HPhi*>* phi_list_; 491 ZoneList<HInstruction*>* uint32_instructions_; 492 SetOncePointer<HConstant> constant_undefined_; 493 SetOncePointer<HConstant> constant_0_; 494 SetOncePointer<HConstant> constant_1_; 495 SetOncePointer<HConstant> constant_minus1_; 496 SetOncePointer<HConstant> constant_true_; 497 SetOncePointer<HConstant> constant_false_; 498 SetOncePointer<HConstant> constant_the_hole_; 499 SetOncePointer<HConstant> constant_null_; 500 SetOncePointer<HConstant> constant_invalid_context_; 501 SetOncePointer<HArgumentsObject> arguments_object_; 502 503 HOsrBuilder* osr_; 504 505 CompilationInfo* info_; 506 Zone* zone_; 507 508 bool is_recursive_; 509 bool use_optimistic_licm_; 510 bool depends_on_empty_array_proto_elements_; 511 int type_change_checksum_; 512 int maximum_environment_size_; 513 int no_side_effects_scope_count_; 514 bool disallow_adding_new_values_; 515 516 class InlinedFunctionInfo { 517 public: 518 explicit InlinedFunctionInfo(Handle<SharedFunctionInfo> shared) 519 : shared_(shared), start_position_(shared->start_position()) { 520 } 521 522 Handle<SharedFunctionInfo> shared() const { return shared_; } 523 int start_position() const { return start_position_; } 524 525 private: 526 Handle<SharedFunctionInfo> shared_; 527 int start_position_; 528 }; 529 530 int next_inline_id_; 531 ZoneList<InlinedFunctionInfo> inlined_functions_; 532 533 DISALLOW_COPY_AND_ASSIGN(HGraph); 534 }; 535 536 537 Zone* HBasicBlock::zone() const { return graph_->zone(); } 538 539 540 // Type of stack frame an environment might refer to. 541 enum FrameType { 542 JS_FUNCTION, 543 JS_CONSTRUCT, 544 JS_GETTER, 545 JS_SETTER, 546 ARGUMENTS_ADAPTOR, 547 STUB 548 }; 549 550 551 class HEnvironment FINAL : public ZoneObject { 552 public: 553 HEnvironment(HEnvironment* outer, 554 Scope* scope, 555 Handle<JSFunction> closure, 556 Zone* zone); 557 558 HEnvironment(Zone* zone, int parameter_count); 559 560 HEnvironment* arguments_environment() { 561 return outer()->frame_type() == ARGUMENTS_ADAPTOR ? outer() : this; 562 } 563 564 // Simple accessors. 565 Handle<JSFunction> closure() const { return closure_; } 566 const ZoneList<HValue*>* values() const { return &values_; } 567 const GrowableBitVector* assigned_variables() const { 568 return &assigned_variables_; 569 } 570 FrameType frame_type() const { return frame_type_; } 571 int parameter_count() const { return parameter_count_; } 572 int specials_count() const { return specials_count_; } 573 int local_count() const { return local_count_; } 574 HEnvironment* outer() const { return outer_; } 575 int pop_count() const { return pop_count_; } 576 int push_count() const { return push_count_; } 577 578 BailoutId ast_id() const { return ast_id_; } 579 void set_ast_id(BailoutId id) { ast_id_ = id; } 580 581 HEnterInlined* entry() const { return entry_; } 582 void set_entry(HEnterInlined* entry) { entry_ = entry; } 583 584 int length() const { return values_.length(); } 585 586 int first_expression_index() const { 587 return parameter_count() + specials_count() + local_count(); 588 } 589 590 int first_local_index() const { 591 return parameter_count() + specials_count(); 592 } 593 594 void Bind(Variable* variable, HValue* value) { 595 Bind(IndexFor(variable), value); 596 } 597 598 void Bind(int index, HValue* value); 599 600 void BindContext(HValue* value) { 601 Bind(parameter_count(), value); 602 } 603 604 HValue* Lookup(Variable* variable) const { 605 return Lookup(IndexFor(variable)); 606 } 607 608 HValue* Lookup(int index) const { 609 HValue* result = values_[index]; 610 DCHECK(result != NULL); 611 return result; 612 } 613 614 HValue* context() const { 615 // Return first special. 616 return Lookup(parameter_count()); 617 } 618 619 void Push(HValue* value) { 620 DCHECK(value != NULL); 621 ++push_count_; 622 values_.Add(value, zone()); 623 } 624 625 HValue* Pop() { 626 DCHECK(!ExpressionStackIsEmpty()); 627 if (push_count_ > 0) { 628 --push_count_; 629 } else { 630 ++pop_count_; 631 } 632 return values_.RemoveLast(); 633 } 634 635 void Drop(int count); 636 637 HValue* Top() const { return ExpressionStackAt(0); } 638 639 bool ExpressionStackIsEmpty() const; 640 641 HValue* ExpressionStackAt(int index_from_top) const { 642 int index = length() - index_from_top - 1; 643 DCHECK(HasExpressionAt(index)); 644 return values_[index]; 645 } 646 647 void SetExpressionStackAt(int index_from_top, HValue* value); 648 649 HEnvironment* Copy() const; 650 HEnvironment* CopyWithoutHistory() const; 651 HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const; 652 653 // Create an "inlined version" of this environment, where the original 654 // environment is the outer environment but the top expression stack 655 // elements are moved to an inner environment as parameters. 656 HEnvironment* CopyForInlining(Handle<JSFunction> target, 657 int arguments, 658 FunctionLiteral* function, 659 HConstant* undefined, 660 InliningKind inlining_kind) const; 661 662 HEnvironment* DiscardInlined(bool drop_extra) { 663 HEnvironment* outer = outer_; 664 while (outer->frame_type() != JS_FUNCTION) outer = outer->outer_; 665 if (drop_extra) outer->Drop(1); 666 return outer; 667 } 668 669 void AddIncomingEdge(HBasicBlock* block, HEnvironment* other); 670 671 void ClearHistory() { 672 pop_count_ = 0; 673 push_count_ = 0; 674 assigned_variables_.Clear(); 675 } 676 677 void SetValueAt(int index, HValue* value) { 678 DCHECK(index < length()); 679 values_[index] = value; 680 } 681 682 // Map a variable to an environment index. Parameter indices are shifted 683 // by 1 (receiver is parameter index -1 but environment index 0). 684 // Stack-allocated local indices are shifted by the number of parameters. 685 int IndexFor(Variable* variable) const { 686 DCHECK(variable->IsStackAllocated()); 687 int shift = variable->IsParameter() 688 ? 1 689 : parameter_count_ + specials_count_; 690 return variable->index() + shift; 691 } 692 693 bool is_local_index(int i) const { 694 return i >= first_local_index() && i < first_expression_index(); 695 } 696 697 bool is_parameter_index(int i) const { 698 return i >= 0 && i < parameter_count(); 699 } 700 701 bool is_special_index(int i) const { 702 return i >= parameter_count() && i < parameter_count() + specials_count(); 703 } 704 705 Zone* zone() const { return zone_; } 706 707 private: 708 HEnvironment(const HEnvironment* other, Zone* zone); 709 710 HEnvironment(HEnvironment* outer, 711 Handle<JSFunction> closure, 712 FrameType frame_type, 713 int arguments, 714 Zone* zone); 715 716 // Create an artificial stub environment (e.g. for argument adaptor or 717 // constructor stub). 718 HEnvironment* CreateStubEnvironment(HEnvironment* outer, 719 Handle<JSFunction> target, 720 FrameType frame_type, 721 int arguments) const; 722 723 // True if index is included in the expression stack part of the environment. 724 bool HasExpressionAt(int index) const; 725 726 void Initialize(int parameter_count, int local_count, int stack_height); 727 void Initialize(const HEnvironment* other); 728 729 Handle<JSFunction> closure_; 730 // Value array [parameters] [specials] [locals] [temporaries]. 731 ZoneList<HValue*> values_; 732 GrowableBitVector assigned_variables_; 733 FrameType frame_type_; 734 int parameter_count_; 735 int specials_count_; 736 int local_count_; 737 HEnvironment* outer_; 738 HEnterInlined* entry_; 739 int pop_count_; 740 int push_count_; 741 BailoutId ast_id_; 742 Zone* zone_; 743 }; 744 745 746 OStream& operator<<(OStream& os, const HEnvironment& env); 747 748 749 class HOptimizedGraphBuilder; 750 751 enum ArgumentsAllowedFlag { 752 ARGUMENTS_NOT_ALLOWED, 753 ARGUMENTS_ALLOWED 754 }; 755 756 757 class HIfContinuation; 758 759 // This class is not BASE_EMBEDDED because our inlining implementation uses 760 // new and delete. 761 class AstContext { 762 public: 763 bool IsEffect() const { return kind_ == Expression::kEffect; } 764 bool IsValue() const { return kind_ == Expression::kValue; } 765 bool IsTest() const { return kind_ == Expression::kTest; } 766 767 // 'Fill' this context with a hydrogen value. The value is assumed to 768 // have already been inserted in the instruction stream (or not need to 769 // be, e.g., HPhi). Call this function in tail position in the Visit 770 // functions for expressions. 771 virtual void ReturnValue(HValue* value) = 0; 772 773 // Add a hydrogen instruction to the instruction stream (recording an 774 // environment simulation if necessary) and then fill this context with 775 // the instruction as value. 776 virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id) = 0; 777 778 // Finishes the current basic block and materialize a boolean for 779 // value context, nothing for effect, generate a branch for test context. 780 // Call this function in tail position in the Visit functions for 781 // expressions. 782 virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id) = 0; 783 784 // Finishes the current basic block and materialize a boolean for 785 // value context, nothing for effect, generate a branch for test context. 786 // Call this function in tail position in the Visit functions for 787 // expressions that use an IfBuilder. 788 virtual void ReturnContinuation(HIfContinuation* continuation, 789 BailoutId ast_id) = 0; 790 791 void set_for_typeof(bool for_typeof) { for_typeof_ = for_typeof; } 792 bool is_for_typeof() { return for_typeof_; } 793 794 protected: 795 AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind); 796 virtual ~AstContext(); 797 798 HOptimizedGraphBuilder* owner() const { return owner_; } 799 800 inline Zone* zone() const; 801 802 // We want to be able to assert, in a context-specific way, that the stack 803 // height makes sense when the context is filled. 804 #ifdef DEBUG 805 int original_length_; 806 #endif 807 808 private: 809 HOptimizedGraphBuilder* owner_; 810 Expression::Context kind_; 811 AstContext* outer_; 812 bool for_typeof_; 813 }; 814 815 816 class EffectContext FINAL : public AstContext { 817 public: 818 explicit EffectContext(HOptimizedGraphBuilder* owner) 819 : AstContext(owner, Expression::kEffect) { 820 } 821 virtual ~EffectContext(); 822 823 virtual void ReturnValue(HValue* value) OVERRIDE; 824 virtual void ReturnInstruction(HInstruction* instr, 825 BailoutId ast_id) OVERRIDE; 826 virtual void ReturnControl(HControlInstruction* instr, 827 BailoutId ast_id) OVERRIDE; 828 virtual void ReturnContinuation(HIfContinuation* continuation, 829 BailoutId ast_id) OVERRIDE; 830 }; 831 832 833 class ValueContext FINAL : public AstContext { 834 public: 835 ValueContext(HOptimizedGraphBuilder* owner, ArgumentsAllowedFlag flag) 836 : AstContext(owner, Expression::kValue), flag_(flag) { 837 } 838 virtual ~ValueContext(); 839 840 virtual void ReturnValue(HValue* value) OVERRIDE; 841 virtual void ReturnInstruction(HInstruction* instr, 842 BailoutId ast_id) OVERRIDE; 843 virtual void ReturnControl(HControlInstruction* instr, 844 BailoutId ast_id) OVERRIDE; 845 virtual void ReturnContinuation(HIfContinuation* continuation, 846 BailoutId ast_id) OVERRIDE; 847 848 bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; } 849 850 private: 851 ArgumentsAllowedFlag flag_; 852 }; 853 854 855 class TestContext FINAL : public AstContext { 856 public: 857 TestContext(HOptimizedGraphBuilder* owner, 858 Expression* condition, 859 HBasicBlock* if_true, 860 HBasicBlock* if_false) 861 : AstContext(owner, Expression::kTest), 862 condition_(condition), 863 if_true_(if_true), 864 if_false_(if_false) { 865 } 866 867 virtual void ReturnValue(HValue* value) OVERRIDE; 868 virtual void ReturnInstruction(HInstruction* instr, 869 BailoutId ast_id) OVERRIDE; 870 virtual void ReturnControl(HControlInstruction* instr, 871 BailoutId ast_id) OVERRIDE; 872 virtual void ReturnContinuation(HIfContinuation* continuation, 873 BailoutId ast_id) OVERRIDE; 874 875 static TestContext* cast(AstContext* context) { 876 DCHECK(context->IsTest()); 877 return reinterpret_cast<TestContext*>(context); 878 } 879 880 Expression* condition() const { return condition_; } 881 HBasicBlock* if_true() const { return if_true_; } 882 HBasicBlock* if_false() const { return if_false_; } 883 884 private: 885 // Build the shared core part of the translation unpacking a value into 886 // control flow. 887 void BuildBranch(HValue* value); 888 889 Expression* condition_; 890 HBasicBlock* if_true_; 891 HBasicBlock* if_false_; 892 }; 893 894 895 class FunctionState FINAL { 896 public: 897 FunctionState(HOptimizedGraphBuilder* owner, 898 CompilationInfo* info, 899 InliningKind inlining_kind, 900 int inlining_id); 901 ~FunctionState(); 902 903 CompilationInfo* compilation_info() { return compilation_info_; } 904 AstContext* call_context() { return call_context_; } 905 InliningKind inlining_kind() const { return inlining_kind_; } 906 HBasicBlock* function_return() { return function_return_; } 907 TestContext* test_context() { return test_context_; } 908 void ClearInlinedTestContext() { 909 delete test_context_; 910 test_context_ = NULL; 911 } 912 913 FunctionState* outer() { return outer_; } 914 915 HEnterInlined* entry() { return entry_; } 916 void set_entry(HEnterInlined* entry) { entry_ = entry; } 917 918 HArgumentsObject* arguments_object() { return arguments_object_; } 919 void set_arguments_object(HArgumentsObject* arguments_object) { 920 arguments_object_ = arguments_object; 921 } 922 923 HArgumentsElements* arguments_elements() { return arguments_elements_; } 924 void set_arguments_elements(HArgumentsElements* arguments_elements) { 925 arguments_elements_ = arguments_elements; 926 } 927 928 bool arguments_pushed() { return arguments_elements() != NULL; } 929 930 int inlining_id() const { return inlining_id_; } 931 932 private: 933 HOptimizedGraphBuilder* owner_; 934 935 CompilationInfo* compilation_info_; 936 937 // During function inlining, expression context of the call being 938 // inlined. NULL when not inlining. 939 AstContext* call_context_; 940 941 // The kind of call which is currently being inlined. 942 InliningKind inlining_kind_; 943 944 // When inlining in an effect or value context, this is the return block. 945 // It is NULL otherwise. When inlining in a test context, there are a 946 // pair of return blocks in the context. When not inlining, there is no 947 // local return point. 948 HBasicBlock* function_return_; 949 950 // When inlining a call in a test context, a context containing a pair of 951 // return blocks. NULL in all other cases. 952 TestContext* test_context_; 953 954 // When inlining HEnterInlined instruction corresponding to the function 955 // entry. 956 HEnterInlined* entry_; 957 958 HArgumentsObject* arguments_object_; 959 HArgumentsElements* arguments_elements_; 960 961 int inlining_id_; 962 HSourcePosition outer_source_position_; 963 964 FunctionState* outer_; 965 }; 966 967 968 class HIfContinuation FINAL { 969 public: 970 HIfContinuation() 971 : continuation_captured_(false), 972 true_branch_(NULL), 973 false_branch_(NULL) {} 974 HIfContinuation(HBasicBlock* true_branch, 975 HBasicBlock* false_branch) 976 : continuation_captured_(true), true_branch_(true_branch), 977 false_branch_(false_branch) {} 978 ~HIfContinuation() { DCHECK(!continuation_captured_); } 979 980 void Capture(HBasicBlock* true_branch, 981 HBasicBlock* false_branch) { 982 DCHECK(!continuation_captured_); 983 true_branch_ = true_branch; 984 false_branch_ = false_branch; 985 continuation_captured_ = true; 986 } 987 988 void Continue(HBasicBlock** true_branch, 989 HBasicBlock** false_branch) { 990 DCHECK(continuation_captured_); 991 *true_branch = true_branch_; 992 *false_branch = false_branch_; 993 continuation_captured_ = false; 994 } 995 996 bool IsTrueReachable() { return true_branch_ != NULL; } 997 bool IsFalseReachable() { return false_branch_ != NULL; } 998 bool TrueAndFalseReachable() { 999 return IsTrueReachable() || IsFalseReachable(); 1000 } 1001 1002 HBasicBlock* true_branch() const { return true_branch_; } 1003 HBasicBlock* false_branch() const { return false_branch_; } 1004 1005 private: 1006 bool continuation_captured_; 1007 HBasicBlock* true_branch_; 1008 HBasicBlock* false_branch_; 1009 }; 1010 1011 1012 class HAllocationMode FINAL BASE_EMBEDDED { 1013 public: 1014 explicit HAllocationMode(Handle<AllocationSite> feedback_site) 1015 : current_site_(NULL), feedback_site_(feedback_site), 1016 pretenure_flag_(NOT_TENURED) {} 1017 explicit HAllocationMode(HValue* current_site) 1018 : current_site_(current_site), pretenure_flag_(NOT_TENURED) {} 1019 explicit HAllocationMode(PretenureFlag pretenure_flag) 1020 : current_site_(NULL), pretenure_flag_(pretenure_flag) {} 1021 HAllocationMode() 1022 : current_site_(NULL), pretenure_flag_(NOT_TENURED) {} 1023 1024 HValue* current_site() const { return current_site_; } 1025 Handle<AllocationSite> feedback_site() const { return feedback_site_; } 1026 1027 bool CreateAllocationMementos() const WARN_UNUSED_RESULT { 1028 return current_site() != NULL; 1029 } 1030 1031 PretenureFlag GetPretenureMode() const WARN_UNUSED_RESULT { 1032 if (!feedback_site().is_null()) return feedback_site()->GetPretenureMode(); 1033 return pretenure_flag_; 1034 } 1035 1036 private: 1037 HValue* current_site_; 1038 Handle<AllocationSite> feedback_site_; 1039 PretenureFlag pretenure_flag_; 1040 }; 1041 1042 1043 class HGraphBuilder { 1044 public: 1045 explicit HGraphBuilder(CompilationInfo* info) 1046 : info_(info), 1047 graph_(NULL), 1048 current_block_(NULL), 1049 scope_(info->scope()), 1050 position_(HSourcePosition::Unknown()), 1051 start_position_(0) {} 1052 virtual ~HGraphBuilder() {} 1053 1054 Scope* scope() const { return scope_; } 1055 void set_scope(Scope* scope) { scope_ = scope; } 1056 1057 HBasicBlock* current_block() const { return current_block_; } 1058 void set_current_block(HBasicBlock* block) { current_block_ = block; } 1059 HEnvironment* environment() const { 1060 return current_block()->last_environment(); 1061 } 1062 Zone* zone() const { return info_->zone(); } 1063 HGraph* graph() const { return graph_; } 1064 Isolate* isolate() const { return graph_->isolate(); } 1065 CompilationInfo* top_info() { return info_; } 1066 1067 HGraph* CreateGraph(); 1068 1069 // Bailout environment manipulation. 1070 void Push(HValue* value) { environment()->Push(value); } 1071 HValue* Pop() { return environment()->Pop(); } 1072 1073 virtual HValue* context() = 0; 1074 1075 // Adding instructions. 1076 HInstruction* AddInstruction(HInstruction* instr); 1077 void FinishCurrentBlock(HControlInstruction* last); 1078 void FinishExitCurrentBlock(HControlInstruction* instruction); 1079 1080 void Goto(HBasicBlock* from, 1081 HBasicBlock* target, 1082 FunctionState* state = NULL, 1083 bool add_simulate = true) { 1084 from->Goto(target, source_position(), state, add_simulate); 1085 } 1086 void Goto(HBasicBlock* target, 1087 FunctionState* state = NULL, 1088 bool add_simulate = true) { 1089 Goto(current_block(), target, state, add_simulate); 1090 } 1091 void GotoNoSimulate(HBasicBlock* from, HBasicBlock* target) { 1092 Goto(from, target, NULL, false); 1093 } 1094 void GotoNoSimulate(HBasicBlock* target) { 1095 Goto(target, NULL, false); 1096 } 1097 void AddLeaveInlined(HBasicBlock* block, 1098 HValue* return_value, 1099 FunctionState* state) { 1100 block->AddLeaveInlined(return_value, state, source_position()); 1101 } 1102 void AddLeaveInlined(HValue* return_value, FunctionState* state) { 1103 return AddLeaveInlined(current_block(), return_value, state); 1104 } 1105 1106 template<class I> 1107 HInstruction* NewUncasted() { return I::New(zone(), context()); } 1108 1109 template<class I> 1110 I* New() { return I::New(zone(), context()); } 1111 1112 template<class I> 1113 HInstruction* AddUncasted() { return AddInstruction(NewUncasted<I>());} 1114 1115 template<class I> 1116 I* Add() { return AddInstructionTyped(New<I>());} 1117 1118 template<class I, class P1> 1119 HInstruction* NewUncasted(P1 p1) { 1120 return I::New(zone(), context(), p1); 1121 } 1122 1123 template<class I, class P1> 1124 I* New(P1 p1) { return I::New(zone(), context(), p1); } 1125 1126 template<class I, class P1> 1127 HInstruction* AddUncasted(P1 p1) { 1128 HInstruction* result = AddInstruction(NewUncasted<I>(p1)); 1129 // Specializations must have their parameters properly casted 1130 // to avoid landing here. 1131 DCHECK(!result->IsReturn() && !result->IsSimulate() && 1132 !result->IsDeoptimize()); 1133 return result; 1134 } 1135 1136 template<class I, class P1> 1137 I* Add(P1 p1) { 1138 I* result = AddInstructionTyped(New<I>(p1)); 1139 // Specializations must have their parameters properly casted 1140 // to avoid landing here. 1141 DCHECK(!result->IsReturn() && !result->IsSimulate() && 1142 !result->IsDeoptimize()); 1143 return result; 1144 } 1145 1146 template<class I, class P1, class P2> 1147 HInstruction* NewUncasted(P1 p1, P2 p2) { 1148 return I::New(zone(), context(), p1, p2); 1149 } 1150 1151 template<class I, class P1, class P2> 1152 I* New(P1 p1, P2 p2) { 1153 return I::New(zone(), context(), p1, p2); 1154 } 1155 1156 template<class I, class P1, class P2> 1157 HInstruction* AddUncasted(P1 p1, P2 p2) { 1158 HInstruction* result = AddInstruction(NewUncasted<I>(p1, p2)); 1159 // Specializations must have their parameters properly casted 1160 // to avoid landing here. 1161 DCHECK(!result->IsSimulate()); 1162 return result; 1163 } 1164 1165 template<class I, class P1, class P2> 1166 I* Add(P1 p1, P2 p2) { 1167 I* result = AddInstructionTyped(New<I>(p1, p2)); 1168 // Specializations must have their parameters properly casted 1169 // to avoid landing here. 1170 DCHECK(!result->IsSimulate()); 1171 return result; 1172 } 1173 1174 template<class I, class P1, class P2, class P3> 1175 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3) { 1176 return I::New(zone(), context(), p1, p2, p3); 1177 } 1178 1179 template<class I, class P1, class P2, class P3> 1180 I* New(P1 p1, P2 p2, P3 p3) { 1181 return I::New(zone(), context(), p1, p2, p3); 1182 } 1183 1184 template<class I, class P1, class P2, class P3> 1185 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3) { 1186 return AddInstruction(NewUncasted<I>(p1, p2, p3)); 1187 } 1188 1189 template<class I, class P1, class P2, class P3> 1190 I* Add(P1 p1, P2 p2, P3 p3) { 1191 return AddInstructionTyped(New<I>(p1, p2, p3)); 1192 } 1193 1194 template<class I, class P1, class P2, class P3, class P4> 1195 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4) { 1196 return I::New(zone(), context(), p1, p2, p3, p4); 1197 } 1198 1199 template<class I, class P1, class P2, class P3, class P4> 1200 I* New(P1 p1, P2 p2, P3 p3, P4 p4) { 1201 return I::New(zone(), context(), p1, p2, p3, p4); 1202 } 1203 1204 template<class I, class P1, class P2, class P3, class P4> 1205 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4) { 1206 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4)); 1207 } 1208 1209 template<class I, class P1, class P2, class P3, class P4> 1210 I* Add(P1 p1, P2 p2, P3 p3, P4 p4) { 1211 return AddInstructionTyped(New<I>(p1, p2, p3, p4)); 1212 } 1213 1214 template<class I, class P1, class P2, class P3, class P4, class P5> 1215 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { 1216 return I::New(zone(), context(), p1, p2, p3, p4, p5); 1217 } 1218 1219 template<class I, class P1, class P2, class P3, class P4, class P5> 1220 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { 1221 return I::New(zone(), context(), p1, p2, p3, p4, p5); 1222 } 1223 1224 template<class I, class P1, class P2, class P3, class P4, class P5> 1225 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { 1226 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5)); 1227 } 1228 1229 template<class I, class P1, class P2, class P3, class P4, class P5> 1230 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { 1231 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5)); 1232 } 1233 1234 template<class I, class P1, class P2, class P3, class P4, class P5, class P6> 1235 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { 1236 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6); 1237 } 1238 1239 template<class I, class P1, class P2, class P3, class P4, class P5, class P6> 1240 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { 1241 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6); 1242 } 1243 1244 template<class I, class P1, class P2, class P3, class P4, class P5, class P6> 1245 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { 1246 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6)); 1247 } 1248 1249 template<class I, class P1, class P2, class P3, class P4, class P5, class P6> 1250 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { 1251 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6)); 1252 } 1253 1254 template<class I, class P1, class P2, class P3, class P4, 1255 class P5, class P6, class P7> 1256 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { 1257 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7); 1258 } 1259 1260 template<class I, class P1, class P2, class P3, class P4, 1261 class P5, class P6, class P7> 1262 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { 1263 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7); 1264 } 1265 1266 template<class I, class P1, class P2, class P3, 1267 class P4, class P5, class P6, class P7> 1268 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { 1269 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7)); 1270 } 1271 1272 template<class I, class P1, class P2, class P3, 1273 class P4, class P5, class P6, class P7> 1274 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { 1275 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7)); 1276 } 1277 1278 template<class I, class P1, class P2, class P3, class P4, 1279 class P5, class P6, class P7, class P8> 1280 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, 1281 P5 p5, P6 p6, P7 p7, P8 p8) { 1282 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8); 1283 } 1284 1285 template<class I, class P1, class P2, class P3, class P4, 1286 class P5, class P6, class P7, class P8> 1287 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) { 1288 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8); 1289 } 1290 1291 template<class I, class P1, class P2, class P3, class P4, 1292 class P5, class P6, class P7, class P8> 1293 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, 1294 P5 p5, P6 p6, P7 p7, P8 p8) { 1295 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8)); 1296 } 1297 1298 template<class I, class P1, class P2, class P3, class P4, 1299 class P5, class P6, class P7, class P8> 1300 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) { 1301 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7, p8)); 1302 } 1303 1304 void AddSimulate(BailoutId id, RemovableSimulate removable = FIXED_SIMULATE); 1305 1306 // When initializing arrays, we'll unfold the loop if the number of elements 1307 // is known at compile time and is <= kElementLoopUnrollThreshold. 1308 static const int kElementLoopUnrollThreshold = 8; 1309 1310 protected: 1311 virtual bool BuildGraph() = 0; 1312 1313 HBasicBlock* CreateBasicBlock(HEnvironment* env); 1314 HBasicBlock* CreateLoopHeaderBlock(); 1315 1316 template <class BitFieldClass> 1317 HValue* BuildDecodeField(HValue* encoded_field) { 1318 HValue* mask_value = Add<HConstant>(static_cast<int>(BitFieldClass::kMask)); 1319 HValue* masked_field = 1320 AddUncasted<HBitwise>(Token::BIT_AND, encoded_field, mask_value); 1321 return AddUncasted<HShr>(masked_field, 1322 Add<HConstant>(static_cast<int>(BitFieldClass::kShift))); 1323 } 1324 1325 HValue* BuildGetElementsKind(HValue* object); 1326 1327 HValue* BuildCheckHeapObject(HValue* object); 1328 HValue* BuildCheckString(HValue* string); 1329 HValue* BuildWrapReceiver(HValue* object, HValue* function); 1330 1331 // Building common constructs 1332 HValue* BuildCheckForCapacityGrow(HValue* object, 1333 HValue* elements, 1334 ElementsKind kind, 1335 HValue* length, 1336 HValue* key, 1337 bool is_js_array, 1338 PropertyAccessType access_type); 1339 1340 HValue* BuildCopyElementsOnWrite(HValue* object, 1341 HValue* elements, 1342 ElementsKind kind, 1343 HValue* length); 1344 1345 void BuildTransitionElementsKind(HValue* object, 1346 HValue* map, 1347 ElementsKind from_kind, 1348 ElementsKind to_kind, 1349 bool is_jsarray); 1350 1351 HValue* BuildNumberToString(HValue* object, Type* type); 1352 1353 void BuildJSObjectCheck(HValue* receiver, 1354 int bit_field_mask); 1355 1356 // Checks a key value that's being used for a keyed element access context. If 1357 // the key is a index, i.e. a smi or a number in a unique string with a cached 1358 // numeric value, the "true" of the continuation is joined. Otherwise, 1359 // if the key is a name or a unique string, the "false" of the continuation is 1360 // joined. Otherwise, a deoptimization is triggered. In both paths of the 1361 // continuation, the key is pushed on the top of the environment. 1362 void BuildKeyedIndexCheck(HValue* key, 1363 HIfContinuation* join_continuation); 1364 1365 // Checks the properties of an object if they are in dictionary case, in which 1366 // case "true" of continuation is taken, otherwise the "false" 1367 void BuildTestForDictionaryProperties(HValue* object, 1368 HIfContinuation* continuation); 1369 1370 void BuildNonGlobalObjectCheck(HValue* receiver); 1371 1372 HValue* BuildKeyedLookupCacheHash(HValue* object, 1373 HValue* key); 1374 1375 HValue* BuildUncheckedDictionaryElementLoad(HValue* receiver, 1376 HValue* elements, 1377 HValue* key, 1378 HValue* hash); 1379 1380 HValue* BuildRegExpConstructResult(HValue* length, 1381 HValue* index, 1382 HValue* input); 1383 1384 // Allocates a new object according with the given allocation properties. 1385 HAllocate* BuildAllocate(HValue* object_size, 1386 HType type, 1387 InstanceType instance_type, 1388 HAllocationMode allocation_mode); 1389 // Computes the sum of two string lengths, taking care of overflow handling. 1390 HValue* BuildAddStringLengths(HValue* left_length, HValue* right_length); 1391 // Creates a cons string using the two input strings. 1392 HValue* BuildCreateConsString(HValue* length, 1393 HValue* left, 1394 HValue* right, 1395 HAllocationMode allocation_mode); 1396 // Copies characters from one sequential string to another. 1397 void BuildCopySeqStringChars(HValue* src, 1398 HValue* src_offset, 1399 String::Encoding src_encoding, 1400 HValue* dst, 1401 HValue* dst_offset, 1402 String::Encoding dst_encoding, 1403 HValue* length); 1404 1405 // Align an object size to object alignment boundary 1406 HValue* BuildObjectSizeAlignment(HValue* unaligned_size, int header_size); 1407 1408 // Both operands are non-empty strings. 1409 HValue* BuildUncheckedStringAdd(HValue* left, 1410 HValue* right, 1411 HAllocationMode allocation_mode); 1412 // Add two strings using allocation mode, validating type feedback. 1413 HValue* BuildStringAdd(HValue* left, 1414 HValue* right, 1415 HAllocationMode allocation_mode); 1416 1417 HInstruction* BuildUncheckedMonomorphicElementAccess( 1418 HValue* checked_object, 1419 HValue* key, 1420 HValue* val, 1421 bool is_js_array, 1422 ElementsKind elements_kind, 1423 PropertyAccessType access_type, 1424 LoadKeyedHoleMode load_mode, 1425 KeyedAccessStoreMode store_mode); 1426 1427 HInstruction* AddElementAccess( 1428 HValue* elements, 1429 HValue* checked_key, 1430 HValue* val, 1431 HValue* dependency, 1432 ElementsKind elements_kind, 1433 PropertyAccessType access_type, 1434 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE); 1435 1436 HInstruction* AddLoadStringInstanceType(HValue* string); 1437 HInstruction* AddLoadStringLength(HValue* string); 1438 HStoreNamedField* AddStoreMapConstant(HValue* object, Handle<Map> map) { 1439 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), 1440 Add<HConstant>(map)); 1441 } 1442 HLoadNamedField* AddLoadMap(HValue* object, 1443 HValue* dependency = NULL); 1444 HLoadNamedField* AddLoadElements(HValue* object, 1445 HValue* dependency = NULL); 1446 1447 bool MatchRotateRight(HValue* left, 1448 HValue* right, 1449 HValue** operand, 1450 HValue** shift_amount); 1451 1452 HValue* BuildBinaryOperation(Token::Value op, 1453 HValue* left, 1454 HValue* right, 1455 Type* left_type, 1456 Type* right_type, 1457 Type* result_type, 1458 Maybe<int> fixed_right_arg, 1459 HAllocationMode allocation_mode); 1460 1461 HLoadNamedField* AddLoadFixedArrayLength(HValue *object, 1462 HValue *dependency = NULL); 1463 1464 HLoadNamedField* AddLoadArrayLength(HValue *object, 1465 ElementsKind kind, 1466 HValue *dependency = NULL); 1467 1468 HValue* AddLoadJSBuiltin(Builtins::JavaScript builtin); 1469 1470 HValue* EnforceNumberType(HValue* number, Type* expected); 1471 HValue* TruncateToNumber(HValue* value, Type** expected); 1472 1473 void FinishExitWithHardDeoptimization(const char* reason); 1474 1475 void AddIncrementCounter(StatsCounter* counter); 1476 1477 class IfBuilder FINAL { 1478 public: 1479 // If using this constructor, Initialize() must be called explicitly! 1480 IfBuilder(); 1481 1482 explicit IfBuilder(HGraphBuilder* builder); 1483 IfBuilder(HGraphBuilder* builder, 1484 HIfContinuation* continuation); 1485 1486 ~IfBuilder() { 1487 if (!finished_) End(); 1488 } 1489 1490 void Initialize(HGraphBuilder* builder); 1491 1492 template<class Condition> 1493 Condition* If(HValue *p) { 1494 Condition* compare = builder()->New<Condition>(p); 1495 AddCompare(compare); 1496 return compare; 1497 } 1498 1499 template<class Condition, class P2> 1500 Condition* If(HValue* p1, P2 p2) { 1501 Condition* compare = builder()->New<Condition>(p1, p2); 1502 AddCompare(compare); 1503 return compare; 1504 } 1505 1506 template<class Condition, class P2, class P3> 1507 Condition* If(HValue* p1, P2 p2, P3 p3) { 1508 Condition* compare = builder()->New<Condition>(p1, p2, p3); 1509 AddCompare(compare); 1510 return compare; 1511 } 1512 1513 template<class Condition> 1514 Condition* IfNot(HValue* p) { 1515 Condition* compare = If<Condition>(p); 1516 compare->Not(); 1517 return compare; 1518 } 1519 1520 template<class Condition, class P2> 1521 Condition* IfNot(HValue* p1, P2 p2) { 1522 Condition* compare = If<Condition>(p1, p2); 1523 compare->Not(); 1524 return compare; 1525 } 1526 1527 template<class Condition, class P2, class P3> 1528 Condition* IfNot(HValue* p1, P2 p2, P3 p3) { 1529 Condition* compare = If<Condition>(p1, p2, p3); 1530 compare->Not(); 1531 return compare; 1532 } 1533 1534 template<class Condition> 1535 Condition* OrIf(HValue *p) { 1536 Or(); 1537 return If<Condition>(p); 1538 } 1539 1540 template<class Condition, class P2> 1541 Condition* OrIf(HValue* p1, P2 p2) { 1542 Or(); 1543 return If<Condition>(p1, p2); 1544 } 1545 1546 template<class Condition, class P2, class P3> 1547 Condition* OrIf(HValue* p1, P2 p2, P3 p3) { 1548 Or(); 1549 return If<Condition>(p1, p2, p3); 1550 } 1551 1552 template<class Condition> 1553 Condition* AndIf(HValue *p) { 1554 And(); 1555 return If<Condition>(p); 1556 } 1557 1558 template<class Condition, class P2> 1559 Condition* AndIf(HValue* p1, P2 p2) { 1560 And(); 1561 return If<Condition>(p1, p2); 1562 } 1563 1564 template<class Condition, class P2, class P3> 1565 Condition* AndIf(HValue* p1, P2 p2, P3 p3) { 1566 And(); 1567 return If<Condition>(p1, p2, p3); 1568 } 1569 1570 void Or(); 1571 void And(); 1572 1573 // Captures the current state of this IfBuilder in the specified 1574 // continuation and ends this IfBuilder. 1575 void CaptureContinuation(HIfContinuation* continuation); 1576 1577 // Joins the specified continuation from this IfBuilder and ends this 1578 // IfBuilder. This appends a Goto instruction from the true branch of 1579 // this IfBuilder to the true branch of the continuation unless the 1580 // true branch of this IfBuilder is already finished. And vice versa 1581 // for the false branch. 1582 // 1583 // The basic idea is as follows: You have several nested IfBuilder's 1584 // that you want to join based on two possible outcomes (i.e. success 1585 // and failure, or whatever). You can do this easily using this method 1586 // now, for example: 1587 // 1588 // HIfContinuation cont(graph()->CreateBasicBlock(), 1589 // graph()->CreateBasicBlock()); 1590 // ... 1591 // IfBuilder if_whatever(this); 1592 // if_whatever.If<Condition>(arg); 1593 // if_whatever.Then(); 1594 // ... 1595 // if_whatever.Else(); 1596 // ... 1597 // if_whatever.JoinContinuation(&cont); 1598 // ... 1599 // IfBuilder if_something(this); 1600 // if_something.If<Condition>(arg1, arg2); 1601 // if_something.Then(); 1602 // ... 1603 // if_something.Else(); 1604 // ... 1605 // if_something.JoinContinuation(&cont); 1606 // ... 1607 // IfBuilder if_finally(this, &cont); 1608 // if_finally.Then(); 1609 // // continues after then code of if_whatever or if_something. 1610 // ... 1611 // if_finally.Else(); 1612 // // continues after else code of if_whatever or if_something. 1613 // ... 1614 // if_finally.End(); 1615 void JoinContinuation(HIfContinuation* continuation); 1616 1617 void Then(); 1618 void Else(); 1619 void End(); 1620 1621 void Deopt(const char* reason); 1622 void ThenDeopt(const char* reason) { 1623 Then(); 1624 Deopt(reason); 1625 } 1626 void ElseDeopt(const char* reason) { 1627 Else(); 1628 Deopt(reason); 1629 } 1630 1631 void Return(HValue* value); 1632 1633 private: 1634 void InitializeDontCreateBlocks(HGraphBuilder* builder); 1635 1636 HControlInstruction* AddCompare(HControlInstruction* compare); 1637 1638 HGraphBuilder* builder() const { 1639 DCHECK(builder_ != NULL); // Have you called "Initialize"? 1640 return builder_; 1641 } 1642 1643 void AddMergeAtJoinBlock(bool deopt); 1644 1645 void Finish(); 1646 void Finish(HBasicBlock** then_continuation, 1647 HBasicBlock** else_continuation); 1648 1649 class MergeAtJoinBlock : public ZoneObject { 1650 public: 1651 MergeAtJoinBlock(HBasicBlock* block, 1652 bool deopt, 1653 MergeAtJoinBlock* next) 1654 : block_(block), 1655 deopt_(deopt), 1656 next_(next) {} 1657 HBasicBlock* block_; 1658 bool deopt_; 1659 MergeAtJoinBlock* next_; 1660 }; 1661 1662 HGraphBuilder* builder_; 1663 bool finished_ : 1; 1664 bool did_then_ : 1; 1665 bool did_else_ : 1; 1666 bool did_else_if_ : 1; 1667 bool did_and_ : 1; 1668 bool did_or_ : 1; 1669 bool captured_ : 1; 1670 bool needs_compare_ : 1; 1671 bool pending_merge_block_ : 1; 1672 HBasicBlock* first_true_block_; 1673 HBasicBlock* first_false_block_; 1674 HBasicBlock* split_edge_merge_block_; 1675 MergeAtJoinBlock* merge_at_join_blocks_; 1676 int normal_merge_at_join_block_count_; 1677 int deopt_merge_at_join_block_count_; 1678 }; 1679 1680 class LoopBuilder FINAL { 1681 public: 1682 enum Direction { 1683 kPreIncrement, 1684 kPostIncrement, 1685 kPreDecrement, 1686 kPostDecrement, 1687 kWhileTrue 1688 }; 1689 1690 explicit LoopBuilder(HGraphBuilder* builder); // while (true) {...} 1691 LoopBuilder(HGraphBuilder* builder, 1692 HValue* context, 1693 Direction direction); 1694 LoopBuilder(HGraphBuilder* builder, 1695 HValue* context, 1696 Direction direction, 1697 HValue* increment_amount); 1698 1699 ~LoopBuilder() { 1700 DCHECK(finished_); 1701 } 1702 1703 HValue* BeginBody( 1704 HValue* initial, 1705 HValue* terminating, 1706 Token::Value token); 1707 1708 void BeginBody(int drop_count); 1709 1710 void Break(); 1711 1712 void EndBody(); 1713 1714 private: 1715 void Initialize(HGraphBuilder* builder, HValue* context, 1716 Direction direction, HValue* increment_amount); 1717 Zone* zone() { return builder_->zone(); } 1718 1719 HGraphBuilder* builder_; 1720 HValue* context_; 1721 HValue* increment_amount_; 1722 HInstruction* increment_; 1723 HPhi* phi_; 1724 HBasicBlock* header_block_; 1725 HBasicBlock* body_block_; 1726 HBasicBlock* exit_block_; 1727 HBasicBlock* exit_trampoline_block_; 1728 Direction direction_; 1729 bool finished_; 1730 }; 1731 1732 HValue* BuildNewElementsCapacity(HValue* old_capacity); 1733 1734 class JSArrayBuilder FINAL { 1735 public: 1736 JSArrayBuilder(HGraphBuilder* builder, 1737 ElementsKind kind, 1738 HValue* allocation_site_payload, 1739 HValue* constructor_function, 1740 AllocationSiteOverrideMode override_mode); 1741 1742 JSArrayBuilder(HGraphBuilder* builder, 1743 ElementsKind kind, 1744 HValue* constructor_function = NULL); 1745 1746 enum FillMode { 1747 DONT_FILL_WITH_HOLE, 1748 FILL_WITH_HOLE 1749 }; 1750 1751 ElementsKind kind() { return kind_; } 1752 HAllocate* elements_location() { return elements_location_; } 1753 1754 HAllocate* AllocateEmptyArray(); 1755 HAllocate* AllocateArray(HValue* capacity, 1756 HValue* length_field, 1757 FillMode fill_mode = FILL_WITH_HOLE); 1758 // Use these allocators when capacity could be unknown at compile time 1759 // but its limit is known. For constant |capacity| the value of 1760 // |capacity_upper_bound| is ignored and the actual |capacity| 1761 // value is used as an upper bound. 1762 HAllocate* AllocateArray(HValue* capacity, 1763 int capacity_upper_bound, 1764 HValue* length_field, 1765 FillMode fill_mode = FILL_WITH_HOLE); 1766 HAllocate* AllocateArray(HValue* capacity, 1767 HConstant* capacity_upper_bound, 1768 HValue* length_field, 1769 FillMode fill_mode = FILL_WITH_HOLE); 1770 HValue* GetElementsLocation() { return elements_location_; } 1771 HValue* EmitMapCode(); 1772 1773 private: 1774 Zone* zone() const { return builder_->zone(); } 1775 int elements_size() const { 1776 return IsFastDoubleElementsKind(kind_) ? kDoubleSize : kPointerSize; 1777 } 1778 HGraphBuilder* builder() { return builder_; } 1779 HGraph* graph() { return builder_->graph(); } 1780 int initial_capacity() { 1781 STATIC_ASSERT(JSArray::kPreallocatedArrayElements > 0); 1782 return JSArray::kPreallocatedArrayElements; 1783 } 1784 1785 HValue* EmitInternalMapCode(); 1786 1787 HGraphBuilder* builder_; 1788 ElementsKind kind_; 1789 AllocationSiteMode mode_; 1790 HValue* allocation_site_payload_; 1791 HValue* constructor_function_; 1792 HAllocate* elements_location_; 1793 }; 1794 1795 HValue* BuildAllocateArrayFromLength(JSArrayBuilder* array_builder, 1796 HValue* length_argument); 1797 HValue* BuildCalculateElementsSize(ElementsKind kind, 1798 HValue* capacity); 1799 HAllocate* AllocateJSArrayObject(AllocationSiteMode mode); 1800 HConstant* EstablishElementsAllocationSize(ElementsKind kind, int capacity); 1801 1802 HAllocate* BuildAllocateElements(ElementsKind kind, HValue* size_in_bytes); 1803 1804 void BuildInitializeElementsHeader(HValue* elements, 1805 ElementsKind kind, 1806 HValue* capacity); 1807 1808 HValue* BuildAllocateElementsAndInitializeElementsHeader(ElementsKind kind, 1809 HValue* capacity); 1810 1811 // |array| must have been allocated with enough room for 1812 // 1) the JSArray and 2) an AllocationMemento if mode requires it. 1813 // If the |elements| value provided is NULL then the array elements storage 1814 // is initialized with empty array. 1815 void BuildJSArrayHeader(HValue* array, 1816 HValue* array_map, 1817 HValue* elements, 1818 AllocationSiteMode mode, 1819 ElementsKind elements_kind, 1820 HValue* allocation_site_payload, 1821 HValue* length_field); 1822 1823 HValue* BuildGrowElementsCapacity(HValue* object, 1824 HValue* elements, 1825 ElementsKind kind, 1826 ElementsKind new_kind, 1827 HValue* length, 1828 HValue* new_capacity); 1829 1830 void BuildFillElementsWithValue(HValue* elements, 1831 ElementsKind elements_kind, 1832 HValue* from, 1833 HValue* to, 1834 HValue* value); 1835 1836 void BuildFillElementsWithHole(HValue* elements, 1837 ElementsKind elements_kind, 1838 HValue* from, 1839 HValue* to); 1840 1841 void BuildCopyElements(HValue* from_elements, 1842 ElementsKind from_elements_kind, 1843 HValue* to_elements, 1844 ElementsKind to_elements_kind, 1845 HValue* length, 1846 HValue* capacity); 1847 1848 HValue* BuildCloneShallowArrayCow(HValue* boilerplate, 1849 HValue* allocation_site, 1850 AllocationSiteMode mode, 1851 ElementsKind kind); 1852 1853 HValue* BuildCloneShallowArrayEmpty(HValue* boilerplate, 1854 HValue* allocation_site, 1855 AllocationSiteMode mode); 1856 1857 HValue* BuildCloneShallowArrayNonEmpty(HValue* boilerplate, 1858 HValue* allocation_site, 1859 AllocationSiteMode mode, 1860 ElementsKind kind); 1861 1862 HValue* BuildElementIndexHash(HValue* index); 1863 1864 void BuildCompareNil( 1865 HValue* value, 1866 Type* type, 1867 HIfContinuation* continuation); 1868 1869 void BuildCreateAllocationMemento(HValue* previous_object, 1870 HValue* previous_object_size, 1871 HValue* payload); 1872 1873 HInstruction* BuildConstantMapCheck(Handle<JSObject> constant); 1874 HInstruction* BuildCheckPrototypeMaps(Handle<JSObject> prototype, 1875 Handle<JSObject> holder); 1876 1877 HInstruction* BuildGetNativeContext(HValue* closure); 1878 HInstruction* BuildGetNativeContext(); 1879 HInstruction* BuildGetArrayFunction(); 1880 1881 protected: 1882 void SetSourcePosition(int position) { 1883 DCHECK(position != RelocInfo::kNoPosition); 1884 position_.set_position(position - start_position_); 1885 } 1886 1887 void EnterInlinedSource(int start_position, int id) { 1888 if (FLAG_hydrogen_track_positions) { 1889 start_position_ = start_position; 1890 position_.set_inlining_id(id); 1891 } 1892 } 1893 1894 // Convert the given absolute offset from the start of the script to 1895 // the HSourcePosition assuming that this position corresponds to the 1896 // same function as current position_. 1897 HSourcePosition ScriptPositionToSourcePosition(int position) { 1898 HSourcePosition pos = position_; 1899 pos.set_position(position - start_position_); 1900 return pos; 1901 } 1902 1903 HSourcePosition source_position() { return position_; } 1904 void set_source_position(HSourcePosition position) { 1905 position_ = position; 1906 } 1907 1908 template <typename ViewClass> 1909 void BuildArrayBufferViewInitialization(HValue* obj, 1910 HValue* buffer, 1911 HValue* byte_offset, 1912 HValue* byte_length); 1913 1914 private: 1915 HGraphBuilder(); 1916 1917 template <class I> 1918 I* AddInstructionTyped(I* instr) { 1919 return I::cast(AddInstruction(instr)); 1920 } 1921 1922 CompilationInfo* info_; 1923 HGraph* graph_; 1924 HBasicBlock* current_block_; 1925 Scope* scope_; 1926 HSourcePosition position_; 1927 int start_position_; 1928 }; 1929 1930 1931 template<> 1932 inline HDeoptimize* HGraphBuilder::Add<HDeoptimize>( 1933 const char* reason, Deoptimizer::BailoutType type) { 1934 if (type == Deoptimizer::SOFT) { 1935 isolate()->counters()->soft_deopts_requested()->Increment(); 1936 if (FLAG_always_opt) return NULL; 1937 } 1938 if (current_block()->IsDeoptimizing()) return NULL; 1939 HBasicBlock* after_deopt_block = CreateBasicBlock( 1940 current_block()->last_environment()); 1941 HDeoptimize* instr = New<HDeoptimize>(reason, type, after_deopt_block); 1942 if (type == Deoptimizer::SOFT) { 1943 isolate()->counters()->soft_deopts_inserted()->Increment(); 1944 } 1945 FinishCurrentBlock(instr); 1946 set_current_block(after_deopt_block); 1947 return instr; 1948 } 1949 1950 1951 template<> 1952 inline HInstruction* HGraphBuilder::AddUncasted<HDeoptimize>( 1953 const char* reason, Deoptimizer::BailoutType type) { 1954 return Add<HDeoptimize>(reason, type); 1955 } 1956 1957 1958 template<> 1959 inline HSimulate* HGraphBuilder::Add<HSimulate>( 1960 BailoutId id, 1961 RemovableSimulate removable) { 1962 HSimulate* instr = current_block()->CreateSimulate(id, removable); 1963 AddInstruction(instr); 1964 return instr; 1965 } 1966 1967 1968 template<> 1969 inline HSimulate* HGraphBuilder::Add<HSimulate>( 1970 BailoutId id) { 1971 return Add<HSimulate>(id, FIXED_SIMULATE); 1972 } 1973 1974 1975 template<> 1976 inline HInstruction* HGraphBuilder::AddUncasted<HSimulate>(BailoutId id) { 1977 return Add<HSimulate>(id, FIXED_SIMULATE); 1978 } 1979 1980 1981 template<> 1982 inline HReturn* HGraphBuilder::Add<HReturn>(HValue* value) { 1983 int num_parameters = graph()->info()->num_parameters(); 1984 HValue* params = AddUncasted<HConstant>(num_parameters); 1985 HReturn* return_instruction = New<HReturn>(value, params); 1986 FinishExitCurrentBlock(return_instruction); 1987 return return_instruction; 1988 } 1989 1990 1991 template<> 1992 inline HReturn* HGraphBuilder::Add<HReturn>(HConstant* value) { 1993 return Add<HReturn>(static_cast<HValue*>(value)); 1994 } 1995 1996 template<> 1997 inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HValue* value) { 1998 return Add<HReturn>(value); 1999 } 2000 2001 2002 template<> 2003 inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HConstant* value) { 2004 return Add<HReturn>(value); 2005 } 2006 2007 2008 template<> 2009 inline HCallRuntime* HGraphBuilder::Add<HCallRuntime>( 2010 Handle<String> name, 2011 const Runtime::Function* c_function, 2012 int argument_count) { 2013 HCallRuntime* instr = New<HCallRuntime>(name, c_function, argument_count); 2014 if (graph()->info()->IsStub()) { 2015 // When compiling code stubs, we don't want to save all double registers 2016 // upon entry to the stub, but instead have the call runtime instruction 2017 // save the double registers only on-demand (in the fallback case). 2018 instr->set_save_doubles(kSaveFPRegs); 2019 } 2020 AddInstruction(instr); 2021 return instr; 2022 } 2023 2024 2025 template<> 2026 inline HInstruction* HGraphBuilder::AddUncasted<HCallRuntime>( 2027 Handle<String> name, 2028 const Runtime::Function* c_function, 2029 int argument_count) { 2030 return Add<HCallRuntime>(name, c_function, argument_count); 2031 } 2032 2033 2034 template<> 2035 inline HContext* HGraphBuilder::New<HContext>() { 2036 return HContext::New(zone()); 2037 } 2038 2039 2040 template<> 2041 inline HInstruction* HGraphBuilder::NewUncasted<HContext>() { 2042 return New<HContext>(); 2043 } 2044 2045 class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { 2046 public: 2047 // A class encapsulating (lazily-allocated) break and continue blocks for 2048 // a breakable statement. Separated from BreakAndContinueScope so that it 2049 // can have a separate lifetime. 2050 class BreakAndContinueInfo FINAL BASE_EMBEDDED { 2051 public: 2052 explicit BreakAndContinueInfo(BreakableStatement* target, 2053 Scope* scope, 2054 int drop_extra = 0) 2055 : target_(target), 2056 break_block_(NULL), 2057 continue_block_(NULL), 2058 scope_(scope), 2059 drop_extra_(drop_extra) { 2060 } 2061 2062 BreakableStatement* target() { return target_; } 2063 HBasicBlock* break_block() { return break_block_; } 2064 void set_break_block(HBasicBlock* block) { break_block_ = block; } 2065 HBasicBlock* continue_block() { return continue_block_; } 2066 void set_continue_block(HBasicBlock* block) { continue_block_ = block; } 2067 Scope* scope() { return scope_; } 2068 int drop_extra() { return drop_extra_; } 2069 2070 private: 2071 BreakableStatement* target_; 2072 HBasicBlock* break_block_; 2073 HBasicBlock* continue_block_; 2074 Scope* scope_; 2075 int drop_extra_; 2076 }; 2077 2078 // A helper class to maintain a stack of current BreakAndContinueInfo 2079 // structures mirroring BreakableStatement nesting. 2080 class BreakAndContinueScope FINAL BASE_EMBEDDED { 2081 public: 2082 BreakAndContinueScope(BreakAndContinueInfo* info, 2083 HOptimizedGraphBuilder* owner) 2084 : info_(info), owner_(owner), next_(owner->break_scope()) { 2085 owner->set_break_scope(this); 2086 } 2087 2088 ~BreakAndContinueScope() { owner_->set_break_scope(next_); } 2089 2090 BreakAndContinueInfo* info() { return info_; } 2091 HOptimizedGraphBuilder* owner() { return owner_; } 2092 BreakAndContinueScope* next() { return next_; } 2093 2094 // Search the break stack for a break or continue target. 2095 enum BreakType { BREAK, CONTINUE }; 2096 HBasicBlock* Get(BreakableStatement* stmt, BreakType type, 2097 Scope** scope, int* drop_extra); 2098 2099 private: 2100 BreakAndContinueInfo* info_; 2101 HOptimizedGraphBuilder* owner_; 2102 BreakAndContinueScope* next_; 2103 }; 2104 2105 explicit HOptimizedGraphBuilder(CompilationInfo* info); 2106 2107 virtual bool BuildGraph() OVERRIDE; 2108 2109 // Simple accessors. 2110 BreakAndContinueScope* break_scope() const { return break_scope_; } 2111 void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; } 2112 2113 HValue* context() { return environment()->context(); } 2114 2115 HOsrBuilder* osr() const { return osr_; } 2116 2117 void Bailout(BailoutReason reason); 2118 2119 HBasicBlock* CreateJoin(HBasicBlock* first, 2120 HBasicBlock* second, 2121 BailoutId join_id); 2122 2123 FunctionState* function_state() const { return function_state_; } 2124 2125 void VisitDeclarations(ZoneList<Declaration*>* declarations); 2126 2127 void* operator new(size_t size, Zone* zone) { 2128 return zone->New(static_cast<int>(size)); 2129 } 2130 void operator delete(void* pointer, Zone* zone) { } 2131 void operator delete(void* pointer) { } 2132 2133 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); 2134 2135 protected: 2136 // Type of a member function that generates inline code for a native function. 2137 typedef void (HOptimizedGraphBuilder::*InlineFunctionGenerator) 2138 (CallRuntime* call); 2139 2140 // Forward declarations for inner scope classes. 2141 class SubgraphScope; 2142 2143 static const InlineFunctionGenerator kInlineFunctionGenerators[]; 2144 2145 static const int kMaxCallPolymorphism = 4; 2146 static const int kMaxLoadPolymorphism = 4; 2147 static const int kMaxStorePolymorphism = 4; 2148 2149 // Even in the 'unlimited' case we have to have some limit in order not to 2150 // overflow the stack. 2151 static const int kUnlimitedMaxInlinedSourceSize = 100000; 2152 static const int kUnlimitedMaxInlinedNodes = 10000; 2153 static const int kUnlimitedMaxInlinedNodesCumulative = 10000; 2154 2155 // Maximum depth and total number of elements and properties for literal 2156 // graphs to be considered for fast deep-copying. 2157 static const int kMaxFastLiteralDepth = 3; 2158 static const int kMaxFastLiteralProperties = 8; 2159 2160 // Simple accessors. 2161 void set_function_state(FunctionState* state) { function_state_ = state; } 2162 2163 AstContext* ast_context() const { return ast_context_; } 2164 void set_ast_context(AstContext* context) { ast_context_ = context; } 2165 2166 // Accessors forwarded to the function state. 2167 CompilationInfo* current_info() const { 2168 return function_state()->compilation_info(); 2169 } 2170 AstContext* call_context() const { 2171 return function_state()->call_context(); 2172 } 2173 HBasicBlock* function_return() const { 2174 return function_state()->function_return(); 2175 } 2176 TestContext* inlined_test_context() const { 2177 return function_state()->test_context(); 2178 } 2179 void ClearInlinedTestContext() { 2180 function_state()->ClearInlinedTestContext(); 2181 } 2182 StrictMode function_strict_mode() { 2183 return function_state()->compilation_info()->strict_mode(); 2184 } 2185 2186 // Generators for inline runtime functions. 2187 #define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize) \ 2188 void Generate##Name(CallRuntime* call); 2189 2190 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION) 2191 INLINE_OPTIMIZED_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION) 2192 #undef INLINE_FUNCTION_GENERATOR_DECLARATION 2193 2194 void VisitDelete(UnaryOperation* expr); 2195 void VisitVoid(UnaryOperation* expr); 2196 void VisitTypeof(UnaryOperation* expr); 2197 void VisitNot(UnaryOperation* expr); 2198 2199 void VisitComma(BinaryOperation* expr); 2200 void VisitLogicalExpression(BinaryOperation* expr); 2201 void VisitArithmeticExpression(BinaryOperation* expr); 2202 2203 bool PreProcessOsrEntry(IterationStatement* statement); 2204 void VisitLoopBody(IterationStatement* stmt, 2205 HBasicBlock* loop_entry); 2206 2207 // Create a back edge in the flow graph. body_exit is the predecessor 2208 // block and loop_entry is the successor block. loop_successor is the 2209 // block where control flow exits the loop normally (e.g., via failure of 2210 // the condition) and break_block is the block where control flow breaks 2211 // from the loop. All blocks except loop_entry can be NULL. The return 2212 // value is the new successor block which is the join of loop_successor 2213 // and break_block, or NULL. 2214 HBasicBlock* CreateLoop(IterationStatement* statement, 2215 HBasicBlock* loop_entry, 2216 HBasicBlock* body_exit, 2217 HBasicBlock* loop_successor, 2218 HBasicBlock* break_block); 2219 2220 // Build a loop entry 2221 HBasicBlock* BuildLoopEntry(); 2222 2223 // Builds a loop entry respectful of OSR requirements 2224 HBasicBlock* BuildLoopEntry(IterationStatement* statement); 2225 2226 HBasicBlock* JoinContinue(IterationStatement* statement, 2227 HBasicBlock* exit_block, 2228 HBasicBlock* continue_block); 2229 2230 HValue* Top() const { return environment()->Top(); } 2231 void Drop(int n) { environment()->Drop(n); } 2232 void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); } 2233 bool IsEligibleForEnvironmentLivenessAnalysis(Variable* var, 2234 int index, 2235 HValue* value, 2236 HEnvironment* env) { 2237 if (!FLAG_analyze_environment_liveness) return false; 2238 // |this| and |arguments| are always live; zapping parameters isn't 2239 // safe because function.arguments can inspect them at any time. 2240 return !var->is_this() && 2241 !var->is_arguments() && 2242 !value->IsArgumentsObject() && 2243 env->is_local_index(index); 2244 } 2245 void BindIfLive(Variable* var, HValue* value) { 2246 HEnvironment* env = environment(); 2247 int index = env->IndexFor(var); 2248 env->Bind(index, value); 2249 if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) { 2250 HEnvironmentMarker* bind = 2251 Add<HEnvironmentMarker>(HEnvironmentMarker::BIND, index); 2252 USE(bind); 2253 #ifdef DEBUG 2254 bind->set_closure(env->closure()); 2255 #endif 2256 } 2257 } 2258 2259 HValue* LookupAndMakeLive(Variable* var) { 2260 HEnvironment* env = environment(); 2261 int index = env->IndexFor(var); 2262 HValue* value = env->Lookup(index); 2263 if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) { 2264 HEnvironmentMarker* lookup = 2265 Add<HEnvironmentMarker>(HEnvironmentMarker::LOOKUP, index); 2266 USE(lookup); 2267 #ifdef DEBUG 2268 lookup->set_closure(env->closure()); 2269 #endif 2270 } 2271 return value; 2272 } 2273 2274 // The value of the arguments object is allowed in some but not most value 2275 // contexts. (It's allowed in all effect contexts and disallowed in all 2276 // test contexts.) 2277 void VisitForValue(Expression* expr, 2278 ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED); 2279 void VisitForTypeOf(Expression* expr); 2280 void VisitForEffect(Expression* expr); 2281 void VisitForControl(Expression* expr, 2282 HBasicBlock* true_block, 2283 HBasicBlock* false_block); 2284 2285 // Visit a list of expressions from left to right, each in a value context. 2286 void VisitExpressions(ZoneList<Expression*>* exprs); 2287 2288 // Remove the arguments from the bailout environment and emit instructions 2289 // to push them as outgoing parameters. 2290 template <class Instruction> HInstruction* PreProcessCall(Instruction* call); 2291 void PushArgumentsFromEnvironment(int count); 2292 2293 void SetUpScope(Scope* scope); 2294 virtual void VisitStatements(ZoneList<Statement*>* statements) OVERRIDE; 2295 2296 #define DECLARE_VISIT(type) virtual void Visit##type(type* node) OVERRIDE; 2297 AST_NODE_LIST(DECLARE_VISIT) 2298 #undef DECLARE_VISIT 2299 2300 Type* ToType(Handle<Map> map); 2301 2302 private: 2303 // Helpers for flow graph construction. 2304 enum GlobalPropertyAccess { 2305 kUseCell, 2306 kUseGeneric 2307 }; 2308 GlobalPropertyAccess LookupGlobalProperty(Variable* var, LookupIterator* it, 2309 PropertyAccessType access_type); 2310 2311 void EnsureArgumentsArePushedForAccess(); 2312 bool TryArgumentsAccess(Property* expr); 2313 2314 // Try to optimize fun.apply(receiver, arguments) pattern. 2315 bool TryCallApply(Call* expr); 2316 2317 bool TryHandleArrayCall(Call* expr, HValue* function); 2318 bool TryHandleArrayCallNew(CallNew* expr, HValue* function); 2319 void BuildArrayCall(Expression* expr, int arguments_count, HValue* function, 2320 Handle<AllocationSite> cell); 2321 2322 enum ArrayIndexOfMode { kFirstIndexOf, kLastIndexOf }; 2323 HValue* BuildArrayIndexOf(HValue* receiver, 2324 HValue* search_element, 2325 ElementsKind kind, 2326 ArrayIndexOfMode mode); 2327 2328 HValue* ImplicitReceiverFor(HValue* function, 2329 Handle<JSFunction> target); 2330 2331 int InliningAstSize(Handle<JSFunction> target); 2332 bool TryInline(Handle<JSFunction> target, 2333 int arguments_count, 2334 HValue* implicit_return_value, 2335 BailoutId ast_id, 2336 BailoutId return_id, 2337 InliningKind inlining_kind, 2338 HSourcePosition position); 2339 2340 bool TryInlineCall(Call* expr); 2341 bool TryInlineConstruct(CallNew* expr, HValue* implicit_return_value); 2342 bool TryInlineGetter(Handle<JSFunction> getter, 2343 Handle<Map> receiver_map, 2344 BailoutId ast_id, 2345 BailoutId return_id); 2346 bool TryInlineSetter(Handle<JSFunction> setter, 2347 Handle<Map> receiver_map, 2348 BailoutId id, 2349 BailoutId assignment_id, 2350 HValue* implicit_return_value); 2351 bool TryInlineApply(Handle<JSFunction> function, 2352 Call* expr, 2353 int arguments_count); 2354 bool TryInlineBuiltinMethodCall(Call* expr, 2355 HValue* receiver, 2356 Handle<Map> receiver_map); 2357 bool TryInlineBuiltinFunctionCall(Call* expr); 2358 enum ApiCallType { 2359 kCallApiFunction, 2360 kCallApiMethod, 2361 kCallApiGetter, 2362 kCallApiSetter 2363 }; 2364 bool TryInlineApiMethodCall(Call* expr, 2365 HValue* receiver, 2366 SmallMapList* receiver_types); 2367 bool TryInlineApiFunctionCall(Call* expr, HValue* receiver); 2368 bool TryInlineApiGetter(Handle<JSFunction> function, 2369 Handle<Map> receiver_map, 2370 BailoutId ast_id); 2371 bool TryInlineApiSetter(Handle<JSFunction> function, 2372 Handle<Map> receiver_map, 2373 BailoutId ast_id); 2374 bool TryInlineApiCall(Handle<JSFunction> function, 2375 HValue* receiver, 2376 SmallMapList* receiver_maps, 2377 int argc, 2378 BailoutId ast_id, 2379 ApiCallType call_type); 2380 2381 // If --trace-inlining, print a line of the inlining trace. Inlining 2382 // succeeded if the reason string is NULL and failed if there is a 2383 // non-NULL reason string. 2384 void TraceInline(Handle<JSFunction> target, 2385 Handle<JSFunction> caller, 2386 const char* failure_reason); 2387 2388 void HandleGlobalVariableAssignment(Variable* var, 2389 HValue* value, 2390 BailoutId ast_id); 2391 2392 void HandlePropertyAssignment(Assignment* expr); 2393 void HandleCompoundAssignment(Assignment* expr); 2394 void HandlePolymorphicNamedFieldAccess(PropertyAccessType access_type, 2395 Expression* expr, 2396 BailoutId ast_id, 2397 BailoutId return_id, 2398 HValue* object, 2399 HValue* value, 2400 SmallMapList* types, 2401 Handle<String> name); 2402 2403 HValue* BuildAllocateExternalElements( 2404 ExternalArrayType array_type, 2405 bool is_zero_byte_offset, 2406 HValue* buffer, HValue* byte_offset, HValue* length); 2407 HValue* BuildAllocateFixedTypedArray( 2408 ExternalArrayType array_type, size_t element_size, 2409 ElementsKind fixed_elements_kind, 2410 HValue* byte_length, HValue* length); 2411 2412 Handle<JSFunction> array_function() { 2413 return handle(isolate()->native_context()->array_function()); 2414 } 2415 2416 bool IsCallArrayInlineable(int argument_count, Handle<AllocationSite> site); 2417 void BuildInlinedCallArray(Expression* expression, int argument_count, 2418 Handle<AllocationSite> site); 2419 2420 class PropertyAccessInfo { 2421 public: 2422 PropertyAccessInfo(HOptimizedGraphBuilder* builder, 2423 PropertyAccessType access_type, 2424 Type* type, 2425 Handle<String> name) 2426 : lookup_(builder->isolate()), 2427 builder_(builder), 2428 access_type_(access_type), 2429 type_(type), 2430 name_(name), 2431 field_type_(HType::Tagged()), 2432 access_(HObjectAccess::ForMap()) { } 2433 2434 // Checkes whether this PropertyAccessInfo can be handled as a monomorphic 2435 // load named. It additionally fills in the fields necessary to generate the 2436 // lookup code. 2437 bool CanAccessMonomorphic(); 2438 2439 // Checks whether all types behave uniform when loading name. If all maps 2440 // behave the same, a single monomorphic load instruction can be emitted, 2441 // guarded by a single map-checks instruction that whether the receiver is 2442 // an instance of any of the types. 2443 // This method skips the first type in types, assuming that this 2444 // PropertyAccessInfo is built for types->first(). 2445 bool CanAccessAsMonomorphic(SmallMapList* types); 2446 2447 Handle<Map> map(); 2448 Type* type() const { return type_; } 2449 Handle<String> name() const { return name_; } 2450 2451 bool IsJSObjectFieldAccessor() { 2452 int offset; // unused 2453 return Accessors::IsJSObjectFieldAccessor<Type>(type_, name_, &offset); 2454 } 2455 2456 bool GetJSObjectFieldAccess(HObjectAccess* access) { 2457 int offset; 2458 if (Accessors::IsJSObjectFieldAccessor<Type>(type_, name_, &offset)) { 2459 if (type_->Is(Type::String())) { 2460 DCHECK(String::Equals(isolate()->factory()->length_string(), name_)); 2461 *access = HObjectAccess::ForStringLength(); 2462 } else if (type_->Is(Type::Array())) { 2463 DCHECK(String::Equals(isolate()->factory()->length_string(), name_)); 2464 *access = HObjectAccess::ForArrayLength(map()->elements_kind()); 2465 } else { 2466 *access = HObjectAccess::ForMapAndOffset(map(), offset); 2467 } 2468 return true; 2469 } 2470 return false; 2471 } 2472 2473 bool has_holder() { return !holder_.is_null(); } 2474 bool IsLoad() const { return access_type_ == LOAD; } 2475 2476 Handle<JSObject> holder() { return holder_; } 2477 Handle<JSFunction> accessor() { return accessor_; } 2478 Handle<Object> constant() { return constant_; } 2479 Handle<Map> transition() { return handle(lookup_.GetTransitionTarget()); } 2480 SmallMapList* field_maps() { return &field_maps_; } 2481 HType field_type() const { return field_type_; } 2482 HObjectAccess access() { return access_; } 2483 2484 bool IsFound() const { return lookup_.IsFound(); } 2485 bool IsProperty() const { return lookup_.IsProperty(); } 2486 bool IsField() const { return lookup_.IsField(); } 2487 bool IsConstant() const { return lookup_.IsConstant(); } 2488 bool IsAccessor() const { return lookup_.IsPropertyCallbacks(); } 2489 bool IsTransition() const { return lookup_.IsTransition(); } 2490 2491 bool IsConfigurable() const { return lookup_.IsConfigurable(); } 2492 bool IsReadOnly() const { return lookup_.IsReadOnly(); } 2493 2494 private: 2495 Handle<Object> GetAccessorsFromMap(Handle<Map> map) const { 2496 return handle(lookup_.GetValueFromMap(*map), isolate()); 2497 } 2498 Handle<Object> GetConstantFromMap(Handle<Map> map) const { 2499 return handle(lookup_.GetConstantFromMap(*map), isolate()); 2500 } 2501 Handle<HeapType> GetFieldTypeFromMap(Handle<Map> map) const { 2502 return handle(lookup_.GetFieldTypeFromMap(*map), isolate()); 2503 } 2504 Handle<Map> GetFieldOwnerFromMap(Handle<Map> map) const { 2505 return handle(lookup_.GetFieldOwnerFromMap(*map)); 2506 } 2507 int GetLocalFieldIndexFromMap(Handle<Map> map) const { 2508 return lookup_.GetLocalFieldIndexFromMap(*map); 2509 } 2510 Representation representation() const { return lookup_.representation(); } 2511 2512 Type* ToType(Handle<Map> map) { return builder_->ToType(map); } 2513 Zone* zone() { return builder_->zone(); } 2514 Isolate* isolate() const { return lookup_.isolate(); } 2515 CompilationInfo* top_info() { return builder_->top_info(); } 2516 CompilationInfo* current_info() { return builder_->current_info(); } 2517 2518 bool LoadResult(Handle<Map> map); 2519 void LoadFieldMaps(Handle<Map> map); 2520 bool LookupDescriptor(); 2521 bool LookupInPrototypes(); 2522 bool IsCompatible(PropertyAccessInfo* other); 2523 2524 void GeneralizeRepresentation(Representation r) { 2525 access_ = access_.WithRepresentation( 2526 access_.representation().generalize(r)); 2527 } 2528 2529 LookupResult lookup_; 2530 HOptimizedGraphBuilder* builder_; 2531 PropertyAccessType access_type_; 2532 Type* type_; 2533 Handle<String> name_; 2534 Handle<JSObject> holder_; 2535 Handle<JSFunction> accessor_; 2536 Handle<JSObject> api_holder_; 2537 Handle<Object> constant_; 2538 SmallMapList field_maps_; 2539 HType field_type_; 2540 HObjectAccess access_; 2541 }; 2542 2543 HInstruction* BuildMonomorphicAccess(PropertyAccessInfo* info, 2544 HValue* object, 2545 HValue* checked_object, 2546 HValue* value, 2547 BailoutId ast_id, 2548 BailoutId return_id, 2549 bool can_inline_accessor = true); 2550 2551 HInstruction* BuildNamedAccess(PropertyAccessType access, 2552 BailoutId ast_id, 2553 BailoutId reutrn_id, 2554 Expression* expr, 2555 HValue* object, 2556 Handle<String> name, 2557 HValue* value, 2558 bool is_uninitialized = false); 2559 2560 void HandlePolymorphicCallNamed(Call* expr, 2561 HValue* receiver, 2562 SmallMapList* types, 2563 Handle<String> name); 2564 void HandleLiteralCompareTypeof(CompareOperation* expr, 2565 Expression* sub_expr, 2566 Handle<String> check); 2567 void HandleLiteralCompareNil(CompareOperation* expr, 2568 Expression* sub_expr, 2569 NilValue nil); 2570 2571 enum PushBeforeSimulateBehavior { 2572 PUSH_BEFORE_SIMULATE, 2573 NO_PUSH_BEFORE_SIMULATE 2574 }; 2575 2576 HControlInstruction* BuildCompareInstruction( 2577 Token::Value op, 2578 HValue* left, 2579 HValue* right, 2580 Type* left_type, 2581 Type* right_type, 2582 Type* combined_type, 2583 HSourcePosition left_position, 2584 HSourcePosition right_position, 2585 PushBeforeSimulateBehavior push_sim_result, 2586 BailoutId bailout_id); 2587 2588 HInstruction* BuildStringCharCodeAt(HValue* string, 2589 HValue* index); 2590 2591 HValue* BuildBinaryOperation( 2592 BinaryOperation* expr, 2593 HValue* left, 2594 HValue* right, 2595 PushBeforeSimulateBehavior push_sim_result); 2596 HInstruction* BuildIncrement(bool returns_original_input, 2597 CountOperation* expr); 2598 HInstruction* BuildKeyedGeneric(PropertyAccessType access_type, 2599 Expression* expr, 2600 HValue* object, 2601 HValue* key, 2602 HValue* value); 2603 2604 HInstruction* TryBuildConsolidatedElementLoad(HValue* object, 2605 HValue* key, 2606 HValue* val, 2607 SmallMapList* maps); 2608 2609 LoadKeyedHoleMode BuildKeyedHoleMode(Handle<Map> map); 2610 2611 HInstruction* BuildMonomorphicElementAccess(HValue* object, 2612 HValue* key, 2613 HValue* val, 2614 HValue* dependency, 2615 Handle<Map> map, 2616 PropertyAccessType access_type, 2617 KeyedAccessStoreMode store_mode); 2618 2619 HValue* HandlePolymorphicElementAccess(Expression* expr, 2620 HValue* object, 2621 HValue* key, 2622 HValue* val, 2623 SmallMapList* maps, 2624 PropertyAccessType access_type, 2625 KeyedAccessStoreMode store_mode, 2626 bool* has_side_effects); 2627 2628 HValue* HandleKeyedElementAccess(HValue* obj, HValue* key, HValue* val, 2629 Expression* expr, BailoutId ast_id, 2630 BailoutId return_id, 2631 PropertyAccessType access_type, 2632 bool* has_side_effects); 2633 2634 HInstruction* BuildNamedGeneric(PropertyAccessType access, 2635 Expression* expr, 2636 HValue* object, 2637 Handle<String> name, 2638 HValue* value, 2639 bool is_uninitialized = false); 2640 2641 HCheckMaps* AddCheckMap(HValue* object, Handle<Map> map); 2642 2643 void BuildLoad(Property* property, 2644 BailoutId ast_id); 2645 void PushLoad(Property* property, 2646 HValue* object, 2647 HValue* key); 2648 2649 void BuildStoreForEffect(Expression* expression, 2650 Property* prop, 2651 BailoutId ast_id, 2652 BailoutId return_id, 2653 HValue* object, 2654 HValue* key, 2655 HValue* value); 2656 2657 void BuildStore(Expression* expression, 2658 Property* prop, 2659 BailoutId ast_id, 2660 BailoutId return_id, 2661 bool is_uninitialized = false); 2662 2663 HInstruction* BuildLoadNamedField(PropertyAccessInfo* info, 2664 HValue* checked_object); 2665 HInstruction* BuildStoreNamedField(PropertyAccessInfo* info, 2666 HValue* checked_object, 2667 HValue* value); 2668 2669 HValue* BuildContextChainWalk(Variable* var); 2670 2671 HInstruction* BuildThisFunction(); 2672 2673 HInstruction* BuildFastLiteral(Handle<JSObject> boilerplate_object, 2674 AllocationSiteUsageContext* site_context); 2675 2676 void BuildEmitObjectHeader(Handle<JSObject> boilerplate_object, 2677 HInstruction* object); 2678 2679 void BuildInitElementsInObjectHeader(Handle<JSObject> boilerplate_object, 2680 HInstruction* object, 2681 HInstruction* object_elements); 2682 2683 void BuildEmitInObjectProperties(Handle<JSObject> boilerplate_object, 2684 HInstruction* object, 2685 AllocationSiteUsageContext* site_context, 2686 PretenureFlag pretenure_flag); 2687 2688 void BuildEmitElements(Handle<JSObject> boilerplate_object, 2689 Handle<FixedArrayBase> elements, 2690 HValue* object_elements, 2691 AllocationSiteUsageContext* site_context); 2692 2693 void BuildEmitFixedDoubleArray(Handle<FixedArrayBase> elements, 2694 ElementsKind kind, 2695 HValue* object_elements); 2696 2697 void BuildEmitFixedArray(Handle<FixedArrayBase> elements, 2698 ElementsKind kind, 2699 HValue* object_elements, 2700 AllocationSiteUsageContext* site_context); 2701 2702 void AddCheckPrototypeMaps(Handle<JSObject> holder, 2703 Handle<Map> receiver_map); 2704 2705 HInstruction* NewPlainFunctionCall(HValue* fun, 2706 int argument_count, 2707 bool pass_argument_count); 2708 2709 HInstruction* NewArgumentAdaptorCall(HValue* fun, HValue* context, 2710 int argument_count, 2711 HValue* expected_param_count); 2712 2713 HInstruction* BuildCallConstantFunction(Handle<JSFunction> target, 2714 int argument_count); 2715 2716 // The translation state of the currently-being-translated function. 2717 FunctionState* function_state_; 2718 2719 // The base of the function state stack. 2720 FunctionState initial_function_state_; 2721 2722 // Expression context of the currently visited subexpression. NULL when 2723 // visiting statements. 2724 AstContext* ast_context_; 2725 2726 // A stack of breakable statements entered. 2727 BreakAndContinueScope* break_scope_; 2728 2729 int inlined_count_; 2730 ZoneList<Handle<Object> > globals_; 2731 2732 bool inline_bailout_; 2733 2734 HOsrBuilder* osr_; 2735 2736 friend class FunctionState; // Pushes and pops the state stack. 2737 friend class AstContext; // Pushes and pops the AST context stack. 2738 friend class KeyedLoadFastElementStub; 2739 friend class HOsrBuilder; 2740 2741 DISALLOW_COPY_AND_ASSIGN(HOptimizedGraphBuilder); 2742 }; 2743 2744 2745 Zone* AstContext::zone() const { return owner_->zone(); } 2746 2747 2748 class HStatistics FINAL: public Malloced { 2749 public: 2750 HStatistics() 2751 : times_(5), 2752 names_(5), 2753 sizes_(5), 2754 total_size_(0), 2755 source_size_(0) { } 2756 2757 void Initialize(CompilationInfo* info); 2758 void Print(const char* stats_name); 2759 void SaveTiming(const char* name, base::TimeDelta time, unsigned size); 2760 2761 void IncrementFullCodeGen(base::TimeDelta full_code_gen) { 2762 full_code_gen_ += full_code_gen; 2763 } 2764 2765 void IncrementCreateGraph(base::TimeDelta delta) { create_graph_ += delta; } 2766 2767 void IncrementOptimizeGraph(base::TimeDelta delta) { 2768 optimize_graph_ += delta; 2769 } 2770 2771 void IncrementGenerateCode(base::TimeDelta delta) { generate_code_ += delta; } 2772 2773 void IncrementSubtotals(base::TimeDelta create_graph, 2774 base::TimeDelta optimize_graph, 2775 base::TimeDelta generate_code) { 2776 IncrementCreateGraph(create_graph); 2777 IncrementOptimizeGraph(optimize_graph); 2778 IncrementGenerateCode(generate_code); 2779 } 2780 2781 private: 2782 List<base::TimeDelta> times_; 2783 List<const char*> names_; 2784 List<unsigned> sizes_; 2785 base::TimeDelta create_graph_; 2786 base::TimeDelta optimize_graph_; 2787 base::TimeDelta generate_code_; 2788 unsigned total_size_; 2789 base::TimeDelta full_code_gen_; 2790 double source_size_; 2791 }; 2792 2793 2794 class HPhase : public CompilationPhase { 2795 public: 2796 HPhase(const char* name, HGraph* graph) 2797 : CompilationPhase(name, graph->info()), 2798 graph_(graph) { } 2799 ~HPhase(); 2800 2801 protected: 2802 HGraph* graph() const { return graph_; } 2803 2804 private: 2805 HGraph* graph_; 2806 2807 DISALLOW_COPY_AND_ASSIGN(HPhase); 2808 }; 2809 2810 2811 class HTracer FINAL : public Malloced { 2812 public: 2813 explicit HTracer(int isolate_id) 2814 : trace_(&string_allocator_), indent_(0) { 2815 if (FLAG_trace_hydrogen_file == NULL) { 2816 SNPrintF(filename_, 2817 "hydrogen-%d-%d.cfg", 2818 base::OS::GetCurrentProcessId(), 2819 isolate_id); 2820 } else { 2821 StrNCpy(filename_, FLAG_trace_hydrogen_file, filename_.length()); 2822 } 2823 WriteChars(filename_.start(), "", 0, false); 2824 } 2825 2826 void TraceCompilation(CompilationInfo* info); 2827 void TraceHydrogen(const char* name, HGraph* graph); 2828 void TraceLithium(const char* name, LChunk* chunk); 2829 void TraceLiveRanges(const char* name, LAllocator* allocator); 2830 2831 private: 2832 class Tag FINAL BASE_EMBEDDED { 2833 public: 2834 Tag(HTracer* tracer, const char* name) { 2835 name_ = name; 2836 tracer_ = tracer; 2837 tracer->PrintIndent(); 2838 tracer->trace_.Add("begin_%s\n", name); 2839 tracer->indent_++; 2840 } 2841 2842 ~Tag() { 2843 tracer_->indent_--; 2844 tracer_->PrintIndent(); 2845 tracer_->trace_.Add("end_%s\n", name_); 2846 DCHECK(tracer_->indent_ >= 0); 2847 tracer_->FlushToFile(); 2848 } 2849 2850 private: 2851 HTracer* tracer_; 2852 const char* name_; 2853 }; 2854 2855 void TraceLiveRange(LiveRange* range, const char* type, Zone* zone); 2856 void Trace(const char* name, HGraph* graph, LChunk* chunk); 2857 void FlushToFile(); 2858 2859 void PrintEmptyProperty(const char* name) { 2860 PrintIndent(); 2861 trace_.Add("%s\n", name); 2862 } 2863 2864 void PrintStringProperty(const char* name, const char* value) { 2865 PrintIndent(); 2866 trace_.Add("%s \"%s\"\n", name, value); 2867 } 2868 2869 void PrintLongProperty(const char* name, int64_t value) { 2870 PrintIndent(); 2871 trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000)); 2872 } 2873 2874 void PrintBlockProperty(const char* name, int block_id) { 2875 PrintIndent(); 2876 trace_.Add("%s \"B%d\"\n", name, block_id); 2877 } 2878 2879 void PrintIntProperty(const char* name, int value) { 2880 PrintIndent(); 2881 trace_.Add("%s %d\n", name, value); 2882 } 2883 2884 void PrintIndent() { 2885 for (int i = 0; i < indent_; i++) { 2886 trace_.Add(" "); 2887 } 2888 } 2889 2890 EmbeddedVector<char, 64> filename_; 2891 HeapStringAllocator string_allocator_; 2892 StringStream trace_; 2893 int indent_; 2894 }; 2895 2896 2897 class NoObservableSideEffectsScope FINAL { 2898 public: 2899 explicit NoObservableSideEffectsScope(HGraphBuilder* builder) : 2900 builder_(builder) { 2901 builder_->graph()->IncrementInNoSideEffectsScope(); 2902 } 2903 ~NoObservableSideEffectsScope() { 2904 builder_->graph()->DecrementInNoSideEffectsScope(); 2905 } 2906 2907 private: 2908 HGraphBuilder* builder_; 2909 }; 2910 2911 2912 } } // namespace v8::internal 2913 2914 #endif // V8_HYDROGEN_H_ 2915