@@ -113,7 +113,6 @@ class DynamicDispatcher {
113
113
// all we care about is code size, we might do best to use constant maps or
114
114
// one function per selector. On the other hand, we could also try a hybrid
115
115
// IC like approach using globals, rewiring logic, and a state machine.
116
- // TODO(joshualitt): Handle the case of a null receiver.
117
116
w.Local cidLocal = addLocal (w.NumType .i32);
118
117
119
118
// Outer block searches through the methods and invokes the method if it
@@ -155,28 +154,26 @@ class DynamicDispatcher {
155
154
}
156
155
translator.functions.activateSelector (selector);
157
156
for (int classID in selector.classIds) {
157
+ final Reference target = selector.targets[classID]! ;
158
+ if (target.asMember.isAbstract) {
159
+ continue ;
160
+ }
161
+
158
162
b.local_get (cidLocal);
159
163
b.i32_const (classID);
160
164
b.i32_eq ();
161
165
b.if_ ();
162
166
163
- // TODO(joshualitt): We should be able to make this a direct
164
- // invocation. However, there appear to be corner cases today where we
165
- // still need to do the actual invocation as an indirect call, for
166
- // example if the procedure we are invoking is abstract.
167
167
b.comment ("Dynamic invocation of '${selector .name }'" );
168
168
b.local_get (receiverVar);
169
169
translator.convertType (function, translator.topInfo.nullableType,
170
170
selector.signature.inputs[0 ]);
171
171
172
172
pushArguments (selector);
173
- b.local_get (cidLocal);
174
- int offset = selector.offset! ;
175
- if (offset != 0 ) {
176
- b.i32_const (offset);
177
- b.i32_add ();
178
- }
179
- b.call_indirect (selector.signature);
173
+
174
+ final w.BaseFunction targetFunction =
175
+ translator.functions.getFunction (target);
176
+ b.call (targetFunction);
180
177
181
178
w.ValueType result =
182
179
translator.outputOrVoid (selector.signature.outputs);
0 commit comments