| OLD | NEW |
| 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'; |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 }); | 224 }); |
| 225 return libraries; | 225 return libraries; |
| 226 } | 226 } |
| 227 | 227 |
| 228 // Note that a library-element may have multiple [Library]s, if it is split | 228 // Note that a library-element may have multiple [Library]s, if it is split |
| 229 // into multiple output units. | 229 // into multiple output units. |
| 230 Library _buildLibrary(LibraryElement library, List<Element> elements) { | 230 Library _buildLibrary(LibraryElement library, List<Element> elements) { |
| 231 String uri = library.canonicalUri.toString(); | 231 String uri = library.canonicalUri.toString(); |
| 232 | 232 |
| 233 List<StaticMethod> statics = elements | 233 List<StaticMethod> statics = elements |
| 234 .where((e) => e is FunctionElement).map(_buildStaticMethod).toList(); | |
| 235 | |
| 236 statics.addAll(elements | |
| 237 .where((e) => e is FunctionElement) | 234 .where((e) => e is FunctionElement) |
| 238 .where((e) => universe.staticFunctionsNeedingGetter.contains(e)) | 235 .map(_buildStaticMethod) |
| 239 .map(_buildStaticMethodTearOff)); | 236 .toList(); |
| 240 | 237 |
| 241 if (library == backend.interceptorsLibrary) { | 238 if (library == backend.interceptorsLibrary) { |
| 242 statics.addAll(_generateGetInterceptorMethods()); | 239 statics.addAll(_generateGetInterceptorMethods()); |
| 243 statics.addAll(_generateOneShotInterceptors()); | 240 statics.addAll(_generateOneShotInterceptors()); |
| 244 } | 241 } |
| 245 | 242 |
| 246 List<Class> classes = elements | 243 List<Class> classes = elements |
| 247 .where((e) => e is ClassElement) | 244 .where((e) => e is ClassElement) |
| 248 .map(_buildClass) | 245 .map(_buildClass) |
| 249 .toList(growable: false); | 246 .toList(growable: false); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 name, holder, methods, fields, | 309 name, holder, methods, fields, |
| 313 isDirectlyInstantiated: isInstantiated, | 310 isDirectlyInstantiated: isInstantiated, |
| 314 onlyForRti: onlyForRti); | 311 onlyForRti: onlyForRti); |
| 315 } | 312 } |
| 316 _classes[element] = result; | 313 _classes[element] = result; |
| 317 return result; | 314 return result; |
| 318 } | 315 } |
| 319 | 316 |
| 320 Method _buildMethod(FunctionElement element, js.Expression code) { | 317 Method _buildMethod(FunctionElement element, js.Expression code) { |
| 321 String name = namer.getNameOfInstanceMember(element); | 318 String name = namer.getNameOfInstanceMember(element); |
| 322 return new Method(element, name, code); | 319 // TODO(floitsch): compute `needsTearOff`. |
| 320 return new Method(element, name, code, needsTearOff: false); |
| 323 } | 321 } |
| 324 | 322 |
| 325 Method _buildStubMethod(String name, js.Expression code) { | 323 Method _buildStubMethod(String name, js.Expression code) { |
| 326 return new StubMethod(name, code); | 324 // TODO(floitsch): compute `needsTearOff`. |
| 325 return new StubMethod(name, code, needsTearOff: false); |
| 327 } | 326 } |
| 328 | 327 |
| 329 // The getInterceptor methods directly access the prototype of classes. | 328 // The getInterceptor methods directly access the prototype of classes. |
| 330 // We must evaluate these classes eagerly so that the prototype is | 329 // We must evaluate these classes eagerly so that the prototype is |
| 331 // accessible. | 330 // accessible. |
| 332 void _markEagerInterceptorClasses() { | 331 void _markEagerInterceptorClasses() { |
| 333 Map<String, Set<ClassElement>> specializedGetInterceptors = | 332 Map<String, Set<ClassElement>> specializedGetInterceptors = |
| 334 backend.specializedGetInterceptors; | 333 backend.specializedGetInterceptors; |
| 335 for (Set<ClassElement> classes in specializedGetInterceptors.values) { | 334 for (Set<ClassElement> classes in specializedGetInterceptors.values) { |
| 336 for (ClassElement element in classes) { | 335 for (ClassElement element in classes) { |
| 337 Class cls = _classes[element]; | 336 Class cls = _classes[element]; |
| 338 if (cls != null) cls.isEager = true; | 337 if (cls != null) cls.isEager = true; |
| 339 } | 338 } |
| 340 } | 339 } |
| 341 } | 340 } |
| 342 | 341 |
| 343 Iterable<StaticMethod> _generateGetInterceptorMethods() { | 342 Iterable<StaticMethod> _generateGetInterceptorMethods() { |
| 344 emitterTask.InterceptorStubGenerator stubGenerator = | 343 emitterTask.InterceptorStubGenerator stubGenerator = |
| 345 new emitterTask.InterceptorStubGenerator(_compiler, namer, backend); | 344 new emitterTask.InterceptorStubGenerator(_compiler, namer, backend); |
| 346 | 345 |
| 347 String holderName = namer.globalObjectFor(backend.interceptorsLibrary); | 346 String holderName = namer.globalObjectFor(backend.interceptorsLibrary); |
| 348 Holder holder = _registry.registerHolder(holderName); | 347 Holder holder = _registry.registerHolder(holderName); |
| 349 | 348 |
| 350 Map<String, Set<ClassElement>> specializedGetInterceptors = | 349 Map<String, Set<ClassElement>> specializedGetInterceptors = |
| 351 backend.specializedGetInterceptors; | 350 backend.specializedGetInterceptors; |
| 352 List<String> names = specializedGetInterceptors.keys.toList()..sort(); | 351 List<String> names = specializedGetInterceptors.keys.toList()..sort(); |
| 353 return names.map((String name) { | 352 return names.map((String name) { |
| 354 Set<ClassElement> classes = specializedGetInterceptors[name]; | 353 Set<ClassElement> classes = specializedGetInterceptors[name]; |
| 355 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); | 354 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); |
| 356 return new StaticStubMethod(name, holder, code); | 355 // TODO(floitsch): compute `needsTearOff`. |
| 356 return new StaticStubMethod(name, holder, code, needsTearOff: false); |
| 357 }); | 357 }); |
| 358 } | 358 } |
| 359 | 359 |
| 360 bool _fieldNeedsGetter(VariableElement field) { | 360 bool _fieldNeedsGetter(VariableElement field) { |
| 361 assert(field.isField); | 361 assert(field.isField); |
| 362 if (_fieldAccessNeverThrows(field)) return false; | 362 if (_fieldAccessNeverThrows(field)) return false; |
| 363 return backend.shouldRetainGetter(field) | 363 return backend.shouldRetainGetter(field) |
| 364 || _compiler.codegenWorld.hasInvokedGetter(field, _compiler.world); | 364 || _compiler.codegenWorld.hasInvokedGetter(field, _compiler.world); |
| 365 } | 365 } |
| 366 | 366 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 Iterable<StaticMethod> _generateOneShotInterceptors() { | 416 Iterable<StaticMethod> _generateOneShotInterceptors() { |
| 417 emitterTask.InterceptorStubGenerator stubGenerator = | 417 emitterTask.InterceptorStubGenerator stubGenerator = |
| 418 new emitterTask.InterceptorStubGenerator(_compiler, namer, backend); | 418 new emitterTask.InterceptorStubGenerator(_compiler, namer, backend); |
| 419 | 419 |
| 420 String holderName = namer.globalObjectFor(backend.interceptorsLibrary); | 420 String holderName = namer.globalObjectFor(backend.interceptorsLibrary); |
| 421 Holder holder = _registry.registerHolder(holderName); | 421 Holder holder = _registry.registerHolder(holderName); |
| 422 | 422 |
| 423 List<String> names = backend.oneShotInterceptors.keys.toList()..sort(); | 423 List<String> names = backend.oneShotInterceptors.keys.toList()..sort(); |
| 424 return names.map((String name) { | 424 return names.map((String name) { |
| 425 js.Expression code = stubGenerator.generateOneShotInterceptor(name); | 425 js.Expression code = stubGenerator.generateOneShotInterceptor(name); |
| 426 return new StaticStubMethod(name, holder, code); | 426 return new StaticStubMethod(name, holder, code, needsTearOff: false); |
| 427 }); | 427 }); |
| 428 } | 428 } |
| 429 | 429 |
| 430 StaticMethod _buildStaticMethod(FunctionElement element) { | 430 StaticMethod _buildStaticMethod(FunctionElement element) { |
| 431 String name = namer.getNameOfMember(element); | 431 String name = namer.getNameOfMember(element); |
| 432 String holder = namer.globalObjectFor(element); | 432 String holder = namer.globalObjectFor(element); |
| 433 js.Expression code = backend.generatedCode[element]; | 433 js.Expression code = backend.generatedCode[element]; |
| 434 bool needsTearOff = |
| 435 universe.staticFunctionsNeedingGetter.contains(element); |
| 436 // TODO(floitsch): add tear-off name: namer.getStaticClosureName(element). |
| 434 return new StaticMethod(element, | 437 return new StaticMethod(element, |
| 435 name, _registry.registerHolder(holder), code); | 438 name, _registry.registerHolder(holder), code, |
| 436 } | 439 needsTearOff: needsTearOff); |
| 437 | |
| 438 StaticMethod _buildStaticMethodTearOff(FunctionElement element) { | |
| 439 String name = namer.getStaticClosureName(element); | |
| 440 String holder = namer.globalObjectFor(element); | |
| 441 // TODO(kasperl): This clearly doesn't work yet. | |
| 442 js.Expression code = js.string("<<unimplemented>>"); | |
| 443 return new StaticMethod(element, | |
| 444 name, _registry.registerHolder(holder), code); | |
| 445 } | 440 } |
| 446 | 441 |
| 447 void _registerConstants(OutputUnit outputUnit, | 442 void _registerConstants(OutputUnit outputUnit, |
| 448 Iterable<ConstantValue> constantValues) { | 443 Iterable<ConstantValue> constantValues) { |
| 449 // `constantValues` is null if an outputUnit doesn't contain any constants. | 444 // `constantValues` is null if an outputUnit doesn't contain any constants. |
| 450 if (constantValues == null) return; | 445 if (constantValues == null) return; |
| 451 for (ConstantValue constantValue in constantValues) { | 446 for (ConstantValue constantValue in constantValues) { |
| 452 _registry.registerConstant(outputUnit, constantValue); | 447 _registry.registerConstant(outputUnit, constantValue); |
| 453 assert(!_constants.containsKey(constantValue)); | 448 assert(!_constants.containsKey(constantValue)); |
| 454 String name = namer.constantName(constantValue); | 449 String name = namer.constantName(constantValue); |
| 455 String constantObject = namer.globalObjectForConstant(constantValue); | 450 String constantObject = namer.globalObjectForConstant(constantValue); |
| 456 Holder holder = _registry.registerHolder(constantObject); | 451 Holder holder = _registry.registerHolder(constantObject); |
| 457 Constant constant = new Constant(name, holder, constantValue); | 452 Constant constant = new Constant(name, holder, constantValue); |
| 458 _constants[constantValue] = constant; | 453 _constants[constantValue] = constant; |
| 459 } | 454 } |
| 460 } | 455 } |
| 461 } | 456 } |
| OLD | NEW |