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