Chromium Code Reviews| Index: dart/lib/compiler/implementation/native_handler.dart |
| =================================================================== |
| --- dart/lib/compiler/implementation/native_handler.dart (revision 5968) |
| +++ dart/lib/compiler/implementation/native_handler.dart (working copy) |
| @@ -178,16 +178,7 @@ |
| } |
| void handleSsaNative(SsaBuilder builder, Send node) { |
| - // Register NoSuchMethodException and captureStackTrace in the compiler |
| - // because the dynamic dispatch for native classes may use them. |
| Compiler compiler = builder.compiler; |
| - 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.
|
| - Compiler.NO_SUCH_METHOD_EXCEPTION); |
| - cls.ensureResolved(compiler); |
| - compiler.addToWorkList(cls.lookupConstructor(cls.name)); |
| - compiler.registerStaticUse( |
| - compiler.findHelper(new SourceString('captureStackTrace'))); |
| - |
| FunctionElement element = builder.work.element; |
| element.setNative(); |
| NativeEmitter nativeEmitter = compiler.emitter.nativeEmitter; |
| @@ -199,19 +190,19 @@ |
| if (element.name == const SourceString('typeName') |
| && element.isGetter() |
| && nativeEmitter.toNativeName(element.enclosingElement) == 'DOMType') { |
| - DartString jsCode = new DartString.literal( |
| - '${nativeEmitter.typeNameOfName}(#)'); |
| - List<HInstruction> inputs = |
| - <HInstruction>[builder.localsHandler.readThis()]; |
| - builder.push(new HForeign( |
| - jsCode, const LiteralDartString('String'), inputs)); |
| + 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.
|
| + const SourceString('getTypeNameOf')); |
| + HStatic method = new HStatic(element); |
| + builder.add(method); |
| + builder.push(new HInvokeStatic(Selector.INVOCATION_1, |
| + <HInstruction>[method, builder.localsHandler.readThis()])); |
| return; |
| } |
| HInstruction convertDartClosure(Element parameter) { |
| HInstruction local = builder.localsHandler.readLocal(parameter); |
| // TODO(ngeoffray): by better analyzing the function type and |
| - // its formal parameters, we could just pass, eg closure.$call$0. |
| + // its formal parameters, we could pass a method with a defined arity. |
| builder.push(new HStatic(builder.interceptors.getClosureConverter())); |
| List<HInstruction> callInputs = <HInstruction>[builder.pop(), local]; |
| HInstruction closure = new HInvokeStatic(Selector.INVOCATION_1, callInputs); |
| @@ -219,8 +210,30 @@ |
| return closure; |
| } |
| + |
| + // Check which pattern this native method follows: |
| + // 1) foo() native; hasBody = false, isRedirecting = false |
| + // 2) foo() native "bar"; hasBody = false, isRedirecting = true |
| + // 3) foo() native "return 42"; hasBody = true, isRedirecting = false |
| + bool hasBody = false; |
| + bool isRedirecting = false; |
| + String nativeMethodName = element.name.slowToString(); |
| + if (!node.arguments.isEmpty()) { |
| + if (!node.arguments.tail.isEmpty()) { |
| + builder.compiler.cancel('More than one argument to native'); |
| + } |
| + LiteralString jsCode = node.arguments.head; |
| + String str = jsCode.dartString.slowToString(); |
| + if (const RegExp(@'^[a-zA-Z][a-zA-Z_$0-9]*$').hasMatch(str)) { |
| + nativeMethodName = str; |
| + isRedirecting = true; |
| + } else { |
| + hasBody = true; |
| + } |
| + } |
| + |
| FunctionParameters parameters = element.computeParameters(builder.compiler); |
| - if (node.arguments.isEmpty()) { |
| + if (!hasBody) { |
| List<String> arguments = <String>[]; |
| List<HInstruction> inputs = <HInstruction>[]; |
| String receiver = ''; |
| @@ -238,7 +251,6 @@ |
| String foreignParameters = Strings.join(arguments, ','); |
| String dartMethodName; |
| - String nativeMethodName = element.name.slowToString(); |
| String nativeMethodCall; |
| if (element.kind == ElementKind.FUNCTION) { |
| @@ -321,9 +333,13 @@ |
| builder.current.addPhi(phi); |
| builder.stack.add(phi); |
| } |
| - |
| - } else if (!node.arguments.tail.isEmpty()) { |
| - builder.compiler.cancel('More than one argument to native'); |
| + if (isRedirecting) { |
| + // The parser creates a return node if there is no string literal |
| + // after the native keyword. In case of a redirecting method, there |
| + // is a string literal, therefore we must emit a return instruction |
| + // in the builder. |
| + builder.push(new HReturn(builder.pop())); |
| + } |
| } else { |
| // This is JS code written in a Dart file with the construct |
| // native """ ... """;. It does not work well with mangling, |