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