| 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 * A function element that represents a closure call. The signature is copied | 6 * A function element that represents a closure call. The signature is copied |
| 7 * from the given element. | 7 * from the given element. |
| 8 */ | 8 */ |
| 9 class ClosureInvocationElement extends FunctionElement { | 9 class ClosureInvocationElement extends FunctionElement { |
| 10 ClosureInvocationElement(SourceString name, | 10 ClosureInvocationElement(SourceString name, |
| 11 FunctionElement other) | 11 FunctionElement other) |
| 12 : super.from(name, other, other.enclosingElement); | 12 : super.from(name, other, other.enclosingElement); |
| 13 | 13 |
| 14 isInstanceMember() => true; | 14 isInstanceMember() => true; |
| 15 } | 15 } |
| 16 | 16 |
| 17 /** | 17 /** |
| 18 * Generates the code for all used classes in the program. Static fields (even | 18 * Generates the code for all used classes in the program. Static fields (even |
| 19 * in classes) are ignored, since they can be treated as non-class elements. | 19 * in classes) are ignored, since they can be treated as non-class elements. |
| 20 * | 20 * |
| 21 * The code for the containing (used) methods must exist in the [:universe:]. | 21 * The code for the containing (used) methods must exist in the [:universe:]. |
| 22 */ | 22 */ |
| 23 class CodeEmitterTask extends CompilerTask { | 23 class CodeEmitterTask extends CompilerTask { |
| 24 bool needsInheritFunction = false; | 24 bool needsInheritFunction = false; |
| 25 bool needsDefineClass = false; | 25 bool needsDefineClass = false; |
| 26 bool needsClosureClass = false; | 26 bool needsClosureClass = false; |
| 27 final Namer namer; | 27 final Namer namer; |
| 28 NativeEmitter nativeEmitter; | 28 NativeEmitter nativeEmitter; |
| 29 StringBuffer boundClosureBuffer; | 29 CodeBuffer boundClosureBuffer; |
| 30 StringBuffer mainBuffer; | 30 CodeBuffer mainBuffer; |
| 31 /** Shorter access to [isolatePropertiesName]. Both here in the code, as | 31 /** Shorter access to [isolatePropertiesName]. Both here in the code, as |
| 32 well as in the generated code. */ | 32 well as in the generated code. */ |
| 33 String isolateProperties; | 33 String isolateProperties; |
| 34 String classesCollector; | 34 String classesCollector; |
| 35 final Map<int, String> boundClosureCache; | 35 final Map<int, String> boundClosureCache; |
| 36 | 36 |
| 37 final bool generateSourceMap; | 37 final bool generateSourceMap; |
| 38 final SourceMapBuilder sourceMapBuilder; | 38 final SourceMapBuilder sourceMapBuilder; |
| 39 | 39 |
| 40 CodeEmitterTask(Compiler compiler, [bool generateSourceMap = false]) | 40 CodeEmitterTask(Compiler compiler, [bool generateSourceMap = false]) |
| 41 : namer = compiler.namer, | 41 : namer = compiler.namer, |
| 42 boundClosureBuffer = new StringBuffer(), | 42 boundClosureBuffer = new CodeBuffer(), |
| 43 mainBuffer = new StringBuffer(), | 43 mainBuffer = new CodeBuffer(), |
| 44 boundClosureCache = new Map<int, String>(), | 44 boundClosureCache = new Map<int, String>(), |
| 45 generateSourceMap = generateSourceMap, | 45 generateSourceMap = generateSourceMap, |
| 46 sourceMapBuilder = new SourceMapBuilder(), | 46 sourceMapBuilder = new SourceMapBuilder(), |
| 47 super(compiler) { | 47 super(compiler) { |
| 48 nativeEmitter = new NativeEmitter(this); | 48 nativeEmitter = new NativeEmitter(this); |
| 49 } | 49 } |
| 50 | 50 |
| 51 String get name() => 'CodeEmitter'; | 51 String get name() => 'CodeEmitter'; |
| 52 | 52 |
| 53 String get defineClassName() | 53 String get defineClassName() |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 } | 226 } |
| 227 str += "}\\n"; | 227 str += "}\\n"; |
| 228 var newIsolate = new Function(str); | 228 var newIsolate = new Function(str); |
| 229 newIsolate.prototype = isolatePrototype; | 229 newIsolate.prototype = isolatePrototype; |
| 230 isolatePrototype.constructor = newIsolate; | 230 isolatePrototype.constructor = newIsolate; |
| 231 newIsolate.${namer.ISOLATE_PROPERTIES} = isolateProperties; | 231 newIsolate.${namer.ISOLATE_PROPERTIES} = isolateProperties; |
| 232 return newIsolate; | 232 return newIsolate; |
| 233 }"""; | 233 }"""; |
| 234 } | 234 } |
| 235 | 235 |
| 236 void addDefineClassAndFinishClassFunctionsIfNecessary(StringBuffer buffer) { | 236 void addDefineClassAndFinishClassFunctionsIfNecessary(CodeBuffer buffer) { |
| 237 if (needsDefineClass) { | 237 if (needsDefineClass) { |
| 238 String isolate = namer.ISOLATE; | 238 String isolate = namer.ISOLATE; |
| 239 buffer.add("$defineClassName = $defineClassFunction;\n"); | 239 buffer.add("$defineClassName = $defineClassFunction;\n"); |
| 240 buffer.add("$pendingClassesName = {};\n"); | 240 buffer.add("$pendingClassesName = {};\n"); |
| 241 buffer.add("$finishClassesName = $finishClassesFunction;\n"); | 241 buffer.add("$finishClassesName = $finishClassesFunction;\n"); |
| 242 } | 242 } |
| 243 } | 243 } |
| 244 | 244 |
| 245 void emitFinishIsolateConstructor(StringBuffer buffer) { | 245 void emitFinishIsolateConstructor(CodeBuffer buffer) { |
| 246 String name = finishIsolateConstructorName; | 246 String name = finishIsolateConstructorName; |
| 247 String value = finishIsolateConstructorFunction; | 247 String value = finishIsolateConstructorFunction; |
| 248 buffer.add("$name = $value;\n"); | 248 buffer.add("$name = $value;\n"); |
| 249 } | 249 } |
| 250 | 250 |
| 251 void emitFinishIsolateConstructorInvocation(StringBuffer buffer) { | 251 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { |
| 252 String isolate = namer.ISOLATE; | 252 String isolate = namer.ISOLATE; |
| 253 buffer.add("$isolate = $finishIsolateConstructorName($isolate);\n"); | 253 buffer.add("$isolate = $finishIsolateConstructorName($isolate);\n"); |
| 254 } | 254 } |
| 255 | 255 |
| 256 void addParameterStub(FunctionElement member, | 256 void addParameterStub(FunctionElement member, |
| 257 Selector selector, | 257 Selector selector, |
| 258 DefineMemberFunction defineInstanceMember) { | 258 DefineMemberFunction defineInstanceMember) { |
| 259 FunctionSignature parameters = member.computeSignature(compiler); | 259 FunctionSignature parameters = member.computeSignature(compiler); |
| 260 int positionalArgumentCount = selector.positionalArgumentCount; | 260 int positionalArgumentCount = selector.positionalArgumentCount; |
| 261 if (positionalArgumentCount == parameters.parameterCount) { | 261 if (positionalArgumentCount == parameters.parameterCount) { |
| 262 assert(selector.namedArgumentCount == 0); | 262 assert(selector.namedArgumentCount == 0); |
| 263 return; | 263 return; |
| 264 } | 264 } |
| 265 ConstantHandler handler = compiler.constantHandler; | 265 ConstantHandler handler = compiler.constantHandler; |
| 266 List<SourceString> names = selector.getOrderedNamedArguments(); | 266 List<SourceString> names = selector.getOrderedNamedArguments(); |
| 267 | 267 |
| 268 String invocationName = | 268 String invocationName = |
| 269 namer.instanceMethodInvocationName(member.getLibrary(), member.name, | 269 namer.instanceMethodInvocationName(member.getLibrary(), member.name, |
| 270 selector); | 270 selector); |
| 271 StringBuffer buffer = new StringBuffer(); | 271 CodeBuffer buffer = new CodeBuffer(); |
| 272 buffer.add('function('); | 272 buffer.add('function('); |
| 273 | 273 |
| 274 // The parameters that this stub takes. | 274 // The parameters that this stub takes. |
| 275 List<String> parametersBuffer = new List<String>(selector.argumentCount); | 275 List<String> parametersBuffer = new List<String>(selector.argumentCount); |
| 276 // The arguments that will be passed to the real method. | 276 // The arguments that will be passed to the real method. |
| 277 List<String> argumentsBuffer = new List<String>(parameters.parameterCount); | 277 List<String> argumentsBuffer = new List<String>(parameters.parameterCount); |
| 278 | 278 |
| 279 // We fill the lists depending on the selector. For example, | 279 // We fill the lists depending on the selector. For example, |
| 280 // take method foo: | 280 // take method foo: |
| 281 // foo(a, b, [c, d]); | 281 // foo(a, b, [c, d]); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 } else { | 328 } else { |
| 329 Constant value = handler.initialVariableValues[element]; | 329 Constant value = handler.initialVariableValues[element]; |
| 330 if (value == null) { | 330 if (value == null) { |
| 331 argumentsBuffer[count] = NullConstant.JsNull; | 331 argumentsBuffer[count] = NullConstant.JsNull; |
| 332 } else { | 332 } else { |
| 333 if (!value.isNull()) { | 333 if (!value.isNull()) { |
| 334 // If the value is the null constant, we should not pass it | 334 // If the value is the null constant, we should not pass it |
| 335 // down to the native method. | 335 // down to the native method. |
| 336 indexOfLastOptionalArgumentInParameters = count; | 336 indexOfLastOptionalArgumentInParameters = count; |
| 337 } | 337 } |
| 338 StringBuffer argumentBuffer = new StringBuffer(); | 338 CodeBuffer argumentBuffer = new CodeBuffer(); |
| 339 handler.writeConstant(argumentBuffer, value); | 339 handler.writeConstant(argumentBuffer, value); |
| 340 argumentsBuffer[count] = argumentBuffer.toString(); | 340 argumentsBuffer[count] = argumentBuffer.toString(); |
| 341 } | 341 } |
| 342 } | 342 } |
| 343 } | 343 } |
| 344 count++; | 344 count++; |
| 345 }); | 345 }); |
| 346 String parametersString = Strings.join(parametersBuffer, ","); | 346 String parametersString = Strings.join(parametersBuffer, ","); |
| 347 buffer.add('$parametersString) {\n'); | 347 buffer.add('$parametersString) {\n'); |
| 348 | 348 |
| 349 if (member.isNative()) { | 349 if (member.isNative()) { |
| 350 nativeEmitter.generateParameterStub( | 350 nativeEmitter.generateParameterStub( |
| 351 member, invocationName, parametersString, argumentsBuffer, | 351 member, invocationName, parametersString, argumentsBuffer, |
| 352 indexOfLastOptionalArgumentInParameters, buffer); | 352 indexOfLastOptionalArgumentInParameters, buffer); |
| 353 } else { | 353 } else { |
| 354 String arguments = Strings.join(argumentsBuffer, ","); | 354 String arguments = Strings.join(argumentsBuffer, ","); |
| 355 buffer.add(' return this.${namer.getName(member)}($arguments)'); | 355 buffer.add(' return this.${namer.getName(member)}($arguments)'); |
| 356 } | 356 } |
| 357 buffer.add('\n}'); | 357 buffer.add('\n}'); |
| 358 defineInstanceMember(invocationName, buffer.toString()); | 358 defineInstanceMember(invocationName, buffer); |
| 359 } | 359 } |
| 360 | 360 |
| 361 void addParameterStubs(FunctionElement member, | 361 void addParameterStubs(FunctionElement member, |
| 362 DefineMemberFunction defineInstanceMember) { | 362 DefineMemberFunction defineInstanceMember) { |
| 363 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; | 363 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; |
| 364 if (selectors == null) return; | 364 if (selectors == null) return; |
| 365 for (Selector selector in selectors) { | 365 for (Selector selector in selectors) { |
| 366 if (!selector.applies(member, compiler)) continue; | 366 if (!selector.applies(member, compiler)) continue; |
| 367 addParameterStub(member, selector, defineInstanceMember); | 367 addParameterStub(member, selector, defineInstanceMember); |
| 368 } | 368 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 389 void addInstanceMember(Element member, | 389 void addInstanceMember(Element member, |
| 390 DefineMemberFunction defineInstanceMember) { | 390 DefineMemberFunction defineInstanceMember) { |
| 391 // TODO(floitsch): we don't need to deal with members of | 391 // TODO(floitsch): we don't need to deal with members of |
| 392 // uninstantiated classes, that have been overwritten by subclasses. | 392 // uninstantiated classes, that have been overwritten by subclasses. |
| 393 | 393 |
| 394 if (member.kind === ElementKind.FUNCTION | 394 if (member.kind === ElementKind.FUNCTION |
| 395 || member.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY | 395 || member.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY |
| 396 || member.kind === ElementKind.GETTER | 396 || member.kind === ElementKind.GETTER |
| 397 || member.kind === ElementKind.SETTER) { | 397 || member.kind === ElementKind.SETTER) { |
| 398 if (member.modifiers !== null && member.modifiers.isAbstract()) return; | 398 if (member.modifiers !== null && member.modifiers.isAbstract()) return; |
| 399 CodeBlock codeBlock = compiler.codegenWorld.generatedCode[member]; | 399 CodeBuffer codeBuffer = compiler.codegenWorld.generatedCode[member]; |
| 400 if (codeBlock == null) return; | 400 if (codeBuffer == null) return; |
| 401 defineInstanceMember(namer.getName(member), | 401 defineInstanceMember(namer.getName(member), codeBuffer); |
| 402 codeBlock.code, | 402 codeBuffer = compiler.codegenWorld.generatedBailoutCode[member]; |
| 403 codeBlock.sourceMappings); | 403 if (codeBuffer !== null) { |
| 404 codeBlock = compiler.codegenWorld.generatedBailoutCode[member]; | 404 defineInstanceMember(compiler.namer.getBailoutName(member), codeBuffer); |
| 405 if (codeBlock !== null) { | |
| 406 defineInstanceMember(compiler.namer.getBailoutName(member), | |
| 407 codeBlock.code, | |
| 408 codeBlock.sourceMappings); | |
| 409 } | 405 } |
| 410 FunctionElement function = member; | 406 FunctionElement function = member; |
| 411 FunctionSignature parameters = function.computeSignature(compiler); | 407 FunctionSignature parameters = function.computeSignature(compiler); |
| 412 if (!parameters.optionalParameters.isEmpty()) { | 408 if (!parameters.optionalParameters.isEmpty()) { |
| 413 addParameterStubs(member, defineInstanceMember); | 409 addParameterStubs(member, defineInstanceMember); |
| 414 } | 410 } |
| 415 } else if (member.kind === ElementKind.FIELD) { | 411 } else if (member.kind === ElementKind.FIELD) { |
| 416 SourceString name = member.name; | 412 SourceString name = member.name; |
| 417 ClassElement cls = member.getEnclosingClass(); | 413 ClassElement cls = member.getEnclosingClass(); |
| 418 if (cls.lookupSuperMember(name) !== null) { | 414 if (cls.lookupSuperMember(name) !== null) { |
| 419 String fieldName = namer.instanceFieldName(cls, name); | 415 String fieldName = namer.instanceFieldName(cls, name); |
| 416 CodeBuffer getterBuffer = new CodeBuffer(); |
| 417 getterBuffer.add('function() {\n return this.$fieldName;\n }'); |
| 420 defineInstanceMember(namer.getterName(cls.getLibrary(), name), | 418 defineInstanceMember(namer.getterName(cls.getLibrary(), name), |
| 421 'function() {\n return this.$fieldName;\n }'); | 419 getterBuffer); |
| 420 CodeBuffer setterBuffer = new CodeBuffer(); |
| 421 setterBuffer.add('function(x) {\n this.$fieldName = x;\n }'); |
| 422 defineInstanceMember(namer.setterName(cls.getLibrary(), name), | 422 defineInstanceMember(namer.setterName(cls.getLibrary(), name), |
| 423 'function(x) {\n this.$fieldName = x;\n }'); | 423 setterBuffer); |
| 424 } | 424 } |
| 425 } else { | 425 } else { |
| 426 compiler.internalError('unexpected kind: "${member.kind}"', | 426 compiler.internalError('unexpected kind: "${member.kind}"', |
| 427 element: member); | 427 element: member); |
| 428 } | 428 } |
| 429 emitExtraAccessors(member, defineInstanceMember); | 429 emitExtraAccessors(member, defineInstanceMember); |
| 430 } | 430 } |
| 431 | 431 |
| 432 Set<Element> emitClassFields(ClassElement classElement, StringBuffer buffer) { | 432 Set<Element> emitClassFields(ClassElement classElement, CodeBuffer buffer) { |
| 433 // If the class is never instantiated we still need to set it up for | 433 // If the class is never instantiated we still need to set it up for |
| 434 // inheritance purposes, but we can simplify its JavaScript constructor. | 434 // inheritance purposes, but we can simplify its JavaScript constructor. |
| 435 bool isInstantiated = | 435 bool isInstantiated = |
| 436 compiler.codegenWorld.instantiatedClasses.contains(classElement); | 436 compiler.codegenWorld.instantiatedClasses.contains(classElement); |
| 437 | 437 |
| 438 bool isFirstField = true; | 438 bool isFirstField = true; |
| 439 void addField(ClassElement enclosingClass, Element member) { | 439 void addField(ClassElement enclosingClass, Element member) { |
| 440 assert(!member.isNative()); | 440 assert(!member.isNative()); |
| 441 // See if we can dynamically create getters and setters. | 441 // See if we can dynamically create getters and setters. |
| 442 // We can only generate getters and setters for [classElement] since | 442 // We can only generate getters and setters for [classElement] since |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 // generate the field getter/setter dynamically. Since this is only | 479 // generate the field getter/setter dynamically. Since this is only |
| 480 // allowed on fields that are in [classElement] we don't need to visit | 480 // allowed on fields that are in [classElement] we don't need to visit |
| 481 // superclasses for non-instantiated classes. | 481 // superclasses for non-instantiated classes. |
| 482 classElement.forEachInstanceField( | 482 classElement.forEachInstanceField( |
| 483 addField, | 483 addField, |
| 484 includeBackendMembers: true, | 484 includeBackendMembers: true, |
| 485 includeSuperMembers: isInstantiated && !classElement.isNative()); | 485 includeSuperMembers: isInstantiated && !classElement.isNative()); |
| 486 } | 486 } |
| 487 | 487 |
| 488 void emitInstanceMembers(ClassElement classElement, | 488 void emitInstanceMembers(ClassElement classElement, |
| 489 StringBuffer buffer, | 489 CodeBuffer buffer, |
| 490 bool needsLeadingComma) { | 490 bool needsLeadingComma) { |
| 491 bool needsComma = needsLeadingComma; | 491 bool needsComma = needsLeadingComma; |
| 492 void defineInstanceMember(String name, | 492 void defineInstanceMember(String name, CodeBuffer memberBuffer) { |
| 493 String value, | |
| 494 [List<SourceMappingEntry> sourceMappings]) { | |
| 495 if (needsComma) buffer.add(','); | 493 if (needsComma) buffer.add(','); |
| 496 needsComma = true; | 494 needsComma = true; |
| 497 buffer.add('\n'); | 495 buffer.add('\n'); |
| 498 buffer.add(' $name: '); | 496 buffer.add(' $name: '); |
| 499 sourceMapBuilder.addCodeBlock(sourceMappings, buffer.length); | 497 addMappings(memberBuffer, buffer.length); |
| 500 buffer.add('$value'); | 498 buffer.add(memberBuffer); |
| 501 } | 499 } |
| 502 | 500 |
| 503 classElement.forEachMember(includeBackendMembers: true, | 501 classElement.forEachMember(includeBackendMembers: true, |
| 504 f: (ClassElement enclosing, Element member) { | 502 f: (ClassElement enclosing, Element member) { |
| 505 if (member.isInstanceMember()) { | 503 if (member.isInstanceMember()) { |
| 506 addInstanceMember(member, defineInstanceMember); | 504 addInstanceMember(member, defineInstanceMember); |
| 507 } | 505 } |
| 508 }); | 506 }); |
| 509 | 507 |
| 510 generateTypeTests(classElement, (Element other) { | 508 generateTypeTests(classElement, (Element other) { |
| 509 String code; |
| 511 if (nativeEmitter.requiresNativeIsCheck(other)) { | 510 if (nativeEmitter.requiresNativeIsCheck(other)) { |
| 512 defineInstanceMember(namer.operatorIs(other), | 511 code = 'function() { return true; }'; |
| 513 'function() { return true; }'); | |
| 514 } else { | 512 } else { |
| 515 defineInstanceMember(namer.operatorIs(other), 'true'); | 513 code = 'true'; |
| 516 } | 514 } |
| 515 CodeBuffer buffer = new CodeBuffer(); |
| 516 buffer.add(code); |
| 517 defineInstanceMember(namer.operatorIs(other), buffer); |
| 517 }); | 518 }); |
| 518 | 519 |
| 519 if (classElement === compiler.objectClass && compiler.enabledNoSuchMethod) { | 520 if (classElement === compiler.objectClass && compiler.enabledNoSuchMethod) { |
| 520 // Emit the noSuchMethods on the Object prototype now, so that | 521 // Emit the noSuchMethods on the Object prototype now, so that |
| 521 // the code in the dynamicMethod can find them. Note that the | 522 // the code in the dynamicMethod can find them. Note that the |
| 522 // code in dynamicMethod is invoked before analyzing the full JS | 523 // code in dynamicMethod is invoked before analyzing the full JS |
| 523 // script. | 524 // script. |
| 524 emitNoSuchMethodCalls(defineInstanceMember); | 525 emitNoSuchMethodCalls(defineInstanceMember); |
| 525 } | 526 } |
| 526 } | 527 } |
| 527 | 528 |
| 528 void generateClass(ClassElement classElement, StringBuffer buffer) { | 529 void generateClass(ClassElement classElement, CodeBuffer buffer) { |
| 529 if (classElement.isNative()) { | 530 if (classElement.isNative()) { |
| 530 nativeEmitter.generateNativeClass(classElement); | 531 nativeEmitter.generateNativeClass(classElement); |
| 531 return; | 532 return; |
| 532 } else { | 533 } else { |
| 533 // TODO(ngeoffray): Instead of switching between buffer, we | 534 // TODO(ngeoffray): Instead of switching between buffer, we |
| 534 // should create code sections, and decide where to emit them at | 535 // should create code sections, and decide where to emit them at |
| 535 // the end. | 536 // the end. |
| 536 buffer = mainBuffer; | 537 buffer = mainBuffer; |
| 537 } | 538 } |
| 538 | 539 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 Element element = interfaceType.element; | 573 Element element = interfaceType.element; |
| 573 if (!alreadyGenerated.contains(element) && | 574 if (!alreadyGenerated.contains(element) && |
| 574 compiler.codegenWorld.isChecks.contains(element)) { | 575 compiler.codegenWorld.isChecks.contains(element)) { |
| 575 alreadyGenerated.add(element); | 576 alreadyGenerated.add(element); |
| 576 generateTypeTest(element); | 577 generateTypeTest(element); |
| 577 } | 578 } |
| 578 generateInterfacesIsTests(element, generateTypeTest, alreadyGenerated); | 579 generateInterfacesIsTests(element, generateTypeTest, alreadyGenerated); |
| 579 } | 580 } |
| 580 } | 581 } |
| 581 | 582 |
| 582 void emitClasses(StringBuffer buffer) { | 583 void emitClasses(CodeBuffer buffer) { |
| 583 Set<ClassElement> instantiatedClasses = | 584 Set<ClassElement> instantiatedClasses = |
| 584 compiler.codegenWorld.instantiatedClasses; | 585 compiler.codegenWorld.instantiatedClasses; |
| 585 Set<ClassElement> neededClasses = | 586 Set<ClassElement> neededClasses = |
| 586 new Set<ClassElement>.from(instantiatedClasses); | 587 new Set<ClassElement>.from(instantiatedClasses); |
| 587 for (ClassElement element in instantiatedClasses) { | 588 for (ClassElement element in instantiatedClasses) { |
| 588 for (ClassElement superclass = element.superclass; | 589 for (ClassElement superclass = element.superclass; |
| 589 superclass !== null; | 590 superclass !== null; |
| 590 superclass = superclass.superclass) { | 591 superclass = superclass.superclass) { |
| 591 if (neededClasses.contains(superclass)) break; | 592 if (neededClasses.contains(superclass)) break; |
| 592 neededClasses.add(superclass); | 593 neededClasses.add(superclass); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 605 } | 606 } |
| 606 | 607 |
| 607 // The closure class could have become necessary because of the generation | 608 // The closure class could have become necessary because of the generation |
| 608 // of stubs. | 609 // of stubs. |
| 609 ClassElement closureClass = compiler.closureClass; | 610 ClassElement closureClass = compiler.closureClass; |
| 610 if (needsClosureClass && !instantiatedClasses.contains(closureClass)) { | 611 if (needsClosureClass && !instantiatedClasses.contains(closureClass)) { |
| 611 generateClass(closureClass, buffer); | 612 generateClass(closureClass, buffer); |
| 612 } | 613 } |
| 613 } | 614 } |
| 614 | 615 |
| 615 void emitFinishClassesInvocationIfNecessary(StringBuffer buffer) { | 616 void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) { |
| 616 if (needsDefineClass) { | 617 if (needsDefineClass) { |
| 617 buffer.add("$finishClassesName($classesCollector);\n"); | 618 buffer.add("$finishClassesName($classesCollector);\n"); |
| 618 // Reset the map. | 619 // Reset the map. |
| 619 buffer.add("$classesCollector = {};\n"); | 620 buffer.add("$classesCollector = {};\n"); |
| 620 } | 621 } |
| 621 } | 622 } |
| 622 | 623 |
| 623 void emitStaticFunctionsWithNamer(StringBuffer buffer, | 624 void emitStaticFunctionsWithNamer(CodeBuffer buffer, |
| 624 Map<Element, CodeBlock> generatedCode, | 625 Map<Element, CodeBuffer> generatedCode, |
| 625 String functionNamer(Element element)) { | 626 String functionNamer(Element element)) { |
| 626 generatedCode.forEach((Element element, CodeBlock codeBlock) { | 627 generatedCode.forEach((Element element, CodeBuffer functionBuffer) { |
| 627 if (!element.isInstanceMember()) { | 628 if (!element.isInstanceMember()) { |
| 628 String functionName = functionNamer(element); | 629 String functionName = functionNamer(element); |
| 629 buffer.add('$isolateProperties.$functionName = '); | 630 buffer.add('$isolateProperties.$functionName = '); |
| 630 sourceMapBuilder.addCodeBlock(codeBlock.sourceMappings, buffer.length); | 631 addMappings(functionBuffer, buffer.length); |
| 631 buffer.add('${codeBlock.code};\n\n'); | 632 buffer.add(functionBuffer); |
| 633 buffer.add(';\n\n'); |
| 632 } | 634 } |
| 633 }); | 635 }); |
| 634 } | 636 } |
| 635 | 637 |
| 636 void emitStaticFunctions(StringBuffer buffer) { | 638 void emitStaticFunctions(CodeBuffer buffer) { |
| 637 emitStaticFunctionsWithNamer(buffer, | 639 emitStaticFunctionsWithNamer(buffer, |
| 638 compiler.codegenWorld.generatedCode, | 640 compiler.codegenWorld.generatedCode, |
| 639 namer.getName); | 641 namer.getName); |
| 640 emitStaticFunctionsWithNamer(buffer, | 642 emitStaticFunctionsWithNamer(buffer, |
| 641 compiler.codegenWorld.generatedBailoutCode, | 643 compiler.codegenWorld.generatedBailoutCode, |
| 642 namer.getBailoutName); | 644 namer.getBailoutName); |
| 643 } | 645 } |
| 644 | 646 |
| 645 void emitStaticFunctionGetters(StringBuffer buffer) { | 647 void emitStaticFunctionGetters(CodeBuffer buffer) { |
| 646 Set<FunctionElement> functionsNeedingGetter = | 648 Set<FunctionElement> functionsNeedingGetter = |
| 647 compiler.codegenWorld.staticFunctionsNeedingGetter; | 649 compiler.codegenWorld.staticFunctionsNeedingGetter; |
| 648 for (FunctionElement element in functionsNeedingGetter) { | 650 for (FunctionElement element in functionsNeedingGetter) { |
| 649 // The static function does not have the correct name. Since | 651 // The static function does not have the correct name. Since |
| 650 // [addParameterStubs] use the name to create its stubs we simply | 652 // [addParameterStubs] use the name to create its stubs we simply |
| 651 // create a fake element with the correct name. | 653 // create a fake element with the correct name. |
| 652 // Note: the callElement will not have any enclosingElement. | 654 // Note: the callElement will not have any enclosingElement. |
| 653 FunctionElement callElement = | 655 FunctionElement callElement = |
| 654 new ClosureInvocationElement(namer.CLOSURE_INVOCATION_NAME, element); | 656 new ClosureInvocationElement(namer.CLOSURE_INVOCATION_NAME, element); |
| 655 String staticName = namer.getName(element); | 657 String staticName = namer.getName(element); |
| 656 int parameterCount = element.parameterCount(compiler); | 658 int parameterCount = element.parameterCount(compiler); |
| 657 String invocationName = | 659 String invocationName = |
| 658 namer.instanceMethodName(element.getLibrary(), callElement.name, | 660 namer.instanceMethodName(element.getLibrary(), callElement.name, |
| 659 parameterCount); | 661 parameterCount); |
| 660 String fieldAccess = '$isolateProperties.$staticName'; | 662 String fieldAccess = '$isolateProperties.$staticName'; |
| 661 buffer.add("$fieldAccess.$invocationName = $fieldAccess;\n"); | 663 buffer.add("$fieldAccess.$invocationName = $fieldAccess;\n"); |
| 662 addParameterStubs(callElement, ( | 664 addParameterStubs(callElement, (String name, CodeBuffer value) { |
| 663 String name, String value, | |
| 664 [List<SourceMappingEntry> sourceMappings]) { | |
| 665 buffer.add('$fieldAccess.$name = $value;\n'); | 665 buffer.add('$fieldAccess.$name = $value;\n'); |
| 666 }); | 666 }); |
| 667 // If a static function is used as a closure we need to add its name | 667 // If a static function is used as a closure we need to add its name |
| 668 // in case it is used in spawnFunction. | 668 // in case it is used in spawnFunction. |
| 669 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; | 669 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; |
| 670 buffer.add('$fieldAccess.$fieldName = "$staticName";\n'); | 670 buffer.add('$fieldAccess.$fieldName = "$staticName";\n'); |
| 671 } | 671 } |
| 672 } | 672 } |
| 673 | 673 |
| 674 void emitDynamicFunctionGetter(FunctionElement member, | 674 void emitDynamicFunctionGetter(FunctionElement member, |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 callElement.name, parameterCount); | 726 callElement.name, parameterCount); |
| 727 List<String> arguments = new List<String>(parameterCount); | 727 List<String> arguments = new List<String>(parameterCount); |
| 728 for (int i = 0; i < parameterCount; i++) { | 728 for (int i = 0; i < parameterCount; i++) { |
| 729 arguments[i] = "p$i"; | 729 arguments[i] = "p$i"; |
| 730 } | 730 } |
| 731 String joinedArgs = Strings.join(arguments, ", "); | 731 String joinedArgs = Strings.join(arguments, ", "); |
| 732 boundClosureBuffer.add( | 732 boundClosureBuffer.add( |
| 733 "$invocationName: function($joinedArgs) {"); | 733 "$invocationName: function($joinedArgs) {"); |
| 734 boundClosureBuffer.add(" return this.self[this.target]($joinedArgs);"); | 734 boundClosureBuffer.add(" return this.self[this.target]($joinedArgs);"); |
| 735 boundClosureBuffer.add(" }"); | 735 boundClosureBuffer.add(" }"); |
| 736 addParameterStubs(callElement, ( | 736 addParameterStubs(callElement, (String stubName, CodeBuffer memberValue) { |
| 737 String stubName, String memberValue, | |
| 738 [List<SourceMappingEntry> sourceMappings]) { | |
| 739 boundClosureBuffer.add(',\n $stubName: $memberValue'); | 737 boundClosureBuffer.add(',\n $stubName: $memberValue'); |
| 740 }); | 738 }); |
| 741 boundClosureBuffer.add("\n});\n"); | 739 boundClosureBuffer.add("\n});\n"); |
| 742 | 740 |
| 743 closureClass = namer.isolateAccess(closureClassElement); | 741 closureClass = namer.isolateAccess(closureClassElement); |
| 744 | 742 |
| 745 // Cache it. | 743 // Cache it. |
| 746 if (!hasOptionalParameters) { | 744 if (!hasOptionalParameters) { |
| 747 boundClosureCache[parameterCount] = closureClass; | 745 boundClosureCache[parameterCount] = closureClass; |
| 748 } | 746 } |
| 749 } | 747 } |
| 750 | 748 |
| 751 // And finally the getter. | 749 // And finally the getter. |
| 752 String getterName = namer.getterName(member.getLibrary(), member.name); | 750 String getterName = namer.getterName(member.getLibrary(), member.name); |
| 753 String targetName = namer.instanceMethodName(member.getLibrary(), | 751 String targetName = namer.instanceMethodName(member.getLibrary(), |
| 754 member.name, parameterCount); | 752 member.name, parameterCount); |
| 755 defineInstanceMember( | 753 CodeBuffer getterBuffer = new CodeBuffer(); |
| 756 getterName, | 754 getterBuffer.add( |
| 757 "function() { return new $closureClass(this, '$targetName'); }"); | 755 "function() { return new $closureClass(this, '$targetName'); }"); |
| 756 defineInstanceMember(getterName, getterBuffer); |
| 758 } | 757 } |
| 759 | 758 |
| 760 void emitCallStubForGetter(Element member, | 759 void emitCallStubForGetter(Element member, |
| 761 Set<Selector> selectors, | 760 Set<Selector> selectors, |
| 762 DefineMemberFunction defineInstanceMember) { | 761 DefineMemberFunction defineInstanceMember) { |
| 763 String getter; | 762 String getter; |
| 764 if (member.kind == ElementKind.GETTER) { | 763 if (member.kind == ElementKind.GETTER) { |
| 765 getter = "this.${namer.getterName(member.getLibrary(), member.name)}()"; | 764 getter = "this.${namer.getterName(member.getLibrary(), member.name)}()"; |
| 766 } else { | 765 } else { |
| 767 String name = namer.instanceFieldName(member.getEnclosingClass(), | 766 String name = namer.instanceFieldName(member.getEnclosingClass(), |
| 768 member.name); | 767 member.name); |
| 769 getter = "this.$name"; | 768 getter = "this.$name"; |
| 770 } | 769 } |
| 771 for (Selector selector in selectors) { | 770 for (Selector selector in selectors) { |
| 772 if (selector.applies(member, compiler)) { | 771 if (selector.applies(member, compiler)) { |
| 773 String invocationName = | 772 String invocationName = |
| 774 namer.instanceMethodInvocationName(member.getLibrary(), member.name, | 773 namer.instanceMethodInvocationName(member.getLibrary(), member.name, |
| 775 selector); | 774 selector); |
| 776 SourceString callName = namer.CLOSURE_INVOCATION_NAME; | 775 SourceString callName = namer.CLOSURE_INVOCATION_NAME; |
| 777 String closureCallName = | 776 String closureCallName = |
| 778 namer.instanceMethodInvocationName(member.getLibrary(), callName, | 777 namer.instanceMethodInvocationName(member.getLibrary(), callName, |
| 779 selector); | 778 selector); |
| 780 List<String> arguments = <String>[]; | 779 List<String> arguments = <String>[]; |
| 781 for (int i = 0; i < selector.argumentCount; i++) { | 780 for (int i = 0; i < selector.argumentCount; i++) { |
| 782 arguments.add("arg$i"); | 781 arguments.add("arg$i"); |
| 783 } | 782 } |
| 784 String joined = Strings.join(arguments, ", "); | 783 String joined = Strings.join(arguments, ", "); |
| 785 defineInstanceMember( | 784 CodeBuffer getterBuffer = new CodeBuffer(); |
| 786 invocationName, | 785 getterBuffer.add( |
| 787 "function($joined) { return $getter.$closureCallName($joined); }"); | 786 "function($joined) { return $getter.$closureCallName($joined); }"); |
| 787 defineInstanceMember(invocationName, getterBuffer); |
| 788 } | 788 } |
| 789 } | 789 } |
| 790 } | 790 } |
| 791 | 791 |
| 792 void emitStaticNonFinalFieldInitializations(StringBuffer buffer) { | 792 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { |
| 793 ConstantHandler handler = compiler.constantHandler; | 793 ConstantHandler handler = compiler.constantHandler; |
| 794 List<VariableElement> staticNonFinalFields = | 794 List<VariableElement> staticNonFinalFields = |
| 795 handler.getStaticNonFinalFieldsForEmission(); | 795 handler.getStaticNonFinalFieldsForEmission(); |
| 796 for (Element element in staticNonFinalFields) { | 796 for (Element element in staticNonFinalFields) { |
| 797 buffer.add('$isolateProperties.${namer.getName(element)} = '); | 797 buffer.add('$isolateProperties.${namer.getName(element)} = '); |
| 798 compiler.withCurrentElement(element, () { | 798 compiler.withCurrentElement(element, () { |
| 799 handler.writeJsCodeForVariable(buffer, element); | 799 handler.writeJsCodeForVariable(buffer, element); |
| 800 }); | 800 }); |
| 801 buffer.add(';\n'); | 801 buffer.add(';\n'); |
| 802 } | 802 } |
| 803 } | 803 } |
| 804 | 804 |
| 805 void emitCompileTimeConstants(StringBuffer buffer) { | 805 void emitCompileTimeConstants(CodeBuffer buffer) { |
| 806 ConstantHandler handler = compiler.constantHandler; | 806 ConstantHandler handler = compiler.constantHandler; |
| 807 List<Constant> constants = handler.getConstantsForEmission(); | 807 List<Constant> constants = handler.getConstantsForEmission(); |
| 808 bool addedMakeConstantList = false; | 808 bool addedMakeConstantList = false; |
| 809 for (Constant constant in constants) { | 809 for (Constant constant in constants) { |
| 810 String name = handler.getNameForConstant(constant); | 810 String name = handler.getNameForConstant(constant); |
| 811 // The name is null when the constant is already a JS constant. | 811 // The name is null when the constant is already a JS constant. |
| 812 // TODO(floitsch): every constant should be registered, so that we can | 812 // TODO(floitsch): every constant should be registered, so that we can |
| 813 // share the ones that take up too much space (like some strings). | 813 // share the ones that take up too much space (like some strings). |
| 814 if (name === null) continue; | 814 if (name === null) continue; |
| 815 if (!addedMakeConstantList && constant.isList()) { | 815 if (!addedMakeConstantList && constant.isList()) { |
| 816 addedMakeConstantList = true; | 816 addedMakeConstantList = true; |
| 817 emitMakeConstantList(buffer); | 817 emitMakeConstantList(buffer); |
| 818 } | 818 } |
| 819 buffer.add('$isolateProperties.$name = '); | 819 buffer.add('$isolateProperties.$name = '); |
| 820 handler.writeJsCode(buffer, constant); | 820 handler.writeJsCode(buffer, constant); |
| 821 buffer.add(';\n'); | 821 buffer.add(';\n'); |
| 822 } | 822 } |
| 823 } | 823 } |
| 824 | 824 |
| 825 void emitMakeConstantList(StringBuffer buffer) { | 825 void emitMakeConstantList(CodeBuffer buffer) { |
| 826 buffer.add(namer.ISOLATE); | 826 buffer.add(namer.ISOLATE); |
| 827 buffer.add(@'''.makeConstantList = function(list) { | 827 buffer.add(@'''.makeConstantList = function(list) { |
| 828 list.immutable$list = true; | 828 list.immutable$list = true; |
| 829 list.fixed$length = true; | 829 list.fixed$length = true; |
| 830 return list; | 830 return list; |
| 831 }; | 831 }; |
| 832 '''); | 832 '''); |
| 833 } | 833 } |
| 834 | 834 |
| 835 void emitExtraAccessors(Element member, | 835 void emitExtraAccessors(Element member, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 851 if (compiler.codegenWorld.instantiatedClasses.isEmpty()) return; | 851 if (compiler.codegenWorld.instantiatedClasses.isEmpty()) return; |
| 852 | 852 |
| 853 ClassElement objectClass = | 853 ClassElement objectClass = |
| 854 compiler.coreLibrary.find(const SourceString('Object')); | 854 compiler.coreLibrary.find(const SourceString('Object')); |
| 855 String runtimeObjectPrototype = | 855 String runtimeObjectPrototype = |
| 856 '${namer.isolateAccess(objectClass)}.prototype'; | 856 '${namer.isolateAccess(objectClass)}.prototype'; |
| 857 String noSuchMethodName = | 857 String noSuchMethodName = |
| 858 namer.instanceMethodName(null, Compiler.NO_SUCH_METHOD, 2); | 858 namer.instanceMethodName(null, Compiler.NO_SUCH_METHOD, 2); |
| 859 Collection<LibraryElement> libraries = compiler.libraries.getValues(); | 859 Collection<LibraryElement> libraries = compiler.libraries.getValues(); |
| 860 | 860 |
| 861 String generateMethod(String methodName, Selector selector) { | 861 CodeBuffer generateMethod(String methodName, Selector selector) { |
| 862 StringBuffer buffer = new StringBuffer(); | 862 CodeBuffer buffer = new CodeBuffer(); |
| 863 buffer.add('function'); | 863 buffer.add('function'); |
| 864 StringBuffer args = new StringBuffer(); | 864 CodeBuffer args = new CodeBuffer(); |
| 865 for (int i = 0; i < selector.argumentCount; i++) { | 865 for (int i = 0; i < selector.argumentCount; i++) { |
| 866 if (i != 0) args.add(', '); | 866 if (i != 0) args.add(', '); |
| 867 args.add('arg$i'); | 867 args.add('arg$i'); |
| 868 } | 868 } |
| 869 // We need to check if the object has a noSuchMethod. If not, it | 869 // We need to check if the object has a noSuchMethod. If not, it |
| 870 // means the object is a native object, and we can just call our | 870 // means the object is a native object, and we can just call our |
| 871 // generic noSuchMethod. Note that when calling this method, the | 871 // generic noSuchMethod. Note that when calling this method, the |
| 872 // 'this' object is not a Dart object. | 872 // 'this' object is not a Dart object. |
| 873 buffer.add(' ($args) {\n'); | 873 buffer.add(' ($args) {\n'); |
| 874 buffer.add(' return this.$noSuchMethodName\n'); | 874 buffer.add(' return this.$noSuchMethodName\n'); |
| 875 buffer.add(" ? this.$noSuchMethodName('$methodName', [$args])\n"); | 875 buffer.add(" ? this.$noSuchMethodName('$methodName', [$args])\n"); |
| 876 buffer.add(" : $runtimeObjectPrototype.$noSuchMethodName.call("); | 876 buffer.add(" : $runtimeObjectPrototype.$noSuchMethodName.call("); |
| 877 buffer.add("this, '$methodName', [$args])\n"); | 877 buffer.add("this, '$methodName', [$args])\n"); |
| 878 buffer.add('}'); | 878 buffer.add('}'); |
| 879 return buffer.toString(); | 879 return buffer; |
| 880 } | 880 } |
| 881 | 881 |
| 882 compiler.codegenWorld.invokedNames.forEach((SourceString methodName, | 882 compiler.codegenWorld.invokedNames.forEach((SourceString methodName, |
| 883 Set<Selector> selectors) { | 883 Set<Selector> selectors) { |
| 884 if (objectClass.lookupLocalMember(methodName) === null | 884 if (objectClass.lookupLocalMember(methodName) === null |
| 885 && methodName != Elements.OPERATOR_EQUALS) { | 885 && methodName != Elements.OPERATOR_EQUALS) { |
| 886 for (Selector selector in selectors) { | 886 for (Selector selector in selectors) { |
| 887 if (methodName.isPrivate()) { | 887 if (methodName.isPrivate()) { |
| 888 for (LibraryElement lib in libraries) { | 888 for (LibraryElement lib in libraries) { |
| 889 String jsName = | 889 String jsName = |
| 890 namer.instanceMethodInvocationName(lib, methodName, selector); | 890 namer.instanceMethodInvocationName(lib, methodName, selector); |
| 891 String method = | 891 CodeBuffer method = |
| 892 generateMethod(methodName.slowToString(), selector); | 892 generateMethod(methodName.slowToString(), selector); |
| 893 defineInstanceMember(jsName, method); | 893 defineInstanceMember(jsName, method); |
| 894 } | 894 } |
| 895 } else { | 895 } else { |
| 896 String jsName = | 896 String jsName = |
| 897 namer.instanceMethodInvocationName(null, methodName, selector); | 897 namer.instanceMethodInvocationName(null, methodName, selector); |
| 898 String method = generateMethod(methodName.slowToString(), selector); | 898 CodeBuffer method = generateMethod(methodName.slowToString(), |
| 899 selector); |
| 899 defineInstanceMember(jsName, method); | 900 defineInstanceMember(jsName, method); |
| 900 } | 901 } |
| 901 } | 902 } |
| 902 } | 903 } |
| 903 }); | 904 }); |
| 904 | 905 |
| 905 compiler.codegenWorld.invokedGetters.forEach((SourceString getterName, | 906 compiler.codegenWorld.invokedGetters.forEach((SourceString getterName, |
| 906 Set<Selector> selectors) { | 907 Set<Selector> selectors) { |
| 907 if (getterName.isPrivate()) { | 908 if (getterName.isPrivate()) { |
| 908 for (LibraryElement lib in libraries) { | 909 for (LibraryElement lib in libraries) { |
| 909 String jsName = namer.getterName(lib, getterName); | 910 String jsName = namer.getterName(lib, getterName); |
| 910 String method = generateMethod('get ${getterName.slowToString()}', | 911 CodeBuffer method = generateMethod('get ${getterName.slowToString()}', |
| 911 Selector.GETTER); | 912 Selector.GETTER); |
| 912 defineInstanceMember(jsName, method); | 913 defineInstanceMember(jsName, method); |
| 913 } | 914 } |
| 914 } else { | 915 } else { |
| 915 String jsName = namer.getterName(null, getterName); | 916 String jsName = namer.getterName(null, getterName); |
| 916 String method = generateMethod('get ${getterName.slowToString()}', | 917 CodeBuffer method = generateMethod('get ${getterName.slowToString()}', |
| 917 Selector.GETTER); | 918 Selector.GETTER); |
| 918 defineInstanceMember(jsName, method); | 919 defineInstanceMember(jsName, method); |
| 919 } | 920 } |
| 920 }); | 921 }); |
| 921 | 922 |
| 922 compiler.codegenWorld.invokedSetters.forEach((SourceString setterName, | 923 compiler.codegenWorld.invokedSetters.forEach((SourceString setterName, |
| 923 Set<Selector> selectors) { | 924 Set<Selector> selectors) { |
| 924 if (setterName.isPrivate()) { | 925 if (setterName.isPrivate()) { |
| 925 for (LibraryElement lib in libraries) { | 926 for (LibraryElement lib in libraries) { |
| 926 String jsName = namer.setterName(lib, setterName); | 927 String jsName = namer.setterName(lib, setterName); |
| 927 String method = generateMethod('set ${setterName.slowToString()}', | 928 CodeBuffer method = generateMethod('set ${setterName.slowToString()}', |
| 928 Selector.SETTER); | 929 Selector.SETTER); |
| 929 defineInstanceMember(jsName, method); | 930 defineInstanceMember(jsName, method); |
| 930 } | 931 } |
| 931 } else { | 932 } else { |
| 932 String jsName = namer.setterName(null, setterName); | 933 String jsName = namer.setterName(null, setterName); |
| 933 String method = generateMethod('set ${setterName.slowToString()}', | 934 CodeBuffer method = generateMethod('set ${setterName.slowToString()}', |
| 934 Selector.SETTER); | 935 Selector.SETTER); |
| 935 defineInstanceMember(jsName, method); | 936 defineInstanceMember(jsName, method); |
| 936 } | 937 } |
| 937 }); | 938 }); |
| 938 } | 939 } |
| 939 | 940 |
| 940 String buildIsolateSetup(StringBuffer buffer, | 941 String buildIsolateSetup(CodeBuffer buffer, |
| 941 Element appMain, | 942 Element appMain, |
| 942 Element isolateMain) { | 943 Element isolateMain) { |
| 943 String mainAccess = "${namer.isolateAccess(appMain)}"; | 944 String mainAccess = "${namer.isolateAccess(appMain)}"; |
| 944 String currentIsolate = "${namer.CURRENT_ISOLATE}"; | 945 String currentIsolate = "${namer.CURRENT_ISOLATE}"; |
| 945 String mainEnsureGetter = ''; | 946 String mainEnsureGetter = ''; |
| 946 // Since we pass the closurized version of the main method to | 947 // Since we pass the closurized version of the main method to |
| 947 // the isolate method, we must make sure that it exists. | 948 // the isolate method, we must make sure that it exists. |
| 948 if (!compiler.codegenWorld.staticFunctionsNeedingGetter.contains(appMain)) { | 949 if (!compiler.codegenWorld.staticFunctionsNeedingGetter.contains(appMain)) { |
| 949 String invocationName = | 950 String invocationName = |
| 950 "${namer.closureInvocationName(Selector.INVOCATION_0)}"; | 951 "${namer.closureInvocationName(Selector.INVOCATION_0)}"; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 968 } | 969 } |
| 969 function \$setGlobals(context) { | 970 function \$setGlobals(context) { |
| 970 $currentIsolate = context.isolateStatics; | 971 $currentIsolate = context.isolateStatics; |
| 971 \$globalThis = $currentIsolate; | 972 \$globalThis = $currentIsolate; |
| 972 } | 973 } |
| 973 $mainEnsureGetter | 974 $mainEnsureGetter |
| 974 """); | 975 """); |
| 975 return "${namer.isolateAccess(isolateMain)}($mainAccess)"; | 976 return "${namer.isolateAccess(isolateMain)}($mainAccess)"; |
| 976 } | 977 } |
| 977 | 978 |
| 978 emitMain(StringBuffer buffer) { | 979 emitMain(CodeBuffer buffer) { |
| 979 if (compiler.isMockCompilation) return; | 980 if (compiler.isMockCompilation) return; |
| 980 Element main = compiler.mainApp.find(Compiler.MAIN); | 981 Element main = compiler.mainApp.find(Compiler.MAIN); |
| 981 String mainCall = null; | 982 String mainCall = null; |
| 982 if (compiler.isolateLibrary != null) { | 983 if (compiler.isolateLibrary != null) { |
| 983 Element isolateMain = | 984 Element isolateMain = |
| 984 compiler.isolateLibrary.find(Compiler.START_ROOT_ISOLATE); | 985 compiler.isolateLibrary.find(Compiler.START_ROOT_ISOLATE); |
| 985 mainCall = buildIsolateSetup(buffer, main, isolateMain); | 986 mainCall = buildIsolateSetup(buffer, main, isolateMain); |
| 986 } else { | 987 } else { |
| 987 mainCall = '${namer.isolateAccess(main)}()'; | 988 mainCall = '${namer.isolateAccess(main)}()'; |
| 988 } | 989 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1050 String sourceMap = sourceMapBuilder.build(compiledFile); | 1051 String sourceMap = sourceMapBuilder.build(compiledFile); |
| 1051 // TODO(podivilov): We should find a better way to return source maps to | 1052 // TODO(podivilov): We should find a better way to return source maps to |
| 1052 // compiler. Using diagnostic handler for that purpose is a temporary | 1053 // compiler. Using diagnostic handler for that purpose is a temporary |
| 1053 // hack. | 1054 // hack. |
| 1054 compiler.reportDiagnostic( | 1055 compiler.reportDiagnostic( |
| 1055 null, sourceMap, new api.Diagnostic(-1, 'source map')); | 1056 null, sourceMap, new api.Diagnostic(-1, 'source map')); |
| 1056 } | 1057 } |
| 1057 }); | 1058 }); |
| 1058 return compiler.assembledCode; | 1059 return compiler.assembledCode; |
| 1059 } | 1060 } |
| 1061 |
| 1062 void addMappings(CodeBuffer buffer, int bufferOffset) { |
| 1063 buffer.forEachSourceLocation((Element element, Token token, int offset) { |
| 1064 SourceFile sourceFile = element.getCompilationUnit().script.file; |
| 1065 String sourceName = null; |
| 1066 if (token.kind === IDENTIFIER_TOKEN) { |
| 1067 sourceName = token.slowToString(); |
| 1068 } |
| 1069 int totalOffset = bufferOffset + offset; |
| 1070 sourceMapBuilder.addMapping( |
| 1071 sourceFile, token.charOffset, sourceName, totalOffset); |
| 1072 }); |
| 1073 } |
| 1060 } | 1074 } |
| 1061 | 1075 |
| 1062 typedef void DefineMemberFunction(String invocationName, | 1076 typedef void DefineMemberFunction(String invocationName, CodeBuffer definition); |
| 1063 String definition, | |
| 1064 [List<SourceMappingEntry> sourceMappings]); | |
| OLD | NEW |