| OLD | NEW |
| 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 // IrNodes are kept in a separate library to have precise control over their | 5 // IrNodes are kept in a separate library to have precise control over their |
| 6 // dependencies on other parts of the system. | 6 // dependencies on other parts of the system. |
| 7 library dart2js.ir_nodes; | 7 library dart2js.ir_nodes; |
| 8 | 8 |
| 9 import '../constants/expressions.dart'; | 9 import '../constants/expressions.dart'; |
| 10 import '../constants/values.dart' as values show ConstantValue; | 10 import '../constants/values.dart' as values show ConstantValue; |
| 11 import '../cps_ir/optimizers.dart'; | |
| 12 import '../dart_types.dart' show DartType, GenericType, TypeVariableType; | 11 import '../dart_types.dart' show DartType, GenericType, TypeVariableType; |
| 13 import '../dart2jslib.dart' as dart2js show | 12 import '../dart2jslib.dart' as dart2js show |
| 14 CURRENT_ELEMENT_SPANNABLE, | 13 CURRENT_ELEMENT_SPANNABLE, |
| 15 InternalErrorFunction, | 14 InternalErrorFunction, |
| 16 invariant; | 15 invariant; |
| 17 import '../elements/elements.dart'; | 16 import '../elements/elements.dart'; |
| 18 import '../io/source_information.dart' show SourceInformation; | 17 import '../io/source_information.dart' show SourceInformation; |
| 19 import '../universe/universe.dart' show Selector, SelectorKind; | 18 import '../universe/universe.dart' show Selector, SelectorKind; |
| 20 | 19 |
| 21 abstract class Node { | 20 abstract class Node { |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 /// [FunctionElement] or [FieldElement]. | 219 /// [FunctionElement] or [FieldElement]. |
| 221 final Entity target; | 220 final Entity target; |
| 222 | 221 |
| 223 /** | 222 /** |
| 224 * The selector encodes how the function is invoked: number of positional | 223 * The selector encodes how the function is invoked: number of positional |
| 225 * arguments, names used in named arguments. This information is required | 224 * arguments, names used in named arguments. This information is required |
| 226 * to build the [StaticCallSiteTypeInformation] for the inference graph. | 225 * to build the [StaticCallSiteTypeInformation] for the inference graph. |
| 227 */ | 226 */ |
| 228 final Selector selector; | 227 final Selector selector; |
| 229 | 228 |
| 229 final List<Reference<Primitive>> arguments; |
| 230 final Reference<Continuation> continuation; | 230 final Reference<Continuation> continuation; |
| 231 final List<Reference<Primitive>> arguments; | |
| 232 final SourceInformation sourceInformation; | 231 final SourceInformation sourceInformation; |
| 233 | 232 |
| 234 InvokeStatic(this.target, | 233 InvokeStatic(this.target, |
| 235 this.selector, | 234 this.selector, |
| 235 List<Primitive> args, |
| 236 Continuation cont, | 236 Continuation cont, |
| 237 List<Primitive> args, | |
| 238 this.sourceInformation) | 237 this.sourceInformation) |
| 239 : continuation = new Reference<Continuation>(cont), | 238 : arguments = _referenceList(args), |
| 240 arguments = _referenceList(args) { | 239 continuation = new Reference<Continuation>(cont) { |
| 241 assert(target is ErroneousElement || selector.name == target.name); | 240 assert(target is ErroneousElement || selector.name == target.name); |
| 242 } | 241 } |
| 243 | 242 |
| 244 accept(Visitor visitor) => visitor.visitInvokeStatic(this); | 243 accept(Visitor visitor) => visitor.visitInvokeStatic(this); |
| 245 } | 244 } |
| 246 | 245 |
| 247 /// A [CallingConvention] codifies how arguments are matched to parameters when | 246 /// A [CallingConvention] codifies how arguments are matched to parameters when |
| 248 /// emitting code for a function call. | 247 /// emitting code for a function call. |
| 249 class CallingConvention { | 248 class CallingConvention { |
| 250 final String name; | 249 final String name; |
| 251 const CallingConvention(this.name); | 250 const CallingConvention(this.name); |
| 252 /// The normal way of calling a Dart function: Positional arguments are | 251 /// The normal way of calling a Dart function: Positional arguments are |
| 253 /// matched with (mandatory and optional) positionals parameters from left to | 252 /// matched with (mandatory and optional) positionals parameters from left to |
| 254 /// right and named arguments are matched by name. | 253 /// right and named arguments are matched by name. |
| 255 static const CallingConvention DART = const CallingConvention("Dart call"); | 254 static const CallingConvention DART = const CallingConvention("Dart call"); |
| 256 /// Intercepted calls have an additional first argument that is the actual | 255 /// Intercepted calls have an additional first argument that is the actual |
| 257 /// receiver of the call. See the documentation of [Interceptor] for more | 256 /// receiver of the call. See the documentation of [Interceptor] for more |
| 258 /// information. | 257 /// information. |
| 259 static const CallingConvention JS_INTERCEPTED = | 258 static const CallingConvention JS_INTERCEPTED = |
| 260 const CallingConvention("intercepted JavaScript call"); | 259 const CallingConvention("intercepted JavaScript call"); |
| 261 } | 260 } |
| 262 | 261 |
| 263 /// Invoke a method, operator, getter, setter, or index getter/setter. | 262 /// Invoke a method, operator, getter, setter, or index getter/setter. |
| 264 /// Converting a method to a function object is treated as a getter invocation. | 263 /// Converting a method to a function object is treated as a getter invocation. |
| 265 class InvokeMethod extends Expression implements Invoke { | 264 class InvokeMethod extends Expression implements Invoke { |
| 266 Reference<Primitive> receiver; | 265 Reference<Primitive> receiver; |
| 267 Selector selector; | 266 Selector selector; |
| 268 CallingConvention callingConvention; | 267 CallingConvention callingConvention; |
| 268 final List<Reference<Primitive>> arguments; |
| 269 final Reference<Continuation> continuation; | 269 final Reference<Continuation> continuation; |
| 270 final List<Reference<Primitive>> arguments; | |
| 271 final SourceInformation sourceInformation; | 270 final SourceInformation sourceInformation; |
| 272 | 271 |
| 273 InvokeMethod(Primitive receiver, | 272 InvokeMethod(Primitive receiver, |
| 274 Selector selector, | 273 Selector selector, |
| 274 List<Primitive> arguments, |
| 275 Continuation continuation, | 275 Continuation continuation, |
| 276 List<Primitive> arguments, | |
| 277 {SourceInformation sourceInformation}) | 276 {SourceInformation sourceInformation}) |
| 278 : this.internal(new Reference<Primitive>(receiver), | 277 : this.internal(new Reference<Primitive>(receiver), |
| 279 selector, | 278 selector, |
| 279 _referenceList(arguments), |
| 280 new Reference<Continuation>(continuation), | 280 new Reference<Continuation>(continuation), |
| 281 _referenceList(arguments), | |
| 282 sourceInformation); | 281 sourceInformation); |
| 283 | 282 |
| 284 InvokeMethod.internal(this.receiver, | 283 InvokeMethod.internal(this.receiver, |
| 285 this.selector, | 284 this.selector, |
| 285 this.arguments, |
| 286 this.continuation, | 286 this.continuation, |
| 287 this.arguments, | |
| 288 this.sourceInformation, | 287 this.sourceInformation, |
| 289 [this.callingConvention = CallingConvention.DART]) { | 288 [this.callingConvention = CallingConvention.DART]) { |
| 290 assert(isValid); | 289 assert(isValid); |
| 291 } | 290 } |
| 292 | 291 |
| 293 /// Returns whether the arguments match the selector under the given calling | 292 /// Returns whether the arguments match the selector under the given calling |
| 294 /// convention. | 293 /// convention. |
| 295 /// | 294 /// |
| 296 /// This check is designed to be used in an assert, as it also checks that the | 295 /// This check is designed to be used in an assert, as it also checks that the |
| 297 /// selector, arguments, and calling convention have meaningful values. | 296 /// selector, arguments, and calling convention have meaningful values. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 /// invocations to intercepted methods, where the effective receiver is instead | 329 /// invocations to intercepted methods, where the effective receiver is instead |
| 331 /// passed as a formal parameter. | 330 /// passed as a formal parameter. |
| 332 /// | 331 /// |
| 333 /// When targeting Dart, this instruction is used to represent super calls. | 332 /// When targeting Dart, this instruction is used to represent super calls. |
| 334 /// Here, [receiver] must always be a reference to `this`, and [target] must be | 333 /// Here, [receiver] must always be a reference to `this`, and [target] must be |
| 335 /// a method that is available in the super class. | 334 /// a method that is available in the super class. |
| 336 class InvokeMethodDirectly extends Expression implements Invoke { | 335 class InvokeMethodDirectly extends Expression implements Invoke { |
| 337 Reference<Primitive> receiver; | 336 Reference<Primitive> receiver; |
| 338 final Element target; | 337 final Element target; |
| 339 final Selector selector; | 338 final Selector selector; |
| 339 final List<Reference<Primitive>> arguments; |
| 340 final Reference<Continuation> continuation; | 340 final Reference<Continuation> continuation; |
| 341 final List<Reference<Primitive>> arguments; | |
| 342 | 341 |
| 343 InvokeMethodDirectly(Primitive receiver, | 342 InvokeMethodDirectly(Primitive receiver, |
| 344 this.target, | 343 this.target, |
| 345 this.selector, | 344 this.selector, |
| 346 Continuation cont, | 345 List<Primitive> args, |
| 347 List<Primitive> args) | 346 Continuation cont) |
| 348 : this.receiver = new Reference<Primitive>(receiver), | 347 : this.receiver = new Reference<Primitive>(receiver), |
| 349 continuation = new Reference<Continuation>(cont), | 348 arguments = _referenceList(args), |
| 350 arguments = _referenceList(args) { | 349 continuation = new Reference<Continuation>(cont) { |
| 351 assert(selector != null); | 350 assert(selector != null); |
| 352 assert(selector.kind == SelectorKind.CALL || | 351 assert(selector.kind == SelectorKind.CALL || |
| 353 selector.kind == SelectorKind.OPERATOR || | 352 selector.kind == SelectorKind.OPERATOR || |
| 354 (selector.kind == SelectorKind.GETTER && arguments.isEmpty) || | 353 (selector.kind == SelectorKind.GETTER && arguments.isEmpty) || |
| 355 (selector.kind == SelectorKind.SETTER && arguments.length == 1) || | 354 (selector.kind == SelectorKind.SETTER && arguments.length == 1) || |
| 356 (selector.kind == SelectorKind.INDEX && arguments.length == 1) || | 355 (selector.kind == SelectorKind.INDEX && arguments.length == 1) || |
| 357 (selector.kind == SelectorKind.INDEX && arguments.length == 2)); | 356 (selector.kind == SelectorKind.INDEX && arguments.length == 2)); |
| 358 } | 357 } |
| 359 | 358 |
| 360 accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this); | 359 accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this); |
| 361 } | 360 } |
| 362 | 361 |
| 363 /// Non-const call to a constructor. The [target] may be a generative | 362 /// Non-const call to a constructor. The [target] may be a generative |
| 364 /// constructor, factory, or redirecting factory. | 363 /// constructor, factory, or redirecting factory. |
| 365 class InvokeConstructor extends Expression implements Invoke { | 364 class InvokeConstructor extends Expression implements Invoke { |
| 366 final DartType type; | 365 final DartType type; |
| 367 final FunctionElement target; | 366 final FunctionElement target; |
| 367 final List<Reference<Primitive>> arguments; |
| 368 final Reference<Continuation> continuation; | 368 final Reference<Continuation> continuation; |
| 369 final List<Reference<Primitive>> arguments; | |
| 370 final Selector selector; | 369 final Selector selector; |
| 371 | 370 |
| 372 /// The class being instantiated. This is the same as `target.enclosingClass` | 371 /// The class being instantiated. This is the same as `target.enclosingClass` |
| 373 /// and `type.element`. | 372 /// and `type.element`. |
| 374 ClassElement get targetClass => target.enclosingElement; | 373 ClassElement get targetClass => target.enclosingElement; |
| 375 | 374 |
| 376 /// True if this is an invocation of a factory constructor. | 375 /// True if this is an invocation of a factory constructor. |
| 377 bool get isFactory => target.isFactoryConstructor; | 376 bool get isFactory => target.isFactoryConstructor; |
| 378 | 377 |
| 379 InvokeConstructor(this.type, | 378 InvokeConstructor(this.type, |
| 380 this.target, | 379 this.target, |
| 381 this.selector, | 380 this.selector, |
| 382 Continuation cont, | 381 List<Primitive> args, |
| 383 List<Primitive> args) | 382 Continuation cont) |
| 384 : continuation = new Reference<Continuation>(cont), | 383 : arguments = _referenceList(args), |
| 385 arguments = _referenceList(args) { | 384 continuation = new Reference<Continuation>(cont) { |
| 386 assert(dart2js.invariant(target, | 385 assert(dart2js.invariant(target, |
| 387 target.isErroneous || | 386 target.isErroneous || |
| 388 type.isDynamic || | 387 type.isDynamic || |
| 389 type.element == target.enclosingClass.declaration, | 388 type.element == target.enclosingClass.declaration, |
| 390 message: "Constructor invocation target is not a constructor: " | 389 message: "Constructor invocation target is not a constructor: " |
| 391 "$target.")); | 390 "$target.")); |
| 392 } | 391 } |
| 393 | 392 |
| 394 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); | 393 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); |
| 395 } | 394 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 414 assert(isTypeTest != null); | 413 assert(isTypeTest != null); |
| 415 } | 414 } |
| 416 | 415 |
| 417 bool get isTypeCast => !isTypeTest; | 416 bool get isTypeCast => !isTypeTest; |
| 418 | 417 |
| 419 accept(Visitor visitor) => visitor.visitTypeOperator(this); | 418 accept(Visitor visitor) => visitor.visitTypeOperator(this); |
| 420 } | 419 } |
| 421 | 420 |
| 422 /// Invoke [toString] on each argument and concatenate the results. | 421 /// Invoke [toString] on each argument and concatenate the results. |
| 423 class ConcatenateStrings extends Expression { | 422 class ConcatenateStrings extends Expression { |
| 423 final List<Reference<Primitive>> arguments; |
| 424 final Reference<Continuation> continuation; | 424 final Reference<Continuation> continuation; |
| 425 final List<Reference<Primitive>> arguments; | |
| 426 | 425 |
| 427 ConcatenateStrings(Continuation cont, List<Primitive> args) | 426 ConcatenateStrings(List<Primitive> args, Continuation cont) |
| 428 : continuation = new Reference<Continuation>(cont), | 427 : arguments = _referenceList(args), |
| 429 arguments = _referenceList(args); | 428 continuation = new Reference<Continuation>(cont); |
| 430 | 429 |
| 431 accept(Visitor visitor) => visitor.visitConcatenateStrings(this); | 430 accept(Visitor visitor) => visitor.visitConcatenateStrings(this); |
| 432 } | 431 } |
| 433 | 432 |
| 434 /// Gets the value from a [MutableVariable]. | 433 /// Gets the value from a [MutableVariable]. |
| 435 /// | 434 /// |
| 436 /// [MutableVariable]s can be seen as ref cells that are not first-class | 435 /// [MutableVariable]s can be seen as ref cells that are not first-class |
| 437 /// values. A [LetPrim] with a [GetMutableVariable] can then be seen as: | 436 /// values. A [LetPrim] with a [GetMutableVariable] can then be seen as: |
| 438 /// | 437 /// |
| 439 /// let prim p = ![variable] in [body] | 438 /// let prim p = ![variable] in [body] |
| (...skipping 820 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1260 processReadTypeVariable(node); | 1259 processReadTypeVariable(node); |
| 1261 processReference(node.target); | 1260 processReference(node.target); |
| 1262 } | 1261 } |
| 1263 | 1262 |
| 1264 processTypeExpression(TypeExpression node) {} | 1263 processTypeExpression(TypeExpression node) {} |
| 1265 visitTypeExpression(TypeExpression node) { | 1264 visitTypeExpression(TypeExpression node) { |
| 1266 processTypeExpression(node); | 1265 processTypeExpression(node); |
| 1267 node.arguments.forEach(processReference); | 1266 node.arguments.forEach(processReference); |
| 1268 } | 1267 } |
| 1269 } | 1268 } |
| OLD | NEW |