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" |
11 #include "vm/locations.h" | 11 #include "vm/locations.h" |
12 #include "vm/method_recognizer.h" | 12 #include "vm/method_recognizer.h" |
13 #include "vm/object.h" | 13 #include "vm/object.h" |
14 #include "vm/parser.h" | 14 #include "vm/parser.h" |
15 #include "vm/token_position.h" | 15 #include "vm/token_position.h" |
16 | 16 |
17 namespace dart { | 17 namespace dart { |
18 | 18 |
19 class BitVector; | 19 class BitVector; |
20 class BlockEntryInstr; | 20 class BlockEntryInstr; |
21 class BoxIntegerInstr; | 21 class BoxIntegerInstr; |
22 class BufferFormatter; | 22 class BufferFormatter; |
23 class CallTargets; | |
23 class CatchBlockEntryInstr; | 24 class CatchBlockEntryInstr; |
24 class ComparisonInstr; | 25 class ComparisonInstr; |
25 class Definition; | 26 class Definition; |
26 class Environment; | 27 class Environment; |
27 class FlowGraph; | 28 class FlowGraph; |
28 class FlowGraphBuilder; | 29 class FlowGraphBuilder; |
29 class FlowGraphCompiler; | 30 class FlowGraphCompiler; |
30 class FlowGraphVisitor; | 31 class FlowGraphVisitor; |
31 class Instruction; | 32 class Instruction; |
32 class LocalVariable; | 33 class LocalVariable; |
(...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
542 #endif // !PRODUCT | 543 #endif // !PRODUCT |
543 | 544 |
544 #ifndef PRODUCT | 545 #ifndef PRODUCT |
545 #define PRINT_OPERANDS_TO_SUPPORT \ | 546 #define PRINT_OPERANDS_TO_SUPPORT \ |
546 virtual void PrintOperandsTo(BufferFormatter* f) const; | 547 virtual void PrintOperandsTo(BufferFormatter* f) const; |
547 #else | 548 #else |
548 #define PRINT_OPERANDS_TO_SUPPORT | 549 #define PRINT_OPERANDS_TO_SUPPORT |
549 #endif // !PRODUCT | 550 #endif // !PRODUCT |
550 | 551 |
551 | 552 |
552 // Represents a mapping from a range of class-ids to a method for a given | 553 // Represents a range of class-ids for use in class checks and polymorphic |
553 // selector (method name). Also can contain an indication of how frequently a | 554 // dispatches. |
554 // given method has been called at a call site. This information can be | 555 struct CidRange : public ZoneAllocated { |
555 // harvested from the inline caches (ICs). | |
556 struct CidRangeTarget { | |
557 intptr_t cid_start; | 556 intptr_t cid_start; |
558 intptr_t cid_end; | 557 intptr_t cid_end; |
559 Function* target; | 558 CidRange(const CidRange& o) |
Vyacheslav Egorov (Google)
2017/05/09 21:07:27
Please order constructors before fields.
erikcorry
2017/05/10 08:47:43
Done.
| |
560 intptr_t count; | 559 : ZoneAllocated(), cid_start(o.cid_start), cid_end(o.cid_end) {} |
561 CidRangeTarget(intptr_t cid_start_arg, | 560 CidRange(intptr_t cid_start_arg, intptr_t cid_end_arg) |
562 intptr_t cid_end_arg, | 561 : cid_start(cid_start_arg), cid_end(cid_end_arg) {} |
563 Function* target_arg, | 562 CidRange(intptr_t cid_start_arg, |
Vyacheslav Egorov (Google)
2017/05/09 21:07:27
I don't think this constructor is used.
erikcorry
2017/05/10 08:47:43
Gone
| |
564 intptr_t count_arg) | 563 intptr_t cid_end_arg, |
565 : cid_start(cid_start_arg), | 564 const Function* target_arg, |
566 cid_end(cid_end_arg), | 565 intptr_t count_arg) |
566 : cid_start(cid_start_arg), cid_end(cid_end_arg) {} | |
567 }; | |
568 | |
569 | |
570 // Together with CidRange, this represents a mapping from a range of class-ids | |
571 // to a method for a given selector (method name). Also can contain an | |
572 // indication of how frequently a given method has been called at a call site. | |
573 // This information can be harvested from the inline caches (ICs). | |
574 struct TargetInfo : public CidRange { | |
575 TargetInfo(intptr_t cid_start_arg, | |
576 intptr_t cid_end_arg, | |
577 const Function* target_arg, | |
578 intptr_t count_arg) | |
579 : CidRange(cid_start_arg, cid_end_arg), | |
567 target(target_arg), | 580 target(target_arg), |
568 count(count_arg) { | 581 count(count_arg) { |
569 ASSERT(target->IsZoneHandle()); | 582 ASSERT(target->IsZoneHandle()); |
570 } | 583 } |
584 const Function* target; | |
585 intptr_t count; | |
571 }; | 586 }; |
572 | 587 |
573 | 588 |
574 class CallTargets : public ZoneAllocated { | 589 // A set of class-ids, arranged in ranges. Used for the CheckClass |
590 // and PolymorphicInstanceCall instructions. | |
591 class Cids : public ZoneAllocated { | |
575 public: | 592 public: |
576 // Creates the off-heap CallTargets object that reflects the contents | 593 explicit Cids(Zone* zone) : zone_(zone) {} |
577 // of the on-VM-heap IC data. Also expands the class-ids to neighbouring | 594 // Creates the off-heap Cids object that reflects the contents |
578 // classes that inherit the same method. | 595 // of the on-VM-heap IC data. |
579 static CallTargets* Create(Zone* zone, const ICData& ic_data); | 596 static Cids* Create(Zone* zone, const ICData& ic_data, int argument_number); |
597 static Cids* CreateMonomorphic(Zone* zone, intptr_t cid); | |
580 | 598 |
581 void Add(const CidRangeTarget& target) { cid_ranges_.Add(target); } | 599 bool Equals(const Cids& other) const; |
582 | 600 |
583 CidRangeTarget& operator[](intptr_t index) const { | 601 bool HasClassId(intptr_t cid) const; |
584 return cid_ranges_[index]; | |
585 } | |
586 | 602 |
587 CidRangeTarget At(int index) { return cid_ranges_.At(index); } | 603 void Add(CidRange* target) { cid_ranges_.Add(target); } |
604 | |
605 CidRange& operator[](intptr_t index) const { return *cid_ranges_[index]; } | |
606 | |
607 CidRange* At(int index) const { return cid_ranges_[index]; } | |
588 | 608 |
589 intptr_t length() const { return cid_ranges_.length(); } | 609 intptr_t length() const { return cid_ranges_.length(); } |
590 | 610 |
591 void SetLength(intptr_t len) { cid_ranges_.SetLength(len); } | 611 void SetLength(intptr_t len) { cid_ranges_.SetLength(len); } |
592 | 612 |
593 bool is_empty() const { return cid_ranges_.is_empty(); } | 613 bool is_empty() const { return cid_ranges_.is_empty(); } |
594 | 614 |
595 void Sort(int compare(const CidRangeTarget* a, const CidRangeTarget* b)) { | 615 void Sort(int compare(CidRange* const* a, CidRange* const* b)) { |
596 cid_ranges_.Sort(compare); | 616 cid_ranges_.Sort(compare); |
597 } | 617 } |
598 | 618 |
619 bool IsMonomorphic() const; | |
620 intptr_t MonomorphicReceiverCid() const; | |
621 bool ContainsExternalizableCids() const; | |
622 intptr_t ComputeLowestCid() const; | |
623 intptr_t ComputeHighestCid() const; | |
624 | |
625 protected: | |
626 void CreateHelper(Zone* zone, | |
627 const ICData& ic_data, | |
628 int argument_number, | |
629 bool include_targets); | |
630 GrowableArray<CidRange*> cid_ranges_; | |
631 Zone* zone_; | |
632 | |
633 private: | |
634 DISALLOW_IMPLICIT_CONSTRUCTORS(Cids); | |
635 }; | |
636 | |
637 | |
638 class CallTargets : public Cids { | |
639 public: | |
640 explicit CallTargets(Zone* zone) : Cids(zone) {} | |
641 // Creates the off-heap CallTargets object that reflects the contents | |
642 // of the on-VM-heap IC data. | |
643 static CallTargets* Create(Zone* zone, const ICData& ic_data); | |
644 | |
645 // This variant also expands the class-ids to neighbouring classes that | |
646 // inherit the same method. | |
647 static CallTargets* CreateAndExpand(Zone* zone, const ICData& ic_data); | |
648 | |
649 TargetInfo* TargetAt(int i) const { | |
650 return reinterpret_cast<TargetInfo*>(At(i)); | |
Vyacheslav Egorov (Google)
2017/05/09 21:07:27
static_cast<TargetInfo*>(...)
erikcorry
2017/05/10 08:47:43
Done.
| |
651 } | |
652 | |
599 intptr_t AggregateCallCount() const; | 653 intptr_t AggregateCallCount() const; |
600 | 654 |
601 bool HasSingleTarget() const; | 655 bool HasSingleTarget() const; |
602 bool HasSingleRecognizedTarget() const; | 656 bool HasSingleRecognizedTarget() const; |
603 Function& FirstTarget() const; | 657 const Function& FirstTarget() const; |
604 Function& MostPopularTarget() const; | 658 const Function& MostPopularTarget() const; |
605 bool IsMonomorphic() const; | |
606 intptr_t MonomorphicReceiverCid() const; | |
607 | 659 |
608 private: | 660 private: |
609 GrowableArray<CidRangeTarget> cid_ranges_; | 661 void MergeIntoRanges(); |
610 }; | 662 }; |
611 | 663 |
612 | 664 |
613 class Instruction : public ZoneAllocated { | 665 class Instruction : public ZoneAllocated { |
614 public: | 666 public: |
615 #define DECLARE_TAG(type) k##type, | 667 #define DECLARE_TAG(type) k##type, |
616 enum Tag { FOR_EACH_INSTRUCTION(DECLARE_TAG) }; | 668 enum Tag { FOR_EACH_INSTRUCTION(DECLARE_TAG) }; |
617 #undef DECLARE_TAG | 669 #undef DECLARE_TAG |
618 | 670 |
619 explicit Instruction(intptr_t deopt_id = Thread::kNoDeoptId) | 671 explicit Instruction(intptr_t deopt_id = Thread::kNoDeoptId) |
(...skipping 6964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7584 ZoneGrowableArray<Value*>* inputs_; | 7636 ZoneGrowableArray<Value*>* inputs_; |
7585 MergedMathInstr::Kind kind_; | 7637 MergedMathInstr::Kind kind_; |
7586 DISALLOW_COPY_AND_ASSIGN(MergedMathInstr); | 7638 DISALLOW_COPY_AND_ASSIGN(MergedMathInstr); |
7587 }; | 7639 }; |
7588 | 7640 |
7589 | 7641 |
7590 class CheckClassInstr : public TemplateInstruction<1, NoThrow> { | 7642 class CheckClassInstr : public TemplateInstruction<1, NoThrow> { |
7591 public: | 7643 public: |
7592 CheckClassInstr(Value* value, | 7644 CheckClassInstr(Value* value, |
7593 intptr_t deopt_id, | 7645 intptr_t deopt_id, |
7594 const ICData& unary_checks, | 7646 const Cids& cids, |
7595 TokenPosition token_pos); | 7647 TokenPosition token_pos); |
7596 | 7648 |
7597 DECLARE_INSTRUCTION(CheckClass) | 7649 DECLARE_INSTRUCTION(CheckClass) |
7598 | 7650 |
7599 virtual bool ComputeCanDeoptimize() const { return true; } | 7651 virtual bool ComputeCanDeoptimize() const { return true; } |
7600 | 7652 |
7601 virtual TokenPosition token_pos() const { return token_pos_; } | 7653 virtual TokenPosition token_pos() const { return token_pos_; } |
7602 | 7654 |
7603 Value* value() const { return inputs_[0]; } | 7655 Value* value() const { return inputs_[0]; } |
7604 | 7656 |
7605 const ICData& unary_checks() const { return unary_checks_; } | 7657 const Cids& cids() const { return cids_; } |
7606 | |
7607 const GrowableArray<intptr_t>& cids() const { return cids_; } | |
7608 | 7658 |
7609 virtual Instruction* Canonicalize(FlowGraph* flow_graph); | 7659 virtual Instruction* Canonicalize(FlowGraph* flow_graph); |
7610 | 7660 |
7611 bool IsNullCheck() const { return DeoptIfNull() || DeoptIfNotNull(); } | 7661 bool IsNullCheck() const { return IsDeoptIfNull() || IsDeoptIfNotNull(); } |
7612 | 7662 |
7613 bool DeoptIfNull() const; | 7663 bool IsDeoptIfNull() const; |
7614 bool DeoptIfNotNull() const; | 7664 bool IsDeoptIfNotNull() const; |
7615 | 7665 |
7616 bool IsDenseSwitch() const; | 7666 bool IsBitTest() const; |
7617 static bool IsDenseCidRange(const ICData& unary_checks); | 7667 static bool IsCompactCidRange(const Cids& cids); |
7618 intptr_t ComputeCidMask() const; | 7668 intptr_t ComputeCidMask() const; |
7619 static bool IsDenseMask(intptr_t mask); | |
7620 | 7669 |
7621 virtual bool AllowsCSE() const { return true; } | 7670 virtual bool AllowsCSE() const { return true; } |
7622 virtual EffectSet Dependencies() const; | 7671 virtual EffectSet Dependencies() const; |
7623 virtual EffectSet Effects() const { return EffectSet::None(); } | 7672 virtual EffectSet Effects() const { return EffectSet::None(); } |
7624 virtual bool AttributesEqual(Instruction* other) const; | 7673 virtual bool AttributesEqual(Instruction* other) const; |
7625 | 7674 |
7626 bool licm_hoisted() const { return licm_hoisted_; } | 7675 bool licm_hoisted() const { return licm_hoisted_; } |
7627 void set_licm_hoisted(bool value) { licm_hoisted_ = value; } | 7676 void set_licm_hoisted(bool value) { licm_hoisted_ = value; } |
7628 | 7677 |
7629 PRINT_OPERANDS_TO_SUPPORT | 7678 PRINT_OPERANDS_TO_SUPPORT |
7630 | 7679 |
7631 private: | 7680 private: |
7632 const ICData& unary_checks_; | 7681 const Cids& cids_; |
7633 GrowableArray<intptr_t> cids_; // Sorted, lowest first. | |
7634 bool licm_hoisted_; | 7682 bool licm_hoisted_; |
7635 bool is_dense_switch_; | 7683 bool is_bit_test_; |
7636 const TokenPosition token_pos_; | 7684 const TokenPosition token_pos_; |
7637 | 7685 |
7686 int EmitCheckCid(FlowGraphCompiler* compiler, | |
7687 int bias, | |
7688 intptr_t cid_start, | |
7689 intptr_t cid_end, | |
7690 bool is_last, | |
7691 Label* is_ok, | |
7692 Label* deopt, | |
7693 bool use_near_jump); | |
7694 void EmitBitTest(FlowGraphCompiler* compiler, | |
7695 intptr_t min, | |
7696 intptr_t max, | |
7697 intptr_t mask, | |
7698 Label* deopt); | |
7699 void EmitNullCheck(FlowGraphCompiler* compiler, Label* deopt); | |
7700 | |
7638 DISALLOW_COPY_AND_ASSIGN(CheckClassInstr); | 7701 DISALLOW_COPY_AND_ASSIGN(CheckClassInstr); |
7639 }; | 7702 }; |
7640 | 7703 |
7641 | 7704 |
7642 class CheckSmiInstr : public TemplateInstruction<1, NoThrow, Pure> { | 7705 class CheckSmiInstr : public TemplateInstruction<1, NoThrow, Pure> { |
7643 public: | 7706 public: |
7644 CheckSmiInstr(Value* value, intptr_t deopt_id, TokenPosition token_pos) | 7707 CheckSmiInstr(Value* value, intptr_t deopt_id, TokenPosition token_pos) |
7645 : TemplateInstruction(deopt_id), | 7708 : TemplateInstruction(deopt_id), |
7646 token_pos_(token_pos), | 7709 token_pos_(token_pos), |
7647 licm_hoisted_(false) { | 7710 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 { \ | 8177 LocationSummary* Name::MakeLocationSummary(Zone* zone, bool opt) const { \ |
8115 UNIMPLEMENTED(); \ | 8178 UNIMPLEMENTED(); \ |
8116 return NULL; \ | 8179 return NULL; \ |
8117 } \ | 8180 } \ |
8118 void Name::EmitNativeCode(FlowGraphCompiler* compiler) { UNIMPLEMENTED(); } | 8181 void Name::EmitNativeCode(FlowGraphCompiler* compiler) { UNIMPLEMENTED(); } |
8119 | 8182 |
8120 | 8183 |
8121 } // namespace dart | 8184 } // namespace dart |
8122 | 8185 |
8123 #endif // RUNTIME_VM_INTERMEDIATE_LANGUAGE_H_ | 8186 #endif // RUNTIME_VM_INTERMEDIATE_LANGUAGE_H_ |
OLD | NEW |