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