| 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 /** | 5 /** |
| 6 * Generates the code for all used classes in the program. Static fields (even | 6 * Generates the code for all used classes in the program. Static fields (even |
| 7 * in classes) are ignored, since they can be treated as non-class elements. | 7 * in classes) are ignored, since they can be treated as non-class elements. |
| 8 * | 8 * |
| 9 * The code for the containing (used) methods must exist in the [:universe:]. | 9 * The code for the containing (used) methods must exist in the [:universe:]. |
| 10 */ | 10 */ |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 null); | 283 null); |
| 284 String staticName = namer.isolatePropertyAccess(element); | 284 String staticName = namer.isolatePropertyAccess(element); |
| 285 int parameterCount = element.parameterCount(compiler); | 285 int parameterCount = element.parameterCount(compiler); |
| 286 String invocationName = | 286 String invocationName = |
| 287 namer.instanceMethodName(callElement.name, parameterCount); | 287 namer.instanceMethodName(callElement.name, parameterCount); |
| 288 buffer.add("$staticName.$invocationName = $staticName;\n"); | 288 buffer.add("$staticName.$invocationName = $staticName;\n"); |
| 289 addParameterStubs(callElement, staticName, buffer); | 289 addParameterStubs(callElement, staticName, buffer); |
| 290 } | 290 } |
| 291 } | 291 } |
| 292 | 292 |
| 293 void emitDynamicFunctionGetter(StringBuffer buffer, |
| 294 ClassElement enclosingClass, |
| 295 FunctionElement member) { |
| 296 // For every method that has the same name as a property-get we create a |
| 297 // getter that returns a bound closure. Say we have a class 'A' with method |
| 298 // 'foo' and somewhere in the code there is a dynamic property get of |
| 299 // 'foo'. Then we generate the following code (in pseudo Dart): |
| 300 // |
| 301 // class A { |
| 302 // foo(x, y, z) { ... } // Original function. |
| 303 // get foo() { return new BoundClosure499(this); } |
| 304 // } |
| 305 // class BoundClosure499 { |
| 306 // var self; |
| 307 // BoundClosure499(this.self); |
| 308 // $call3(x, y, z) { return self.foo(x, y, z); } |
| 309 // } |
| 310 |
| 311 // TODO(floitsch): share the closure classes with other classes |
| 312 // if they share methods with the same signature. |
| 313 |
| 314 // The closure class. |
| 315 SourceString name = const SourceString("BoundClosure"); |
| 316 CompilationUnitElement compilationUnit = member.getCompilationUnit(); |
| 317 ClassElement closureClassElement = new ClassElement(name, compilationUnit); |
| 318 String isolateAccess = namer.isolatePropertyAccess(closureClassElement); |
| 319 buffer.add("$isolateAccess = function(self) { this.self = self; };\n"); |
| 320 String prototype = "$isolateAccess.prototype"; |
| 321 |
| 322 // Now add the methods on the closure class. The instance method does not |
| 323 // have the correct name. Since [addParameterStubs] use the name to create |
| 324 // its stubs we simply create a fake element with the correct name. |
| 325 // Note: the callElement will not have the correct modifiers (in case |
| 326 // of static functions) and will not have any enclosingElement. |
| 327 FunctionElement callElement = |
| 328 new FunctionElement.from(Namer.CLOSURE_INVOCATION_NAME, member, null); |
| 329 |
| 330 int parameterCount = member.parameterCount(compiler); |
| 331 String invocationName = |
| 332 namer.instanceMethodName(callElement.name, parameterCount); |
| 333 String targetName = namer.instanceMethodName(member.name, parameterCount); |
| 334 List<String> arguments = new List<String>(parameterCount); |
| 335 for (int i = 0; i < parameterCount; i++) { |
| 336 arguments[i] = "arg$i"; |
| 337 } |
| 338 String joinedArgs = Strings.join(arguments, ", "); |
| 339 buffer.add("$prototype.$invocationName = function($joinedArgs) {\n"); |
| 340 buffer.add(" return this.self.$targetName($joinedArgs);\n"); |
| 341 buffer.add("};\n"); |
| 342 addParameterStubs(callElement, prototype, buffer); |
| 343 |
| 344 // And finally the getter. |
| 345 String enclosingClassAccess = namer.isolatePropertyAccess(enclosingClass); |
| 346 String enclosingClassPrototype = "$enclosingClassAccess.prototype"; |
| 347 String getterName = namer.getterName(member.name); |
| 348 String closureClass = namer.isolateAccess(closureClassElement); |
| 349 buffer.add("$enclosingClassPrototype.$getterName = function() {\n"); |
| 350 buffer.add(" return new $closureClass(this);\n"); |
| 351 buffer.add("};\n"); |
| 352 } |
| 353 |
| 354 void emitDynamicFunctionGetters(StringBuffer buffer) { |
| 355 for (ClassElement classElement in compiler.universe.instantiatedClasses) { |
| 356 for (ClassElement currentClass = classElement; |
| 357 currentClass !== null; |
| 358 currentClass = currentClass.superclass) { |
| 359 // TODO(floitsch): we don't need to deal with members that have been |
| 360 // overwritten by subclasses. |
| 361 for (Element member in currentClass.members) { |
| 362 if (!member.isInstanceMember()) continue; |
| 363 if (member.kind == ElementKind.FUNCTION) { |
| 364 if (compiler.universe.invokedGetters.contains(member.name)) { |
| 365 emitDynamicFunctionGetter(buffer, currentClass, member); |
| 366 } |
| 367 } |
| 368 } |
| 369 } |
| 370 } |
| 371 } |
| 372 |
| 293 void emitStaticNonFinalFieldInitializations(StringBuffer buffer) { | 373 void emitStaticNonFinalFieldInitializations(StringBuffer buffer) { |
| 294 // Adds initializations inside the Isolate constructor. | 374 // Adds initializations inside the Isolate constructor. |
| 295 // Example: | 375 // Example: |
| 296 // function Isolate() { | 376 // function Isolate() { |
| 297 // this.staticNonFinal = Isolate.prototype.someVal; | 377 // this.staticNonFinal = Isolate.prototype.someVal; |
| 298 // ... | 378 // ... |
| 299 // } | 379 // } |
| 300 CompileTimeConstantHandler constants = compiler.compileTimeConstantHandler; | 380 CompileTimeConstantHandler constants = compiler.compileTimeConstantHandler; |
| 301 List<VariableElement> staticNonFinalFields = | 381 List<VariableElement> staticNonFinalFields = |
| 302 constants.getStaticNonFinalFieldsForEmission(); | 382 constants.getStaticNonFinalFieldsForEmission(); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 String assembleProgram() { | 455 String assembleProgram() { |
| 376 measure(() { | 456 measure(() { |
| 377 StringBuffer buffer = new StringBuffer(); | 457 StringBuffer buffer = new StringBuffer(); |
| 378 buffer.add('function ${namer.ISOLATE}() {'); | 458 buffer.add('function ${namer.ISOLATE}() {'); |
| 379 emitStaticNonFinalFieldInitializations(buffer); | 459 emitStaticNonFinalFieldInitializations(buffer); |
| 380 buffer.add('}\n\n'); | 460 buffer.add('}\n\n'); |
| 381 emitClasses(buffer); | 461 emitClasses(buffer); |
| 382 emitNoSuchMethodCalls(buffer); | 462 emitNoSuchMethodCalls(buffer); |
| 383 emitStaticFunctions(buffer); | 463 emitStaticFunctions(buffer); |
| 384 emitStaticFunctionGetters(buffer); | 464 emitStaticFunctionGetters(buffer); |
| 465 emitDynamicFunctionGetters(buffer); |
| 385 emitStaticFinalFieldInitializations(buffer); | 466 emitStaticFinalFieldInitializations(buffer); |
| 386 buffer.add('var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); | 467 buffer.add('var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); |
| 387 Element main = compiler.mainApp.find(Compiler.MAIN); | 468 Element main = compiler.mainApp.find(Compiler.MAIN); |
| 388 buffer.add('${namer.isolateAccess(main)}();\n'); | 469 buffer.add('${namer.isolateAccess(main)}();\n'); |
| 389 compiler.assembledCode = buffer.toString(); | 470 compiler.assembledCode = buffer.toString(); |
| 390 }); | 471 }); |
| 391 return compiler.assembledCode; | 472 return compiler.assembledCode; |
| 392 } | 473 } |
| 393 } | 474 } |
| OLD | NEW |