OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #ifndef RUNTIME_VM_INTERMEDIATE_LANGUAGE_H_ | 5 #ifndef RUNTIME_VM_INTERMEDIATE_LANGUAGE_H_ |
6 #define RUNTIME_VM_INTERMEDIATE_LANGUAGE_H_ | 6 #define RUNTIME_VM_INTERMEDIATE_LANGUAGE_H_ |
7 | 7 |
8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
9 #include "vm/ast.h" | 9 #include "vm/ast.h" |
10 #include "vm/growable_array.h" | 10 #include "vm/growable_array.h" |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
549 #endif // !PRODUCT | 549 #endif // !PRODUCT |
550 | 550 |
551 | 551 |
552 // Represents a mapping from a range of class-ids to a method for a given | 552 // Represents a mapping from a range of class-ids to a method for a given |
553 // selector (method name). Also can contain an indication of how frequently a | 553 // selector (method name). Also can contain an indication of how frequently a |
554 // given method has been called at a call site. This information can be | 554 // given method has been called at a call site. This information can be |
555 // harvested from the inline caches (ICs). | 555 // harvested from the inline caches (ICs). |
556 struct CidRangeTarget { | 556 struct CidRangeTarget { |
557 intptr_t cid_start; | 557 intptr_t cid_start; |
558 intptr_t cid_end; | 558 intptr_t cid_end; |
559 Function* target; | 559 const Function* target; |
560 intptr_t count; | 560 intptr_t count; |
561 CidRangeTarget(intptr_t cid_start_arg, | 561 CidRangeTarget(intptr_t cid_start_arg, |
562 intptr_t cid_end_arg, | 562 intptr_t cid_end_arg, |
563 Function* target_arg, | 563 const Function* target_arg, |
564 intptr_t count_arg) | 564 intptr_t count_arg) |
565 : cid_start(cid_start_arg), | 565 : cid_start(cid_start_arg), |
566 cid_end(cid_end_arg), | 566 cid_end(cid_end_arg), |
567 target(target_arg), | 567 target(target_arg), |
568 count(count_arg) { | 568 count(count_arg) { |
569 ASSERT(target->IsZoneHandle()); | 569 ASSERT(target == NULL || target->IsZoneHandle()); |
570 } | 570 } |
571 }; | 571 }; |
572 | 572 |
573 | 573 |
574 class CallTargets : public ZoneAllocated { | 574 class CallTargets : public ZoneAllocated { |
Vyacheslav Egorov (Google)
2017/05/01 12:21:25
It feels a bit strange to use CallTargets as a "ci
erikcorry
2017/05/05 15:15:51
I tried several things here. In the end the one t
| |
575 public: | 575 public: |
576 // Creates the off-heap CallTargets object that reflects the contents | 576 // Creates the off-heap CallTargets object that reflects the contents |
577 // of the on-VM-heap IC data. Also expands the class-ids to neighbouring | 577 // of the on-VM-heap IC data. |
578 // classes that inherit the same method. | 578 static CallTargets* Create(Zone* zone, |
579 static CallTargets* Create(Zone* zone, const ICData& ic_data); | 579 const ICData& ic_data, |
580 int argument_number); | |
581 | |
582 // This variant always uses the IC data for argument 0 (the receiver) and | |
583 // also expands the class-ids to neighbouring classes that inherit the same | |
584 // method. | |
585 static CallTargets* CreateAndExpand(Zone* zone, const ICData& ic_data); | |
580 | 586 |
581 void Add(const CidRangeTarget& target) { cid_ranges_.Add(target); } | 587 void Add(const CidRangeTarget& target) { cid_ranges_.Add(target); } |
582 | 588 |
589 bool Equals(const CallTargets& other) const; | |
590 | |
591 bool HasClassId(intptr_t cid) const; | |
592 | |
583 CidRangeTarget& operator[](intptr_t index) const { | 593 CidRangeTarget& operator[](intptr_t index) const { |
584 return cid_ranges_[index]; | 594 return cid_ranges_[index]; |
585 } | 595 } |
586 | 596 |
587 CidRangeTarget At(int index) { return cid_ranges_.At(index); } | 597 CidRangeTarget At(int index) { return cid_ranges_.At(index); } |
588 | 598 |
589 intptr_t length() const { return cid_ranges_.length(); } | 599 intptr_t length() const { return cid_ranges_.length(); } |
590 | 600 |
591 void SetLength(intptr_t len) { cid_ranges_.SetLength(len); } | 601 void SetLength(intptr_t len) { cid_ranges_.SetLength(len); } |
592 | 602 |
593 bool is_empty() const { return cid_ranges_.is_empty(); } | 603 bool is_empty() const { return cid_ranges_.is_empty(); } |
594 | 604 |
595 void Sort(int compare(const CidRangeTarget* a, const CidRangeTarget* b)) { | 605 void Sort(int compare(const CidRangeTarget* a, const CidRangeTarget* b)) { |
596 cid_ranges_.Sort(compare); | 606 cid_ranges_.Sort(compare); |
597 } | 607 } |
598 | 608 |
599 intptr_t AggregateCallCount() const; | 609 intptr_t AggregateCallCount() const; |
600 | 610 |
601 bool HasSingleTarget() const; | 611 bool HasSingleTarget() const; |
602 bool HasSingleRecognizedTarget() const; | 612 bool HasSingleRecognizedTarget() const; |
603 Function& FirstTarget() const; | 613 const Function& FirstTarget() const; |
604 Function& MostPopularTarget() const; | 614 const Function& MostPopularTarget() const; |
605 bool IsMonomorphic() const; | 615 bool IsMonomorphic() const; |
606 intptr_t MonomorphicReceiverCid() const; | 616 intptr_t MonomorphicReceiverCid() const; |
617 bool AreAllChecksImmutable() const; | |
618 bool HasReceiverClassId(intptr_t cid) const; | |
619 intptr_t ComputeLowestCid() const; | |
620 intptr_t ComputeHighestCid() const; | |
621 | |
607 | 622 |
608 private: | 623 private: |
624 void MergeIntoRanges(); | |
625 static CallTargets* CreateHelper(Zone* zone, | |
626 const ICData& ic_data, | |
627 int argument_number); | |
628 | |
609 GrowableArray<CidRangeTarget> cid_ranges_; | 629 GrowableArray<CidRangeTarget> cid_ranges_; |
610 }; | 630 }; |
611 | 631 |
612 | 632 |
613 class Instruction : public ZoneAllocated { | 633 class Instruction : public ZoneAllocated { |
614 public: | 634 public: |
615 #define DECLARE_TAG(type) k##type, | 635 #define DECLARE_TAG(type) k##type, |
616 enum Tag { FOR_EACH_INSTRUCTION(DECLARE_TAG) }; | 636 enum Tag { FOR_EACH_INSTRUCTION(DECLARE_TAG) }; |
617 #undef DECLARE_TAG | 637 #undef DECLARE_TAG |
618 | 638 |
(...skipping 6965 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7584 ZoneGrowableArray<Value*>* inputs_; | 7604 ZoneGrowableArray<Value*>* inputs_; |
7585 MergedMathInstr::Kind kind_; | 7605 MergedMathInstr::Kind kind_; |
7586 DISALLOW_COPY_AND_ASSIGN(MergedMathInstr); | 7606 DISALLOW_COPY_AND_ASSIGN(MergedMathInstr); |
7587 }; | 7607 }; |
7588 | 7608 |
7589 | 7609 |
7590 class CheckClassInstr : public TemplateInstruction<1, NoThrow> { | 7610 class CheckClassInstr : public TemplateInstruction<1, NoThrow> { |
7591 public: | 7611 public: |
7592 CheckClassInstr(Value* value, | 7612 CheckClassInstr(Value* value, |
7593 intptr_t deopt_id, | 7613 intptr_t deopt_id, |
7594 const ICData& unary_checks, | 7614 const CallTargets& targets, |
7595 TokenPosition token_pos); | 7615 TokenPosition token_pos); |
7596 | 7616 |
7597 DECLARE_INSTRUCTION(CheckClass) | 7617 DECLARE_INSTRUCTION(CheckClass) |
7598 | 7618 |
7599 virtual bool ComputeCanDeoptimize() const { return true; } | 7619 virtual bool ComputeCanDeoptimize() const { return true; } |
7600 | 7620 |
7601 virtual TokenPosition token_pos() const { return token_pos_; } | 7621 virtual TokenPosition token_pos() const { return token_pos_; } |
7602 | 7622 |
7603 Value* value() const { return inputs_[0]; } | 7623 Value* value() const { return inputs_[0]; } |
7604 | 7624 |
7605 const ICData& unary_checks() const { return unary_checks_; } | 7625 const CallTargets& targets() const { return targets_; } |
7606 | |
7607 const GrowableArray<intptr_t>& cids() const { return cids_; } | |
7608 | 7626 |
7609 virtual Instruction* Canonicalize(FlowGraph* flow_graph); | 7627 virtual Instruction* Canonicalize(FlowGraph* flow_graph); |
7610 | 7628 |
7611 bool IsNullCheck() const { return DeoptIfNull() || DeoptIfNotNull(); } | 7629 bool IsNullCheck() const { return IsDeoptIfNull() || IsDeoptIfNotNull(); } |
7612 | 7630 |
7613 bool DeoptIfNull() const; | 7631 bool IsDeoptIfNull() const; |
7614 bool DeoptIfNotNull() const; | 7632 bool IsDeoptIfNotNull() const; |
7615 | 7633 |
7616 bool IsDenseSwitch() const; | 7634 bool IsDenseSwitch() const; |
7617 static bool IsDenseCidRange(const ICData& unary_checks); | 7635 static bool IsDenseCidRange(const CallTargets& targets); |
7618 intptr_t ComputeCidMask() const; | 7636 intptr_t ComputeCidMask() const; |
7619 static bool IsDenseMask(intptr_t mask); | |
7620 | 7637 |
7621 virtual bool AllowsCSE() const { return true; } | 7638 virtual bool AllowsCSE() const { return true; } |
7622 virtual EffectSet Dependencies() const; | 7639 virtual EffectSet Dependencies() const; |
7623 virtual EffectSet Effects() const { return EffectSet::None(); } | 7640 virtual EffectSet Effects() const { return EffectSet::None(); } |
7624 virtual bool AttributesEqual(Instruction* other) const; | 7641 virtual bool AttributesEqual(Instruction* other) const; |
7625 | 7642 |
7626 bool licm_hoisted() const { return licm_hoisted_; } | 7643 bool licm_hoisted() const { return licm_hoisted_; } |
7627 void set_licm_hoisted(bool value) { licm_hoisted_ = value; } | 7644 void set_licm_hoisted(bool value) { licm_hoisted_ = value; } |
7628 | 7645 |
7629 PRINT_OPERANDS_TO_SUPPORT | 7646 PRINT_OPERANDS_TO_SUPPORT |
7630 | 7647 |
7631 private: | 7648 private: |
7632 const ICData& unary_checks_; | 7649 const CallTargets& targets_; |
7633 GrowableArray<intptr_t> cids_; // Sorted, lowest first. | |
7634 bool licm_hoisted_; | 7650 bool licm_hoisted_; |
7635 bool is_dense_switch_; | 7651 bool is_dense_switch_; |
7636 const TokenPosition token_pos_; | 7652 const TokenPosition token_pos_; |
7637 | 7653 |
7654 int EmitCheckCid(FlowGraphCompiler* compiler, | |
7655 int bias, | |
7656 intptr_t cid_start, | |
7657 intptr_t cid_end, | |
7658 bool is_last, | |
7659 Label* is_ok, | |
7660 Label* deopt, | |
7661 bool use_near_jump); | |
7662 void EmitDenseSwitch(FlowGraphCompiler* compiler, | |
7663 intptr_t min, | |
7664 intptr_t max, | |
7665 intptr_t mask, | |
7666 Label* deopt); | |
7667 void EmitNullCheck(FlowGraphCompiler* compiler, Label* deopt); | |
7668 | |
7638 DISALLOW_COPY_AND_ASSIGN(CheckClassInstr); | 7669 DISALLOW_COPY_AND_ASSIGN(CheckClassInstr); |
7639 }; | 7670 }; |
7640 | 7671 |
7641 | 7672 |
7642 class CheckSmiInstr : public TemplateInstruction<1, NoThrow, Pure> { | 7673 class CheckSmiInstr : public TemplateInstruction<1, NoThrow, Pure> { |
7643 public: | 7674 public: |
7644 CheckSmiInstr(Value* value, intptr_t deopt_id, TokenPosition token_pos) | 7675 CheckSmiInstr(Value* value, intptr_t deopt_id, TokenPosition token_pos) |
7645 : TemplateInstruction(deopt_id), | 7676 : TemplateInstruction(deopt_id), |
7646 token_pos_(token_pos), | 7677 token_pos_(token_pos), |
7647 licm_hoisted_(false) { | 7678 licm_hoisted_(false) { |
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8114 LocationSummary* Name::MakeLocationSummary(Zone* zone, bool opt) const { \ | 8145 LocationSummary* Name::MakeLocationSummary(Zone* zone, bool opt) const { \ |
8115 UNIMPLEMENTED(); \ | 8146 UNIMPLEMENTED(); \ |
8116 return NULL; \ | 8147 return NULL; \ |
8117 } \ | 8148 } \ |
8118 void Name::EmitNativeCode(FlowGraphCompiler* compiler) { UNIMPLEMENTED(); } | 8149 void Name::EmitNativeCode(FlowGraphCompiler* compiler) { UNIMPLEMENTED(); } |
8119 | 8150 |
8120 | 8151 |
8121 } // namespace dart | 8152 } // namespace dart |
8122 | 8153 |
8123 #endif // RUNTIME_VM_INTERMEDIATE_LANGUAGE_H_ | 8154 #endif // RUNTIME_VM_INTERMEDIATE_LANGUAGE_H_ |
OLD | NEW |