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 a071b47a3b16a5fe29305fb9f578dfc0c252f040..4a8ee1fee234ae4c64df3578ccdbc4b80f1e76b4 100644 |
--- a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart |
+++ b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart |
@@ -6,7 +6,8 @@ import '../../cps_ir/cps_ir_nodes.dart'; |
import '../../cps_ir/optimizers.dart'; |
import '../../constants/expressions.dart'; |
import '../../constants/values.dart'; |
-import '../../elements/elements.dart' show ClassElement, FieldElement, Element; |
+import '../../elements/elements.dart' |
+ show ClassElement, FieldElement, FunctionElement, Element; |
import '../../js_backend/codegen/glue.dart'; |
import '../../dart2jslib.dart' show Selector, World; |
@@ -15,14 +16,16 @@ import '../../dart2jslib.dart' show Selector, World; |
/// |
/// Performs the following rewrites: |
/// - rewrite [IsTrue] in a [Branch] to do boolean conversion. |
+/// - converts two-parameter exception handlers to one-parameter ones. |
class UnsugarVisitor extends RecursiveVisitor { |
Glue _glue; |
+ ParentVisitor _parentVisitor = new ParentVisitor(); |
UnsugarVisitor(this._glue); |
void rewrite(FunctionDefinition function) { |
// Set all parent pointers. |
- new ParentVisitor().visit(function); |
+ _parentVisitor.visit(function); |
visit(function); |
} |
@@ -47,6 +50,62 @@ class UnsugarVisitor extends RecursiveVisitor { |
let.parent = parent; |
} |
+ /// Insert a static call to [function] at the point of [node] with result |
+ /// [result]. |
+ /// |
+ /// Rewrite [node] to |
+ /// |
+ /// let cont continuation(result) = node |
+ /// in invoke function arguments continuation |
+ void insertStaticCall(FunctionElement function, List<Primitive> arguments, |
+ 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, continuation, arguments, null); |
+ _parentVisitor.processInvokeStatic(invoke); |
+ |
+ LetCont letCont = new LetCont(continuation, invoke); |
+ _parentVisitor.processLetCont(letCont); |
+ |
+ parent.body = letCont; |
+ letCont.parent = parent; |
+ } |
+ |
+ processLetHandler(LetHandler node) { |
+ // BEFORE: Handlers have two parameters, exception and stack trace. |
+ // AFTER: Handlers have a single parameter, which is unwrapped to get |
+ // the exception and stack trace. |
+ assert(node.handler.parameters.length == 2); |
+ Parameter exceptionParameter = node.handler.parameters.first; |
+ Parameter stackTraceParameter = node.handler.parameters.last; |
+ Expression body = node.handler.body; |
+ if (exceptionParameter.hasAtLeastOneUse || |
+ stackTraceParameter.hasAtLeastOneUse) { |
+ Parameter exceptionValue = new Parameter(null); |
+ exceptionValue.substituteFor(exceptionParameter); |
+ insertStaticCall(_glue.getExceptionUnwrapper(), [exceptionParameter], |
+ exceptionValue, body); |
+ |
+ if (stackTraceParameter.hasAtLeastOneUse) { |
+ Parameter stackTraceValue = new Parameter(null); |
+ stackTraceValue.substituteFor(stackTraceParameter); |
+ insertStaticCall(_glue.getTraceFromException(), [exceptionValue], |
+ stackTraceValue, body); |
+ } |
+ } |
+ |
+ assert(stackTraceParameter.hasNoUses); |
+ node.handler.parameters.removeLast(); |
+ } |
+ |
processInvokeMethod(InvokeMethod node) { |
Selector selector = node.selector; |
// TODO(karlklose): should we rewrite all selectors? |