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

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 254723003: Remember all deopt reasons in ic_data, not just the last one. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_inliner.cc ('k') | runtime/vm/intermediate_language.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) 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 #include "vm/flow_graph_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/cha.h" 8 #include "vm/cha.h"
9 #include "vm/cpu.h" 9 #include "vm/cpu.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 102
103 103
104 // Attempt to build ICData for call using propagated class-ids. 104 // Attempt to build ICData for call using propagated class-ids.
105 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) { 105 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) {
106 ASSERT(call->HasICData()); 106 ASSERT(call->HasICData());
107 if (call->ic_data()->NumberOfChecks() > 0) { 107 if (call->ic_data()->NumberOfChecks() > 0) {
108 // This occurs when an instance call has too many checks, will be converted 108 // This occurs when an instance call has too many checks, will be converted
109 // to megamorphic call. 109 // to megamorphic call.
110 return false; 110 return false;
111 } 111 }
112 GrowableArray<intptr_t> class_ids(call->ic_data()->num_args_tested()); 112 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested());
113 ASSERT(call->ic_data()->num_args_tested() <= call->ArgumentCount()); 113 ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount());
114 for (intptr_t i = 0; i < call->ic_data()->num_args_tested(); i++) { 114 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) {
115 const intptr_t cid = call->PushArgumentAt(i)->value()->Type()->ToCid(); 115 const intptr_t cid = call->PushArgumentAt(i)->value()->Type()->ToCid();
116 class_ids.Add(cid); 116 class_ids.Add(cid);
117 } 117 }
118 118
119 const Token::Kind op_kind = call->token_kind(); 119 const Token::Kind op_kind = call->token_kind();
120 if (Token::IsRelationalOperator(op_kind) || 120 if (Token::IsRelationalOperator(op_kind) ||
121 Token::IsEqualityOperator(op_kind) || 121 Token::IsEqualityOperator(op_kind) ||
122 Token::IsBinaryOperator(op_kind)) { 122 Token::IsBinaryOperator(op_kind)) {
123 // Guess cid: if one of the inputs is a number assume that the other 123 // Guess cid: if one of the inputs is a number assume that the other
124 // is a number of same type. 124 // is a number of same type.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 } else { 166 } else {
167 ASSERT(class_ids.length() == 1); 167 ASSERT(class_ids.length() == 1);
168 ic_data.AddReceiverCheck(class_ids[0], function); 168 ic_data.AddReceiverCheck(class_ids[0], function);
169 } 169 }
170 call->set_ic_data(&ic_data); 170 call->set_ic_data(&ic_data);
171 return true; 171 return true;
172 } 172 }
173 173
174 174
175 static const ICData& TrySpecializeICData(const ICData& ic_data, intptr_t cid) { 175 static const ICData& TrySpecializeICData(const ICData& ic_data, intptr_t cid) {
176 ASSERT(ic_data.num_args_tested() == 1); 176 ASSERT(ic_data.NumArgsTested() == 1);
177 177
178 if ((ic_data.NumberOfChecks() == 1) && 178 if ((ic_data.NumberOfChecks() == 1) &&
179 (ic_data.GetReceiverClassIdAt(0) == cid)) { 179 (ic_data.GetReceiverClassIdAt(0) == cid)) {
180 return ic_data; // Nothing to do 180 return ic_data; // Nothing to do
181 } 181 }
182 182
183 const Function& function = 183 const Function& function =
184 Function::Handle(ic_data.GetTargetForReceiverClassId(cid)); 184 Function::Handle(ic_data.GetTargetForReceiverClassId(cid));
185 // TODO(fschneider): Try looking up the function on the class if it is 185 // TODO(fschneider): Try looking up the function on the class if it is
186 // not found in the ICData. 186 // not found in the ICData.
187 if (!function.IsNull()) { 187 if (!function.IsNull()) {
188 const ICData& new_ic_data = ICData::ZoneHandle(ICData::New( 188 const ICData& new_ic_data = ICData::ZoneHandle(ICData::New(
189 Function::Handle(ic_data.function()), 189 Function::Handle(ic_data.owner()),
190 String::Handle(ic_data.target_name()), 190 String::Handle(ic_data.target_name()),
191 Object::empty_array(), // Dummy argument descriptor. 191 Object::empty_array(), // Dummy argument descriptor.
192 ic_data.deopt_id(), 192 ic_data.deopt_id(),
193 ic_data.num_args_tested())); 193 ic_data.NumArgsTested()));
194 new_ic_data.set_deopt_reason(ic_data.deopt_reason()); 194 new_ic_data.SetDeoptReasons(ic_data.DeoptReasons());
195 new_ic_data.AddReceiverCheck(cid, function); 195 new_ic_data.AddReceiverCheck(cid, function);
196 return new_ic_data; 196 return new_ic_data;
197 } 197 }
198 198
199 return ic_data; 199 return ic_data;
200 } 200 }
201 201
202 202
203 void FlowGraphOptimizer::SpecializePolymorphicInstanceCall( 203 void FlowGraphOptimizer::SpecializePolymorphicInstanceCall(
204 PolymorphicInstanceCallInstr* call) { 204 PolymorphicInstanceCallInstr* call) {
(...skipping 605 matching lines...) Expand 10 before | Expand all | Expand 10 after
810 } 810 }
811 } 811 }
812 } 812 }
813 813
814 814
815 static bool ICDataHasReceiverArgumentClassIds(const ICData& ic_data, 815 static bool ICDataHasReceiverArgumentClassIds(const ICData& ic_data,
816 intptr_t receiver_class_id, 816 intptr_t receiver_class_id,
817 intptr_t argument_class_id) { 817 intptr_t argument_class_id) {
818 ASSERT(receiver_class_id != kIllegalCid); 818 ASSERT(receiver_class_id != kIllegalCid);
819 ASSERT(argument_class_id != kIllegalCid); 819 ASSERT(argument_class_id != kIllegalCid);
820 if (ic_data.num_args_tested() != 2) return false; 820 if (ic_data.NumArgsTested() != 2) return false;
821 821
822 Function& target = Function::Handle(); 822 Function& target = Function::Handle();
823 const intptr_t len = ic_data.NumberOfChecks(); 823 const intptr_t len = ic_data.NumberOfChecks();
824 for (intptr_t i = 0; i < len; i++) { 824 for (intptr_t i = 0; i < len; i++) {
825 GrowableArray<intptr_t> class_ids; 825 GrowableArray<intptr_t> class_ids;
826 ic_data.GetCheckAt(i, &class_ids, &target); 826 ic_data.GetCheckAt(i, &class_ids, &target);
827 ASSERT(class_ids.length() == 2); 827 ASSERT(class_ids.length() == 2);
828 if ((class_ids[0] == receiver_class_id) && 828 if ((class_ids[0] == receiver_class_id) &&
829 (class_ids[1] == argument_class_id)) { 829 (class_ids[1] == argument_class_id)) {
830 return true; 830 return true;
(...skipping 13 matching lines...) Expand all
844 return false; 844 return false;
845 } 845 }
846 846
847 847
848 // Returns true if ICData tests two arguments and all ICData cids are in the 848 // Returns true if ICData tests two arguments and all ICData cids are in the
849 // required sets 'receiver_class_ids' or 'argument_class_ids', respectively. 849 // required sets 'receiver_class_ids' or 'argument_class_ids', respectively.
850 static bool ICDataHasOnlyReceiverArgumentClassIds( 850 static bool ICDataHasOnlyReceiverArgumentClassIds(
851 const ICData& ic_data, 851 const ICData& ic_data,
852 const GrowableArray<intptr_t>& receiver_class_ids, 852 const GrowableArray<intptr_t>& receiver_class_ids,
853 const GrowableArray<intptr_t>& argument_class_ids) { 853 const GrowableArray<intptr_t>& argument_class_ids) {
854 if (ic_data.num_args_tested() != 2) return false; 854 if (ic_data.NumArgsTested() != 2) return false;
855 Function& target = Function::Handle(); 855 Function& target = Function::Handle();
856 const intptr_t len = ic_data.NumberOfChecks(); 856 const intptr_t len = ic_data.NumberOfChecks();
857 for (intptr_t i = 0; i < len; i++) { 857 for (intptr_t i = 0; i < len; i++) {
858 GrowableArray<intptr_t> class_ids; 858 GrowableArray<intptr_t> class_ids;
859 ic_data.GetCheckAt(i, &class_ids, &target); 859 ic_data.GetCheckAt(i, &class_ids, &target);
860 ASSERT(class_ids.length() == 2); 860 ASSERT(class_ids.length() == 2);
861 if (!ClassIdIsOneOf(class_ids[0], receiver_class_ids) || 861 if (!ClassIdIsOneOf(class_ids[0], receiver_class_ids) ||
862 !ClassIdIsOneOf(class_ids[1], argument_class_ids)) { 862 !ClassIdIsOneOf(class_ids[1], argument_class_ids)) {
863 return false; 863 return false;
864 } 864 }
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
981 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()), 981 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()),
982 call->deopt_id(), 982 call->deopt_id(),
983 call->env(), 983 call->env(),
984 call); 984 call);
985 } 985 }
986 986
987 987
988 static bool ArgIsAlways(intptr_t cid, 988 static bool ArgIsAlways(intptr_t cid,
989 const ICData& ic_data, 989 const ICData& ic_data,
990 intptr_t arg_number) { 990 intptr_t arg_number) {
991 ASSERT(ic_data.num_args_tested() > arg_number); 991 ASSERT(ic_data.NumArgsTested() > arg_number);
992 const intptr_t num_checks = ic_data.NumberOfChecks(); 992 const intptr_t num_checks = ic_data.NumberOfChecks();
993 if (num_checks == 0) return false; 993 if (num_checks == 0) return false;
994 for (intptr_t i = 0; i < num_checks; i++) { 994 for (intptr_t i = 0; i < num_checks; i++) {
995 if (ic_data.GetClassIdAt(i, arg_number) != cid) return false; 995 if (ic_data.GetClassIdAt(i, arg_number) != cid) return false;
996 } 996 }
997 return true; 997 return true;
998 } 998 }
999 999
1000 1000
1001 static bool CanUnboxInt32() { 1001 static bool CanUnboxInt32() {
(...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after
1578 array_cid, 1578 array_cid,
1579 &array, 1579 &array,
1580 index, 1580 index,
1581 &cursor); 1581 &cursor);
1582 1582
1583 intptr_t deopt_id = Isolate::kNoDeoptId; 1583 intptr_t deopt_id = Isolate::kNoDeoptId;
1584 if ((array_cid == kTypedDataInt32ArrayCid) || 1584 if ((array_cid == kTypedDataInt32ArrayCid) ||
1585 (array_cid == kTypedDataUint32ArrayCid)) { 1585 (array_cid == kTypedDataUint32ArrayCid)) {
1586 // Set deopt_id if we can optimistically assume that the result is Smi. 1586 // Set deopt_id if we can optimistically assume that the result is Smi.
1587 // Assume mixed Mint/Smi if this instruction caused deoptimization once. 1587 // Assume mixed Mint/Smi if this instruction caused deoptimization once.
1588 deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ? 1588 deopt_id = ic_data.HasDeoptReasons() ?
1589 call->deopt_id() : Isolate::kNoDeoptId; 1589 Isolate::kNoDeoptId : call->deopt_id();
1590 } 1590 }
1591 1591
1592 // Array load and return. 1592 // Array load and return.
1593 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); 1593 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid);
1594 *last = new LoadIndexedInstr(new Value(array), 1594 *last = new LoadIndexedInstr(new Value(array),
1595 new Value(index), 1595 new Value(index),
1596 index_scale, 1596 index_scale,
1597 array_cid, 1597 array_cid,
1598 deopt_id); 1598 deopt_id);
1599 cursor = flow_graph()->AppendTo( 1599 cursor = flow_graph()->AppendTo(
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1760 } 1760 }
1761 return false; 1761 return false;
1762 } 1762 }
1763 1763
1764 1764
1765 static bool SmiFitsInDouble() { return kSmiBits < 53; } 1765 static bool SmiFitsInDouble() { return kSmiBits < 53; }
1766 1766
1767 bool FlowGraphOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call, 1767 bool FlowGraphOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
1768 Token::Kind op_kind) { 1768 Token::Kind op_kind) {
1769 const ICData& ic_data = *call->ic_data(); 1769 const ICData& ic_data = *call->ic_data();
1770 ASSERT(ic_data.num_args_tested() == 2); 1770 ASSERT(ic_data.NumArgsTested() == 2);
1771 1771
1772 ASSERT(call->ArgumentCount() == 2); 1772 ASSERT(call->ArgumentCount() == 2);
1773 Definition* left = call->ArgumentAt(0); 1773 Definition* left = call->ArgumentAt(0);
1774 Definition* right = call->ArgumentAt(1); 1774 Definition* right = call->ArgumentAt(1);
1775 1775
1776 intptr_t cid = kIllegalCid; 1776 intptr_t cid = kIllegalCid;
1777 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { 1777 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) {
1778 if (TryStringLengthOneEquality(call, op_kind)) { 1778 if (TryStringLengthOneEquality(call, op_kind)) {
1779 return true; 1779 return true;
1780 } else { 1780 } else {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1864 cid, 1864 cid,
1865 call->deopt_id()); 1865 call->deopt_id());
1866 ReplaceCall(call, comp); 1866 ReplaceCall(call, comp);
1867 return true; 1867 return true;
1868 } 1868 }
1869 1869
1870 1870
1871 bool FlowGraphOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call, 1871 bool FlowGraphOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call,
1872 Token::Kind op_kind) { 1872 Token::Kind op_kind) {
1873 const ICData& ic_data = *call->ic_data(); 1873 const ICData& ic_data = *call->ic_data();
1874 ASSERT(ic_data.num_args_tested() == 2); 1874 ASSERT(ic_data.NumArgsTested() == 2);
1875 1875
1876 ASSERT(call->ArgumentCount() == 2); 1876 ASSERT(call->ArgumentCount() == 2);
1877 Definition* left = call->ArgumentAt(0); 1877 Definition* left = call->ArgumentAt(0);
1878 Definition* right = call->ArgumentAt(1); 1878 Definition* right = call->ArgumentAt(1);
1879 1879
1880 intptr_t cid = kIllegalCid; 1880 intptr_t cid = kIllegalCid;
1881 if (HasOnlyTwoOf(ic_data, kSmiCid)) { 1881 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1882 InsertBefore(call, 1882 InsertBefore(call,
1883 new CheckSmiInstr(new Value(left), call->deopt_id()), 1883 new CheckSmiInstr(new Value(left), call->deopt_id()),
1884 call->env(), 1884 call->env(),
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1929 Token::Kind op_kind) { 1929 Token::Kind op_kind) {
1930 intptr_t operands_type = kIllegalCid; 1930 intptr_t operands_type = kIllegalCid;
1931 ASSERT(call->HasICData()); 1931 ASSERT(call->HasICData());
1932 const ICData& ic_data = *call->ic_data(); 1932 const ICData& ic_data = *call->ic_data();
1933 switch (op_kind) { 1933 switch (op_kind) {
1934 case Token::kADD: 1934 case Token::kADD:
1935 case Token::kSUB: 1935 case Token::kSUB:
1936 if (HasOnlyTwoOf(ic_data, kSmiCid)) { 1936 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1937 // Don't generate smi code if the IC data is marked because 1937 // Don't generate smi code if the IC data is marked because
1938 // of an overflow. 1938 // of an overflow.
1939 operands_type = (ic_data.deopt_reason() == kDeoptBinarySmiOp) 1939 operands_type = ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp)
1940 ? kMintCid 1940 ? kMintCid
1941 : kSmiCid; 1941 : kSmiCid;
1942 } else if (HasTwoMintOrSmi(ic_data) && 1942 } else if (HasTwoMintOrSmi(ic_data) &&
1943 FlowGraphCompiler::SupportsUnboxedMints()) { 1943 FlowGraphCompiler::SupportsUnboxedMints()) {
1944 // Don't generate mint code if the IC data is marked because of an 1944 // Don't generate mint code if the IC data is marked because of an
1945 // overflow. 1945 // overflow.
1946 if (ic_data.deopt_reason() == kDeoptBinaryMintOp) return false; 1946 if (ic_data.HasDeoptReason(ICData::kDeoptBinaryMintOp)) return false;
1947 operands_type = kMintCid; 1947 operands_type = kMintCid;
1948 } else if (ShouldSpecializeForDouble(ic_data)) { 1948 } else if (ShouldSpecializeForDouble(ic_data)) {
1949 operands_type = kDoubleCid; 1949 operands_type = kDoubleCid;
1950 } else if (HasOnlyTwoOf(ic_data, kFloat32x4Cid)) { 1950 } else if (HasOnlyTwoOf(ic_data, kFloat32x4Cid)) {
1951 operands_type = kFloat32x4Cid; 1951 operands_type = kFloat32x4Cid;
1952 } else if (HasOnlyTwoOf(ic_data, kInt32x4Cid)) { 1952 } else if (HasOnlyTwoOf(ic_data, kInt32x4Cid)) {
1953 operands_type = kInt32x4Cid; 1953 operands_type = kInt32x4Cid;
1954 } else if (HasOnlyTwoOf(ic_data, kFloat64x2Cid)) { 1954 } else if (HasOnlyTwoOf(ic_data, kFloat64x2Cid)) {
1955 operands_type = kFloat64x2Cid; 1955 operands_type = kFloat64x2Cid;
1956 } else { 1956 } else {
1957 return false; 1957 return false;
1958 } 1958 }
1959 break; 1959 break;
1960 case Token::kMUL: 1960 case Token::kMUL:
1961 if (HasOnlyTwoOf(ic_data, kSmiCid)) { 1961 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1962 // Don't generate smi code if the IC data is marked because of an 1962 // Don't generate smi code if the IC data is marked because of an
1963 // overflow. 1963 // overflow.
1964 // TODO(fschneider): Add unboxed mint multiplication. 1964 // TODO(fschneider): Add unboxed mint multiplication.
1965 if (ic_data.deopt_reason() == kDeoptBinarySmiOp) return false; 1965 if (ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp)) return false;
1966 operands_type = kSmiCid; 1966 operands_type = kSmiCid;
1967 } else if (ShouldSpecializeForDouble(ic_data)) { 1967 } else if (ShouldSpecializeForDouble(ic_data)) {
1968 operands_type = kDoubleCid; 1968 operands_type = kDoubleCid;
1969 } else if (HasOnlyTwoOf(ic_data, kFloat32x4Cid)) { 1969 } else if (HasOnlyTwoOf(ic_data, kFloat32x4Cid)) {
1970 operands_type = kFloat32x4Cid; 1970 operands_type = kFloat32x4Cid;
1971 } else if (HasOnlyTwoOf(ic_data, kFloat64x2Cid)) { 1971 } else if (HasOnlyTwoOf(ic_data, kFloat64x2Cid)) {
1972 operands_type = kFloat64x2Cid; 1972 operands_type = kFloat64x2Cid;
1973 } else { 1973 } else {
1974 return false; 1974 return false;
1975 } 1975 }
(...skipping 22 matching lines...) Expand all
1998 } else { 1998 } else {
1999 return false; 1999 return false;
2000 } 2000 }
2001 break; 2001 break;
2002 case Token::kSHR: 2002 case Token::kSHR:
2003 case Token::kSHL: 2003 case Token::kSHL:
2004 if (HasOnlyTwoOf(ic_data, kSmiCid)) { 2004 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
2005 // Left shift may overflow from smi into mint or big ints. 2005 // Left shift may overflow from smi into mint or big ints.
2006 // Don't generate smi code if the IC data is marked because 2006 // Don't generate smi code if the IC data is marked because
2007 // of an overflow. 2007 // of an overflow.
2008 if (ic_data.deopt_reason() == kDeoptShiftMintOp) { 2008 if (ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) {
2009 return false; 2009 return false;
2010 } 2010 }
2011 operands_type = (ic_data.deopt_reason() == kDeoptBinarySmiOp) 2011 operands_type = ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp)
2012 ? kMintCid 2012 ? kMintCid
2013 : kSmiCid; 2013 : kSmiCid;
2014 } else if (HasTwoMintOrSmi(ic_data) && 2014 } else if (HasTwoMintOrSmi(ic_data) &&
2015 HasOnlyOneSmi(ICData::Handle( 2015 HasOnlyOneSmi(ICData::Handle(
2016 ic_data.AsUnaryClassChecksForArgNr(1)))) { 2016 ic_data.AsUnaryClassChecksForArgNr(1)))) {
2017 // Don't generate mint code if the IC data is marked because of an 2017 // Don't generate mint code if the IC data is marked because of an
2018 // overflow. 2018 // overflow.
2019 if (ic_data.deopt_reason() == kDeoptShiftMintOp) { 2019 if (ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) {
2020 return false; 2020 return false;
2021 } 2021 }
2022 // Check for smi/mint << smi or smi/mint >> smi. 2022 // Check for smi/mint << smi or smi/mint >> smi.
2023 operands_type = kMintCid; 2023 operands_type = kMintCid;
2024 } else { 2024 } else {
2025 return false; 2025 return false;
2026 } 2026 }
2027 break; 2027 break;
2028 case Token::kMOD: 2028 case Token::kMOD:
2029 case Token::kTRUNCDIV: 2029 case Token::kTRUNCDIV:
2030 if (HasOnlyTwoOf(ic_data, kSmiCid)) { 2030 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
2031 if (ic_data.deopt_reason() == kDeoptBinarySmiOp) { 2031 if (ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp)) {
2032 return false; 2032 return false;
2033 } 2033 }
2034 operands_type = kSmiCid; 2034 operands_type = kSmiCid;
2035 } else { 2035 } else {
2036 return false; 2036 return false;
2037 } 2037 }
2038 break; 2038 break;
2039 default: 2039 default:
2040 UNREACHABLE(); 2040 UNREACHABLE();
2041 } 2041 }
(...skipping 782 matching lines...) Expand 10 before | Expand all | Expand 10 after
2824 } 2824 }
2825 2825
2826 if (class_ids[0] == kDoubleCid) { 2826 if (class_ids[0] == kDoubleCid) {
2827 switch (recognized_kind) { 2827 switch (recognized_kind) {
2828 case MethodRecognizer::kDoubleToInteger: { 2828 case MethodRecognizer::kDoubleToInteger: {
2829 AddReceiverCheck(call); 2829 AddReceiverCheck(call);
2830 ASSERT(call->HasICData()); 2830 ASSERT(call->HasICData());
2831 const ICData& ic_data = *call->ic_data(); 2831 const ICData& ic_data = *call->ic_data();
2832 Definition* input = call->ArgumentAt(0); 2832 Definition* input = call->ArgumentAt(0);
2833 Definition* d2i_instr = NULL; 2833 Definition* d2i_instr = NULL;
2834 if (ic_data.deopt_reason() == kDeoptDoubleToSmi) { 2834 if (ic_data.HasDeoptReason(ICData::kDeoptDoubleToSmi)) {
2835 // Do not repeatedly deoptimize because result didn't fit into Smi. 2835 // Do not repeatedly deoptimize because result didn't fit into Smi.
2836 d2i_instr = new DoubleToIntegerInstr(new Value(input), call); 2836 d2i_instr = new DoubleToIntegerInstr(new Value(input), call);
2837 } else { 2837 } else {
2838 // Optimistically assume result fits into Smi. 2838 // Optimistically assume result fits into Smi.
2839 d2i_instr = new DoubleToSmiInstr(new Value(input), call->deopt_id()); 2839 d2i_instr = new DoubleToSmiInstr(new Value(input), call->deopt_id());
2840 } 2840 }
2841 ReplaceCall(call, d2i_instr); 2841 ReplaceCall(call, d2i_instr);
2842 return true; 2842 return true;
2843 } 2843 }
2844 case MethodRecognizer::kDoubleMod: 2844 case MethodRecognizer::kDoubleMod:
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
2932 if ((class_ids[0] == kInt32x4Cid) && (ic_data.NumberOfChecks() == 1)) { 2932 if ((class_ids[0] == kInt32x4Cid) && (ic_data.NumberOfChecks() == 1)) {
2933 return TryInlineInt32x4Method(call, recognized_kind); 2933 return TryInlineInt32x4Method(call, recognized_kind);
2934 } 2934 }
2935 2935
2936 if ((class_ids[0] == kFloat64x2Cid) && (ic_data.NumberOfChecks() == 1)) { 2936 if ((class_ids[0] == kFloat64x2Cid) && (ic_data.NumberOfChecks() == 1)) {
2937 return TryInlineFloat64x2Method(call, recognized_kind); 2937 return TryInlineFloat64x2Method(call, recognized_kind);
2938 } 2938 }
2939 2939
2940 if (recognized_kind == MethodRecognizer::kIntegerLeftShiftWithMask32) { 2940 if (recognized_kind == MethodRecognizer::kIntegerLeftShiftWithMask32) {
2941 ASSERT(call->ArgumentCount() == 3); 2941 ASSERT(call->ArgumentCount() == 3);
2942 ASSERT(ic_data.num_args_tested() == 2); 2942 ASSERT(ic_data.NumArgsTested() == 2);
2943 Definition* value = call->ArgumentAt(0); 2943 Definition* value = call->ArgumentAt(0);
2944 Definition* count = call->ArgumentAt(1); 2944 Definition* count = call->ArgumentAt(1);
2945 Definition* int32_mask = call->ArgumentAt(2); 2945 Definition* int32_mask = call->ArgumentAt(2);
2946 if (HasOnlyTwoOf(ic_data, kSmiCid)) { 2946 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
2947 if (ic_data.deopt_reason() == kDeoptShiftMintOp) { 2947 if (ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) {
2948 return false; 2948 return false;
2949 } 2949 }
2950 // We cannot overflow. The input value must be a Smi 2950 // We cannot overflow. The input value must be a Smi
2951 AddCheckSmi(value, call->deopt_id(), call->env(), call); 2951 AddCheckSmi(value, call->deopt_id(), call->env(), call);
2952 AddCheckSmi(count, call->deopt_id(), call->env(), call); 2952 AddCheckSmi(count, call->deopt_id(), call->env(), call);
2953 ASSERT(int32_mask->IsConstant()); 2953 ASSERT(int32_mask->IsConstant());
2954 const Integer& mask_literal = Integer::Cast( 2954 const Integer& mask_literal = Integer::Cast(
2955 int32_mask->AsConstant()->value()); 2955 int32_mask->AsConstant()->value());
2956 const int64_t mask_value = mask_literal.AsInt64Value(); 2956 const int64_t mask_value = mask_literal.AsInt64Value();
2957 ASSERT(mask_value >= 0); 2957 ASSERT(mask_value >= 0);
(...skipping 16 matching lines...) Expand all
2974 new Value(left_shift), new Value(int32_mask), 2974 new Value(left_shift), new Value(int32_mask),
2975 call->deopt_id()); 2975 call->deopt_id());
2976 ReplaceCall(call, bit_and); 2976 ReplaceCall(call, bit_and);
2977 } 2977 }
2978 return true; 2978 return true;
2979 } 2979 }
2980 2980
2981 if (HasTwoMintOrSmi(ic_data) && 2981 if (HasTwoMintOrSmi(ic_data) &&
2982 HasOnlyOneSmi(ICData::Handle(ic_data.AsUnaryClassChecksForArgNr(1)))) { 2982 HasOnlyOneSmi(ICData::Handle(ic_data.AsUnaryClassChecksForArgNr(1)))) {
2983 if (!FlowGraphCompiler::SupportsUnboxedMints() || 2983 if (!FlowGraphCompiler::SupportsUnboxedMints() ||
2984 (ic_data.deopt_reason() == kDeoptShiftMintOp)) { 2984 ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) {
2985 return false; 2985 return false;
2986 } 2986 }
2987 ShiftMintOpInstr* left_shift = 2987 ShiftMintOpInstr* left_shift =
2988 new ShiftMintOpInstr(Token::kSHL, 2988 new ShiftMintOpInstr(Token::kSHL,
2989 new Value(value), new Value(count), 2989 new Value(value), new Value(count),
2990 call->deopt_id()); 2990 call->deopt_id());
2991 InsertBefore(call, left_shift, call->env(), Definition::kValue); 2991 InsertBefore(call, left_shift, call->env(), Definition::kValue);
2992 BinaryMintOpInstr* bit_and = 2992 BinaryMintOpInstr* bit_and =
2993 new BinaryMintOpInstr(Token::kBIT_AND, 2993 new BinaryMintOpInstr(Token::kBIT_AND,
2994 new Value(left_shift), new Value(int32_mask), 2994 new Value(left_shift), new Value(int32_mask),
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after
3400 view_cid, 3400 view_cid,
3401 &array, 3401 &array,
3402 index, 3402 index,
3403 &cursor); 3403 &cursor);
3404 3404
3405 intptr_t deopt_id = Isolate::kNoDeoptId; 3405 intptr_t deopt_id = Isolate::kNoDeoptId;
3406 if ((array_cid == kTypedDataInt32ArrayCid) || 3406 if ((array_cid == kTypedDataInt32ArrayCid) ||
3407 (array_cid == kTypedDataUint32ArrayCid)) { 3407 (array_cid == kTypedDataUint32ArrayCid)) {
3408 // Set deopt_id if we can optimistically assume that the result is Smi. 3408 // Set deopt_id if we can optimistically assume that the result is Smi.
3409 // Assume mixed Mint/Smi if this instruction caused deoptimization once. 3409 // Assume mixed Mint/Smi if this instruction caused deoptimization once.
3410 deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ? 3410 deopt_id = ic_data.HasDeoptReasons() ?
3411 call->deopt_id() : Isolate::kNoDeoptId; 3411 Isolate::kNoDeoptId : call->deopt_id();
3412 } 3412 }
3413 3413
3414 *last = new LoadIndexedInstr(new Value(array), 3414 *last = new LoadIndexedInstr(new Value(array),
3415 new Value(index), 3415 new Value(index),
3416 1, 3416 1,
3417 view_cid, 3417 view_cid,
3418 deopt_id); 3418 deopt_id);
3419 cursor = flow_graph()->AppendTo( 3419 cursor = flow_graph()->AppendTo(
3420 cursor, 3420 cursor,
3421 *last, 3421 *last,
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
3482 Isolate::kNoDeoptId, 3482 Isolate::kNoDeoptId,
3483 1); 3483 1);
3484 value_check.AddReceiverCheck(kSmiCid, target); 3484 value_check.AddReceiverCheck(kSmiCid, target);
3485 break; 3485 break;
3486 } 3486 }
3487 case kTypedDataInt32ArrayCid: 3487 case kTypedDataInt32ArrayCid:
3488 case kTypedDataUint32ArrayCid: 3488 case kTypedDataUint32ArrayCid:
3489 // We don't have ICData for the value stored, so we optimistically assume 3489 // We don't have ICData for the value stored, so we optimistically assume
3490 // smis first. If we ever deoptimized here, we require to unbox the value 3490 // smis first. If we ever deoptimized here, we require to unbox the value
3491 // before storing to handle the mint case, too. 3491 // before storing to handle the mint case, too.
3492 if (i_call->ic_data()->deopt_reason() == kDeoptUnknown) { 3492 if (!i_call->ic_data()->HasDeoptReasons()) {
3493 value_check = ICData::New(flow_graph_->parsed_function().function(), 3493 value_check = ICData::New(flow_graph_->parsed_function().function(),
3494 i_call->function_name(), 3494 i_call->function_name(),
3495 Object::empty_array(), // Dummy args. descr. 3495 Object::empty_array(), // Dummy args. descr.
3496 Isolate::kNoDeoptId, 3496 Isolate::kNoDeoptId,
3497 1); 3497 1);
3498 value_check.AddReceiverCheck(kSmiCid, target); 3498 value_check.AddReceiverCheck(kSmiCid, target);
3499 } 3499 }
3500 break; 3500 break;
3501 case kTypedDataFloat32ArrayCid: 3501 case kTypedDataFloat32ArrayCid:
3502 case kTypedDataFloat64ArrayCid: { 3502 case kTypedDataFloat64ArrayCid: {
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
3677 // return mapping cid->result in 'results' (i : cid; i + 1: result). 3677 // return mapping cid->result in 'results' (i : cid; i + 1: result).
3678 // If all tests yield the same result, return it otherwise return Bool::null. 3678 // If all tests yield the same result, return it otherwise return Bool::null.
3679 // If no mapping is possible, 'results' is empty. 3679 // If no mapping is possible, 'results' is empty.
3680 // An instance-of test returning all same results can be converted to a class 3680 // An instance-of test returning all same results can be converted to a class
3681 // check. 3681 // check.
3682 RawBool* FlowGraphOptimizer::InstanceOfAsBool( 3682 RawBool* FlowGraphOptimizer::InstanceOfAsBool(
3683 const ICData& ic_data, 3683 const ICData& ic_data,
3684 const AbstractType& type, 3684 const AbstractType& type,
3685 ZoneGrowableArray<intptr_t>* results) const { 3685 ZoneGrowableArray<intptr_t>* results) const {
3686 results->Clear(); 3686 results->Clear();
3687 ASSERT(ic_data.num_args_tested() == 1); // Unary checks only. 3687 ASSERT(ic_data.NumArgsTested() == 1); // Unary checks only.
3688 if (!type.IsInstantiated() || type.IsMalformedOrMalbounded()) { 3688 if (!type.IsInstantiated() || type.IsMalformedOrMalbounded()) {
3689 return Bool::null(); 3689 return Bool::null();
3690 } 3690 }
3691 const Class& type_class = Class::Handle(type.type_class()); 3691 const Class& type_class = Class::Handle(type.type_class());
3692 const intptr_t num_type_args = type_class.NumTypeArguments(); 3692 const intptr_t num_type_args = type_class.NumTypeArguments();
3693 if (num_type_args > 0) { 3693 if (num_type_args > 0) {
3694 // Only raw types can be directly compared, thus disregarding type 3694 // Only raw types can be directly compared, thus disregarding type
3695 // arguments. 3695 // arguments.
3696 const intptr_t num_type_params = type_class.NumTypeParameters(); 3696 const intptr_t num_type_params = type_class.NumTypeParameters();
3697 const intptr_t from_index = num_type_args - num_type_params; 3697 const intptr_t from_index = num_type_args - num_type_params;
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after
4221 } else { 4221 } else {
4222 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); 4222 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field);
4223 } 4223 }
4224 } 4224 }
4225 } 4225 }
4226 4226
4227 4227
4228 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr, 4228 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr,
4229 const ICData& unary_ic_data) { 4229 const ICData& unary_ic_data) {
4230 ASSERT((unary_ic_data.NumberOfChecks() > 0) && 4230 ASSERT((unary_ic_data.NumberOfChecks() > 0) &&
4231 (unary_ic_data.num_args_tested() == 1)); 4231 (unary_ic_data.NumArgsTested() == 1));
4232 if (FLAG_enable_type_checks) { 4232 if (FLAG_enable_type_checks) {
4233 // Checked mode setters are inlined like normal methods by conventional 4233 // Checked mode setters are inlined like normal methods by conventional
4234 // inlining. 4234 // inlining.
4235 return false; 4235 return false;
4236 } 4236 }
4237 4237
4238 ASSERT(instr->HasICData()); 4238 ASSERT(instr->HasICData());
4239 if (unary_ic_data.NumberOfChecks() == 0) { 4239 if (unary_ic_data.NumberOfChecks() == 0) {
4240 // No type feedback collected. 4240 // No type feedback collected.
4241 return false; 4241 return false;
(...skipping 4911 matching lines...) Expand 10 before | Expand all | Expand 10 after
9153 } 9153 }
9154 9154
9155 // Insert materializations at environment uses. 9155 // Insert materializations at environment uses.
9156 for (intptr_t i = 0; i < exits.length(); i++) { 9156 for (intptr_t i = 0; i < exits.length(); i++) {
9157 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); 9157 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots);
9158 } 9158 }
9159 } 9159 }
9160 9160
9161 9161
9162 } // namespace dart 9162 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_inliner.cc ('k') | runtime/vm/intermediate_language.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698