Index: pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
index 61a5ddd961408f55925d59b7b72f0c03c72b194b..728b4b9f3bca90bfa52812f339cb1229c036b2b4 100644 |
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
@@ -65,14 +65,15 @@ abstract class Node { |
/// |
/// Avoid using nodes as keys if there is a chance that two keys are the |
/// same node. |
- String debugString([Map annotations]) { |
+ String debugString([Map annotations = const {}]) { |
return new SExpressionStringifier() |
.withAnnotations(annotations) |
+ .withTypes() |
.visit(this); |
} |
/// Prints the result of [debugString]. |
- void debugPrint([Map annotations]) { |
+ void debugPrint([Map annotations = const {}]) { |
print(debugString(annotations)); |
} |
} |
@@ -416,18 +417,20 @@ class MutableVariable extends Variable<MutableVariable> { |
/// continuation to invoke when returning from the function. |
class FunctionDefinition extends InteriorNode { |
final ExecutableElement element; |
- final Parameter thisParameter; |
+ Parameter interceptorParameter; |
+ final Parameter receiverParameter; |
final List<Parameter> parameters; |
final Continuation returnContinuation; |
Expression body; |
- FunctionDefinition(this.element, this.thisParameter, this.parameters, |
- this.returnContinuation, this.body); |
+ FunctionDefinition(this.element, this.receiverParameter, this.parameters, |
+ this.returnContinuation, this.body, {this.interceptorParameter}); |
accept(BlockVisitor visitor) => visitor.visitFunctionDefinition(this); |
void setParentPointers() { |
- if (thisParameter != null) thisParameter.parent = this; |
+ if (interceptorParameter != null) interceptorParameter.parent = this; |
+ if (receiverParameter != null) receiverParameter.parent = this; |
_setParentsOnNodes(parameters, this); |
returnContinuation.parent = this; |
if (body != null) body.parent = this; |
@@ -491,6 +494,9 @@ enum CallingConvention { |
/// |
/// This class defines the common interface of function invocations. |
abstract class InvocationPrimitive extends UnsafePrimitive { |
+ Reference<Primitive> get interceptorRef => null; |
+ Primitive get interceptor => interceptorRef?.definition; |
+ |
Reference<Primitive> get receiverRef => null; |
Primitive get receiver => receiverRef?.definition; |
@@ -498,30 +504,8 @@ abstract class InvocationPrimitive extends UnsafePrimitive { |
Primitive argument(int n) => argumentRefs[n].definition; |
Iterable<Primitive> get arguments => _dereferenceList(argumentRefs); |
- Reference<Primitive> get dartReceiverRef => null; |
- Primitive get dartReceiver => dartReceiverRef?.definition; |
- |
CallingConvention get callingConvention => CallingConvention.Normal; |
- Reference<Primitive> dartArgumentReference(int n) { |
- switch (callingConvention) { |
- case CallingConvention.Normal: |
- case CallingConvention.OneShotIntercepted: |
- return argumentRefs[n]; |
- |
- case CallingConvention.Intercepted: |
- case CallingConvention.DummyIntercepted: |
- return argumentRefs[n + 1]; |
- } |
- } |
- |
- Primitive dartArgument(int n) => dartArgumentReference(n).definition; |
- |
- int get dartArgumentsLength => |
- argumentRefs.length - |
- (callingConvention == CallingConvention.Intercepted || |
- callingConvention == CallingConvention.DummyIntercepted ? 1 : 0); |
- |
SourceInformation get sourceInformation; |
} |
@@ -565,35 +549,56 @@ class InvokeStatic extends InvocationPrimitive { |
/// The [selector] records the names of named arguments. The value of named |
/// arguments occur at the end of the [arguments] list, in normalized order. |
class InvokeMethod extends InvocationPrimitive { |
+ Reference<Primitive> interceptorRef; |
Reference<Primitive> receiverRef; |
Selector selector; |
TypeMask mask; |
final List<Reference<Primitive>> argumentRefs; |
final SourceInformation sourceInformation; |
+ CallingConvention _callingConvention; |
- CallingConvention callingConvention = CallingConvention.Normal; |
- |
- Reference<Primitive> get dartReceiverRef { |
- return callingConvention == CallingConvention.Intercepted |
- ? argumentRefs[0] |
- : receiverRef; |
- } |
+ CallingConvention get callingConvention => _callingConvention; |
InvokeMethod( |
Primitive receiver, this.selector, this.mask, List<Primitive> arguments, |
{this.sourceInformation, |
- this.callingConvention: CallingConvention.Normal}) |
+ CallingConvention callingConvention, |
+ Primitive interceptor}) |
: this.receiverRef = new Reference<Primitive>(receiver), |
- this.argumentRefs = _referenceList(arguments); |
+ this.argumentRefs = _referenceList(arguments), |
+ this.interceptorRef = _optionalReference(interceptor), |
+ this._callingConvention = callingConvention ?? |
+ (interceptor != null |
+ ? CallingConvention.Intercepted |
+ : CallingConvention.Normal); |
accept(Visitor visitor) => visitor.visitInvokeMethod(this); |
bool get hasValue => true; |
void setParentPointers() { |
+ interceptorRef?.parent = this; |
receiverRef.parent = this; |
_setParentsOnList(argumentRefs, this); |
} |
+ |
+ void makeIntercepted(Primitive interceptor) { |
+ interceptorRef?.unlink(); |
+ interceptorRef = new Reference<Primitive>(interceptor)..parent = this; |
+ _callingConvention = CallingConvention.Intercepted; |
+ } |
+ |
+ void makeOneShotIntercepted() { |
+ interceptorRef?.unlink(); |
+ interceptorRef = null; |
+ _callingConvention = CallingConvention.OneShotIntercepted; |
+ } |
+ |
+ void makeDummyIntercepted() { |
+ interceptorRef?.unlink(); |
+ interceptorRef = null; |
+ _callingConvention = CallingConvention.DummyIntercepted; |
+ } |
} |
/// Invoke [target] on [receiver], bypassing dispatch and override semantics. |
@@ -616,37 +621,37 @@ class InvokeMethod extends InvocationPrimitive { |
/// All optional arguments declared by [target] are passed in explicitly, and |
/// occur at the end of [arguments] list, in normalized order. |
class InvokeMethodDirectly extends InvocationPrimitive { |
+ Reference<Primitive> interceptorRef; |
Reference<Primitive> receiverRef; |
final FunctionElement target; |
final Selector selector; |
final List<Reference<Primitive>> argumentRefs; |
final SourceInformation sourceInformation; |
- CallingConvention callingConvention; |
- |
- Reference<Primitive> get dartReceiverRef { |
- return callingConvention == CallingConvention.Intercepted |
- ? argumentRefs[0] |
- : receiverRef; |
- } |
- |
InvokeMethodDirectly(Primitive receiver, this.target, this.selector, |
List<Primitive> arguments, this.sourceInformation, |
- {this.callingConvention: CallingConvention.Normal}) |
+ {Primitive interceptor}) |
: this.receiverRef = new Reference<Primitive>(receiver), |
- this.argumentRefs = _referenceList(arguments); |
+ this.argumentRefs = _referenceList(arguments), |
+ this.interceptorRef = _optionalReference(interceptor); |
accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this); |
bool get hasValue => true; |
void setParentPointers() { |
+ interceptorRef?.parent = this; |
receiverRef.parent = this; |
_setParentsOnList(argumentRefs, this); |
} |
bool get isConstructorBodyCall => target is ConstructorBodyElement; |
bool get isTearOff => selector.isGetter && !target.isGetter; |
+ |
+ void makeIntercepted(Primitive interceptor) { |
+ interceptorRef?.unlink(); |
+ interceptorRef = new Reference<Primitive>(interceptor)..parent = this; |
+ } |
} |
/// Non-const call to a constructor. |
@@ -2273,7 +2278,8 @@ class DeepRecursiveVisitor implements Visitor { |
processFunctionDefinition(FunctionDefinition node) {} |
visitFunctionDefinition(FunctionDefinition node) { |
processFunctionDefinition(node); |
- if (node.thisParameter != null) visit(node.thisParameter); |
+ if (node.interceptorParameter != null) visit(node.interceptorParameter); |
+ if (node.receiverParameter != null) visit(node.receiverParameter); |
node.parameters.forEach(visit); |
visit(node.body); |
} |
@@ -2331,6 +2337,9 @@ class DeepRecursiveVisitor implements Visitor { |
processInvokeMethod(InvokeMethod node) {} |
visitInvokeMethod(InvokeMethod node) { |
processInvokeMethod(node); |
+ if (node.interceptorRef != null) { |
+ processReference(node.interceptorRef); |
+ } |
processReference(node.receiverRef); |
node.argumentRefs.forEach(processReference); |
} |
@@ -2338,6 +2347,9 @@ class DeepRecursiveVisitor implements Visitor { |
processInvokeMethodDirectly(InvokeMethodDirectly node) {} |
visitInvokeMethodDirectly(InvokeMethodDirectly node) { |
processInvokeMethodDirectly(node); |
+ if (node.interceptorRef != null) { |
+ processReference(node.interceptorRef); |
+ } |
processReference(node.receiverRef); |
node.argumentRefs.forEach(processReference); |
} |
@@ -2626,7 +2638,8 @@ class TrampolineRecursiveVisitor extends DeepRecursiveVisitor { |
visitFunctionDefinition(FunctionDefinition node) { |
processFunctionDefinition(node); |
- if (node.thisParameter != null) visit(node.thisParameter); |
+ if (node.interceptorParameter != null) visit(node.interceptorParameter); |
+ if (node.receiverParameter != null) visit(node.receiverParameter); |
node.parameters.forEach(visit); |
visit(node.body); |
} |
@@ -2775,13 +2788,14 @@ class DefinitionCopyingVisitor extends Visitor<Definition> { |
return new InvokeMethod(getCopy(node.receiverRef), node.selector, node.mask, |
getList(node.argumentRefs), |
sourceInformation: node.sourceInformation, |
- callingConvention: node.callingConvention); |
+ callingConvention: node.callingConvention, |
+ interceptor: getCopyOrNull(node.interceptorRef)); |
} |
Definition visitInvokeMethodDirectly(InvokeMethodDirectly node) { |
return new InvokeMethodDirectly(getCopy(node.receiverRef), node.target, |
node.selector, getList(node.argumentRefs), node.sourceInformation, |
- callingConvention: node.callingConvention); |
+ interceptor: getCopyOrNull(node.interceptorRef)); |
} |
Definition visitInvokeConstructor(InvokeConstructor node) { |
@@ -3007,9 +3021,12 @@ class CopyingVisitor extends TrampolineRecursiveVisitor { |
_first = _current = null; |
// Definitions are copied where they are bound, before processing |
// expressions in the scope of their binding. |
- Parameter thisParameter = node.thisParameter == null |
+ Parameter thisParameter = node.receiverParameter == null |
+ ? null |
+ : _definitions.copy(node.receiverParameter); |
+ Parameter interceptorParameter = node.interceptorParameter == null |
? null |
- : _definitions.copy(node.thisParameter); |
+ : _definitions.copy(node.interceptorParameter); |
List<Parameter> parameters = |
node.parameters.map(_definitions.copy).toList(); |
// Though the return continuation's parameter does not have any uses, |
@@ -3022,7 +3039,8 @@ class CopyingVisitor extends TrampolineRecursiveVisitor { |
visit(node.body); |
FunctionDefinition copy = new FunctionDefinition( |
- node.element, thisParameter, parameters, returnContinuation, _first); |
+ node.element, thisParameter, parameters, returnContinuation, _first, |
+ interceptorParameter: interceptorParameter); |
_first = _current = null; |
return copy; |
} |