| 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.new_js_emitter.model; | 5 library dart2js.new_js_emitter.model; |
| 6 | 6 |
| 7 import '../js/js.dart' as js show Expression, Statement; | 7 import '../js/js.dart' as js show Expression, Statement, Name, Literal; |
| 8 import '../constants/values.dart' show ConstantValue; | 8 import '../constants/values.dart' show ConstantValue; |
| 9 | 9 |
| 10 import '../deferred_load.dart' show OutputUnit; | 10 import '../deferred_load.dart' show OutputUnit; |
| 11 | 11 |
| 12 import 'js_emitter.dart' show MetadataCollector, TokenFinalizer; | 12 import 'js_emitter.dart' show MetadataCollector, TokenFinalizer; |
| 13 | 13 |
| 14 import '../common.dart'; | 14 import '../common.dart'; |
| 15 | 15 |
| 16 class Program { | 16 class Program { |
| 17 final List<Fragment> fragments; | 17 final List<Fragment> fragments; |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 outputFileName, | 158 outputFileName, |
| 159 libraries, | 159 libraries, |
| 160 staticNonFinalFields, | 160 staticNonFinalFields, |
| 161 staticLazilyInitializedFields, | 161 staticLazilyInitializedFields, |
| 162 constants); | 162 constants); |
| 163 | 163 |
| 164 bool get isMainFragment => false; | 164 bool get isMainFragment => false; |
| 165 } | 165 } |
| 166 | 166 |
| 167 class Constant { | 167 class Constant { |
| 168 final String name; | 168 final js.Name name; |
| 169 final Holder holder; | 169 final Holder holder; |
| 170 final ConstantValue value; | 170 final ConstantValue value; |
| 171 | 171 |
| 172 Constant(this.name, this.holder, this.value); | 172 Constant(this.name, this.holder, this.value); |
| 173 } | 173 } |
| 174 | 174 |
| 175 abstract class FieldContainer { | 175 abstract class FieldContainer { |
| 176 List<Field> get staticFieldsForReflection; | 176 List<Field> get staticFieldsForReflection; |
| 177 } | 177 } |
| 178 | 178 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 189 | 189 |
| 190 Library(this.element, this.uri, this.statics, this.classes, | 190 Library(this.element, this.uri, this.statics, this.classes, |
| 191 this.staticFieldsForReflection); | 191 this.staticFieldsForReflection); |
| 192 } | 192 } |
| 193 | 193 |
| 194 class StaticField { | 194 class StaticField { |
| 195 /// The element should only be used during the transition to the new model. | 195 /// The element should only be used during the transition to the new model. |
| 196 /// Uses indicate missing information in the model. | 196 /// Uses indicate missing information in the model. |
| 197 final Element element; | 197 final Element element; |
| 198 | 198 |
| 199 final String name; | 199 js.Name name; |
| 200 // TODO(floitsch): the holder for static fields is the isolate object. We | 200 // TODO(floitsch): the holder for static fields is the isolate object. We |
| 201 // could remove this field and use the isolate object directly. | 201 // could remove this field and use the isolate object directly. |
| 202 final Holder holder; | 202 final Holder holder; |
| 203 final js.Expression code; | 203 final js.Expression code; |
| 204 final bool isFinal; | 204 final bool isFinal; |
| 205 final bool isLazy; | 205 final bool isLazy; |
| 206 | 206 |
| 207 StaticField(this.element, | 207 StaticField(this.element, |
| 208 this.name, this.holder, this.code, | 208 this.name, this.holder, this.code, |
| 209 this.isFinal, this.isLazy); | 209 this.isFinal, this.isLazy); |
| 210 } | 210 } |
| 211 | 211 |
| 212 class Class implements FieldContainer { | 212 class Class implements FieldContainer { |
| 213 /// The element should only be used during the transition to the new model. | 213 /// The element should only be used during the transition to the new model. |
| 214 /// Uses indicate missing information in the model. | 214 /// Uses indicate missing information in the model. |
| 215 final Element element; | 215 final Element element; |
| 216 | 216 |
| 217 final String name; | 217 final js.Name name; |
| 218 final Holder holder; | 218 final Holder holder; |
| 219 Class _superclass; | 219 Class _superclass; |
| 220 final List<Method> methods; | 220 final List<Method> methods; |
| 221 final List<Field> fields; | 221 final List<Field> fields; |
| 222 final List<StubMethod> isChecks; | 222 final List<StubMethod> isChecks; |
| 223 | 223 |
| 224 /// Stub methods for this class that are call stubs for getters. | 224 /// Stub methods for this class that are call stubs for getters. |
| 225 final List<StubMethod> callStubs; | 225 final List<StubMethod> callStubs; |
| 226 | 226 |
| 227 /// Stub methods for this class handling reads to type variables. | 227 /// Stub methods for this class handling reads to type variables. |
| 228 final List<StubMethod> typeVariableReaderStubs; | 228 final List<StubMethod> typeVariableReaderStubs; |
| 229 | 229 |
| 230 /// noSuchMethod stubs in the special case that the class is Object. | 230 /// noSuchMethod stubs in the special case that the class is Object. |
| 231 final List<StubMethod> noSuchMethodStubs; | 231 final List<StubMethod> noSuchMethodStubs; |
| 232 final List<Field> staticFieldsForReflection; | 232 final List<Field> staticFieldsForReflection; |
| 233 final bool onlyForRti; | 233 final bool onlyForRti; |
| 234 final bool isDirectlyInstantiated; | 234 final bool isDirectlyInstantiated; |
| 235 final bool isNative; | 235 final bool isNative; |
| 236 | 236 |
| 237 // If the class implements a function type, and the type is encoded in the | 237 // If the class implements a function type, and the type is encoded in the |
| 238 // metatada table, then this field contains the index into that field. | 238 // metatada table, then this field contains the index into that field. |
| 239 final js.Expression functionTypeIndex; | 239 final js.Expression functionTypeIndex; |
| 240 | 240 |
| 241 /// Whether the class must be evaluated eagerly. | 241 /// Whether the class must be evaluated eagerly. |
| 242 bool isEager = false; | 242 bool isEager = false; |
| 243 | 243 |
| 244 /// Data that must be emitted with the class for native interop. | 244 /// Data that must be emitted with the class for native interop. |
| 245 String nativeInfo; | 245 js.Literal nativeInfo; |
| 246 | 246 |
| 247 Class(this.element, this.name, this.holder, | 247 Class(this.element, this.name, this.holder, |
| 248 this.methods, | 248 this.methods, |
| 249 this.fields, | 249 this.fields, |
| 250 this.staticFieldsForReflection, | 250 this.staticFieldsForReflection, |
| 251 this.callStubs, | 251 this.callStubs, |
| 252 this.typeVariableReaderStubs, | 252 this.typeVariableReaderStubs, |
| 253 this.noSuchMethodStubs, | 253 this.noSuchMethodStubs, |
| 254 this.isChecks, | 254 this.isChecks, |
| 255 this.functionTypeIndex, | 255 this.functionTypeIndex, |
| 256 {this.onlyForRti, | 256 {this.onlyForRti, |
| 257 this.isDirectlyInstantiated, | 257 this.isDirectlyInstantiated, |
| 258 this.isNative}) { | 258 this.isNative}) { |
| 259 assert(onlyForRti != null); | 259 assert(onlyForRti != null); |
| 260 assert(isDirectlyInstantiated != null); | 260 assert(isDirectlyInstantiated != null); |
| 261 assert(isNative != null); | 261 assert(isNative != null); |
| 262 } | 262 } |
| 263 | 263 |
| 264 bool get isMixinApplication => false; | 264 bool get isMixinApplication => false; |
| 265 Class get superclass => _superclass; | 265 Class get superclass => _superclass; |
| 266 | 266 |
| 267 void setSuperclass(Class superclass) { | 267 void setSuperclass(Class superclass) { |
| 268 _superclass = superclass; | 268 _superclass = superclass; |
| 269 } | 269 } |
| 270 | 270 |
| 271 String get superclassName | 271 js.Name get superclassName |
| 272 => (superclass == null) ? "" : superclass.name; | 272 => superclass == null ? null : superclass.name; |
| 273 |
| 273 int get superclassHolderIndex | 274 int get superclassHolderIndex |
| 274 => (superclass == null) ? 0 : superclass.holder.index; | 275 => (superclass == null) ? 0 : superclass.holder.index; |
| 275 } | 276 } |
| 276 | 277 |
| 277 class MixinApplication extends Class { | 278 class MixinApplication extends Class { |
| 278 Class _mixinClass; | 279 Class _mixinClass; |
| 279 | 280 |
| 280 MixinApplication(Element element, String name, Holder holder, | 281 MixinApplication(Element element, js.Name name, Holder holder, |
| 281 List<Field> instanceFields, | 282 List<Field> instanceFields, |
| 282 List<Field> staticFieldsForReflection, | 283 List<Field> staticFieldsForReflection, |
| 283 List<StubMethod> callStubs, | 284 List<StubMethod> callStubs, |
| 284 List<StubMethod> typeVariableReaderStubs, | 285 List<StubMethod> typeVariableReaderStubs, |
| 285 List<StubMethod> isChecks, | 286 List<StubMethod> isChecks, |
| 286 js.Expression functionTypeIndex, | 287 js.Expression functionTypeIndex, |
| 287 {bool onlyForRti, | 288 {bool onlyForRti, |
| 288 bool isDirectlyInstantiated}) | 289 bool isDirectlyInstantiated}) |
| 289 : super(element, | 290 : super(element, |
| 290 name, holder, | 291 name, holder, |
| (...skipping 18 matching lines...) Expand all Loading... |
| 309 | 310 |
| 310 /// A field. | 311 /// A field. |
| 311 /// | 312 /// |
| 312 /// In general represents an instance field, but for reflection may also | 313 /// In general represents an instance field, but for reflection may also |
| 313 /// represent static fields. | 314 /// represent static fields. |
| 314 class Field { | 315 class Field { |
| 315 /// The element should only be used during the transition to the new model. | 316 /// The element should only be used during the transition to the new model. |
| 316 /// Uses indicate missing information in the model. | 317 /// Uses indicate missing information in the model. |
| 317 final Element element; | 318 final Element element; |
| 318 | 319 |
| 319 final String name; | 320 final js.Name name; |
| 320 final String accessorName; | 321 final js.Name accessorName; |
| 321 | 322 |
| 322 /// 00: Does not need any getter. | 323 /// 00: Does not need any getter. |
| 323 /// 01: function() { return this.field; } | 324 /// 01: function() { return this.field; } |
| 324 /// 10: function(receiver) { return receiver.field; } | 325 /// 10: function(receiver) { return receiver.field; } |
| 325 /// 11: function(receiver) { return this.field; } | 326 /// 11: function(receiver) { return this.field; } |
| 326 final int getterFlags; | 327 final int getterFlags; |
| 327 | 328 |
| 328 /// 00: Does not need any setter. | 329 /// 00: Does not need any setter. |
| 329 /// 01: function(value) { this.field = value; } | 330 /// 01: function(value) { this.field = value; } |
| 330 /// 10: function(receiver, value) { receiver.field = value; } | 331 /// 10: function(receiver, value) { receiver.field = value; } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 342 bool get needsUncheckedSetter => setterFlags != 0; | 343 bool get needsUncheckedSetter => setterFlags != 0; |
| 343 | 344 |
| 344 bool get needsInterceptedGetter => getterFlags > 1; | 345 bool get needsInterceptedGetter => getterFlags > 1; |
| 345 bool get needsInterceptedSetter => setterFlags > 1; | 346 bool get needsInterceptedSetter => setterFlags > 1; |
| 346 } | 347 } |
| 347 | 348 |
| 348 abstract class Method { | 349 abstract class Method { |
| 349 /// The element should only be used during the transition to the new model. | 350 /// The element should only be used during the transition to the new model. |
| 350 /// Uses indicate missing information in the model. | 351 /// Uses indicate missing information in the model. |
| 351 final Element element; | 352 final Element element; |
| 352 final String name; | 353 final js.Name name; |
| 353 final js.Expression code; | 354 final js.Expression code; |
| 354 | 355 |
| 355 Method(this.element, this.name, this.code); | 356 Method(this.element, this.name, this.code); |
| 356 } | 357 } |
| 357 | 358 |
| 358 /// A method that corresponds to a method in the original Dart program. | 359 /// A method that corresponds to a method in the original Dart program. |
| 359 class DartMethod extends Method { | 360 class DartMethod extends Method { |
| 360 final bool needsTearOff; | 361 final bool needsTearOff; |
| 361 final String tearOffName; | 362 final js.Name tearOffName; |
| 362 final List<ParameterStubMethod> parameterStubs; | 363 final List<ParameterStubMethod> parameterStubs; |
| 363 final bool canBeApplied; | 364 final bool canBeApplied; |
| 364 final bool canBeReflected; | 365 final bool canBeReflected; |
| 365 | 366 |
| 366 // Is non-null if [needsTearOff] or [canBeReflected]. | 367 // Is non-null if [needsTearOff] or [canBeReflected]. |
| 367 // | 368 // |
| 368 // If the type is encoded in the metadata table this field contains an index | 369 // If the type is encoded in the metadata table this field contains an index |
| 369 // into the table. Otherwise the type contains type variables in which case | 370 // into the table. Otherwise the type contains type variables in which case |
| 370 // this field holds a function computing the function signature. | 371 // this field holds a function computing the function signature. |
| 371 final js.Expression functionType; | 372 final js.Expression functionType; |
| 372 | 373 |
| 373 // Signature information for this method. This is only required and stored | 374 // Signature information for this method. This is only required and stored |
| 374 // here if the method [canBeApplied] or [canBeReflected] | 375 // here if the method [canBeApplied] or [canBeReflected] |
| 375 final int requiredParameterCount; | 376 final int requiredParameterCount; |
| 376 final /* Map | List */ optionalParameterDefaultValues; | 377 final /* Map | List */ optionalParameterDefaultValues; |
| 377 | 378 |
| 378 // If this method can be torn off, contains the name of the corresponding | 379 // If this method can be torn off, contains the name of the corresponding |
| 379 // call method. For example, for the member `foo$1$name` it would be | 380 // call method. For example, for the member `foo$1$name` it would be |
| 380 // `call$1$name` (in unminified mode). | 381 // `call$1$name` (in unminified mode). |
| 381 final String callName; | 382 final js.Name callName; |
| 382 | 383 |
| 383 DartMethod(Element element, String name, js.Expression code, | 384 DartMethod(Element element, js.Name name, js.Expression code, |
| 384 this.parameterStubs, this.callName, | 385 this.parameterStubs, this.callName, |
| 385 {this.needsTearOff, this.tearOffName, this.canBeApplied, | 386 {this.needsTearOff, this.tearOffName, this.canBeApplied, |
| 386 this.canBeReflected, this.requiredParameterCount, | 387 this.canBeReflected, this.requiredParameterCount, |
| 387 this.optionalParameterDefaultValues, this.functionType}) | 388 this.optionalParameterDefaultValues, this.functionType}) |
| 388 : super(element, name, code) { | 389 : super(element, name, code) { |
| 389 assert(needsTearOff != null); | 390 assert(needsTearOff != null); |
| 390 assert(!needsTearOff || tearOffName != null); | 391 assert(!needsTearOff || tearOffName != null); |
| 391 assert(canBeApplied != null); | 392 assert(canBeApplied != null); |
| 392 assert(canBeReflected != null); | 393 assert(canBeReflected != null); |
| 393 assert((!canBeReflected && !canBeApplied) || | 394 assert((!canBeReflected && !canBeApplied) || |
| 394 (requiredParameterCount != null && | 395 (requiredParameterCount != null && |
| 395 optionalParameterDefaultValues != null)); | 396 optionalParameterDefaultValues != null)); |
| 396 } | 397 } |
| 397 } | 398 } |
| 398 | 399 |
| 399 class InstanceMethod extends DartMethod { | 400 class InstanceMethod extends DartMethod { |
| 400 /// An alternative name for this method. This is used to model calls to | 401 /// An alternative name for this method. This is used to model calls to |
| 401 /// a method via `super`. If [aliasName] is non-null, the emitter has to | 402 /// a method via `super`. If [aliasName] is non-null, the emitter has to |
| 402 /// ensure that this method is registered on the prototype under both [name] | 403 /// ensure that this method is registered on the prototype under both [name] |
| 403 /// and [aliasName]. | 404 /// and [aliasName]. |
| 404 final String aliasName; | 405 final js.Name aliasName; |
| 405 final bool isClosure; | 406 final bool isClosure; |
| 406 | 407 |
| 407 | 408 |
| 408 InstanceMethod(Element element, String name, js.Expression code, | 409 InstanceMethod(Element element, js.Name name, js.Expression code, |
| 409 List<ParameterStubMethod> parameterStubs, | 410 List<ParameterStubMethod> parameterStubs, |
| 410 String callName, | 411 js.Name callName, |
| 411 {bool needsTearOff, | 412 {bool needsTearOff, |
| 412 String tearOffName, | 413 js.Name tearOffName, |
| 413 this.aliasName, | 414 this.aliasName, |
| 414 bool canBeApplied, | 415 bool canBeApplied, |
| 415 bool canBeReflected, | 416 bool canBeReflected, |
| 416 int requiredParameterCount, | 417 int requiredParameterCount, |
| 417 /* List | Map */ optionalParameterDefaultValues, | 418 /* List | Map */ optionalParameterDefaultValues, |
| 418 this.isClosure, | 419 this.isClosure, |
| 419 js.Expression functionType}) | 420 js.Expression functionType}) |
| 420 : super(element, name, code, parameterStubs, callName, | 421 : super(element, name, code, parameterStubs, callName, |
| 421 needsTearOff: needsTearOff, | 422 needsTearOff: needsTearOff, |
| 422 tearOffName: tearOffName, | 423 tearOffName: tearOffName, |
| 423 canBeApplied: canBeApplied, | 424 canBeApplied: canBeApplied, |
| 424 canBeReflected: canBeReflected, | 425 canBeReflected: canBeReflected, |
| 425 requiredParameterCount: requiredParameterCount, | 426 requiredParameterCount: requiredParameterCount, |
| 426 optionalParameterDefaultValues: optionalParameterDefaultValues, | 427 optionalParameterDefaultValues: optionalParameterDefaultValues, |
| 427 functionType: functionType) { | 428 functionType: functionType) { |
| 428 assert(isClosure != null); | 429 assert(isClosure != null); |
| 429 } | 430 } |
| 430 } | 431 } |
| 431 | 432 |
| 432 /// A method that is generated by the backend and has not direct correspondence | 433 /// A method that is generated by the backend and has not direct correspondence |
| 433 /// to a method in the original Dart program. Examples are getter and setter | 434 /// to a method in the original Dart program. Examples are getter and setter |
| 434 /// stubs and stubs to dispatch calls to methods with optional parameters. | 435 /// stubs and stubs to dispatch calls to methods with optional parameters. |
| 435 class StubMethod extends Method { | 436 class StubMethod extends Method { |
| 436 StubMethod(String name, js.Expression code, | 437 StubMethod(js.Name name, js.Expression code, |
| 437 {Element element}) | 438 {Element element}) |
| 438 : super(element, name, code); | 439 : super(element, name, code); |
| 439 } | 440 } |
| 440 | 441 |
| 441 /// A stub that adapts and redirects to the main method (the one containing) | 442 /// A stub that adapts and redirects to the main method (the one containing) |
| 442 /// the actual code. | 443 /// the actual code. |
| 443 /// | 444 /// |
| 444 /// For example, given a method `foo$2(x, [y: 499])` a possible parameter | 445 /// For example, given a method `foo$2(x, [y: 499])` a possible parameter |
| 445 /// stub-method could be `foo$1(x) => foo$2(x, 499)`. | 446 /// stub-method could be `foo$1(x) => foo$2(x, 499)`. |
| 446 /// | 447 /// |
| 447 /// ParameterStubMethods are always attached to (static or instance) methods. | 448 /// ParameterStubMethods are always attached to (static or instance) methods. |
| 448 class ParameterStubMethod extends StubMethod { | 449 class ParameterStubMethod extends StubMethod { |
| 449 /// The `call` name of this stub. | 450 /// The `call` name of this stub. |
| 450 /// | 451 /// |
| 451 /// When an instance method is torn off, it is invoked as a `call` member and | 452 /// When an instance method is torn off, it is invoked as a `call` member and |
| 452 /// not it's original name anymore. The [callName] provides the stub's | 453 /// not it's original name anymore. The [callName] provides the stub's |
| 453 /// name when it is used this way. | 454 /// name when it is used this way. |
| 454 /// | 455 /// |
| 455 /// If a stub's member can not be torn off, the [callName] is `null`. | 456 /// If a stub's member can not be torn off, the [callName] is `null`. |
| 456 String callName; | 457 js.Name callName; |
| 457 | 458 |
| 458 ParameterStubMethod(String name, this.callName, js.Expression code) | 459 ParameterStubMethod(js.Name name, this.callName, js.Expression code) |
| 459 : super(name, code); | 460 : super(name, code); |
| 460 } | 461 } |
| 461 | 462 |
| 462 abstract class StaticMethod implements Method { | 463 abstract class StaticMethod implements Method { |
| 463 Holder get holder; | 464 Holder get holder; |
| 464 } | 465 } |
| 465 | 466 |
| 466 class StaticDartMethod extends DartMethod implements StaticMethod { | 467 class StaticDartMethod extends DartMethod implements StaticMethod { |
| 467 final Holder holder; | 468 final Holder holder; |
| 468 | 469 |
| 469 StaticDartMethod(Element element, String name, this.holder, | 470 StaticDartMethod(Element element, js.Name name, this.holder, |
| 470 js.Expression code, List<ParameterStubMethod> parameterStubs, | 471 js.Expression code, List<ParameterStubMethod> parameterStubs, |
| 471 String callName, | 472 js.Name callName, |
| 472 {bool needsTearOff, String tearOffName, bool canBeApplied, | 473 {bool needsTearOff, js.Name tearOffName, |
| 473 bool canBeReflected, int requiredParameterCount, | 474 bool canBeApplied, bool canBeReflected, |
| 475 int requiredParameterCount, |
| 474 /* List | Map */ optionalParameterDefaultValues, | 476 /* List | Map */ optionalParameterDefaultValues, |
| 475 js.Expression functionType}) | 477 js.Expression functionType}) |
| 476 : super(element, name, code, parameterStubs, callName, | 478 : super(element, name, code, parameterStubs, callName, |
| 477 needsTearOff: needsTearOff, | 479 needsTearOff: needsTearOff, |
| 478 tearOffName : tearOffName, | 480 tearOffName : tearOffName, |
| 479 canBeApplied : canBeApplied, | 481 canBeApplied : canBeApplied, |
| 480 canBeReflected : canBeReflected, | 482 canBeReflected : canBeReflected, |
| 481 requiredParameterCount: requiredParameterCount, | 483 requiredParameterCount: requiredParameterCount, |
| 482 optionalParameterDefaultValues: optionalParameterDefaultValues, | 484 optionalParameterDefaultValues: optionalParameterDefaultValues, |
| 483 functionType: functionType); | 485 functionType: functionType); |
| 484 } | 486 } |
| 485 | 487 |
| 486 class StaticStubMethod extends StubMethod implements StaticMethod { | 488 class StaticStubMethod extends StubMethod implements StaticMethod { |
| 487 Holder holder; | 489 Holder holder; |
| 488 StaticStubMethod(String name, this.holder, js.Expression code) | 490 StaticStubMethod(js.Name name, this.holder, js.Expression code) |
| 489 : super(name, code); | 491 : super(name, code); |
| 490 } | 492 } |
| OLD | NEW |