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 part of js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A function element that represents a closure call. The signature is copied | 8 * A function element that represents a closure call. The signature is copied |
| 9 * from the given element. | 9 * from the given element. |
| 10 */ | 10 */ |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 78 String classesCollector; | 78 String classesCollector; |
| 79 final Set<ClassElement> neededClasses = new Set<ClassElement>(); | 79 final Set<ClassElement> neededClasses = new Set<ClassElement>(); |
| 80 final List<ClassElement> regularClasses = <ClassElement>[]; | 80 final List<ClassElement> regularClasses = <ClassElement>[]; |
| 81 final List<ClassElement> deferredClasses = <ClassElement>[]; | 81 final List<ClassElement> deferredClasses = <ClassElement>[]; |
| 82 final List<ClassElement> nativeClasses = <ClassElement>[]; | 82 final List<ClassElement> nativeClasses = <ClassElement>[]; |
| 83 final List<Selector> trivialNsmHandlers = <Selector>[]; | 83 final List<Selector> trivialNsmHandlers = <Selector>[]; |
| 84 final Map<String, String> mangledFieldNames = <String, String>{}; | 84 final Map<String, String> mangledFieldNames = <String, String>{}; |
| 85 final Set<String> recordedMangledNames = new Set<String>(); | 85 final Set<String> recordedMangledNames = new Set<String>(); |
| 86 final Set<String> interceptorInvocationNames = new Set<String>(); | 86 final Set<String> interceptorInvocationNames = new Set<String>(); |
| 87 | 87 |
| 88 /// A list of JS expressions that represent metadata, parameter names and | |
| 89 /// type, and return types. | |
| 90 final List<String> globalMetadata = []; | |
| 91 | |
| 92 /// A map used to canonicalize the entries of globalMetadata. | |
| 93 final Map<String, int> globalMetadataMap = <String, int>{}; | |
| 94 | |
| 88 // TODO(ngeoffray): remove this field. | 95 // TODO(ngeoffray): remove this field. |
| 89 Set<ClassElement> instantiatedClasses; | 96 Set<ClassElement> instantiatedClasses; |
| 90 | 97 |
| 91 final List<jsAst.Expression> boundClosures = <jsAst.Expression>[]; | 98 final List<jsAst.Expression> boundClosures = <jsAst.Expression>[]; |
| 92 | 99 |
| 93 JavaScriptBackend get backend => compiler.backend; | 100 JavaScriptBackend get backend => compiler.backend; |
| 94 | 101 |
| 95 String get _ => compiler.enableMinification ? "" : " "; | 102 String get _ => compiler.enableMinification ? "" : " "; |
| 96 String get n => compiler.enableMinification ? "" : "\n"; | 103 String get n => compiler.enableMinification ? "" : "\n"; |
| 97 String get N => compiler.enableMinification ? "\n" : ";\n"; | 104 String get N => compiler.enableMinification ? "\n" : ";\n"; |
| (...skipping 1102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1200 if (member.isFunction() | 1207 if (member.isFunction() |
| 1201 || member.isGenerativeConstructorBody() | 1208 || member.isGenerativeConstructorBody() |
| 1202 || member.isAccessor()) { | 1209 || member.isAccessor()) { |
| 1203 if (member.isAbstract(compiler)) return; | 1210 if (member.isAbstract(compiler)) return; |
| 1204 jsAst.Expression code = backend.generatedCode[member]; | 1211 jsAst.Expression code = backend.generatedCode[member]; |
| 1205 if (code == null) return; | 1212 if (code == null) return; |
| 1206 String name = namer.getName(member); | 1213 String name = namer.getName(member); |
| 1207 if (backend.isInterceptedMethod(member)) { | 1214 if (backend.isInterceptedMethod(member)) { |
| 1208 interceptorInvocationNames.add(name); | 1215 interceptorInvocationNames.add(name); |
| 1209 } | 1216 } |
| 1217 code = extendWithMetadata(member, code); | |
| 1210 builder.addProperty(name, code); | 1218 builder.addProperty(name, code); |
| 1211 var metadata = buildMetadataFunction(member); | |
| 1212 if (metadata != null) { | |
| 1213 builder.addProperty('@$name', metadata); | |
| 1214 } | |
| 1215 String reflectionName = getReflectionName(member, name); | 1219 String reflectionName = getReflectionName(member, name); |
| 1216 if (reflectionName != null) { | 1220 if (reflectionName != null) { |
| 1217 builder.addProperty('+$reflectionName', js('0')); | 1221 builder.addProperty('+$reflectionName', js('0')); |
| 1218 } | 1222 } |
| 1219 code = backend.generatedBailoutCode[member]; | 1223 code = backend.generatedBailoutCode[member]; |
| 1220 if (code != null) { | 1224 if (code != null) { |
| 1221 builder.addProperty(namer.getBailoutName(member), code); | 1225 builder.addProperty(namer.getBailoutName(member), code); |
| 1222 } | 1226 } |
| 1223 FunctionElement function = member; | 1227 FunctionElement function = member; |
| 1224 FunctionSignature parameters = function.computeSignature(compiler); | 1228 FunctionSignature parameters = function.computeSignature(compiler); |
| (...skipping 824 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2049 backend.generatedCode.keys.where(isStaticFunction); | 2053 backend.generatedCode.keys.where(isStaticFunction); |
| 2050 Set<Element> pendingElementsWithBailouts = | 2054 Set<Element> pendingElementsWithBailouts = |
| 2051 backend.generatedBailoutCode.keys | 2055 backend.generatedBailoutCode.keys |
| 2052 .where(isStaticFunction) | 2056 .where(isStaticFunction) |
| 2053 .toSet(); | 2057 .toSet(); |
| 2054 | 2058 |
| 2055 for (Element element in Elements.sortedByPosition(elements)) { | 2059 for (Element element in Elements.sortedByPosition(elements)) { |
| 2056 CodeBuffer buffer = bufferForElement(element, eagerBuffer); | 2060 CodeBuffer buffer = bufferForElement(element, eagerBuffer); |
| 2057 jsAst.Expression code = backend.generatedCode[element]; | 2061 jsAst.Expression code = backend.generatedCode[element]; |
| 2058 String name = namer.getName(element); | 2062 String name = namer.getName(element); |
| 2063 code = extendWithMetadata(element, code); | |
| 2059 emitStaticFunction(buffer, name, code); | 2064 emitStaticFunction(buffer, name, code); |
| 2060 var metadata = buildMetadataFunction(element); | |
| 2061 if (metadata != null) { | |
| 2062 buffer.write(',$n$n"@$name":$_'); | |
| 2063 buffer.write(jsAst.prettyPrint(metadata, compiler)); | |
| 2064 } | |
| 2065 String reflectionName = getReflectionName(element, name); | 2065 String reflectionName = getReflectionName(element, name); |
| 2066 if (reflectionName != null) { | 2066 if (reflectionName != null) { |
| 2067 buffer.write(',$n$n"+$reflectionName":${_}0'); | 2067 buffer.write(',$n$n"+$reflectionName":${_}0'); |
| 2068 } | 2068 } |
| 2069 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element]; | 2069 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element]; |
| 2070 if (bailoutCode != null) { | 2070 if (bailoutCode != null) { |
| 2071 pendingElementsWithBailouts.remove(element); | 2071 pendingElementsWithBailouts.remove(element); |
| 2072 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); | 2072 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); |
| 2073 } | 2073 } |
| 2074 } | 2074 } |
| (...skipping 1180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3255 metadata.add(constantReference(value)); | 3255 metadata.add(constantReference(value)); |
| 3256 } | 3256 } |
| 3257 } | 3257 } |
| 3258 } | 3258 } |
| 3259 if (metadata.isEmpty) return null; | 3259 if (metadata.isEmpty) return null; |
| 3260 return js.fun( | 3260 return js.fun( |
| 3261 [], [js.return_(new jsAst.ArrayInitializer.from(metadata))]); | 3261 [], [js.return_(new jsAst.ArrayInitializer.from(metadata))]); |
| 3262 }); | 3262 }); |
| 3263 } | 3263 } |
| 3264 | 3264 |
| 3265 int reifyMetadata(MetadataAnnotation annotation) { | |
| 3266 Constant value = annotation.value; | |
| 3267 if (value == null) { | |
| 3268 compiler.reportInternalError( | |
| 3269 annotation, 'Internal error: value is null'); | |
| 3270 return -1; | |
| 3271 } | |
| 3272 return addGlobalMetadata( | |
| 3273 jsAst.prettyPrint(constantReference(value), compiler).getText()); | |
| 3274 } | |
| 3275 | |
| 3276 int reifyType(DartType type) { | |
| 3277 // TODO(ahe): Handle type variables correctly instead of using "#". | |
| 3278 String representation = backend.rti.getTypeRepresentation(type, (_) {}); | |
| 3279 return addGlobalMetadata(representation.replaceAll('#', 'null')); | |
| 3280 } | |
| 3281 | |
| 3282 int reifyName(SourceString name) { | |
| 3283 return addGlobalMetadata('"${name.slowToString()}"'); | |
| 3284 } | |
| 3285 | |
| 3286 int addGlobalMetadata(String string) { | |
| 3287 return globalMetadataMap.putIfAbsent( | |
| 3288 string, | |
| 3289 () => (globalMetadata..add(string)).length - 1); | |
|
kasperl
2013/06/28 10:18:09
I think this is a little bit hard to read.
ahe
2013/06/28 11:07:12
Done.
| |
| 3290 } | |
| 3291 | |
| 3292 jsAst.Fun extendWithMetadata(FunctionElement element, jsAst.Fun code) { | |
| 3293 if (!backend.retainMetadataOf(element)) return code; | |
| 3294 return compiler.withCurrentElement(element, () { | |
| 3295 List<int> metadata = <int>[]; | |
| 3296 FunctionSignature signature = element.functionSignature; | |
| 3297 if (element.isConstructor()) { | |
| 3298 metadata.add(reifyType(element.getEnclosingClass().thisType)); | |
| 3299 } else { | |
| 3300 metadata.add(reifyType(signature.returnType)); | |
| 3301 } | |
| 3302 signature.forEachParameter((Element parameter) { | |
| 3303 metadata | |
| 3304 ..add(reifyName(parameter.name)) | |
| 3305 ..add(reifyType(parameter.computeType(compiler))); | |
| 3306 }); | |
| 3307 Link link = element.metadata; | |
| 3308 // TODO(ahe): Why is metadata sometimes null? | |
| 3309 if (link != null) { | |
| 3310 for (; !link.isEmpty; link = link.tail) { | |
| 3311 metadata.add(reifyMetadata(link.head)); | |
| 3312 } | |
| 3313 } | |
| 3314 code.body.statements.add(js.string(metadata.join(',')).toStatement()); | |
| 3315 return code; | |
| 3316 }); | |
| 3317 } | |
| 3318 | |
| 3319 void emitMetadata(CodeBuffer buffer) { | |
| 3320 buffer.write('init.metadata$_=$_['); | |
| 3321 for (var metadata in globalMetadata) { | |
| 3322 if (metadata is String) { | |
| 3323 if (metadata != 'null') { | |
| 3324 buffer.write(metadata); | |
| 3325 } | |
| 3326 } else { | |
| 3327 throw 'Unexpected value in metadata: ${Error.safeToString(metadata)}'; | |
| 3328 } | |
| 3329 buffer.write(',$n'); | |
| 3330 } | |
| 3331 buffer.write('];$n'); | |
| 3332 } | |
| 3333 | |
| 3265 String assembleProgram() { | 3334 String assembleProgram() { |
| 3266 measure(() { | 3335 measure(() { |
| 3267 // Compute the required type checks to know which classes need a | 3336 // Compute the required type checks to know which classes need a |
| 3268 // 'is$' method. | 3337 // 'is$' method. |
| 3269 computeRequiredTypeChecks(); | 3338 computeRequiredTypeChecks(); |
| 3270 | 3339 |
| 3271 computeNeededClasses(); | 3340 computeNeededClasses(); |
| 3272 | 3341 |
| 3273 mainBuffer.add(buildGeneratedBy()); | 3342 mainBuffer.add(buildGeneratedBy()); |
| 3274 addComment(HOOKS_API_USAGE, mainBuffer); | 3343 addComment(HOOKS_API_USAGE, mainBuffer); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3413 emitCompileTimeConstants(mainBuffer); | 3482 emitCompileTimeConstants(mainBuffer); |
| 3414 // Static field initializations require the classes and compile-time | 3483 // Static field initializations require the classes and compile-time |
| 3415 // constants to be set up. | 3484 // constants to be set up. |
| 3416 emitStaticNonFinalFieldInitializations(mainBuffer); | 3485 emitStaticNonFinalFieldInitializations(mainBuffer); |
| 3417 emitOneShotInterceptors(mainBuffer); | 3486 emitOneShotInterceptors(mainBuffer); |
| 3418 emitInterceptedNames(mainBuffer); | 3487 emitInterceptedNames(mainBuffer); |
| 3419 emitLazilyInitializedStaticFields(mainBuffer); | 3488 emitLazilyInitializedStaticFields(mainBuffer); |
| 3420 | 3489 |
| 3421 mainBuffer.add(nativeBuffer); | 3490 mainBuffer.add(nativeBuffer); |
| 3422 | 3491 |
| 3492 emitMetadata(mainBuffer); | |
| 3423 | 3493 |
| 3424 isolateProperties = isolatePropertiesName; | 3494 isolateProperties = isolatePropertiesName; |
| 3425 // The following code should not use the short-hand for the | 3495 // The following code should not use the short-hand for the |
| 3426 // initialStatics. | 3496 // initialStatics. |
| 3427 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=${_}null$N'); | 3497 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=${_}null$N'); |
| 3428 | 3498 |
| 3429 emitFinishIsolateConstructorInvocation(mainBuffer); | 3499 emitFinishIsolateConstructorInvocation(mainBuffer); |
| 3430 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=' | 3500 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=' |
| 3431 '${_}new ${namer.isolateName}()$N'); | 3501 '${_}new ${namer.isolateName}()$N'); |
| 3432 | 3502 |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3629 | 3699 |
| 3630 const String HOOKS_API_USAGE = """ | 3700 const String HOOKS_API_USAGE = """ |
| 3631 // The code supports the following hooks: | 3701 // The code supports the following hooks: |
| 3632 // dartPrint(message) - if this function is defined it is called | 3702 // dartPrint(message) - if this function is defined it is called |
| 3633 // instead of the Dart [print] method. | 3703 // instead of the Dart [print] method. |
| 3634 // dartMainRunner(main) - if this function is defined, the Dart [main] | 3704 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 3635 // method will not be invoked directly. | 3705 // method will not be invoked directly. |
| 3636 // Instead, a closure that will invoke [main] is | 3706 // Instead, a closure that will invoke [main] is |
| 3637 // passed to [dartMainRunner]. | 3707 // passed to [dartMainRunner]. |
| 3638 """; | 3708 """; |
| OLD | NEW |