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 |