@@ -164,8 +164,10 @@ class DynamicDispatcher {
164164 w.Instructions b = function.body;
165165 w.Local addLocal (w.ValueType type) => function.addLocal (type);
166166
167- Iterable <SelectorInfo >? selectors =
168- translator.dispatchTable.selectorsForDynamicNode (node);
167+ // We make a copy of the list of selectors to avoid concurrent
168+ // modification.
169+ List <SelectorInfo > selectors =
170+ translator.dispatchTable.selectorsForDynamicNode (node)? .toList () ?? [];
169171
170172 // Test the receiver's class ID against every class that implements a given
171173 // selector. If there is a match then invoke the selector, otherwise calls
@@ -179,47 +181,43 @@ class DynamicDispatcher {
179181 b.local_get (receiverVar);
180182 b.struct_get (translator.topInfo.struct, FieldIndex .classId);
181183 b.local_set (cidLocal);
182- if (selectors != null ) {
183- // We make a copy of the list of selectors to avoid concurrent
184- // modification.
185- for (SelectorInfo selector in selectors.toList ()) {
186- if (! preSelector (selector)) {
187- continue ;
188- }
189- translator.functions.activateSelector (selector);
190- for (int classID in selector.classIds) {
191- b.local_get (cidLocal);
192- b.i32_const (classID);
193- b.i32_eq ();
194- b.if_ ();
195-
196- // TODO(joshualitt): We should be able to make this a direct
197- // invocation. However, there appear to be corner cases today where we
198- // still need to do the actual invocation as an indirect call, for
199- // example if the procedure we are invoking is abstract.
200- b.comment ("Dynamic invocation of '${selector .name }'" );
201- b.local_get (receiverVar);
202- translator.convertType (function, translator.topInfo.nullableType,
203- selector.signature.inputs[0 ]);
204-
205- pushArguments (selector);
206- b.local_get (cidLocal);
207- int offset = selector.offset! ;
208- if (offset != 0 ) {
209- b.i32_const (offset);
210- b.i32_add ();
211- }
212- b.call_indirect (selector.signature);
213-
214- w.ValueType result =
215- translator.outputOrVoid (selector.signature.outputs);
216- translator.convertType (
217- function, result, translator.topInfo.nullableType);
218- onCallSuccess ();
219- b.end (); // end if
184+ for (SelectorInfo selector in selectors) {
185+ if (! preSelector (selector)) {
186+ continue ;
187+ }
188+ translator.functions.activateSelector (selector);
189+ for (int classID in selector.classIds) {
190+ b.local_get (cidLocal);
191+ b.i32_const (classID);
192+ b.i32_eq ();
193+ b.if_ ();
194+
195+ // TODO(joshualitt): We should be able to make this a direct
196+ // invocation. However, there appear to be corner cases today where we
197+ // still need to do the actual invocation as an indirect call, for
198+ // example if the procedure we are invoking is abstract.
199+ b.comment ("Dynamic invocation of '${selector .name }'" );
200+ b.local_get (receiverVar);
201+ translator.convertType (function, translator.topInfo.nullableType,
202+ selector.signature.inputs[0 ]);
203+
204+ pushArguments (selector);
205+ b.local_get (cidLocal);
206+ int offset = selector.offset! ;
207+ if (offset != 0 ) {
208+ b.i32_const (offset);
209+ b.i32_add ();
220210 }
221- postSelector ();
211+ b.call_indirect (selector.signature);
212+
213+ w.ValueType result =
214+ translator.outputOrVoid (selector.signature.outputs);
215+ translator.convertType (
216+ function, result, translator.topInfo.nullableType);
217+ onCallSuccess ();
218+ b.end (); // end if
222219 }
220+ postSelector ();
223221 }
224222
225223 // Handle the case where no test succeeded.
0 commit comments