Index: pkg/compiler/lib/src/js_backend/codegen/unsugar.dart |
diff --git a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart |
index 3fa6f1826031657c093fafb7dfe41bb7cc12c210..4c841348047d1509863719f5613d663e6b6d2707 100644 |
--- a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart |
+++ b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart |
@@ -8,7 +8,6 @@ import '../../elements/elements.dart'; |
import '../../js_backend/codegen/glue.dart'; |
import '../../universe/selector.dart' show Selector; |
import '../../cps_ir/cps_ir_builder.dart' show ThisParameterLocal; |
-import '../../cps_ir/cps_fragment.dart'; |
class ExplicitReceiverParameterEntity implements Local { |
String get name => 'receiver'; |
@@ -26,6 +25,7 @@ class InterceptorEntity extends Entity { |
String get name => interceptedVariable.name + '_'; |
} |
+ |
/// Rewrites the initial CPS IR to make Dart semantics explicit and inserts |
/// special nodes that respect JavaScript behavior. |
/// |
@@ -34,8 +34,9 @@ class InterceptorEntity extends Entity { |
/// - Add explicit receiver argument for methods that are called in interceptor |
/// calling convention. |
/// - Convert two-parameter exception handlers to one-parameter ones. |
-class UnsugarVisitor extends TrampolineRecursiveVisitor implements Pass { |
+class UnsugarVisitor extends RecursiveVisitor implements Pass { |
Glue _glue; |
+ ParentVisitor _parentVisitor = new ParentVisitor(); |
Parameter thisParameter; |
Parameter explicitReceiverParameter; |
@@ -71,11 +72,14 @@ class UnsugarVisitor extends TrampolineRecursiveVisitor implements Pass { |
if (inInterceptedMethod) { |
ThisParameterLocal holder = thisParameter.hint; |
explicitReceiverParameter = new Parameter( |
- new ExplicitReceiverParameterEntity(holder.executableContext)); |
- explicitReceiverParameter.parent = function; |
+ new ExplicitReceiverParameterEntity( |
+ holder.executableContext)); |
function.parameters.insert(0, explicitReceiverParameter); |
} |
+ // Set all parent pointers. |
+ _parentVisitor.visit(function); |
+ |
if (inInterceptedMethod && methodUsesReceiverArgument(function.element)) { |
explicitReceiverParameter.substituteFor(thisParameter); |
} |
@@ -97,7 +101,11 @@ class UnsugarVisitor extends TrampolineRecursiveVisitor implements Pass { |
void insertLetPrim(Primitive primitive, Expression node) { |
LetPrim let = new LetPrim(primitive); |
- let.insertAbove(node); |
+ InteriorNode parent = node.parent; |
+ parent.body = let; |
+ let.body = node; |
+ node.parent = let; |
+ let.parent = parent; |
} |
void insertEqNullCheck(FunctionDefinition function) { |
@@ -112,14 +120,28 @@ class UnsugarVisitor extends TrampolineRecursiveVisitor implements Pass { |
// else |
// body; |
// |
- CpsFragment cps = new CpsFragment(); |
- Primitive isNull = cps.applyBuiltin( |
+ Continuation originalBody = new Continuation(<Parameter>[]); |
+ originalBody.body = function.body; |
+ |
+ Continuation returnFalse = new Continuation(<Parameter>[]); |
+ Primitive falsePrimitive = falseConstant; |
+ returnFalse.body = |
+ new LetPrim(falsePrimitive, |
+ new InvokeContinuation( |
+ function.returnContinuation, <Primitive>[falsePrimitive])); |
+ |
+ Primitive nullPrimitive = nullConstant; |
+ Primitive test = new ApplyBuiltinOperator( |
BuiltinOperator.Identical, |
- <Primitive>[function.parameters.single, cps.makeNull()]); |
- CpsFragment trueBranch = cps.ifTruthy(isNull); |
- trueBranch.invokeContinuation(function.returnContinuation, |
- <Primitive>[trueBranch.makeFalse()]); |
- cps.insertAbove(function.body); |
+ <Primitive>[function.parameters.single, nullPrimitive], |
+ function.parameters.single.sourceInformation); |
+ |
+ Expression newBody = |
+ new LetCont.many(<Continuation>[returnFalse, originalBody], |
+ new LetPrim(nullPrimitive, |
+ new LetPrim(test, |
+ new Branch.loose(test, returnFalse, originalBody)))); |
+ function.body = newBody; |
} |
/// Insert a static call to [function] at the point of [node] with result |
@@ -130,22 +152,25 @@ class UnsugarVisitor extends TrampolineRecursiveVisitor implements Pass { |
/// let cont continuation(result) = node |
/// in invoke function arguments continuation |
void insertStaticCall(FunctionElement function, List<Primitive> arguments, |
- Parameter result, Expression node) { |
+ Parameter result, |
+ Expression node) { |
InteriorNode parent = node.parent; |
Continuation continuation = new Continuation([result]); |
+ continuation.body = node; |
+ _parentVisitor.processContinuation(continuation); |
Selector selector = new Selector.fromElement(function); |
// TODO(johnniwinther): Come up with an implementation of SourceInformation |
// for calls such as this one that don't appear in the original source. |
InvokeStatic invoke = new InvokeStatic( |
function, selector, arguments, continuation, null); |
+ _parentVisitor.processInvokeStatic(invoke); |
LetCont letCont = new LetCont(continuation, invoke); |
+ _parentVisitor.processLetCont(letCont); |
parent.body = letCont; |
letCont.parent = parent; |
- continuation.body = node; |
- node.parent = continuation; |
} |
@override |
@@ -185,10 +210,11 @@ class UnsugarVisitor extends TrampolineRecursiveVisitor implements Pass { |
processThrow(Throw node) { |
// The subexpression of throw is wrapped in the JavaScript output. |
- Parameter wrappedException = new Parameter(null); |
+ Parameter value = new Parameter(null); |
insertStaticCall(_glue.getWrapExceptionHelper(), [node.value.definition], |
- wrappedException, node); |
- node.value.changeTo(wrappedException); |
+ value, node); |
+ node.value.unlink(); |
+ node.value = new Reference<Primitive>(value); |
} |
processRethrow(Rethrow node) { |
@@ -236,7 +262,7 @@ class UnsugarVisitor extends TrampolineRecursiveVisitor implements Pass { |
insertLetPrim(newReceiver, contBinding); |
} |
node.arguments.insert(0, node.receiver); |
- node.receiver = new Reference<Primitive>(newReceiver)..parent = node; |
+ node.receiver = new Reference<Primitive>(newReceiver); |
node.receiverIsIntercepted = true; |
} |
@@ -262,7 +288,7 @@ class UnsugarVisitor extends TrampolineRecursiveVisitor implements Pass { |
insertLetPrim(newReceiver, contBinding); |
} |
node.arguments.insert(0, node.receiver); |
- node.receiver = new Reference<Primitive>(newReceiver)..parent = node; |
+ node.receiver = new Reference<Primitive>(newReceiver); |
} |
processInterceptor(Interceptor node) { |