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

Side by Side Diff: frog/var_member.dart

Issue 8540030: Fix dispatch on MemberSets to always go dynamic if needed. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 9 years, 1 month 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
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 /** A dynamic member stub. */ 5 /** A dynamic member stub. */
6 class VarMember { 6 class VarMember {
7 final String name; 7 final String name;
8 8
9 VarMember(this.name); 9 VarMember(this.name);
10 10
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 VarMethodStub(String name, this.member, this.args, this.body): super(name); 117 VarMethodStub(String name, this.member, this.args, this.body): super(name);
118 118
119 Type get returnType() => 119 Type get returnType() =>
120 member != null ? member.returnType : world.varType; 120 member != null ? member.returnType : world.varType;
121 121
122 String get typeName() => 122 String get typeName() =>
123 member != null ? member.declaringType.jsname : 'Object'; 123 member != null ? member.declaringType.jsname : 'Object';
124 124
125 void generate(CodeWriter code) { 125 void generate(CodeWriter code) {
126 code.write('$typeName.prototype.$name = '); 126 code.write('$typeName.prototype.$name = ');
127 generateBody(code); 127 generateBody(code, ';');
128 code.writeln(';');
129 } 128 }
130 129
131 void generateBody(CodeWriter code) { 130 void generateBody(CodeWriter code, String end) {
132 if (_useDirectCall(member, args)) { 131 if (_useDirectCall(member, args)) {
133 code.write('$typeName.prototype.${member.jsname}'); 132 code.writeln('$typeName.prototype.${member.jsname}$end');
134 } else { 133 } else {
135 code.enterBlock('function(${args.getCode()}) {'); 134 code.enterBlock('function(${args.getCode()}) {');
136 code.writeln('return ${body.code};'); 135 code.writeln('return ${body.code};');
137 code.exitBlock('}'); 136 code.exitBlock('}$end');
138 } 137 }
139 } 138 }
140 139
141 bool _useDirectCall(Member member, Arguments args) { 140 bool _useDirectCall(Member member, Arguments args) {
142 // TODO(jmesserly): for now disallow direct references to DOM types until we 141 // TODO(jmesserly): for now disallow direct references to DOM types until we
143 // figure out which types can be patched reliably. 142 // figure out which types can be patched reliably.
144 // I don't think our other native libs have this issue. 143 // I don't think our other native libs have this issue.
145 if (member is MethodMember && member.declaringType.library != world.dom) { 144 if (member is MethodMember && member.declaringType.library != world.dom) {
146 MethodMember method = member; 145 MethodMember method = member;
147 if (method.needsArgumentConversion(args)) { 146 if (method.needsArgumentConversion(args)) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 184
186 Value invoke(MethodGenerator context, Node node, Value target, Arguments args) { 185 Value invoke(MethodGenerator context, Node node, Value target, Arguments args) {
187 _invokeMembers(context, node); 186 _invokeMembers(context, node);
188 return super.invoke(context, node, target, args); 187 return super.invoke(context, node, target, args);
189 } 188 }
190 189
191 /** Invokes members to ensure they're generated. */ 190 /** Invokes members to ensure they're generated. */
192 _invokeMembers(MethodGenerator context, Node node) { 191 _invokeMembers(MethodGenerator context, Node node) {
193 if (_fallbackStubs != null) return; 192 if (_fallbackStubs != null) return;
194 193
194 var objectStub = null;
195 _fallbackStubs = []; 195 _fallbackStubs = [];
196 for (var member in members) { 196 for (var member in members) {
197 // Invoke the member with the stub args (this gives us the method body), 197 // Invoke the member with the stub args (this gives us the method body),
198 // then create the stub method. 198 // then create the stub method.
199 final target = new Value(member.declaringType, 'this', node.span); 199 final target = new Value(member.declaringType, 'this', node.span);
200 var result = member.invoke(context, node, target, args); 200 var result = member.invoke(context, node, target, args);
201 var stub = new VarMethodStub(name, member, args, result); 201 var stub = new VarMethodStub(name, member, args, result);
202 202
203 // Put the stub on the type directly if possible. Otherwise 203 // Put the stub on the type directly if possible. Otherwise
204 // put the stub on Object.prototype. 204 // put the stub on Object.prototype.
205 var type = member.declaringType; 205 var type = member.declaringType;
206 if (type.library != world.dom && !type.isObject) { 206 if (type.isObject) {
207 objectStub = stub;
208 } else if (type.library != world.dom) {
207 _addVarStub(type, stub); 209 _addVarStub(type, stub);
208 } else { 210 } else {
209 _fallbackStubs.add(stub); 211 _fallbackStubs.add(stub);
210 } 212 }
211 } 213 }
212 214
213 // Finally, invoke noSuchMethod 215 // Create a noSuchMethod fallback on Object if needed.
214 final target = new Value(world.objectType, 'this', node.span); 216 // Some methods, like toString and == already have a fallback on Object.
215 var result = target.invokeNoSuchMethod(context, baseName, node, args); 217 if (objectStub == null) {
216 var stub = new VarMethodStub(name, null, args, result); 218 final target = new Value(world.objectType, 'this', node.span);
219 var result = target.invokeNoSuchMethod(context, baseName, node, args);
220 objectStub = new VarMethodStub(name, null, args, result);
221 }
217 if (_fallbackStubs.length == 0) { 222 if (_fallbackStubs.length == 0) {
218 _addVarStub(world.objectType, stub); 223 _addVarStub(world.objectType, objectStub);
219 } else { 224 } else {
220 _fallbackStubs.add(stub); 225 _fallbackStubs.add(objectStub);
221 world.gen.corejs.useVarMethod = true; 226 world.gen.corejs.useVarMethod = true;
222 } 227 }
223 } 228 }
224 229
225 static _addVarStub(Type type, VarMember stub) { 230 static _addVarStub(Type type, VarMember stub) {
226 if (type.varStubs == null) type.varStubs = {}; 231 if (type.varStubs == null) type.varStubs = {};
227 type.varStubs[stub.name] = stub; 232 type.varStubs[stub.name] = stub;
228 } 233 }
229 234
230 /** 235 /**
231 * Generate var call fallbacks, like this: 236 * Generate var call fallbacks, like this:
232 * 237 *
233 * $varMethod('addEventListener$1$capture', { 238 * $varMethod('addEventListener$1$capture', {
234 * 'HTMLElement': function($0, capture) { 239 * 'HTMLElement': function($0, capture) {
235 * return this.addEventListener($0, capture); 240 * return this.addEventListener($0, capture);
236 * }, 241 * },
237 * 'SomeOtherDOMType': function($0, capture) { 242 * 'SomeOtherDOMType': function($0, capture) {
238 * return this.addEventListener($0, false, true, capture); 243 * return this.addEventListener($0, false, true, capture);
239 * }, 244 * },
240 * 'Object': function($0, capture) { 245 * 'Object': function($0, capture) {
241 * return this.noSuchMethod('addEventListener', [$0], 246 * return this.noSuchMethod('addEventListener', [$0],
242 * {'capture': capture}); 247 * {'capture': capture});
243 * } 248 * }
244 * }); 249 * });
245 */ 250 */
246 void generate(CodeWriter code) { 251 void generate(CodeWriter code) {
247 if (_fallbackStubs.length == 0) return; 252 if (_fallbackStubs.length == 0) return;
248 253
249 code.enterBlock('\$varMethod("$name", {'); 254 code.enterBlock('\$varMethod("$name", {');
250 var lastOne = _fallbackStubs[_fallbackStubs.length - 1]; 255 var lastOne = _fallbackStubs.last();
251 for (var stub in _fallbackStubs) { 256 for (var stub in _fallbackStubs) {
252 code.write('"${stub.typeName}": '); 257 code.write('"${stub.typeName}": ');
253 stub.generateBody(code); 258 stub.generateBody(code, stub == lastOne ? '' : ',');
254 code.writeln(stub == lastOne ? '' : ',');
255 } 259 }
256 code.exitBlock('});'); 260 code.exitBlock('});');
257 } 261 }
258 } 262 }
259 263
260 String _getCallStubName(String name, Arguments args) { 264 String _getCallStubName(String name, Arguments args) {
261 final nameBuilder = new StringBuffer('${name}\$${args.bareCount}'); 265 final nameBuilder = new StringBuffer('${name}\$${args.bareCount}');
262 for (int i = args.bareCount; i < args.length; i++) { 266 for (int i = args.bareCount; i < args.length; i++) {
263 nameBuilder.add('\$').add(args.getName(i)); 267 nameBuilder.add('\$').add(args.getName(i));
264 } 268 }
265 return nameBuilder.toString(); 269 return nameBuilder.toString();
266 } 270 }
OLDNEW
« frog/member.dart ('K') | « frog/type.dart ('k') | frog/world.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698