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