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

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

Issue 27524003: Generate tear-off closures dynamically. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Merged with r30954 Created 7 years 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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 class ClassEmitter extends CodeEmitterHelper { 7 class ClassEmitter extends CodeEmitterHelper {
8 /** 8 /**
9 * Documentation wanted -- johnniwinther 9 * Documentation wanted -- johnniwinther
10 * 10 *
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 bool isLibrary = false; 101 bool isLibrary = false;
102 if (element.isClass()) { 102 if (element.isClass()) {
103 isClass = true; 103 isClass = true;
104 } else if (element.isLibrary()) { 104 } else if (element.isLibrary()) {
105 isLibrary = false; 105 isLibrary = false;
106 assert(invariant(element, emitStatics)); 106 assert(invariant(element, emitStatics));
107 } else { 107 } else {
108 throw new SpannableAssertionFailure( 108 throw new SpannableAssertionFailure(
109 element, 'Must be a ClassElement or a LibraryElement'); 109 element, 'Must be a ClassElement or a LibraryElement');
110 } 110 }
111 StringBuffer buffer = new StringBuffer();
112 if (emitStatics) { 111 if (emitStatics) {
113 assert(invariant(element, superName == null, message: superName)); 112 assert(invariant(element, superName == null, message: superName));
114 } else { 113 } else {
115 assert(invariant(element, superName != null)); 114 assert(invariant(element, superName != null));
116 String nativeName = 115 String nativeName =
117 namer.getPrimitiveInterceptorRuntimeName(element); 116 namer.getPrimitiveInterceptorRuntimeName(element);
118 if (nativeName != null) { 117 if (nativeName != null) {
119 buffer.write('$nativeName/'); 118 builder.nativeName = nativeName;
120 } 119 }
121 buffer.write('$superName;'); 120 builder.superName = superName;
122 } 121 }
123 int bufferClassLength = buffer.length;
124
125 String separator = '';
126
127 var fieldMetadata = []; 122 var fieldMetadata = [];
128 bool hasMetadata = false; 123 bool hasMetadata = false;
124 bool fieldsAdded = false;
129 125
130 if (!onlyForRti) { 126 if (!onlyForRti) {
131 visitFields(element, emitStatics, 127 visitFields(element, emitStatics,
132 (VariableElement field, 128 (VariableElement field,
133 String name, 129 String name,
134 String accessorName, 130 String accessorName,
135 bool needsGetter, 131 bool needsGetter,
136 bool needsSetter, 132 bool needsSetter,
137 bool needsCheckedSetter) { 133 bool needsCheckedSetter) {
138 // Ignore needsCheckedSetter - that is handled below. 134 // Ignore needsCheckedSetter - that is handled below.
139 bool needsAccessor = (needsGetter || needsSetter); 135 bool needsAccessor = (needsGetter || needsSetter);
140 // We need to output the fields for non-native classes so we can auto- 136 // We need to output the fields for non-native classes so we can auto-
141 // generate the constructor. For native classes there are no 137 // generate the constructor. For native classes there are no
142 // constructors, so we don't need the fields unless we are generating 138 // constructors, so we don't need the fields unless we are generating
143 // accessors at runtime. 139 // accessors at runtime.
144 if (!classIsNative || needsAccessor) { 140 if (!classIsNative || needsAccessor) {
145 buffer.write(separator);
146 separator = ',';
147 var metadata = task.metadataEmitter.buildMetadataFunction(field); 141 var metadata = task.metadataEmitter.buildMetadataFunction(field);
148 if (metadata != null) { 142 if (metadata != null) {
149 hasMetadata = true; 143 hasMetadata = true;
150 } else { 144 } else {
151 metadata = new jsAst.LiteralNull(); 145 metadata = new jsAst.LiteralNull();
152 } 146 }
153 fieldMetadata.add(metadata); 147 fieldMetadata.add(metadata);
154 recordMangledField(field, accessorName, field.name); 148 recordMangledField(field, accessorName, field.name);
149 String fieldName = name;
150 String fieldCode = '';
151 String reflectionMarker = '';
155 if (!needsAccessor) { 152 if (!needsAccessor) {
156 // Emit field for constructor generation. 153 // Emit field for constructor generation.
157 assert(!classIsNative); 154 assert(!classIsNative);
158 buffer.write(name);
159 } else { 155 } else {
160 // Emit (possibly renaming) field name so we can add accessors at 156 // Emit (possibly renaming) field name so we can add accessors at
161 // runtime. 157 // runtime.
162 buffer.write(accessorName);
163 if (name != accessorName) { 158 if (name != accessorName) {
164 buffer.write(':$name'); 159 fieldName = '$accessorName:$name';
165 } 160 }
166 161
167 int getterCode = 0; 162 int getterCode = 0;
168 if (needsGetter) { 163 if (needsGetter) {
169 if (field.isInstanceMember()) { 164 if (field.isInstanceMember()) {
170 // 01: function() { return this.field; } 165 // 01: function() { return this.field; }
171 // 10: function(receiver) { return receiver.field; } 166 // 10: function(receiver) { return receiver.field; }
172 // 11: function(receiver) { return this.field; } 167 // 11: function(receiver) { return this.field; }
173 bool isIntercepted = backend.fieldHasInterceptedGetter(field); 168 bool isIntercepted = backend.fieldHasInterceptedGetter(field);
174 getterCode += isIntercepted ? 2 : 0; 169 getterCode += isIntercepted ? 2 : 0;
(...skipping 26 matching lines...) Expand all
201 } 196 }
202 } else { 197 } else {
203 setterCode = 1; 198 setterCode = 1;
204 } 199 }
205 } 200 }
206 int code = getterCode + (setterCode << 2); 201 int code = getterCode + (setterCode << 2);
207 if (code == 0) { 202 if (code == 0) {
208 compiler.reportInternalError( 203 compiler.reportInternalError(
209 field, 'Internal error: code is 0 ($element/$field)'); 204 field, 'Internal error: code is 0 ($element/$field)');
210 } else { 205 } else {
211 buffer.write(FIELD_CODE_CHARACTERS[code - FIRST_FIELD_CODE]); 206 fieldCode = FIELD_CODE_CHARACTERS[code - FIRST_FIELD_CODE];
212 } 207 }
213 } 208 }
214 if (backend.isAccessibleByReflection(field)) { 209 if (backend.isAccessibleByReflection(field)) {
215 buffer.write('-'); 210 reflectionMarker = '-';
216 if (backend.isNeededForReflection(field)) { 211 if (backend.isNeededForReflection(field)) {
217 DartType type = field.computeType(compiler); 212 DartType type = field.computeType(compiler);
218 buffer.write('${task.metadataEmitter.reifyType(type)}'); 213 reflectionMarker = '-${task.metadataEmitter.reifyType(type)}';
219 } 214 }
220 } 215 }
216 builder.addField('$fieldName$fieldCode$reflectionMarker');
217 fieldsAdded = true;
221 } 218 }
222 }); 219 });
223 } 220 }
224 221
225 bool fieldsAdded = buffer.length > bufferClassLength;
226 String compactClassData = buffer.toString();
227 jsAst.Expression classDataNode = js.string(compactClassData);
228 if (hasMetadata) { 222 if (hasMetadata) {
229 fieldMetadata.insert(0, classDataNode); 223 builder.fieldMetadata = fieldMetadata;
230 classDataNode = new jsAst.ArrayInitializer.from(fieldMetadata);
231 } 224 }
232 builder.addProperty('', classDataNode);
233 return fieldsAdded; 225 return fieldsAdded;
234 } 226 }
235 227
236 void emitClassGettersSetters(ClassElement classElement, 228 void emitClassGettersSetters(ClassElement classElement,
237 ClassBuilder builder, 229 ClassBuilder builder,
238 {bool onlyForRti: false}) { 230 {bool onlyForRti: false}) {
239 if (onlyForRti) return; 231 if (onlyForRti) return;
240 232
241 visitFields(classElement, false, 233 visitFields(classElement, false,
242 (VariableElement member, 234 (VariableElement member,
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 if ((!typeVariableProperties.isEmpty && !hasSuper) || 306 if ((!typeVariableProperties.isEmpty && !hasSuper) ||
315 (hasSuper && superclass.typeVariables != typeVars)) { 307 (hasSuper && superclass.typeVariables != typeVars)) {
316 classBuilder.addProperty('<>', 308 classBuilder.addProperty('<>',
317 new jsAst.ArrayInitializer.from(typeVariableProperties)); 309 new jsAst.ArrayInitializer.from(typeVariableProperties));
318 } 310 }
319 } 311 }
320 312
321 List<jsAst.Property> statics = new List<jsAst.Property>(); 313 List<jsAst.Property> statics = new List<jsAst.Property>();
322 ClassBuilder staticsBuilder = new ClassBuilder(); 314 ClassBuilder staticsBuilder = new ClassBuilder();
323 if (emitFields(classElement, staticsBuilder, null, emitStatics: true)) { 315 if (emitFields(classElement, staticsBuilder, null, emitStatics: true)) {
324 statics.add(staticsBuilder.properties.single); 316 statics.add(staticsBuilder.toObjectInitializer().properties.single);
325 } 317 }
326 318
327 Map<String, ClassBuilder> classPropertyLists = 319 Map<String, ClassBuilder> classPropertyLists =
328 task.elementDecriptors.remove(classElement); 320 task.elementDecriptors.remove(classElement);
329 if (classPropertyLists != null) { 321 if (classPropertyLists != null) {
330 for (ClassBuilder classProperties in classPropertyLists.values) { 322 for (ClassBuilder classProperties in classPropertyLists.values) {
331 // TODO(ahe): What about deferred? 323 // TODO(ahe): What about deferred?
332 if (classProperties != null) { 324 if (classProperties != null) {
333 statics.addAll(classProperties.properties); 325 statics.addAll(classProperties.properties);
334 } 326 }
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 computeTypeVariable = 592 computeTypeVariable =
601 js(r'this.$builtinTypeInfo && this.$builtinTypeInfo[#]', index); 593 js(r'this.$builtinTypeInfo && this.$builtinTypeInfo[#]', index);
602 } 594 }
603 jsAst.Expression convertRtiToRuntimeType = 595 jsAst.Expression convertRtiToRuntimeType =
604 namer.elementAccess(compiler.findHelper('convertRtiToRuntimeType')); 596 namer.elementAccess(compiler.findHelper('convertRtiToRuntimeType'));
605 builder.addProperty( 597 builder.addProperty(
606 name, js.fun( 598 name, js.fun(
607 [], [js.return_(convertRtiToRuntimeType(computeTypeVariable))])); 599 [], [js.return_(convertRtiToRuntimeType(computeTypeVariable))]));
608 } 600 }
609 } 601 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698