Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Side by Side Diff: dart/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart

Issue 25657008: Only have one method for generating a method. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Change name of writeOn to make it absolutely clear that it shouldn't be used in normal situations. Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 dart2js.js_emitter; 5 part of dart2js.js_emitter;
6 6
7 /** 7 /**
8 * Generates the code for all used classes in the program. Static fields (even 8 * Generates the code for all used classes in the program. Static fields (even
9 * in classes) are ignored, since they can be treated as non-class elements. 9 * in classes) are ignored, since they can be treated as non-class elements.
10 * 10 *
(...skipping 893 matching lines...) Expand 10 before | Expand all | Expand 10 after
904 || compiler.codegenWorld.hasInvokedSetter(field, compiler)); 904 || compiler.codegenWorld.hasInvokedSetter(field, compiler));
905 } 905 }
906 906
907 // We never access a field in a closure (a captured variable) without knowing 907 // We never access a field in a closure (a captured variable) without knowing
908 // that it is there. Therefore we don't need to use a getter (that will throw 908 // that it is there. Therefore we don't need to use a getter (that will throw
909 // if the getter method is missing), but can always access the field directly. 909 // if the getter method is missing), but can always access the field directly.
910 static bool fieldAccessNeverThrows(VariableElement field) { 910 static bool fieldAccessNeverThrows(VariableElement field) {
911 return field is ClosureFieldElement; 911 return field is ClosureFieldElement;
912 } 912 }
913 913
914 /**
915 * Documentation wanted -- johnniwinther
916 *
917 * Invariant: [member] must be a declaration element.
918 */
919 void addInstanceMember(Element member, ClassBuilder builder) {
920 assert(invariant(member, member.isDeclaration));
921 // TODO(floitsch): we don't need to deal with members of
922 // uninstantiated classes, that have been overwritten by subclasses.
923
924 if (member.isFunction()
925 || member.isGenerativeConstructorBody()
926 || member.isAccessor()) {
927 if (member.isAbstract(compiler)) return;
928 jsAst.Expression code = backend.generatedCode[member];
929 if (code == null) return;
930 String name = namer.getNameOfInstanceMember(member);
931 if (backend.isInterceptedMethod(member)) {
932 interceptorInvocationNames.add(name);
933 }
934 code = extendWithMetadata(member, code);
935 builder.addProperty(name, code);
936 String reflectionName = getReflectionName(member, name);
937 if (reflectionName != null) {
938 var reflectable =
939 js(backend.isAccessibleByReflection(member) ? '1' : '0');
940 builder.addProperty('+$reflectionName', reflectable);
941 jsAst.Node defaultValues = reifyDefaultArguments(member);
942 if (defaultValues != null) {
943 String unmangledName = member.name.slowToString();
944 builder.addProperty('*$unmangledName', defaultValues);
945 }
946 }
947 code = backend.generatedBailoutCode[member];
948 if (code != null) {
949 builder.addProperty(namer.getBailoutName(member), code);
950 }
951 FunctionElement function = member;
952 FunctionSignature parameters = function.computeSignature(compiler);
953 if (!parameters.optionalParameters.isEmpty) {
954 containerBuilder.addParameterStubs(function, builder.addProperty);
955 }
956 } else if (!member.isField()) {
957 compiler.internalError('unexpected kind: "${member.kind}"',
958 element: member);
959 }
960 containerBuilder.emitExtraAccessors(member, builder);
961 }
962
963 /// Returns the "reflection name" of an [Element] or [Selector]. 914 /// Returns the "reflection name" of an [Element] or [Selector].
964 /// The reflection name of a getter 'foo' is 'foo'. 915 /// The reflection name of a getter 'foo' is 'foo'.
965 /// The reflection name of a setter 'foo' is 'foo='. 916 /// The reflection name of a setter 'foo' is 'foo='.
966 /// The reflection name of a method 'foo' is 'foo:N:M:O', where N is the 917 /// The reflection name of a method 'foo' is 'foo:N:M:O', where N is the
967 /// number of required arguments, M is the number of optional arguments, and 918 /// number of required arguments, M is the number of optional arguments, and
968 /// O is the named arguments. 919 /// O is the named arguments.
969 /// The reflection name of a constructor is similar to a regular method but 920 /// The reflection name of a constructor is similar to a regular method but
970 /// starts with 'new '. 921 /// starts with 'new '.
971 /// The reflection name of class 'C' is 'C'. 922 /// The reflection name of class 'C' is 'C'.
972 /// An anonymous mixin application has no reflection name. 923 /// An anonymous mixin application has no reflection name.
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1075 * 1026 *
1076 * Invariant: [classElement] must be a declaration element. 1027 * Invariant: [classElement] must be a declaration element.
1077 */ 1028 */
1078 void emitInstanceMembers(ClassElement classElement, 1029 void emitInstanceMembers(ClassElement classElement,
1079 ClassBuilder builder) { 1030 ClassBuilder builder) {
1080 assert(invariant(classElement, classElement.isDeclaration)); 1031 assert(invariant(classElement, classElement.isDeclaration));
1081 1032
1082 void visitMember(ClassElement enclosing, Element member) { 1033 void visitMember(ClassElement enclosing, Element member) {
1083 assert(invariant(classElement, member.isDeclaration)); 1034 assert(invariant(classElement, member.isDeclaration));
1084 if (member.isInstanceMember()) { 1035 if (member.isInstanceMember()) {
1085 addInstanceMember(member, builder); 1036 containerBuilder.addMember(member, builder);
1086 } 1037 }
1087 } 1038 }
1088 1039
1089 classElement.implementation.forEachMember( 1040 classElement.implementation.forEachMember(
1090 visitMember, 1041 visitMember,
1091 includeBackendMembers: true); 1042 includeBackendMembers: true);
1092 1043
1093 if (identical(classElement, compiler.objectClass) 1044 if (identical(classElement, compiler.objectClass)
1094 && compiler.enabledNoSuchMethod) { 1045 && compiler.enabledNoSuchMethod) {
1095 // Emit the noSuchMethod handlers on the Object prototype now, 1046 // Emit the noSuchMethod handlers on the Object prototype now,
(...skipping 935 matching lines...) Expand 10 before | Expand all | Expand 10 after
2031 if (needsDefineClass) { 1982 if (needsDefineClass) {
2032 buffer.write('$finishClassesName($classesCollector,' 1983 buffer.write('$finishClassesName($classesCollector,'
2033 '$_$isolateProperties,' 1984 '$_$isolateProperties,'
2034 '${_}null)$N'); 1985 '${_}null)$N');
2035 1986
2036 // Reset the map. 1987 // Reset the map.
2037 buffer.write("$classesCollector$_=${_}null$N$n"); 1988 buffer.write("$classesCollector$_=${_}null$N$n");
2038 } 1989 }
2039 } 1990 }
2040 1991
2041 void emitStaticFunction(CodeBuffer buffer,
2042 String name,
2043 jsAst.Expression functionExpression) {
2044 // TODO(ahe): This method (emitStaticFunction) should return a
2045 // jsAst.Expression.
2046 if (!buffer.isEmpty) {
2047 buffer.write(',$n$n');
2048 }
2049 buffer.write('$name:$_');
2050 buffer.write(jsAst.prettyPrint(functionExpression, compiler));
2051 }
2052
2053 void emitStaticFunctions(CodeBuffer eagerBuffer) { 1992 void emitStaticFunctions(CodeBuffer eagerBuffer) {
2054 bool isStaticFunction(Element element) => 1993 bool isStaticFunction(Element element) =>
2055 !element.isInstanceMember() && !element.isField(); 1994 !element.isInstanceMember() && !element.isField();
2056 1995
2057 Iterable<Element> elements = 1996 Iterable<Element> elements =
2058 backend.generatedCode.keys.where(isStaticFunction); 1997 backend.generatedCode.keys.where(isStaticFunction);
2059 Set<Element> pendingElementsWithBailouts = 1998 Set<Element> pendingElementsWithBailouts =
2060 backend.generatedBailoutCode.keys 1999 backend.generatedBailoutCode.keys
2061 .where(isStaticFunction) 2000 .where(isStaticFunction)
2062 .toSet(); 2001 .toSet();
2063 2002
2064 for (Element element in Elements.sortedByPosition(elements)) { 2003 for (Element element in Elements.sortedByPosition(elements)) {
2065 CodeBuffer buffer = bufferForElement(element, eagerBuffer); 2004 pendingElementsWithBailouts.remove(element);
2066 jsAst.Expression code = backend.generatedCode[element]; 2005 ClassBuilder builder = new ClassBuilder();
2067 String name = namer.getNameOfGlobalFunction(element); 2006 containerBuilder.addMember(element, builder);
2068 code = extendWithMetadata(element, code); 2007 builder.writeOn_DO_NOT_USE(
2069 emitStaticFunction(buffer, name, code); 2008 bufferForElement(element, eagerBuffer), compiler, ',$n$n');
2070 String reflectionName = getReflectionName(element, name);
2071 if (reflectionName != null) {
2072 var reflectable = backend.isAccessibleByReflection(element) ? 1 : 0;
2073 buffer.write(',$n$n"+$reflectionName":${_}$reflectable');
2074 jsAst.Node defaultValues = reifyDefaultArguments(element);
2075 if (defaultValues != null) {
2076 String unmangledName = element.name.slowToString();
2077 buffer.write(',$n$n"*$unmangledName":${_}');
2078 buffer.write(jsAst.prettyPrint(defaultValues, compiler));
2079 }
2080 }
2081 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element];
2082 if (bailoutCode != null) {
2083 pendingElementsWithBailouts.remove(element);
2084 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode);
2085 }
2086 } 2009 }
2087 2010
2088 if (!pendingElementsWithBailouts.isEmpty) { 2011 if (!pendingElementsWithBailouts.isEmpty) {
2089 addComment('pendingElementsWithBailouts', eagerBuffer); 2012 addComment('pendingElementsWithBailouts', eagerBuffer);
2090 } 2013 }
2091 // Is it possible the primary function was inlined but the bailout was not? 2014 // Is it possible the primary function was inlined but the bailout was not?
2092 for (Element element in 2015 for (Element element in
2093 Elements.sortedByPosition(pendingElementsWithBailouts)) { 2016 Elements.sortedByPosition(pendingElementsWithBailouts)) {
2094 CodeBuffer buffer = bufferForElement(element, eagerBuffer);
2095 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element]; 2017 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element];
2096 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); 2018 new ClassBuilder()
2019 ..addProperty(namer.getBailoutName(element), bailoutCode)
2020 ..writeOn_DO_NOT_USE(
2021 bufferForElement(element, eagerBuffer), compiler, ',$n$n');
2097 } 2022 }
2098 } 2023 }
2099 2024
2100 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { 2025 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) {
2101 ConstantHandler handler = compiler.constantHandler; 2026 ConstantHandler handler = compiler.constantHandler;
2102 Iterable<VariableElement> staticNonFinalFields = 2027 Iterable<VariableElement> staticNonFinalFields =
2103 handler.getStaticNonFinalFieldsForEmission(); 2028 handler.getStaticNonFinalFieldsForEmission();
2104 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { 2029 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) {
2105 // [:interceptedNames:] is handled in [emitInterceptedNames]. 2030 // [:interceptedNames:] is handled in [emitInterceptedNames].
2106 if (element == backend.interceptedNames) continue; 2031 if (element == backend.interceptedNames) continue;
(...skipping 952 matching lines...) Expand 10 before | Expand all | Expand 10 after
3059 return addGlobalMetadata('"${name.slowToString()}"'); 2984 return addGlobalMetadata('"${name.slowToString()}"');
3060 } 2985 }
3061 2986
3062 int addGlobalMetadata(String string) { 2987 int addGlobalMetadata(String string) {
3063 return globalMetadataMap.putIfAbsent(string, () { 2988 return globalMetadataMap.putIfAbsent(string, () {
3064 globalMetadata.add(string); 2989 globalMetadata.add(string);
3065 return globalMetadata.length - 1; 2990 return globalMetadata.length - 1;
3066 }); 2991 });
3067 } 2992 }
3068 2993
3069 jsAst.Fun extendWithMetadata(FunctionElement element, jsAst.Fun code) {
3070 if (!backend.retainMetadataOf(element)) return code;
3071 return compiler.withCurrentElement(element, () {
3072 List<int> metadata = <int>[];
3073 FunctionSignature signature = element.functionSignature;
3074 if (element.isConstructor()) {
3075 metadata.add(reifyType(element.getEnclosingClass().thisType));
3076 } else {
3077 metadata.add(reifyType(signature.returnType));
3078 }
3079 signature.forEachParameter((Element parameter) {
3080 metadata
3081 ..add(reifyName(parameter.name))
3082 ..add(reifyType(parameter.computeType(compiler)));
3083 });
3084 Link link = element.metadata;
3085 // TODO(ahe): Why is metadata sometimes null?
3086 if (link != null) {
3087 for (; !link.isEmpty; link = link.tail) {
3088 metadata.add(reifyMetadata(link.head));
3089 }
3090 }
3091 code.body.statements.add(js.string(metadata.join(',')).toStatement());
3092 return code;
3093 });
3094 }
3095
3096 void emitMetadata(CodeBuffer buffer) { 2994 void emitMetadata(CodeBuffer buffer) {
3097 var literals = backend.typedefTypeLiterals.toList(); 2995 var literals = backend.typedefTypeLiterals.toList();
3098 Elements.sortedByPosition(literals); 2996 Elements.sortedByPosition(literals);
3099 var properties = []; 2997 var properties = [];
3100 for (TypedefElement literal in literals) { 2998 for (TypedefElement literal in literals) {
3101 var key = namer.getNameX(literal); 2999 var key = namer.getNameX(literal);
3102 var value = js.toExpression(reifyType(literal.rawType)); 3000 var value = js.toExpression(reifyType(literal.rawType));
3103 properties.add(new jsAst.Property(js.string(key), value)); 3001 properties.add(new jsAst.Property(js.string(key), value));
3104 } 3002 }
3105 var map = new jsAst.ObjectInitializer(properties); 3003 var map = new jsAst.ObjectInitializer(properties);
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after
3598 } 3496 }
3599 3497
3600 bool isDeferred(Element element) { 3498 bool isDeferred(Element element) {
3601 return compiler.deferredLoadTask.isDeferred(element); 3499 return compiler.deferredLoadTask.isDeferred(element);
3602 } 3500 }
3603 3501
3604 bool get areAnyElementsDeferred { 3502 bool get areAnyElementsDeferred {
3605 return compiler.deferredLoadTask.areAnyElementsDeferred; 3503 return compiler.deferredLoadTask.areAnyElementsDeferred;
3606 } 3504 }
3607 } 3505 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698