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

Side by Side Diff: dart/lib/compiler/implementation/native_handler.dart

Issue 9909011: Implement redirecting natives. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 8 years, 8 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 | « dart/frog/tests/native/native.status ('k') | dart/lib/compiler/implementation/ssa/nodes.dart » ('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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 #library('native'); 5 #library('native');
6 #import('../../uri/uri.dart'); 6 #import('../../uri/uri.dart');
7 #import('leg.dart'); 7 #import('leg.dart');
8 #import('elements/elements.dart'); 8 #import('elements/elements.dart');
9 #import('scanner/scannerlib.dart'); 9 #import('scanner/scannerlib.dart');
10 #import('ssa/ssa.dart'); 10 #import('ssa/ssa.dart');
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 NativeEmitter nativeEmitter) { 171 NativeEmitter nativeEmitter) {
172 List<ClassElement> subtypes = nativeEmitter.subtypes[cls]; 172 List<ClassElement> subtypes = nativeEmitter.subtypes[cls];
173 if (subtypes == null) return false; 173 if (subtypes == null) return false;
174 for (ClassElement subtype in subtypes) { 174 for (ClassElement subtype in subtypes) {
175 if (subtype.lookupLocalMember(element.name) != null) return true; 175 if (subtype.lookupLocalMember(element.name) != null) return true;
176 } 176 }
177 return false; 177 return false;
178 } 178 }
179 179
180 void handleSsaNative(SsaBuilder builder, Send node) { 180 void handleSsaNative(SsaBuilder builder, Send node) {
181 // Register NoSuchMethodException and captureStackTrace in the compiler
182 // because the dynamic dispatch for native classes may use them.
183 Compiler compiler = builder.compiler; 181 Compiler compiler = builder.compiler;
184 ClassElement cls = compiler.coreLibrary.find(
floitsch 2012/03/29 23:25:52 this is not necessary anymore, because the functio
ngeoffray 2012/03/30 09:30:19 Correct.
185 Compiler.NO_SUCH_METHOD_EXCEPTION);
186 cls.ensureResolved(compiler);
187 compiler.addToWorkList(cls.lookupConstructor(cls.name));
188 compiler.registerStaticUse(
189 compiler.findHelper(new SourceString('captureStackTrace')));
190
191 FunctionElement element = builder.work.element; 182 FunctionElement element = builder.work.element;
192 element.setNative(); 183 element.setNative();
193 NativeEmitter nativeEmitter = compiler.emitter.nativeEmitter; 184 NativeEmitter nativeEmitter = compiler.emitter.nativeEmitter;
194 // If what we're compiling is a getter named 'typeName' and the native 185 // If what we're compiling is a getter named 'typeName' and the native
195 // class is named 'DOMType', we generate a call to the typeNameOf 186 // class is named 'DOMType', we generate a call to the typeNameOf
196 // function attached on the isolate. 187 // function attached on the isolate.
197 // The DOM classes assume that their 'typeName' property, which is 188 // The DOM classes assume that their 'typeName' property, which is
198 // not a JS property on the DOM types, returns the type name. 189 // not a JS property on the DOM types, returns the type name.
199 if (element.name == const SourceString('typeName') 190 if (element.name == const SourceString('typeName')
200 && element.isGetter() 191 && element.isGetter()
201 && nativeEmitter.toNativeName(element.enclosingElement) == 'DOMType') { 192 && nativeEmitter.toNativeName(element.enclosingElement) == 'DOMType') {
202 DartString jsCode = new DartString.literal( 193 Element element = compiler.findHelper(
floitsch 2012/03/29 23:25:52 Are you sure this doesn't fit on one line? If not,
ngeoffray 2012/03/30 09:30:19 Done.
203 '${nativeEmitter.typeNameOfName}(#)'); 194 const SourceString('getTypeNameOf'));
204 List<HInstruction> inputs = 195 HStatic method = new HStatic(element);
205 <HInstruction>[builder.localsHandler.readThis()]; 196 builder.add(method);
206 builder.push(new HForeign( 197 builder.push(new HInvokeStatic(Selector.INVOCATION_1,
207 jsCode, const LiteralDartString('String'), inputs)); 198 <HInstruction>[method, builder.localsHandler.readThis()]));
208 return; 199 return;
209 } 200 }
210 201
211 HInstruction convertDartClosure(Element parameter) { 202 HInstruction convertDartClosure(Element parameter) {
212 HInstruction local = builder.localsHandler.readLocal(parameter); 203 HInstruction local = builder.localsHandler.readLocal(parameter);
213 // TODO(ngeoffray): by better analyzing the function type and 204 // TODO(ngeoffray): by better analyzing the function type and
214 // its formal parameters, we could just pass, eg closure.$call$0. 205 // its formal parameters, we could pass a method with a defined arity.
215 builder.push(new HStatic(builder.interceptors.getClosureConverter())); 206 builder.push(new HStatic(builder.interceptors.getClosureConverter()));
216 List<HInstruction> callInputs = <HInstruction>[builder.pop(), local]; 207 List<HInstruction> callInputs = <HInstruction>[builder.pop(), local];
217 HInstruction closure = new HInvokeStatic(Selector.INVOCATION_1, callInputs); 208 HInstruction closure = new HInvokeStatic(Selector.INVOCATION_1, callInputs);
218 builder.add(closure); 209 builder.add(closure);
219 return closure; 210 return closure;
220 } 211 }
221 212
213
214 // Check which pattern this native method follows:
215 // 1) foo() native; hasBody = false, isRedirecting = false
216 // 2) foo() native "bar"; hasBody = false, isRedirecting = true
217 // 3) foo() native "return 42"; hasBody = true, isRedirecting = false
218 bool hasBody = false;
219 bool isRedirecting = false;
220 String nativeMethodName = element.name.slowToString();
221 if (!node.arguments.isEmpty()) {
222 if (!node.arguments.tail.isEmpty()) {
223 builder.compiler.cancel('More than one argument to native');
224 }
225 LiteralString jsCode = node.arguments.head;
226 String str = jsCode.dartString.slowToString();
227 if (const RegExp(@'^[a-zA-Z][a-zA-Z_$0-9]*$').hasMatch(str)) {
228 nativeMethodName = str;
229 isRedirecting = true;
230 } else {
231 hasBody = true;
232 }
233 }
234
222 FunctionParameters parameters = element.computeParameters(builder.compiler); 235 FunctionParameters parameters = element.computeParameters(builder.compiler);
223 if (node.arguments.isEmpty()) { 236 if (!hasBody) {
224 List<String> arguments = <String>[]; 237 List<String> arguments = <String>[];
225 List<HInstruction> inputs = <HInstruction>[]; 238 List<HInstruction> inputs = <HInstruction>[];
226 String receiver = ''; 239 String receiver = '';
227 if (element.isInstanceMember()) { 240 if (element.isInstanceMember()) {
228 receiver = '#.'; 241 receiver = '#.';
229 inputs.add(builder.localsHandler.readThis()); 242 inputs.add(builder.localsHandler.readThis());
230 } 243 }
231 parameters.forEachParameter((Element parameter) { 244 parameters.forEachParameter((Element parameter) {
232 Type type = parameter.computeType(compiler); 245 Type type = parameter.computeType(compiler);
233 HInstruction input = builder.localsHandler.readLocal(parameter); 246 HInstruction input = builder.localsHandler.readLocal(parameter);
234 if (type is FunctionType) input = convertDartClosure(parameter); 247 if (type is FunctionType) input = convertDartClosure(parameter);
235 inputs.add(input); 248 inputs.add(input);
236 arguments.add('#'); 249 arguments.add('#');
237 }); 250 });
238 String foreignParameters = Strings.join(arguments, ','); 251 String foreignParameters = Strings.join(arguments, ',');
239 252
240 String dartMethodName; 253 String dartMethodName;
241 String nativeMethodName = element.name.slowToString();
242 String nativeMethodCall; 254 String nativeMethodCall;
243 255
244 if (element.kind == ElementKind.FUNCTION) { 256 if (element.kind == ElementKind.FUNCTION) {
245 dartMethodName = builder.compiler.namer.instanceMethodName( 257 dartMethodName = builder.compiler.namer.instanceMethodName(
246 element.getLibrary(), element.name, parameters.parameterCount); 258 element.getLibrary(), element.name, parameters.parameterCount);
247 nativeMethodCall = '$receiver$nativeMethodName($foreignParameters)'; 259 nativeMethodCall = '$receiver$nativeMethodName($foreignParameters)';
248 } else if (element.kind == ElementKind.GETTER) { 260 } else if (element.kind == ElementKind.GETTER) {
249 dartMethodName = builder.compiler.namer.getterName( 261 dartMethodName = builder.compiler.namer.getterName(
250 element.getLibrary(), element.name); 262 element.getLibrary(), element.name);
251 nativeMethodCall = '$receiver$nativeMethodName'; 263 nativeMethodCall = '$receiver$nativeMethodName';
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 jsCode, const LiteralDartString('Object'), 326 jsCode, const LiteralDartString('Object'),
315 <HInstruction>[builder.localsHandler.readThis(), constant])); 327 <HInstruction>[builder.localsHandler.readThis(), constant]));
316 328
317 builder.handleIf(visitThen, visitElse); 329 builder.handleIf(visitThen, visitElse);
318 330
319 HPhi phi = new HPhi.manyInputs( 331 HPhi phi = new HPhi.manyInputs(
320 null, <HInstruction>[thenInstruction, elseInstruction]); 332 null, <HInstruction>[thenInstruction, elseInstruction]);
321 builder.current.addPhi(phi); 333 builder.current.addPhi(phi);
322 builder.stack.add(phi); 334 builder.stack.add(phi);
323 } 335 }
324 336 if (isRedirecting) {
325 } else if (!node.arguments.tail.isEmpty()) { 337 // The parser creates a return node if there is no string literal
326 builder.compiler.cancel('More than one argument to native'); 338 // after the native keyword. In case of a redirecting method, there
339 // is a string literal, therefore we must emit a return instruction
340 // in the builder.
341 builder.push(new HReturn(builder.pop()));
342 }
327 } else { 343 } else {
328 // This is JS code written in a Dart file with the construct 344 // This is JS code written in a Dart file with the construct
329 // native """ ... """;. It does not work well with mangling, 345 // native """ ... """;. It does not work well with mangling,
330 // but there should currently be no clash between leg mangling 346 // but there should currently be no clash between leg mangling
331 // and the library where this construct is being used. This 347 // and the library where this construct is being used. This
332 // mangling problem will go away once we switch these libraries 348 // mangling problem will go away once we switch these libraries
333 // to use Leg's 'JS' function. 349 // to use Leg's 'JS' function.
334 parameters.forEachParameter((Element parameter) { 350 parameters.forEachParameter((Element parameter) {
335 Type type = parameter.computeType(compiler); 351 Type type = parameter.computeType(compiler);
336 if (type is FunctionType) { 352 if (type is FunctionType) {
337 HInstruction jsClosure = convertDartClosure(parameter); 353 HInstruction jsClosure = convertDartClosure(parameter);
338 // Because the JS code references the argument name directly, 354 // Because the JS code references the argument name directly,
339 // we must keep the name and assign the JS closure to it. 355 // we must keep the name and assign the JS closure to it.
340 builder.add(new HForeign( 356 builder.add(new HForeign(
341 new DartString.literal('${parameter.name.slowToString()} = #'), 357 new DartString.literal('${parameter.name.slowToString()} = #'),
342 const LiteralDartString('void'), 358 const LiteralDartString('void'),
343 <HInstruction>[jsClosure])); 359 <HInstruction>[jsClosure]));
344 } 360 }
345 }); 361 });
346 LiteralString jsCode = node.arguments.head; 362 LiteralString jsCode = node.arguments.head;
347 builder.push(new HForeign(jsCode.dartString, 363 builder.push(new HForeign(jsCode.dartString,
348 const LiteralDartString('Object'), 364 const LiteralDartString('Object'),
349 <HInstruction>[])); 365 <HInstruction>[]));
350 } 366 }
351 } 367 }
OLDNEW
« no previous file with comments | « dart/frog/tests/native/native.status ('k') | dart/lib/compiler/implementation/ssa/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698