Chromium Code Reviews| OLD | NEW |
|---|---|
| 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('leg.dart'); | 6 #import('leg.dart'); |
| 7 #import('elements/elements.dart'); | 7 #import('elements/elements.dart'); |
| 8 #import('scanner/scannerlib.dart'); | 8 #import('scanner/scannerlib.dart'); |
| 9 #import('ssa/ssa.dart'); | 9 #import('ssa/ssa.dart'); |
| 10 #import('tree/tree.dart'); | 10 #import('tree/tree.dart'); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 121 i++; | 121 i++; |
| 122 inputs.add(builder.localsHandler.readThis()); | 122 inputs.add(builder.localsHandler.readThis()); |
| 123 } | 123 } |
| 124 parameters.forEachParameter((Element parameter) { | 124 parameters.forEachParameter((Element parameter) { |
| 125 arguments.add('\$$i'); | 125 arguments.add('\$$i'); |
| 126 inputs.add(builder.localsHandler.readLocal(parameter)); | 126 inputs.add(builder.localsHandler.readLocal(parameter)); |
| 127 i++; | 127 i++; |
| 128 }); | 128 }); |
| 129 String foreignParameters = Strings.join(arguments, ','); | 129 String foreignParameters = Strings.join(arguments, ','); |
| 130 | 130 |
| 131 String methodName = builder.compiler.namer.instanceMethodName( | 131 String dartMethodName; |
|
kasperl
2012/02/29 10:16:38
I guess this almost calls for an abstraction with
ngeoffray
2012/02/29 10:19:19
We have the element, but I'm not sure I want to po
| |
| 132 element.name, parameters.parameterCount); | 132 String nativeMethodName = element.name.slowToString(); |
| 133 String nativeMethodCall; | |
| 134 | |
| 135 if (element.kind == ElementKind.FUNCTION) { | |
| 136 dartMethodName = builder.compiler.namer.instanceMethodName( | |
| 137 element.name, parameters.parameterCount); | |
| 138 nativeMethodCall = '$receiver$nativeMethodName($foreignParameters)'; | |
| 139 } else if (element.kind == ElementKind.GETTER) { | |
| 140 dartMethodName = builder.compiler.namer.getterName(element.name); | |
| 141 nativeMethodCall = '$receiver$nativeMethodName'; | |
| 142 } else if (element.kind == ElementKind.SETTER) { | |
| 143 dartMethodName = builder.compiler.namer.setterName(element.name); | |
| 144 nativeMethodCall = '$receiver$nativeMethodName = $foreignParameters'; | |
| 145 } else { | |
| 146 builder.compiler.internalError('unexpected kind: "${element.kind}"', | |
| 147 element: element); | |
| 148 } | |
| 133 | 149 |
| 134 HInstruction thenInstruction; | 150 HInstruction thenInstruction; |
| 135 void visitThen() { | 151 void visitThen() { |
| 136 SourceString jsCode = new SourceString( | 152 SourceString jsCode = new SourceString(nativeMethodCall); |
| 137 '$receiver${element.name.slowToString()}($foreignParameters)'); | |
| 138 thenInstruction = | 153 thenInstruction = |
| 139 new HForeign(jsCode, const SourceString('Object'), inputs); | 154 new HForeign(jsCode, const SourceString('Object'), inputs); |
| 140 builder.add(thenInstruction); | 155 builder.add(thenInstruction); |
| 141 } | 156 } |
| 142 | 157 |
| 143 if (!element.isInstanceMember()) { | 158 if (!element.isInstanceMember()) { |
| 144 // If the method is a non-instance method, we just generate a direct | 159 // If the method is a non-instance method, we just generate a direct |
| 145 // call to the native method. | 160 // call to the native method. |
| 146 visitThen(); | 161 visitThen(); |
| 147 builder.stack.add(thenInstruction); | 162 builder.stack.add(thenInstruction); |
| 148 } else { | 163 } else { |
| 149 // If the method is an instance method, we generate the following code: | 164 // If the method is an instance method, we generate the following code: |
| 150 // function(params) { | 165 // function(params) { |
| 151 // return Object.getPrototypeOf(this).hasOwnProperty(methodName)) | 166 // return Object.getPrototypeOf(this).hasOwnProperty(dartMethodName)) |
| 152 // ? this.methodName(params) | 167 // ? this.methodName(params) |
| 153 // : Object.prototype.methodName.call(this, params); | 168 // : Object.prototype.methodName.call(this, params); |
| 154 // } | 169 // } |
| 155 // | 170 // |
| 156 // The property check at the beginning is to make sure we won't | 171 // The property check at the beginning is to make sure we won't |
| 157 // call the method from the super class, in case the prototype of | 172 // call the method from the super class, in case the prototype of |
| 158 // 'this' does not have the method yet. | 173 // 'this' does not have the method yet. |
| 159 // | 174 // |
| 160 // TODO(ngeoffray): We can avoid this if we know the class of this | 175 // TODO(ngeoffray): We can avoid this if we know the class of this |
| 161 // method does not have subclasses. | 176 // method does not have subclasses. |
| 162 HInstruction elseInstruction; | 177 HInstruction elseInstruction; |
| 163 void visitElse() { | 178 void visitElse() { |
| 164 SourceString jsCode = new SourceString('Object.prototype.$methodName'); | 179 SourceString jsCode = |
| 180 new SourceString('Object.prototype.$dartMethodName'); | |
| 165 HInstruction instruction = | 181 HInstruction instruction = |
| 166 new HForeign(jsCode, const SourceString('Object'), []); | 182 new HForeign(jsCode, const SourceString('Object'), []); |
| 167 builder.add(instruction); | 183 builder.add(instruction); |
| 168 List<HInstruction> elseInputs = new List<HInstruction>.from(inputs); | 184 List<HInstruction> elseInputs = new List<HInstruction>.from(inputs); |
| 169 elseInputs.add(instruction); | 185 elseInputs.add(instruction); |
| 170 String params = arguments.isEmpty() ? '' : ', $foreignParameters'; | 186 String params = arguments.isEmpty() ? '' : ', $foreignParameters'; |
| 171 jsCode = new SourceString('\$${i}.call(\$0$params)'); | 187 jsCode = new SourceString('\$${i}.call(\$0$params)'); |
| 172 elseInstruction = | 188 elseInstruction = |
| 173 new HForeign(jsCode, const SourceString('Object'), elseInputs); | 189 new HForeign(jsCode, const SourceString('Object'), elseInputs); |
| 174 builder.add(elseInstruction); | 190 builder.add(elseInstruction); |
| 175 } | 191 } |
| 176 | 192 |
| 177 HLiteral literal = builder.graph.addNewLiteralString( | 193 HLiteral literal = builder.graph.addNewLiteralString( |
| 178 new DartString.literal('$methodName')); | 194 new DartString.literal('$dartMethodName')); |
| 179 SourceString jsCode = new SourceString( | 195 SourceString jsCode = new SourceString( |
| 180 'Object.getPrototypeOf(\$0).hasOwnProperty(\$1)'); | 196 'Object.getPrototypeOf(\$0).hasOwnProperty(\$1)'); |
| 181 builder.push(new HForeign( | 197 builder.push(new HForeign( |
| 182 jsCode, const SourceString('Object'), | 198 jsCode, const SourceString('Object'), |
| 183 <HInstruction>[builder.localsHandler.readThis(), literal])); | 199 <HInstruction>[builder.localsHandler.readThis(), literal])); |
| 184 | 200 |
| 185 builder.handleIf(visitThen, visitElse); | 201 builder.handleIf(visitThen, visitElse); |
| 186 | 202 |
| 187 HPhi phi = new HPhi.manyInputs( | 203 HPhi phi = new HPhi.manyInputs( |
| 188 null, <HInstruction>[thenInstruction, elseInstruction]); | 204 null, <HInstruction>[thenInstruction, elseInstruction]); |
| 189 builder.current.addPhi(phi); | 205 builder.current.addPhi(phi); |
| 190 builder.stack.add(phi); | 206 builder.stack.add(phi); |
| 191 } | 207 } |
| 192 | 208 |
| 193 } else if (!node.arguments.tail.isEmpty()) { | 209 } else if (!node.arguments.tail.isEmpty()) { |
| 194 builder.compiler.cancel('More than one argument to native'); | 210 builder.compiler.cancel('More than one argument to native'); |
| 195 } else { | 211 } else { |
| 196 LiteralString jsCode = node.arguments.head; | 212 LiteralString jsCode = node.arguments.head; |
| 197 int start = jsCode.value.slowToString()[0] === '@' ? 1 : 0; | 213 int start = jsCode.value.slowToString()[0] === '@' ? 1 : 0; |
| 198 builder.push(new HForeign(builder.unquote(jsCode, start), | 214 builder.push(new HForeign(builder.unquote(jsCode, start), |
| 199 const SourceString('Object'), | 215 const SourceString('Object'), |
| 200 <HInstruction>[])); | 216 <HInstruction>[])); |
| 201 } | 217 } |
| 202 } | 218 } |
| OLD | NEW |