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

Side by Side Diff: pkg/compiler/lib/src/js_emitter/program_builder.dart

Issue 869543004: dart2js: store fields in the model and make the emitters use it. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 5 years, 11 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
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 library dart2js.js_emitter.program_builder; 5 library dart2js.js_emitter.program_builder;
6 6
7 import 'js_emitter.dart' show computeMixinClass; 7 import 'js_emitter.dart' show computeMixinClass;
8 import 'model.dart'; 8 import 'model.dart';
9 9
10 import '../common.dart'; 10 import '../common.dart';
11 import '../js/js.dart' as js; 11 import '../js/js.dart' as js;
12 12
13 import '../js_backend/js_backend.dart' show 13 import '../js_backend/js_backend.dart' show
14 Namer, 14 Namer,
15 JavaScriptBackend, 15 JavaScriptBackend,
16 JavaScriptConstantCompiler; 16 JavaScriptConstantCompiler;
17 17
18 import '../closure.dart' show ClosureFieldElement;
19
20 import 'js_emitter.dart' as emitterTask show 18 import 'js_emitter.dart' as emitterTask show
21 CodeEmitterTask, 19 CodeEmitterTask,
22 Emitter, 20 Emitter,
23 InterceptorStubGenerator, 21 InterceptorStubGenerator,
24 TypeTestGenerator, 22 TypeTestGenerator,
25 TypeTestProperties; 23 TypeTestProperties;
26 24
27 import '../universe/universe.dart' show Universe; 25 import '../universe/universe.dart' show Universe;
28 import '../deferred_load.dart' show DeferredLoadTask, OutputUnit; 26 import '../deferred_load.dart' show DeferredLoadTask, OutputUnit;
29 27
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 if (library == backend.interceptorsLibrary) { 248 if (library == backend.interceptorsLibrary) {
251 statics.addAll(_generateGetInterceptorMethods()); 249 statics.addAll(_generateGetInterceptorMethods());
252 statics.addAll(_generateOneShotInterceptors()); 250 statics.addAll(_generateOneShotInterceptors());
253 } 251 }
254 252
255 List<Class> classes = elements 253 List<Class> classes = elements
256 .where((e) => e is ClassElement) 254 .where((e) => e is ClassElement)
257 .map(_buildClass) 255 .map(_buildClass)
258 .toList(growable: false); 256 .toList(growable: false);
259 257
260 return new Library(library, uri, statics, classes); 258 bool visitStatics = true;
259 List<Field> staticFieldsForReflection = _buildFields(library, visitStatics);
260
261 return new Library(library, uri, statics, classes,
262 staticFieldsForReflection);
261 } 263 }
262 264
263 Class _buildClass(ClassElement element) { 265 Class _buildClass(ClassElement element) {
266 bool onlyForRti = _task.typeTestRegistry.rtiNeededClasses.contains(element);
267
264 List<Method> methods = []; 268 List<Method> methods = [];
265 List<InstanceField> fields = [];
266 269
267 void visitMember(ClassElement enclosing, Element member) { 270 void visitMember(ClassElement enclosing, Element member) {
268 assert(invariant(element, member.isDeclaration)); 271 assert(invariant(element, member.isDeclaration));
269 assert(invariant(element, element == enclosing)); 272 assert(invariant(element, element == enclosing));
270 273
271 if (Elements.isNonAbstractInstanceMember(member)) { 274 if (Elements.isNonAbstractInstanceMember(member)) {
272 js.Expression code = backend.generatedCode[member]; 275 js.Expression code = backend.generatedCode[member];
273 // TODO(kasperl): Figure out under which conditions code is null. 276 // TODO(kasperl): Figure out under which conditions code is null.
274 if (code != null) methods.add(_buildMethod(member, code)); 277 if (code != null) methods.add(_buildMethod(member, code));
275 } else if (member.isField && !member.isStatic) {
276 fields.add(_buildInstanceField(member, enclosing));
277 } 278 }
278 } 279 }
279 280
280 ClassElement implementation = element.implementation; 281 ClassElement implementation = element.implementation;
281 282
282 // MixinApplications run through the members of their mixin. Here, we are 283 // MixinApplications run through the members of their mixin. Here, we are
283 // only interested in direct members. 284 // only interested in direct members.
284 if (!element.isMixinApplication) { 285 if (!element.isMixinApplication) {
285 implementation.forEachMember(visitMember, includeBackendMembers: true); 286 implementation.forEachMember(visitMember, includeBackendMembers: true);
286 } 287 }
287 288
289 List<Field> instanceFields =
290 onlyForRti ? const <Field>[] : _buildFields(element, false);
291 List<Field> staticFieldsForReflection =
292 onlyForRti ? const <Field>[] : _buildFields(element, true);
293
288 emitterTask.TypeTestGenerator generator = 294 emitterTask.TypeTestGenerator generator =
289 new emitterTask.TypeTestGenerator(_compiler, _task, namer); 295 new emitterTask.TypeTestGenerator(_compiler, _task, namer);
290 emitterTask.TypeTestProperties typeTests = 296 emitterTask.TypeTestProperties typeTests =
291 generator.generateIsTests( 297 generator.generateIsTests(
292 element, 298 element,
293 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); 299 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata);
294 300
295 List<StubMethod> isChecks = <StubMethod>[]; 301 List<StubMethod> isChecks = <StubMethod>[];
296 typeTests.properties.forEach((String name, js.Node code) { 302 typeTests.properties.forEach((String name, js.Node code) {
297 isChecks.add(_buildStubMethod(name, code)); 303 isChecks.add(_buildStubMethod(name, code));
298 }); 304 });
299 305
300 String name = namer.getNameOfClass(element); 306 String name = namer.getNameOfClass(element);
301 String holderName = namer.globalObjectFor(element); 307 String holderName = namer.globalObjectFor(element);
302 Holder holder = _registry.registerHolder(holderName); 308 Holder holder = _registry.registerHolder(holderName);
303 bool onlyForRti = _task.typeTestRegistry.rtiNeededClasses.contains(element);
304 bool isInstantiated = 309 bool isInstantiated =
305 _compiler.codegenWorld.directlyInstantiatedClasses.contains(element); 310 _compiler.codegenWorld.directlyInstantiatedClasses.contains(element);
306 311
307 Class result; 312 Class result;
308 if (element.isMixinApplication && !onlyForRti) { 313 if (element.isMixinApplication && !onlyForRti) {
309 assert(!element.isNative); 314 assert(!element.isNative);
310 assert(methods.isEmpty); 315 assert(methods.isEmpty);
311 assert(fields.isEmpty);
312 316
313 result = new MixinApplication(element, 317 result = new MixinApplication(element,
314 name, holder, isChecks, 318 name, holder,
319 instanceFields,
320 staticFieldsForReflection,
321 isChecks,
315 typeTests.functionTypeIndex, 322 typeTests.functionTypeIndex,
316 isDirectlyInstantiated: isInstantiated, 323 isDirectlyInstantiated: isInstantiated,
317 onlyForRti: onlyForRti); 324 onlyForRti: onlyForRti);
318 } else { 325 } else {
319 result = new Class(element, 326 result = new Class(element,
320 name, holder, methods, fields, isChecks, 327 name, holder, methods, instanceFields,
328 staticFieldsForReflection,
329 isChecks,
321 typeTests.functionTypeIndex, 330 typeTests.functionTypeIndex,
322 isDirectlyInstantiated: isInstantiated, 331 isDirectlyInstantiated: isInstantiated,
323 onlyForRti: onlyForRti, 332 onlyForRti: onlyForRti,
324 isNative: element.isNative); 333 isNative: element.isNative);
325 } 334 }
326 _classes[element] = result; 335 _classes[element] = result;
327 return result; 336 return result;
328 } 337 }
329 338
330 Method _buildMethod(FunctionElement element, js.Expression code) { 339 Method _buildMethod(FunctionElement element, js.Expression code) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 backend.specializedGetInterceptors; 372 backend.specializedGetInterceptors;
364 List<String> names = specializedGetInterceptors.keys.toList()..sort(); 373 List<String> names = specializedGetInterceptors.keys.toList()..sort();
365 return names.map((String name) { 374 return names.map((String name) {
366 Set<ClassElement> classes = specializedGetInterceptors[name]; 375 Set<ClassElement> classes = specializedGetInterceptors[name];
367 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); 376 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes);
368 // TODO(floitsch): compute `needsTearOff`. 377 // TODO(floitsch): compute `needsTearOff`.
369 return new StaticStubMethod(name, holder, code, needsTearOff: false); 378 return new StaticStubMethod(name, holder, code, needsTearOff: false);
370 }); 379 });
371 } 380 }
372 381
373 bool _fieldNeedsGetter(VariableElement field) { 382 List<Field> _buildFields(Element holder, bool visitStatics) {
374 assert(field.isField); 383 List<Field> fields = <Field>[];
375 if (_fieldAccessNeverThrows(field)) return false; 384 _task.oldEmitter.classEmitter.visitFields(
376 return backend.shouldRetainGetter(field) 385 holder, visitStatics, (VariableElement field,
377 || _compiler.codegenWorld.hasInvokedGetter(field, _compiler.world); 386 String name,
378 } 387 String accessorName,
388 bool needsGetter,
389 bool needsSetter,
390 bool needsCheckedSetter) {
391 assert(invariant(field, field.isDeclaration));
379 392
380 bool _fieldNeedsSetter(VariableElement field) { 393 int getterFlags = 0;
381 assert(field.isField); 394 if (needsGetter) {
382 if (_fieldAccessNeverThrows(field)) return false; 395 if (visitStatics || !backend.fieldHasInterceptedGetter(field)) {
383 return (!field.isFinal && !field.isConst) 396 getterFlags = 1;
384 && (backend.shouldRetainSetter(field) 397 } else {
385 || _compiler.codegenWorld.hasInvokedSetter(field, _compiler.world)); 398 getterFlags += 2;
386 } 399 // TODO(sra): 'isInterceptorClass' might not be the correct test
400 // for methods forced to use the interceptor convention because
401 // the method's class was elsewhere mixed-in to an interceptor.
402 if (!backend.isInterceptorClass(holder)) {
403 getterFlags += 1;
404 }
405 }
406 }
387 407
388 // We never access a field in a closure (a captured variable) without knowing 408 int setterFlags = 0;
389 // that it is there. Therefore we don't need to use a getter (that will throw 409 if (needsSetter) {
390 // if the getter method is missing), but can always access the field directly. 410 if (visitStatics || !backend.fieldHasInterceptedSetter(field)) {
391 bool _fieldAccessNeverThrows(VariableElement field) { 411 setterFlags = 1;
392 return field is ClosureFieldElement; 412 } else {
393 } 413 setterFlags += 2;
414 if (!backend.isInterceptorClass(holder)) {
415 setterFlags += 1;
416 }
417 }
418 }
394 419
395 InstanceField _buildInstanceField(VariableElement field, 420 fields.add(new Field(field, name, accessorName,
396 ClassElement holder) { 421 getterFlags, setterFlags,
397 assert(invariant(field, field.isDeclaration)); 422 needsCheckedSetter));
398 String name = namer.fieldPropertyName(field); 423 });
399 424
400 int getterFlags = 0; 425 return fields;
401 if (_fieldNeedsGetter(field)) {
402 bool isIntercepted = backend.fieldHasInterceptedGetter(field);
403 if (isIntercepted) {
404 getterFlags += 2;
405 if (!backend.isInterceptorClass(holder)) {
406 getterFlags += 1;
407 }
408 } else {
409 getterFlags = 1;
410 }
411 }
412
413 int setterFlags = 0;
414 if (_fieldNeedsSetter(field)) {
415 bool isIntercepted = backend.fieldHasInterceptedSetter(field);
416 if (isIntercepted) {
417 setterFlags += 2;
418 if (!backend.isInterceptorClass(holder)) {
419 setterFlags += 1;
420 }
421 } else {
422 setterFlags = 1;
423 }
424 }
425
426 return new InstanceField(field, name, getterFlags, setterFlags);
427 } 426 }
428 427
429 Iterable<StaticMethod> _generateOneShotInterceptors() { 428 Iterable<StaticMethod> _generateOneShotInterceptors() {
430 emitterTask.InterceptorStubGenerator stubGenerator = 429 emitterTask.InterceptorStubGenerator stubGenerator =
431 new emitterTask.InterceptorStubGenerator(_compiler, namer, backend); 430 new emitterTask.InterceptorStubGenerator(_compiler, namer, backend);
432 431
433 String holderName = namer.globalObjectFor(backend.interceptorsLibrary); 432 String holderName = namer.globalObjectFor(backend.interceptorsLibrary);
434 Holder holder = _registry.registerHolder(holderName); 433 Holder holder = _registry.registerHolder(holderName);
435 434
436 List<String> names = backend.oneShotInterceptors.keys.toList()..sort(); 435 List<String> names = backend.oneShotInterceptors.keys.toList()..sort();
(...skipping 23 matching lines...) Expand all
460 _registry.registerConstant(outputUnit, constantValue); 459 _registry.registerConstant(outputUnit, constantValue);
461 assert(!_constants.containsKey(constantValue)); 460 assert(!_constants.containsKey(constantValue));
462 String name = namer.constantName(constantValue); 461 String name = namer.constantName(constantValue);
463 String constantObject = namer.globalObjectForConstant(constantValue); 462 String constantObject = namer.globalObjectForConstant(constantValue);
464 Holder holder = _registry.registerHolder(constantObject); 463 Holder holder = _registry.registerHolder(constantObject);
465 Constant constant = new Constant(name, holder, constantValue); 464 Constant constant = new Constant(name, holder, constantValue);
466 _constants[constantValue] = constant; 465 _constants[constantValue] = constant;
467 } 466 }
468 } 467 }
469 } 468 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698