Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(221)

Side by Side Diff: runtime/vm/object.h

Issue 1149403005: Prevent excessive deoptimization when optimistically assuming Smi in typed data stores. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: ws Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/flow_graph_optimizer.cc ('k') | runtime/vm/object.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 VM_OBJECT_H_ 5 #ifndef VM_OBJECT_H_
6 #define VM_OBJECT_H_ 6 #define VM_OBJECT_H_
7 7
8 #include "include/dart_api.h" 8 #include "include/dart_api.h"
9 #include "platform/assert.h" 9 #include "platform/assert.h"
10 #include "platform/utils.h" 10 #include "platform/utils.h"
(...skipping 1688 matching lines...) Expand 10 before | Expand all | Expand 10 after
1699 void set_patched_class(const Class& value) const; 1699 void set_patched_class(const Class& value) const;
1700 void set_source_class(const Class& value) const; 1700 void set_source_class(const Class& value) const;
1701 1701
1702 static RawPatchClass* New(); 1702 static RawPatchClass* New();
1703 1703
1704 FINAL_HEAP_OBJECT_IMPLEMENTATION(PatchClass, Object); 1704 FINAL_HEAP_OBJECT_IMPLEMENTATION(PatchClass, Object);
1705 friend class Class; 1705 friend class Class;
1706 }; 1706 };
1707 1707
1708 1708
1709 // Object holding information about an IC: test classes and their
Florian Schneider 2015/06/01 07:50:16 Is there any diff here or did you just move class
srdjan 2015/06/01 15:23:40 Done. No diffs, ICData moved ahead of class Functi
1710 // corresponding targets.
1711 class ICData : public Object {
1712 public:
1713 RawFunction* owner() const {
1714 return raw_ptr()->owner_;
1715 }
1716
1717 RawString* target_name() const {
1718 return raw_ptr()->target_name_;
1719 }
1720
1721 RawArray* arguments_descriptor() const {
1722 return raw_ptr()->args_descriptor_;
1723 }
1724
1725 intptr_t NumArgsTested() const;
1726
1727 intptr_t deopt_id() const {
1728 return raw_ptr()->deopt_id_;
1729 }
1730
1731 // Note: only deopts with reasons before Unknown in this list are recorded in
1732 // the ICData. All other reasons are used purely for informational messages
1733 // printed during deoptimization itself.
1734 #define DEOPT_REASONS(V) \
1735 V(BinarySmiOp) \
1736 V(BinaryMintOp) \
1737 V(DoubleToSmi) \
1738 V(CheckSmi) \
1739 V(Unknown) \
1740 V(PolymorphicInstanceCallTestFail) \
1741 V(UnaryMintOp) \
1742 V(BinaryDoubleOp) \
1743 V(UnaryOp) \
1744 V(UnboxInteger) \
1745 V(CheckClass) \
1746 V(CheckArrayBound) \
1747 V(AtCall) \
1748 V(Uint32Load) \
1749 V(GuardField) \
1750 V(TestCids) \
1751 V(NumReasons) \
1752
1753 enum DeoptReasonId {
1754 #define DEFINE_ENUM_LIST(name) kDeopt##name,
1755 DEOPT_REASONS(DEFINE_ENUM_LIST)
1756 #undef DEFINE_ENUM_LIST
1757 };
1758
1759 static const intptr_t kLastRecordedDeoptReason = kDeoptUnknown - 1;
1760
1761 enum DeoptFlags {
1762 // Deoptimization is caused by an optimistically hoisted instruction.
1763 kHoisted = 1 << 0,
1764
1765 // Deoptimization is caused by an optimistically generalized bounds check.
1766 kGeneralized = 1 << 1
1767 };
1768
1769 bool HasDeoptReasons() const { return DeoptReasons() != 0; }
1770 uint32_t DeoptReasons() const;
1771 void SetDeoptReasons(uint32_t reasons) const;
1772
1773 bool HasDeoptReason(ICData::DeoptReasonId reason) const;
1774 void AddDeoptReason(ICData::DeoptReasonId reason) const;
1775
1776 bool IssuedJSWarning() const;
1777 void SetIssuedJSWarning() const;
1778
1779 // Return true if the target function of this IC data may check for (and
1780 // possibly issue) a Javascript compatibility warning.
1781 bool MayCheckForJSWarning() const;
1782
1783 intptr_t NumberOfChecks() const;
1784
1785 // Discounts any checks with usage of zero.
1786 intptr_t NumberOfUsedChecks() const;
1787
1788 static intptr_t InstanceSize() {
1789 return RoundedAllocationSize(sizeof(RawICData));
1790 }
1791
1792 static intptr_t target_name_offset() {
1793 return OFFSET_OF(RawICData, target_name_);
1794 }
1795
1796 static intptr_t state_bits_offset() {
1797 return OFFSET_OF(RawICData, state_bits_);
1798 }
1799
1800 static intptr_t NumArgsTestedShift() {
1801 return kNumArgsTestedPos;
1802 }
1803
1804 static intptr_t NumArgsTestedMask() {
1805 return ((1 << kNumArgsTestedSize) - 1) << kNumArgsTestedPos;
1806 }
1807
1808 static intptr_t arguments_descriptor_offset() {
1809 return OFFSET_OF(RawICData, args_descriptor_);
1810 }
1811
1812 static intptr_t ic_data_offset() {
1813 return OFFSET_OF(RawICData, ic_data_);
1814 }
1815
1816 static intptr_t owner_offset() {
1817 return OFFSET_OF(RawICData, owner_);
1818 }
1819
1820 // Used for unoptimized static calls when no class-ids are checked.
1821 void AddTarget(const Function& target) const;
1822
1823 // Adding checks.
1824
1825 // Adds one more class test to ICData. Length of 'classes' must be equal to
1826 // the number of arguments tested. Use only for num_args_tested > 1.
1827 void AddCheck(const GrowableArray<intptr_t>& class_ids,
1828 const Function& target) const;
1829 // Adds sorted so that Smi is the first class-id. Use only for
1830 // num_args_tested == 1.
1831 void AddReceiverCheck(intptr_t receiver_class_id,
1832 const Function& target,
1833 intptr_t count = 1) const;
1834
1835 // Retrieving checks.
1836
1837 // TODO(srdjan): GetCheckAt without target.
1838 void GetCheckAt(intptr_t index,
1839 GrowableArray<intptr_t>* class_ids,
1840 Function* target) const;
1841 // Only for 'num_args_checked == 1'.
1842 void GetOneClassCheckAt(intptr_t index,
1843 intptr_t* class_id,
1844 Function* target) const;
1845 // Only for 'num_args_checked == 1'.
1846 intptr_t GetCidAt(intptr_t index) const;
1847
1848 intptr_t GetReceiverClassIdAt(intptr_t index) const;
1849 intptr_t GetClassIdAt(intptr_t index, intptr_t arg_nr) const;
1850
1851 RawFunction* GetTargetAt(intptr_t index) const;
1852 RawFunction* GetTargetForReceiverClassId(intptr_t class_id) const;
1853
1854 void IncrementCountAt(intptr_t index, intptr_t value) const;
1855 void SetCountAt(intptr_t index, intptr_t value) const;
1856 intptr_t GetCountAt(intptr_t index) const;
1857 intptr_t AggregateCount() const;
1858
1859 // Returns this->raw() if num_args_tested == 1 and arg_nr == 1, otherwise
1860 // returns a new ICData object containing only unique arg_nr checks.
1861 // Returns only used entries.
1862 RawICData* AsUnaryClassChecksForArgNr(intptr_t arg_nr) const;
1863 RawICData* AsUnaryClassChecks() const {
1864 return AsUnaryClassChecksForArgNr(0);
1865 }
1866 RawICData* AsUnaryClassChecksForCid(
1867 intptr_t cid, const Function& target) const;
1868
1869 // Consider only used entries.
1870 bool AllTargetsHaveSameOwner(intptr_t owner_cid) const;
1871 bool AllReceiversAreNumbers() const;
1872 bool HasOneTarget() const;
1873 bool HasReceiverClassId(intptr_t class_id) const;
1874
1875 static RawICData* New(const Function& owner,
1876 const String& target_name,
1877 const Array& arguments_descriptor,
1878 intptr_t deopt_id,
1879 intptr_t num_args_tested);
1880 static RawICData* NewFrom(const ICData& from, intptr_t num_args_tested);
1881
1882 static intptr_t TestEntryLengthFor(intptr_t num_args);
1883
1884 static intptr_t TargetIndexFor(intptr_t num_args) {
1885 return num_args;
1886 }
1887
1888 static intptr_t CountIndexFor(intptr_t num_args) {
1889 return (num_args + 1);
1890 }
1891
1892 bool IsUsedAt(intptr_t i) const;
1893
1894 void GetUsedCidsForTwoArgs(GrowableArray<intptr_t>* first,
1895 GrowableArray<intptr_t>* second) const;
1896
1897 // Range feedback tracking functionality.
1898
1899 // For arithmetic operations we store range information for inputs and the
1900 // result. The goal is to discover:
1901 //
1902 // - on 32-bit platforms:
1903 // - when Mint operation is actually a int32/uint32 operation;
1904 // - when Smi operation produces non-smi results;
1905 //
1906 // - on 64-bit platforms:
1907 // - when Smi operation is actually int32/uint32 operation;
1908 // - when Mint operation produces non-smi results;
1909 //
1910 enum RangeFeedback {
1911 kSmiRange,
1912 kInt32Range,
1913 kUint32Range,
1914 kInt64Range
1915 };
1916
1917 // We use 4 bits per operand/result feedback. Our lattice allows us to
1918 // express the following states:
1919 //
1920 // - usmi 0000 [used only on 32bit platforms]
1921 // - smi 0001
1922 // - uint31 0010
1923 // - int32 0011
1924 // - uint32 0100
1925 // - int33 x1x1
1926 // - int64 1xxx
1927 //
1928 // DecodeRangeFeedbackAt() helper maps these states into the RangeFeedback
1929 // enumeration.
1930 enum RangeFeedbackLatticeBits {
1931 kSignedRangeBit = 1 << 0,
1932 kInt32RangeBit = 1 << 1,
1933 kUint32RangeBit = 1 << 2,
1934 kInt64RangeBit = 1 << 3,
1935 kBitsPerRangeFeedback = 4,
1936 kRangeFeedbackMask = (1 << kBitsPerRangeFeedback) - 1,
1937 kRangeFeedbackSlots = 3
1938 };
1939
1940 static bool IsValidRangeFeedbackIndex(intptr_t index) {
1941 return (0 <= index) && (index < kRangeFeedbackSlots);
1942 }
1943
1944 static intptr_t RangeFeedbackShift(intptr_t index) {
1945 return (index * kBitsPerRangeFeedback) + kRangeFeedbackPos;
1946 }
1947
1948 static const char* RangeFeedbackToString(RangeFeedback feedback) {
1949 switch (feedback) {
1950 case kSmiRange:
1951 return "smi";
1952 case kInt32Range:
1953 return "int32";
1954 case kUint32Range:
1955 return "uint32";
1956 case kInt64Range:
1957 return "int64";
1958 default:
1959 UNREACHABLE();
1960 return "?";
1961 }
1962 }
1963
1964 // It is only meaningful to interptret range feedback stored in the ICData
1965 // when all checks are Mint or Smi.
1966 bool HasRangeFeedback() const;
1967 RangeFeedback DecodeRangeFeedbackAt(intptr_t idx) const;
1968
1969 void PrintToJSONArray(const JSONArray& jsarray,
1970 intptr_t token_pos,
1971 bool is_static_call) const;
1972
1973 private:
1974 RawArray* ic_data() const {
1975 return raw_ptr()->ic_data_;
1976 }
1977
1978 void set_owner(const Function& value) const;
1979 void set_target_name(const String& value) const;
1980 void set_arguments_descriptor(const Array& value) const;
1981 void set_deopt_id(intptr_t value) const;
1982 void SetNumArgsTested(intptr_t value) const;
1983 void set_ic_data(const Array& value) const;
1984 void set_state_bits(uint32_t bits) const;
1985
1986 enum {
1987 kNumArgsTestedPos = 0,
1988 kNumArgsTestedSize = 2,
1989 kDeoptReasonPos = kNumArgsTestedPos + kNumArgsTestedSize,
1990 kDeoptReasonSize = kLastRecordedDeoptReason + 1,
1991 kIssuedJSWarningBit = kDeoptReasonPos + kDeoptReasonSize,
1992 kRangeFeedbackPos = kIssuedJSWarningBit + 1,
1993 kRangeFeedbackSize = kBitsPerRangeFeedback * kRangeFeedbackSlots
1994 };
1995
1996 class NumArgsTestedBits : public BitField<uint32_t,
1997 kNumArgsTestedPos, kNumArgsTestedSize> {}; // NOLINT
1998 class DeoptReasonBits : public BitField<uint32_t,
1999 ICData::kDeoptReasonPos, ICData::kDeoptReasonSize> {}; // NOLINT
2000 class IssuedJSWarningBit : public BitField<bool, kIssuedJSWarningBit, 1> {};
2001 class RangeFeedbackBits : public BitField<uint32_t,
2002 ICData::kRangeFeedbackPos, ICData::kRangeFeedbackSize> {}; // NOLINT
2003
2004 #if defined(DEBUG)
2005 // Used in asserts to verify that a check is not added twice.
2006 bool HasCheck(const GrowableArray<intptr_t>& cids) const;
2007 #endif // DEBUG
2008
2009 intptr_t TestEntryLength() const;
2010 void WriteSentinel(const Array& data) const;
2011
2012 FINAL_HEAP_OBJECT_IMPLEMENTATION(ICData, Object);
2013 friend class Class;
2014 };
2015
2016
1709 class Function : public Object { 2017 class Function : public Object {
1710 public: 2018 public:
1711 RawString* name() const { return raw_ptr()->name_; } 2019 RawString* name() const { return raw_ptr()->name_; }
1712 RawString* PrettyName() const; 2020 RawString* PrettyName() const;
1713 RawString* UserVisibleName() const; 2021 RawString* UserVisibleName() const;
1714 RawString* QualifiedPrettyName() const; 2022 RawString* QualifiedPrettyName() const;
1715 RawString* QualifiedUserVisibleName() const; 2023 RawString* QualifiedUserVisibleName() const;
1716 virtual RawString* DictionaryName() const { return name(); } 2024 virtual RawString* DictionaryName() const { return name(); }
1717 2025
1718 RawString* GetSource() const; 2026 RawString* GetSource() const;
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after
2224 // Return false and report an error if the fingerprint does not match. 2532 // Return false and report an error if the fingerprint does not match.
2225 bool CheckSourceFingerprint(const char* prefix, int32_t fp) const; 2533 bool CheckSourceFingerprint(const char* prefix, int32_t fp) const;
2226 2534
2227 // Works with map [deopt-id] -> ICData. 2535 // Works with map [deopt-id] -> ICData.
2228 void SaveICDataMap( 2536 void SaveICDataMap(
2229 const ZoneGrowableArray<const ICData*>& deopt_id_to_ic_data) const; 2537 const ZoneGrowableArray<const ICData*>& deopt_id_to_ic_data) const;
2230 void RestoreICDataMap( 2538 void RestoreICDataMap(
2231 ZoneGrowableArray<const ICData*>* deopt_id_to_ic_data) const; 2539 ZoneGrowableArray<const ICData*>* deopt_id_to_ic_data) const;
2232 2540
2233 RawArray* ic_data_array() const; 2541 RawArray* ic_data_array() const;
2234 void ClearICData() const; 2542 void ClearICDataArray() const;
2543
2544 // Sets deopt reason in all ICData-s with given deopt_id.
2545 void SetDeoptReasonForAll(intptr_t deopt_id, ICData::DeoptReasonId reason);
2235 2546
2236 static const int kCtorPhaseInit = 1 << 0; 2547 static const int kCtorPhaseInit = 1 << 0;
2237 static const int kCtorPhaseBody = 1 << 1; 2548 static const int kCtorPhaseBody = 1 << 1;
2238 static const int kCtorPhaseAll = (kCtorPhaseInit | kCtorPhaseBody); 2549 static const int kCtorPhaseAll = (kCtorPhaseInit | kCtorPhaseBody);
2239 2550
2240 void set_modifier(RawFunction::AsyncModifier value) const; 2551 void set_modifier(RawFunction::AsyncModifier value) const;
2241 2552
2242 // static: Considered during class-side or top-level resolution rather than 2553 // static: Considered during class-side or top-level resolution rather than
2243 // instance-side resolution. 2554 // instance-side resolution.
2244 // const: Valid target of a const constructor call. 2555 // const: Valid target of a const constructor call.
(...skipping 1299 matching lines...) Expand 10 before | Expand all | Expand 10 after
3544 3855
3545 3856
3546 private: 3857 private:
3547 static void UnpackInto(const Array& table, 3858 static void UnpackInto(const Array& table,
3548 const TypedData& packed, 3859 const TypedData& packed,
3549 GrowableArray<DeoptInstr*>* instructions, 3860 GrowableArray<DeoptInstr*>* instructions,
3550 intptr_t length); 3861 intptr_t length);
3551 }; 3862 };
3552 3863
3553 3864
3554 // Object holding information about an IC: test classes and their
3555 // corresponding targets.
3556 class ICData : public Object {
3557 public:
3558 RawFunction* owner() const {
3559 return raw_ptr()->owner_;
3560 }
3561
3562 RawString* target_name() const {
3563 return raw_ptr()->target_name_;
3564 }
3565
3566 RawArray* arguments_descriptor() const {
3567 return raw_ptr()->args_descriptor_;
3568 }
3569
3570 intptr_t NumArgsTested() const;
3571
3572 intptr_t deopt_id() const {
3573 return raw_ptr()->deopt_id_;
3574 }
3575
3576 // Note: only deopts with reasons before Unknown in this list are recorded in
3577 // the ICData. All other reasons are used purely for informational messages
3578 // printed during deoptimization itself.
3579 #define DEOPT_REASONS(V) \
3580 V(BinarySmiOp) \
3581 V(BinaryMintOp) \
3582 V(DoubleToSmi) \
3583 V(Unknown) \
3584 V(PolymorphicInstanceCallTestFail) \
3585 V(UnaryMintOp) \
3586 V(BinaryDoubleOp) \
3587 V(UnaryOp) \
3588 V(UnboxInteger) \
3589 V(CheckClass) \
3590 V(CheckSmi) \
3591 V(CheckArrayBound) \
3592 V(AtCall) \
3593 V(Uint32Load) \
3594 V(GuardField) \
3595 V(TestCids) \
3596 V(NumReasons) \
3597
3598 enum DeoptReasonId {
3599 #define DEFINE_ENUM_LIST(name) kDeopt##name,
3600 DEOPT_REASONS(DEFINE_ENUM_LIST)
3601 #undef DEFINE_ENUM_LIST
3602 };
3603
3604 static const intptr_t kLastRecordedDeoptReason = kDeoptUnknown - 1;
3605
3606 enum DeoptFlags {
3607 // Deoptimization is caused by an optimistically hoisted instruction.
3608 kHoisted = 1 << 0,
3609
3610 // Deoptimization is caused by an optimistically generalized bounds check.
3611 kGeneralized = 1 << 1
3612 };
3613
3614 bool HasDeoptReasons() const { return DeoptReasons() != 0; }
3615 uint32_t DeoptReasons() const;
3616 void SetDeoptReasons(uint32_t reasons) const;
3617
3618 bool HasDeoptReason(ICData::DeoptReasonId reason) const;
3619 void AddDeoptReason(ICData::DeoptReasonId reason) const;
3620
3621 bool IssuedJSWarning() const;
3622 void SetIssuedJSWarning() const;
3623
3624 // Return true if the target function of this IC data may check for (and
3625 // possibly issue) a Javascript compatibility warning.
3626 bool MayCheckForJSWarning() const;
3627
3628 intptr_t NumberOfChecks() const;
3629
3630 // Discounts any checks with usage of zero.
3631 intptr_t NumberOfUsedChecks() const;
3632
3633 static intptr_t InstanceSize() {
3634 return RoundedAllocationSize(sizeof(RawICData));
3635 }
3636
3637 static intptr_t target_name_offset() {
3638 return OFFSET_OF(RawICData, target_name_);
3639 }
3640
3641 static intptr_t state_bits_offset() {
3642 return OFFSET_OF(RawICData, state_bits_);
3643 }
3644
3645 static intptr_t NumArgsTestedShift() {
3646 return kNumArgsTestedPos;
3647 }
3648
3649 static intptr_t NumArgsTestedMask() {
3650 return ((1 << kNumArgsTestedSize) - 1) << kNumArgsTestedPos;
3651 }
3652
3653 static intptr_t arguments_descriptor_offset() {
3654 return OFFSET_OF(RawICData, args_descriptor_);
3655 }
3656
3657 static intptr_t ic_data_offset() {
3658 return OFFSET_OF(RawICData, ic_data_);
3659 }
3660
3661 static intptr_t owner_offset() {
3662 return OFFSET_OF(RawICData, owner_);
3663 }
3664
3665 // Used for unoptimized static calls when no class-ids are checked.
3666 void AddTarget(const Function& target) const;
3667
3668 // Adding checks.
3669
3670 // Adds one more class test to ICData. Length of 'classes' must be equal to
3671 // the number of arguments tested. Use only for num_args_tested > 1.
3672 void AddCheck(const GrowableArray<intptr_t>& class_ids,
3673 const Function& target) const;
3674 // Adds sorted so that Smi is the first class-id. Use only for
3675 // num_args_tested == 1.
3676 void AddReceiverCheck(intptr_t receiver_class_id,
3677 const Function& target,
3678 intptr_t count = 1) const;
3679
3680 // Retrieving checks.
3681
3682 // TODO(srdjan): GetCheckAt without target.
3683 void GetCheckAt(intptr_t index,
3684 GrowableArray<intptr_t>* class_ids,
3685 Function* target) const;
3686 // Only for 'num_args_checked == 1'.
3687 void GetOneClassCheckAt(intptr_t index,
3688 intptr_t* class_id,
3689 Function* target) const;
3690 // Only for 'num_args_checked == 1'.
3691 intptr_t GetCidAt(intptr_t index) const;
3692
3693 intptr_t GetReceiverClassIdAt(intptr_t index) const;
3694 intptr_t GetClassIdAt(intptr_t index, intptr_t arg_nr) const;
3695
3696 RawFunction* GetTargetAt(intptr_t index) const;
3697 RawFunction* GetTargetForReceiverClassId(intptr_t class_id) const;
3698
3699 void IncrementCountAt(intptr_t index, intptr_t value) const;
3700 void SetCountAt(intptr_t index, intptr_t value) const;
3701 intptr_t GetCountAt(intptr_t index) const;
3702 intptr_t AggregateCount() const;
3703
3704 // Returns this->raw() if num_args_tested == 1 and arg_nr == 1, otherwise
3705 // returns a new ICData object containing only unique arg_nr checks.
3706 // Returns only used entries.
3707 RawICData* AsUnaryClassChecksForArgNr(intptr_t arg_nr) const;
3708 RawICData* AsUnaryClassChecks() const {
3709 return AsUnaryClassChecksForArgNr(0);
3710 }
3711 RawICData* AsUnaryClassChecksForCid(
3712 intptr_t cid, const Function& target) const;
3713
3714 // Consider only used entries.
3715 bool AllTargetsHaveSameOwner(intptr_t owner_cid) const;
3716 bool AllReceiversAreNumbers() const;
3717 bool HasOneTarget() const;
3718 bool HasReceiverClassId(intptr_t class_id) const;
3719
3720 static RawICData* New(const Function& owner,
3721 const String& target_name,
3722 const Array& arguments_descriptor,
3723 intptr_t deopt_id,
3724 intptr_t num_args_tested);
3725 static RawICData* NewFrom(const ICData& from, intptr_t num_args_tested);
3726
3727 static intptr_t TestEntryLengthFor(intptr_t num_args);
3728
3729 static intptr_t TargetIndexFor(intptr_t num_args) {
3730 return num_args;
3731 }
3732
3733 static intptr_t CountIndexFor(intptr_t num_args) {
3734 return (num_args + 1);
3735 }
3736
3737 bool IsUsedAt(intptr_t i) const;
3738
3739 void GetUsedCidsForTwoArgs(GrowableArray<intptr_t>* first,
3740 GrowableArray<intptr_t>* second) const;
3741
3742 // Range feedback tracking functionality.
3743
3744 // For arithmetic operations we store range information for inputs and the
3745 // result. The goal is to discover:
3746 //
3747 // - on 32-bit platforms:
3748 // - when Mint operation is actually a int32/uint32 operation;
3749 // - when Smi operation produces non-smi results;
3750 //
3751 // - on 64-bit platforms:
3752 // - when Smi operation is actually int32/uint32 operation;
3753 // - when Mint operation produces non-smi results;
3754 //
3755 enum RangeFeedback {
3756 kSmiRange,
3757 kInt32Range,
3758 kUint32Range,
3759 kInt64Range
3760 };
3761
3762 // We use 4 bits per operand/result feedback. Our lattice allows us to
3763 // express the following states:
3764 //
3765 // - usmi 0000 [used only on 32bit platforms]
3766 // - smi 0001
3767 // - uint31 0010
3768 // - int32 0011
3769 // - uint32 0100
3770 // - int33 x1x1
3771 // - int64 1xxx
3772 //
3773 // DecodeRangeFeedbackAt() helper maps these states into the RangeFeedback
3774 // enumeration.
3775 enum RangeFeedbackLatticeBits {
3776 kSignedRangeBit = 1 << 0,
3777 kInt32RangeBit = 1 << 1,
3778 kUint32RangeBit = 1 << 2,
3779 kInt64RangeBit = 1 << 3,
3780 kBitsPerRangeFeedback = 4,
3781 kRangeFeedbackMask = (1 << kBitsPerRangeFeedback) - 1,
3782 kRangeFeedbackSlots = 3
3783 };
3784
3785 static bool IsValidRangeFeedbackIndex(intptr_t index) {
3786 return (0 <= index) && (index < kRangeFeedbackSlots);
3787 }
3788
3789 static intptr_t RangeFeedbackShift(intptr_t index) {
3790 return (index * kBitsPerRangeFeedback) + kRangeFeedbackPos;
3791 }
3792
3793 static const char* RangeFeedbackToString(RangeFeedback feedback) {
3794 switch (feedback) {
3795 case kSmiRange:
3796 return "smi";
3797 case kInt32Range:
3798 return "int32";
3799 case kUint32Range:
3800 return "uint32";
3801 case kInt64Range:
3802 return "int64";
3803 default:
3804 UNREACHABLE();
3805 return "?";
3806 }
3807 }
3808
3809 // It is only meaningful to interptret range feedback stored in the ICData
3810 // when all checks are Mint or Smi.
3811 bool HasRangeFeedback() const;
3812 RangeFeedback DecodeRangeFeedbackAt(intptr_t idx) const;
3813
3814 void PrintToJSONArray(const JSONArray& jsarray,
3815 intptr_t token_pos,
3816 bool is_static_call) const;
3817
3818 private:
3819 RawArray* ic_data() const {
3820 return raw_ptr()->ic_data_;
3821 }
3822
3823 void set_owner(const Function& value) const;
3824 void set_target_name(const String& value) const;
3825 void set_arguments_descriptor(const Array& value) const;
3826 void set_deopt_id(intptr_t value) const;
3827 void SetNumArgsTested(intptr_t value) const;
3828 void set_ic_data(const Array& value) const;
3829 void set_state_bits(uint32_t bits) const;
3830
3831 enum {
3832 kNumArgsTestedPos = 0,
3833 kNumArgsTestedSize = 2,
3834 kDeoptReasonPos = kNumArgsTestedPos + kNumArgsTestedSize,
3835 kDeoptReasonSize = kLastRecordedDeoptReason + 1,
3836 kIssuedJSWarningBit = kDeoptReasonPos + kDeoptReasonSize,
3837 kRangeFeedbackPos = kIssuedJSWarningBit + 1,
3838 kRangeFeedbackSize = kBitsPerRangeFeedback * kRangeFeedbackSlots
3839 };
3840
3841 class NumArgsTestedBits : public BitField<uint32_t,
3842 kNumArgsTestedPos, kNumArgsTestedSize> {}; // NOLINT
3843 class DeoptReasonBits : public BitField<uint32_t,
3844 ICData::kDeoptReasonPos, ICData::kDeoptReasonSize> {}; // NOLINT
3845 class IssuedJSWarningBit : public BitField<bool, kIssuedJSWarningBit, 1> {};
3846 class RangeFeedbackBits : public BitField<uint32_t,
3847 ICData::kRangeFeedbackPos, ICData::kRangeFeedbackSize> {}; // NOLINT
3848
3849 #if defined(DEBUG)
3850 // Used in asserts to verify that a check is not added twice.
3851 bool HasCheck(const GrowableArray<intptr_t>& cids) const;
3852 #endif // DEBUG
3853
3854 intptr_t TestEntryLength() const;
3855 void WriteSentinel(const Array& data) const;
3856
3857 FINAL_HEAP_OBJECT_IMPLEMENTATION(ICData, Object);
3858 friend class Class;
3859 };
3860
3861
3862 class Code : public Object { 3865 class Code : public Object {
3863 public: 3866 public:
3864 RawInstructions* instructions() const { return raw_ptr()->instructions_; } 3867 RawInstructions* instructions() const { return raw_ptr()->instructions_; }
3865 static intptr_t instructions_offset() { 3868 static intptr_t instructions_offset() {
3866 return OFFSET_OF(RawCode, instructions_); 3869 return OFFSET_OF(RawCode, instructions_);
3867 } 3870 }
3868 intptr_t pointer_offsets_length() const { 3871 intptr_t pointer_offsets_length() const {
3869 return PtrOffBits::decode(raw_ptr()->state_bits_); 3872 return PtrOffBits::decode(raw_ptr()->state_bits_);
3870 } 3873 }
3871 3874
(...skipping 3917 matching lines...) Expand 10 before | Expand all | Expand 10 after
7789 7792
7790 7793
7791 RawObject* MegamorphicCache::GetTargetFunction(const Array& array, 7794 RawObject* MegamorphicCache::GetTargetFunction(const Array& array,
7792 intptr_t index) { 7795 intptr_t index) {
7793 return array.At((index * kEntryLength) + kTargetFunctionIndex); 7796 return array.At((index * kEntryLength) + kTargetFunctionIndex);
7794 } 7797 }
7795 7798
7796 } // namespace dart 7799 } // namespace dart
7797 7800
7798 #endif // VM_OBJECT_H_ 7801 #endif // VM_OBJECT_H_
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.cc ('k') | runtime/vm/object.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698