Skip to content

Commit 6433038

Browse files
rmacnak-googlecommit-bot@chromium.org
authored andcommitted
[vm] Use stricter checks when deciding to keep a switchable call in the monomorphic state.
- Don't stay in the monomorphic state if the corresponding ICData is no longer monomorphic, even if the call site itself encountered the same CID as before. - Don't assume the ICData's entries array hasn't been replaced. TEST=ci Bug: #47010 Change-Id: I00f59eb59ed52e21bd638fec876accda42db0e2f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/211464 Reviewed-by: Alexander Aprelev <[email protected]> Reviewed-by: Martin Kustermann <[email protected]> Commit-Queue: Ryan Macnak <[email protected]>
1 parent 93d111d commit 6433038

File tree

2 files changed

+300
-18
lines changed

2 files changed

+300
-18
lines changed
Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
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.
4+
5+
// VMOptions=--use_slow_path --deterministic
6+
7+
// Reduced from:
8+
// The Dart Project Fuzz Tester (1.91).
9+
// Program generated as:
10+
// dart dartfuzz.dart --seed 1339276199 --no-fp --no-ffi --no-flat
11+
// @dart=2.14
12+
13+
import 'dart:collection';
14+
import 'dart:typed_data';
15+
16+
MapEntry<Map<bool, int>, List<String>>? var0 =
17+
MapEntry<Map<bool, int>, List<String>>(
18+
<bool, int>{true: -32, true: 47, false: -11, false: 9, false: -69},
19+
<String>['n', 'Rz!4\u2665']);
20+
Uint8List? var9 = Uint8List.fromList(Uint64List.fromList(
21+
Int64List.fromList(Int16List.fromList(Int16List.fromList(Uint8List(38))))));
22+
Uint8ClampedList var10 = Uint8ClampedList.fromList(
23+
Int32List.fromList(Uint64List.fromList(<int>[-27, -74])));
24+
Uint8ClampedList? var11 = Uint8ClampedList(31);
25+
Int16List var12 = Int16List(5);
26+
Int16List? var13 = Int16List(44);
27+
Uint16List var14 = Uint16List.fromList(<int>[-96, 24, -43, -9]);
28+
Uint16List? var15 = Uint16List.fromList(Int8List.fromList(Int32List(34)));
29+
Int32List var16 = Int32List(7);
30+
Int32List? var17 =
31+
Int32List.fromList(<int>[-67, if (false) -98 else -36, -4294967295]);
32+
Uint32List var18 = Uint32List(28);
33+
Uint32List? var19 = Uint32List(18);
34+
Int64List var20 = Int64List.fromList(Uint64List.fromList(Uint16List(47)));
35+
Int64List? var21 = Int64List(1);
36+
Uint64List var22 = Uint64List(49);
37+
Uint64List? var23 = Uint64List(43);
38+
Int32x4List var24 = Int32x4List(45);
39+
Int32x4List? var25 = Int32x4List(46);
40+
Int32x4 var26 = Int32x4(46, 24, 23, 15);
41+
Int32x4? var27 = Int32x4(20, 28, 20, 2);
42+
Deprecated var28 = Deprecated('G-Ki');
43+
Deprecated? var29 = Deprecated('#Ww');
44+
Provisional var30 = Provisional();
45+
Provisional? var31 = Provisional();
46+
bool var32 = bool.fromEnvironment('');
47+
bool? var33 = bool.hasEnvironment('P9LY');
48+
Duration var34 = Duration();
49+
Duration? var35 = Duration();
50+
Error var36 = Error();
51+
Error? var37 = Error();
52+
AssertionError var38 = AssertionError(17);
53+
AssertionError? var39 = AssertionError(8);
54+
TypeError var40 = TypeError();
55+
TypeError? var41 = TypeError();
56+
CastError var42 = CastError();
57+
CastError? var43 = new CastError();
58+
NullThrownError var44 = NullThrownError();
59+
NullThrownError? var45 = new NullThrownError();
60+
ArgumentError var46 = ArgumentError.value(22, 'K90\u{1f600}QtS', 33);
61+
ArgumentError? var47 = ArgumentError.notNull(')');
62+
RangeError var48 = RangeError.range(2, 23, 36, 'H', 'w&');
63+
RangeError? var49 = new RangeError(22);
64+
IndexError var50 = IndexError(15, 14, 'ZuC', '#1z9xJ', 1);
65+
IndexError? var51 = IndexError(14, 36, 'V(', '9Jf!0\u2665', 2);
66+
FallThroughError var52 = FallThroughError();
67+
FallThroughError? var53 = FallThroughError();
68+
AbstractClassInstantiationError var54 = AbstractClassInstantiationError('J!');
69+
AbstractClassInstantiationError? var55 =
70+
AbstractClassInstantiationError('L48ynpV');
71+
UnsupportedError var56 = UnsupportedError('5txzg');
72+
UnsupportedError? var57 = UnsupportedError('W4vVdfv');
73+
UnimplementedError var58 = UnimplementedError('pK00TI\u2665');
74+
UnimplementedError? var59 = UnimplementedError('J(teto2');
75+
StateError var60 = StateError('L\u2665');
76+
StateError? var61 = StateError('e\u2665mykMK');
77+
ConcurrentModificationError var62 = new ConcurrentModificationError(22);
78+
ConcurrentModificationError? var63 = ConcurrentModificationError(7);
79+
StackOverflowError var64 = StackOverflowError();
80+
StackOverflowError? var65 = new StackOverflowError();
81+
CyclicInitializationError var66 = CyclicInitializationError('\u{1f600}');
82+
CyclicInitializationError? var67 = CyclicInitializationError('C');
83+
Exception var68 = Exception(14);
84+
Exception? var69 = Exception(40);
85+
FormatException var70 = FormatException('\u{1f600}lv32', 21, 28);
86+
FormatException? var71 = FormatException('e', 19, 12);
87+
IntegerDivisionByZeroException var72 = IntegerDivisionByZeroException();
88+
IntegerDivisionByZeroException? var73 = IntegerDivisionByZeroException();
89+
int var74 = 40;
90+
int? var75 = -44;
91+
Null var76 = null;
92+
Null? var77 = null;
93+
num var78 = 42;
94+
num? var79 = -85;
95+
RegExp var80 = new RegExp('M5O');
96+
RegExp? var81 = RegExp('Fs2');
97+
String var82 = 'W6';
98+
String? var83 = 'h';
99+
Runes var84 = Runes('+');
100+
Runes? var85 = Runes('');
101+
RuneIterator var86 = RuneIterator('\u2665w');
102+
RuneIterator? var87 = new RuneIterator('iNEK\u{1f600}');
103+
StringBuffer var88 = StringBuffer(47);
104+
StringBuffer? var89 = StringBuffer(5);
105+
Symbol var90 = new Symbol('q\u{1f600}');
106+
Symbol? var91 = new Symbol('&j5');
107+
Expando<bool> var92 = Expando<bool>(' ');
108+
Expando<bool>? var93 = Expando<bool>('f5B');
109+
Expando<int> var94 = Expando<int>('');
110+
Expando<int>? var95 = Expando<int>('\u{1f600}1AwU\u2665C');
111+
Expando<String> var96 = Expando<String>('Xzj(d');
112+
Expando<String>? var97 = Expando<String>('Ulsd');
113+
List<bool> var98 = <bool>[false, false, false];
114+
List<bool>? var99 = <bool>[false, false, false, true];
115+
List<int> var100 = Uint8ClampedList(17);
116+
List<int>? var101 = Uint8ClampedList(40);
117+
List<String> var102 = <String>['Y h', 'f', '\u{1f600}ip dQ', ')p', '2Qo'];
118+
List<String>? var103 = <String>[
119+
'BQ(6-',
120+
'\u{1f600}6\u2665yJaC',
121+
'3wa',
122+
'VJ',
123+
'k',
124+
''
125+
];
126+
Set<bool> var104 = <bool>{false, true, false};
127+
Set<bool>? var105 = <bool>{false, true, false, true, false, false};
128+
Set<int> var106 = <int>{44, 11};
129+
Set<int>? var107 = <int>{if (false) -94, 35};
130+
Set<String> var108 = <String>{''};
131+
Set<String>? var109 = <String>{'4'};
132+
Map<bool, bool> var110 = <bool, bool>{
133+
false: true,
134+
false: true,
135+
false: true,
136+
true: false
137+
};
138+
Map<bool, bool>? var111 = <bool, bool>{
139+
false: false,
140+
true: false,
141+
false: false,
142+
true: false
143+
};
144+
Map<bool, int> var112 = <bool, int>{
145+
true: 35,
146+
true: -4,
147+
true: -14,
148+
false: 30,
149+
false: -25
150+
};
151+
Map<bool, int>? var113 = null;
152+
Map<bool, String> var114 = <bool, String>{
153+
false: '7d',
154+
false: '\u{1f600}sv+',
155+
false: 'aY',
156+
false: 'dt'
157+
};
158+
Map<bool, String>? var115 = <bool, String>{
159+
false: '',
160+
false: '(G7\u{1f600}TBN',
161+
true: '',
162+
true: 'zZ-\u{1f600}\u2665)X',
163+
false: ')-9',
164+
false: ''
165+
};
166+
Map<int, bool> var116 = <int, bool>{
167+
3: true,
168+
10: true,
169+
-59: true,
170+
15: false,
171+
-36: true
172+
};
173+
Map<int, bool>? var117 = <int, bool>{16: false, 0: false};
174+
Map<int, int> var118 = <int, int>{
175+
-92: 29,
176+
-12: 40,
177+
-29: -26,
178+
-21: 1,
179+
13: 28,
180+
28: -44
181+
};
182+
Map<int, int>? var119 = <int, int>{-54: -37};
183+
Map<int, String> var120 = <int, String>{-80: '', -62: 'h', 40: 'C\u2665FVU'};
184+
Map<int, String>? var121 = <int, String>{
185+
...<int, String>{
186+
-8: 'S\u{1f600}kjRb',
187+
23: '4',
188+
-9223372034707292160: '',
189+
28: 'uz',
190+
-69: '@'
191+
},
192+
-53: 'nU6f',
193+
-5: '',
194+
-9223372034707292159: '',
195+
20: 'h7EB+'
196+
};
197+
Map<String, bool> var122 = <String, bool>{'8+G': false};
198+
Map<String, bool>? var123 = <String, bool>{'rM9m6k': true, '2': true};
199+
Map<String, int> var124 = <String, int>{'Z+p@\u2665Ww': -55};
200+
Map<String, int>? var125 = <String, int>{'9': -2147483647, 'uQ': 40};
201+
Map<String, String> var126 = <String, String>{
202+
'Q!': ' V\u{1f600}A2\u{1f600}',
203+
'z': '\u2665)',
204+
'cM@7\u{1f600}': 'XUT',
205+
'oLoh': 'bLPrZ',
206+
'YmR67nj': 'BdeuR'
207+
};
208+
Map<String, String>? var127 = <String, String>{'nOsSM1': '3 @yIj'};
209+
MapEntry<bool, bool> var128 = MapEntry<bool, bool>(true, false);
210+
MapEntry<bool, bool>? var129 = MapEntry<bool, bool>(true, false);
211+
MapEntry<bool, int> var130 = MapEntry<bool, int>(false, 13);
212+
MapEntry<bool, int>? var131 = MapEntry<bool, int>(true, 31);
213+
MapEntry<bool, String> var132 =
214+
MapEntry<bool, String>(true, '\u26653KE\u{1f600}');
215+
MapEntry<bool, String>? var133 = MapEntry<bool, String>(false, 'd');
216+
MapEntry<int, bool> var134 = MapEntry<int, bool>(46, true);
217+
MapEntry<int, bool>? var135 = MapEntry<int, bool>(34, false);
218+
MapEntry<int, int> var136 = MapEntry<int, int>(22, 30);
219+
MapEntry<int, int>? var137 = MapEntry<int, int>(30, 48);
220+
MapEntry<int, String> var138 = MapEntry<int, String>(46, 'by#@-nv');
221+
MapEntry<int, String>? var139 = MapEntry<int, String>(49, 'N@KF');
222+
MapEntry<String, bool> var140 =
223+
MapEntry<String, bool>('\u{1f600}km\u2665', true);
224+
MapEntry<String, bool>? var141 = new MapEntry<String, bool>('7PZX', false);
225+
MapEntry<String, int> var142 = new MapEntry<String, int>('OE', 27);
226+
227+
Map<String, Map<String, bool>> var446 = <String, Map<String, bool>>{
228+
'YJ\u{1f600}': <String, bool>{'BcKzE': true, 'Cz1A+n': false, '': true},
229+
'u!KEz9I': <String, bool>{
230+
'\u26653Hjr': true,
231+
'-\u{1f600}': true,
232+
'': true,
233+
')-': false,
234+
'ygN': true
235+
},
236+
'+R6': <String, bool>{'ta\u2665dKu)': true, 'rao9j': true},
237+
'YGXS!': <String, bool>{
238+
'': false,
239+
'6R': false,
240+
'': true,
241+
'MV\u{1f600} PP': true
242+
}
243+
};
244+
Map<MapEntry<String, int>, Map<int, bool>> var2000 =
245+
<MapEntry<String, int>, Map<int, bool>>{
246+
new MapEntry<String, int>('', 7): <int, bool>{
247+
-55: true,
248+
4294967295: false,
249+
48: true,
250+
-1: true,
251+
-96: false
252+
},
253+
MapEntry<String, int>('ORLVr', 1): <int, bool>{
254+
-21: false,
255+
4294967297: false,
256+
-12: false,
257+
-84: false
258+
}
259+
};
260+
261+
void foo1_Extension0() {
262+
var446.forEach((loc0, loc1) {
263+
for (int loc2 = 0; loc2 < 34; loc2++) {
264+
print(<MapEntry<bool, bool>, String>{
265+
MapEntry<bool, bool>(true, false): 'pqKqb',
266+
MapEntry<bool, bool>(true, true): 'Fkx',
267+
MapEntry<bool, bool>(true, false): '',
268+
MapEntry<bool, bool>(false, true): 'fJvVWOW',
269+
MapEntry<bool, bool>(false, true): 'q\u2665NR',
270+
MapEntry<bool, bool>(false, true): '\u2665'
271+
});
272+
var2000.forEach((loc3, loc4) {
273+
print(MapEntry<Map<bool, String>, MapEntry<int, bool>>(
274+
<bool, String>{false: 'L'}, MapEntry<int, bool>(42, false)));
275+
});
276+
}
277+
});
278+
}
279+
280+
main() {
281+
foo1_Extension0();
282+
283+
print(
284+
'$var0\n$var9\n$var11\n$var12\n$var13\n$var14\n$var15\n$var16\n$var17\n$var18\n$var19\n$var20\n$var21\n$var22\n$var23\n$var24\n$var25\n$var26\n$var27\n$var28\n$var29\n$var30\n$var31\n$var32\n$var33\n$var34\n$var35\n$var36\n$var37\n$var38\n$var39\n$var40\n$var41\n$var42\n$var43\n$var44\n$var45\n$var46\n$var47\n$var48\n$var49\n$var50\n$var51\n$var52\n$var53\n$var54\n$var55\n$var56\n$var57\n$var58\n$var59\n$var60\n$var61\n$var62\n$var63\n$var64\n$var65\n$var66\n$var67\n$var68\n$var69\n$var70\n$var71\n$var72\n$var73\n$var74\n$var75\n$var76\n$var77\n$var78\n$var79\n$var80\n$var81\n$var82\n$var83\n$var84\n$var85\n$var86\n$var87\n$var88\n$var89\n$var90\n$var91\n$var92\n$var93\n$var94\n$var95\n$var96\n$var97\n$var98\n$var99\n$var100\n$var101\n$var102\n$var103\n$var104\n$var105\n$var106\n$var107\n$var108\n$var109\n$var110\n$var111\n$var112\n$var113\n$var114\n$var115\n$var116\n$var117\n$var118\n$var119\n$var120\n$var121\n$var122\n$var123\n$var124\n$var125\n$var126\n$var127\n$var128\n$var129\n$var130\n$var131\n$var132\n');
285+
}

runtime/vm/runtime_entry.cc

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1697,7 +1697,7 @@ class PatchableCallHandler {
16971697

16981698
void DoUnlinkedCallAOT(const UnlinkedCall& unlinked,
16991699
const Function& target_function);
1700-
void DoMonomorphicMissAOT(const Object& data,
1700+
void DoMonomorphicMissAOT(const Object& old_data,
17011701
const Function& target_function);
17021702
void DoSingleTargetMissAOT(const SingleTargetCache& data,
17031703
const Function& target_function);
@@ -1712,7 +1712,7 @@ class PatchableCallHandler {
17121712
const Code& old_target,
17131713
const Function& target_function);
17141714

1715-
void DoMonomorphicMissJIT(const Object& data,
1715+
void DoMonomorphicMissJIT(const Object& old_data,
17161716
const Function& target_function);
17171717
void DoICDataMissJIT(const ICData& data,
17181718
const Object& old_data,
@@ -1839,14 +1839,14 @@ bool PatchableCallHandler::CanExtendSingleTargetRange(
18391839

18401840
#if defined(DART_PRECOMPILED_RUNTIME)
18411841
void PatchableCallHandler::DoMonomorphicMissAOT(
1842-
const Object& data,
1842+
const Object& old_data,
18431843
const Function& target_function) {
18441844
classid_t old_expected_cid;
1845-
if (data.IsSmi()) {
1846-
old_expected_cid = Smi::Cast(data).Value();
1845+
if (old_data.IsSmi()) {
1846+
old_expected_cid = Smi::Cast(old_data).Value();
18471847
} else {
1848-
RELEASE_ASSERT(data.IsMonomorphicSmiableCall());
1849-
old_expected_cid = MonomorphicSmiableCall::Cast(data).expected_cid();
1848+
RELEASE_ASSERT(old_data.IsMonomorphicSmiableCall());
1849+
old_expected_cid = MonomorphicSmiableCall::Cast(old_data).expected_cid();
18501850
}
18511851
const bool is_monomorphic_hit = old_expected_cid == receiver().GetClassId();
18521852
const auto& old_receiver_class = Class::Handle(
@@ -1900,20 +1900,17 @@ void PatchableCallHandler::DoMonomorphicMissAOT(
19001900

19011901
#if !defined(DART_PRECOMPILED_RUNTIME)
19021902
void PatchableCallHandler::DoMonomorphicMissJIT(
1903-
const Object& data,
1903+
const Object& old_data,
19041904
const Function& target_function) {
19051905
// Monomorphic calls use the ICData::entries() as their data.
1906-
const auto& ic_data_entries = Array::Cast(data);
1906+
const auto& old_ic_data_entries = Array::Cast(old_data);
19071907
// Any non-empty ICData::entries() has a backref to it's ICData.
19081908
const auto& ic_data =
1909-
ICData::Handle(zone_, ICData::ICDataOfEntriesArray(ic_data_entries));
1910-
1911-
const classid_t current_cid = receiver().GetClassId();
1912-
const classid_t old_cid = Smi::Value(Smi::RawCast(ic_data_entries.At(0)));
1913-
const bool same_receiver = current_cid == old_cid;
1909+
ICData::Handle(zone_, ICData::ICDataOfEntriesArray(old_ic_data_entries));
19141910

19151911
// The target didn't change, so we can stay inside monomorphic state.
1916-
if (same_receiver) {
1912+
if (ic_data.NumberOfChecksIs(1) &&
1913+
(ic_data.GetReceiverClassIdAt(0) == receiver().GetClassId())) {
19171914
// We got a miss because the old target code got disabled.
19181915
// Notice the reverse is not true: If the old code got disabled, the call
19191916
// might still have a different receiver then last time and possibly a
@@ -1929,10 +1926,10 @@ void PatchableCallHandler::DoMonomorphicMissJIT(
19291926
caller_frame_->pc());
19301927
}
19311928

1932-
// We stay in monomorphic state, patch the code object and keep the same
1933-
// data (old ICData entries array).
1929+
// We stay in monomorphic state, patch the code object and reload the icdata
1930+
// entries array.
19341931
const auto& code = Code::Handle(zone_, target_function.EnsureHasCode());
1935-
ASSERT(data.ptr() == ic_data.entries());
1932+
const auto& data = Object::Handle(zone_, ic_data.entries());
19361933
CodePatcher::PatchInstanceCallAt(caller_frame_->pc(), caller_code_, data,
19371934
code);
19381935
ReturnJIT(code, data, target_function);

0 commit comments

Comments
 (0)