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 = []; | |
|
ngeoffray
2013/07/12 09:16:55
<String>[]
| |
| 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(string, () { | |
| 3288 globalMetadata.add(string); | |
| 3289 return globalMetadata.length - 1; | |
| 3290 }); | |
| 3291 } | |
| 3292 | |
| 3293 jsAst.Fun extendWithMetadata(FunctionElement element, jsAst.Fun code) { | |
| 3294 if (!backend.retainMetadataOf(element)) return code; | |
| 3295 return compiler.withCurrentElement(element, () { | |
| 3296 List<int> metadata = <int>[]; | |
| 3297 FunctionSignature signature = element.functionSignature; | |
| 3298 if (element.isConstructor()) { | |
| 3299 metadata.add(reifyType(element.getEnclosingClass().thisType)); | |
| 3300 } else { | |
| 3301 metadata.add(reifyType(signature.returnType)); | |
| 3302 } | |
| 3303 signature.forEachParameter((Element parameter) { | |
| 3304 metadata | |
| 3305 ..add(reifyName(parameter.name)) | |
| 3306 ..add(reifyType(parameter.computeType(compiler))); | |
| 3307 }); | |
| 3308 Link link = element.metadata; | |
| 3309 // TODO(ahe): Why is metadata sometimes null? | |
| 3310 if (link != null) { | |
| 3311 for (; !link.isEmpty; link = link.tail) { | |
| 3312 metadata.add(reifyMetadata(link.head)); | |
| 3313 } | |
| 3314 } | |
| 3315 code.body.statements.add(js.string(metadata.join(',')).toStatement()); | |
| 3316 return code; | |
| 3317 }); | |
| 3318 } | |
| 3319 | |
| 3320 void emitMetadata(CodeBuffer buffer) { | |
| 3321 buffer.write('init.metadata$_=$_['); | |
| 3322 for (var metadata in globalMetadata) { | |
| 3323 if (metadata is String) { | |
| 3324 if (metadata != 'null') { | |
| 3325 buffer.write(metadata); | |
| 3326 } | |
| 3327 } else { | |
| 3328 throw 'Unexpected value in metadata: ${Error.safeToString(metadata)}'; | |
| 3329 } | |
| 3330 buffer.write(',$n'); | |
| 3331 } | |
| 3332 buffer.write('];$n'); | |
| 3333 } | |
| 3334 | |
| 3265 String assembleProgram() { | 3335 String assembleProgram() { |
| 3266 measure(() { | 3336 measure(() { |
| 3267 // Compute the required type checks to know which classes need a | 3337 // Compute the required type checks to know which classes need a |
| 3268 // 'is$' method. | 3338 // 'is$' method. |
| 3269 computeRequiredTypeChecks(); | 3339 computeRequiredTypeChecks(); |
| 3270 | 3340 |
| 3271 computeNeededClasses(); | 3341 computeNeededClasses(); |
| 3272 | 3342 |
| 3273 mainBuffer.add(buildGeneratedBy()); | 3343 mainBuffer.add(buildGeneratedBy()); |
| 3274 addComment(HOOKS_API_USAGE, mainBuffer); | 3344 addComment(HOOKS_API_USAGE, mainBuffer); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3413 emitCompileTimeConstants(mainBuffer); | 3483 emitCompileTimeConstants(mainBuffer); |
| 3414 // Static field initializations require the classes and compile-time | 3484 // Static field initializations require the classes and compile-time |
| 3415 // constants to be set up. | 3485 // constants to be set up. |
| 3416 emitStaticNonFinalFieldInitializations(mainBuffer); | 3486 emitStaticNonFinalFieldInitializations(mainBuffer); |
| 3417 emitOneShotInterceptors(mainBuffer); | 3487 emitOneShotInterceptors(mainBuffer); |
| 3418 emitInterceptedNames(mainBuffer); | 3488 emitInterceptedNames(mainBuffer); |
| 3419 emitLazilyInitializedStaticFields(mainBuffer); | 3489 emitLazilyInitializedStaticFields(mainBuffer); |
| 3420 | 3490 |
| 3421 mainBuffer.add(nativeBuffer); | 3491 mainBuffer.add(nativeBuffer); |
| 3422 | 3492 |
| 3493 emitMetadata(mainBuffer); | |
| 3423 | 3494 |
| 3424 isolateProperties = isolatePropertiesName; | 3495 isolateProperties = isolatePropertiesName; |
| 3425 // The following code should not use the short-hand for the | 3496 // The following code should not use the short-hand for the |
| 3426 // initialStatics. | 3497 // initialStatics. |
| 3427 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=${_}null$N'); | 3498 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=${_}null$N'); |
| 3428 | 3499 |
| 3429 emitFinishIsolateConstructorInvocation(mainBuffer); | 3500 emitFinishIsolateConstructorInvocation(mainBuffer); |
| 3430 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=' | 3501 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=' |
| 3431 '${_}new ${namer.isolateName}()$N'); | 3502 '${_}new ${namer.isolateName}()$N'); |
| 3432 | 3503 |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3629 | 3700 |
| 3630 const String HOOKS_API_USAGE = """ | 3701 const String HOOKS_API_USAGE = """ |
| 3631 // The code supports the following hooks: | 3702 // The code supports the following hooks: |
| 3632 // dartPrint(message) - if this function is defined it is called | 3703 // dartPrint(message) - if this function is defined it is called |
| 3633 // instead of the Dart [print] method. | 3704 // instead of the Dart [print] method. |
| 3634 // dartMainRunner(main) - if this function is defined, the Dart [main] | 3705 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 3635 // method will not be invoked directly. | 3706 // method will not be invoked directly. |
| 3636 // Instead, a closure that will invoke [main] is | 3707 // Instead, a closure that will invoke [main] is |
| 3637 // passed to [dartMainRunner]. | 3708 // passed to [dartMainRunner]. |
| 3638 """; | 3709 """; |
| OLD | NEW |