Chromium Code Reviews| 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 |