Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(778)

Unified Diff: pkg/compiler/lib/src/cps_ir/cps_fragment.dart

Issue 1223813006: dart2js cps: Direct access on JS arrays. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Update unit tests and remove unused functions Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/cps_ir/cps_fragment.dart
diff --git a/pkg/compiler/lib/src/cps_ir/cps_fragment.dart b/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
new file mode 100644
index 0000000000000000000000000000000000000000..1b92edc489bef36a9aacd5851442f493a5dd5873
--- /dev/null
+++ b/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
@@ -0,0 +1,266 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library cps_ir.cps_fragment;
+
+import 'cps_ir_nodes.dart';
+import '../constants/values.dart';
+import '../universe/universe.dart' show Selector;
+import '../types/types.dart' show TypeMask;
+import '../io/source_information.dart';
+import '../elements/elements.dart';
+
+/// Builds a CPS fragment that can be plugged into another CPS term.
+///
+/// A CPS fragment contains a CPS term, possibly with a "hole" in it denoting
+/// where to insert new IR nodes. We say a fragment is "open" if it has such
+/// a hole. Otherwise, the fragment is "closed" and cannot be extended further.
+///
+/// This class is designed for building non-trivial CPS terms in a readable and
+/// non-error prone manner. It is not designed to manipulate existing IR nodes,
+/// nor is it intended to shield the user from every complexity in the IR.
+///
+/// EXAMPLES:
+///
+/// Call `cont` with `obj.field + 1` as argument:
+///
+/// CpsFragment cps = new CpsFragment();
+/// var fieldValue = cps.letPrim(new GetField(obj, field));
+/// var plusOne = cps.applyBuiltin(BuiltinOperator.NumAdd,
+/// [fieldValue, cps.makeOne()]);
+/// cps.invokeContinuation(cont, [plusOne]);
+///
+/// If `condition` is true then invoke `cont1`, else `cont2`.
+///
+/// cps.ifTrue(condition).invokeContinuation(cont1, []);
+/// cps.invokeContinuation(cont2, []);
+///
+/// If `condition` is true then invoke `cont` with a bound primitive:
+///
+/// CpsFragment branch = cps.ifTrue(condition);
+/// branch.invokeContinuation(cont, [branch.letPrim(arg)]);
+///
+/// Loop and call a method until it returns false:
+///
+/// Continuation loop = cps.beginLoop();
+/// var result = cps.invokeMethod(receiver, selector, ...);
+/// cps.ifFalse(result).invokeContinuation(exit, []);
+/// cps.continueLoop(loop);
+///
+class CpsFragment {
+ /// The root of the IR built using this fragment.
+ Expression root;
+
+ /// Node whose body is the hole in this CPS fragment. May be null.
+ InteriorNode context;
+
+ /// Source information to attach to every IR node created in the fragment.
+ SourceInformation sourceInformation;
+
+ CpsFragment([this.sourceInformation, this.context]);
+
+ /// Asserts that the fragment is closed and returns the IR that was built.
+ Expression get result {
+ assert(context == null);
+ assert(root != null);
+ return root;
+ }
+
+ /// Put the given expression into the fragment's hole.
+ ///
+ /// Afterwards the fragment is closed and cannot be extended until a new
+ /// [context] is set.
+ void put(Expression node) {
+ assert(root == null || context != null); // We must put the node somewhere.
+ if (root == null) {
+ root = node;
+ }
+ if (context != null) {
+ context.body = node;
+ }
+ context = null;
+ }
+
+ /// Bind a primitive. Returns the same primitive for convenience.
+ Primitive letPrim(Primitive prim) {
+ assert(prim != null);
+ LetPrim let = new LetPrim(prim);
+ put(let);
+ context = let;
+ return prim;
+ }
+
+ /// Bind a constant value.
+ Primitive makeConstant(ConstantValue constant) {
+ return letPrim(new Constant(constant));
+ }
+
+ Primitive makeZero() => makeConstant(new IntConstantValue(0));
+ Primitive makeOne() => makeConstant(new IntConstantValue(1));
+ Primitive makeNull() => makeConstant(new NullConstantValue());
+
+ /// Invoke a built-in operator.
+ Primitive applyBuiltin(BuiltinOperator op, List<Primitive> args) {
+ return letPrim(new ApplyBuiltinOperator(op, args));
+ }
+
+ /// Inserts an invocation. binds its continuation, and returns the
+ /// continuation parameter (i.e. the return value of the invocation).
+ ///
+ /// The continuation body becomes the new hole.
+ Parameter invokeMethod(Primitive receiver,
+ Selector selector,
+ TypeMask mask,
+ List<Primitive> arguments) {
+ Continuation cont = new Continuation(<Parameter>[new Parameter(null)]);
+ InvokeMethod invoke =
+ new InvokeMethod(receiver, selector, mask, arguments, cont,
+ sourceInformation);
+ put(new LetCont(cont, invoke));
+ context = cont;
+ return cont.parameters.single;
+ }
+
+ /// Inserts an invocation. binds its continuation, and returns the
+ /// continuation parameter (i.e. the return value of the invocation).
+ ///
+ /// The continuation body becomes the new hole.
+ Parameter invokeStatic(FunctionElement target, List<Primitive> arguments) {
+ Continuation cont = new Continuation(<Parameter>[new Parameter(null)]);
+ InvokeStatic invoke =
+ new InvokeStatic(target, new Selector.fromElement(target), arguments,
+ cont, sourceInformation);
+ put(new LetCont(cont, invoke));
+ context = cont;
+ return cont.parameters.single;
+ }
+
+ /// Inserts an invocation to a static function that throws an error.
+ ///
+ /// This closes the fragment; no more nodes may be added.
+ void invokeStaticThrower(FunctionElement target, List<Primitive> arguments) {
+ invokeStatic(target, arguments);
+ put(new Unreachable());
+ }
+
+ /// Invoke a non-recursive continuation.
+ ///
+ /// This closes the fragment; no more nodes may be inserted.
+ void invokeContinuation(Continuation cont, [List<Primitive> arguments]) {
+ if (arguments == null) arguments = <Primitive>[];
+ put(new InvokeContinuation(cont, arguments));
+ }
+
+ /// Build a loop with the given loop variables and initial values.
+ /// Call [continueLoop] with the returned continuation to iterate the loop.
+ ///
+ /// The loop body becomes the new hole.
+ Continuation beginLoop([List<Parameter> loopVars,
+ List<Primitive> initialValues]) {
+ if (initialValues == null) {
+ assert(loopVars == null);
+ loopVars = <Parameter>[];
+ initialValues = <Primitive>[];
+ }
+ Continuation cont = new Continuation(loopVars);
+ put(new LetCont(cont, new InvokeContinuation(cont, initialValues)));
+ context = cont;
+ return cont;
+ }
+
+ /// Continue a loop started by [beginLoop].
+ ///
+ /// This closes the fragment; no more nodes may be inserted.
+ void continueLoop(Continuation cont, [List<Primitive> updatedLoopVariables]) {
+ put(new InvokeContinuation(cont, updatedLoopVariables, isRecursive: true));
+ }
+
+ /// Branch on [condition].
+ ///
+ /// Returns a new fragment for the 'then' branch.
+ ///
+ /// The 'else' branch becomes the new hole.
+ CpsFragment ifTrue(Primitive condition) {
+ Continuation trueCont = new Continuation(<Parameter>[]);
+ Continuation falseCont = new Continuation(<Parameter>[]);
+ put(new LetCont.two(trueCont, falseCont,
+ new Branch(new IsTrue(condition), trueCont, falseCont)));
+ context = falseCont;
+ return new CpsFragment(sourceInformation, trueCont);
+ }
+
+ /// Branch on [condition].
+ ///
+ /// Returns a new fragment for the 'else' branch.
+ ///
+ /// The 'then' branch becomes the new hole.
+ CpsFragment ifFalse(Primitive condition) {
+ Continuation trueCont = new Continuation(<Parameter>[]);
+ Continuation falseCont = new Continuation(<Parameter>[]);
+ put(new LetCont.two(trueCont, falseCont,
+ new Branch(new IsTrue(condition), trueCont, falseCont)));
+ context = trueCont;
+ return new CpsFragment(sourceInformation, falseCont);
+ }
+
+ /// Create a new empty continuation and bind it here.
+ ///
+ /// Convenient for making a join point where multiple branches
+ /// meet later.
+ ///
+ /// The LetCont body becomes the new hole.
+ ///
+ /// Example use:
+ ///
+ /// Continuation fail = cps.letCont();
+ ///
+ /// // Fail if something
+ /// cps.ifTrue(<condition>)
+ /// ..invokeMethod(<method>)
+ /// ..invokeContinuation(fail);
+ ///
+ /// // Fail if something else
+ /// cps.ifTrue(<anotherCondition>)
+ /// ..invokeMethod(<anotherMethod>)
+ /// ..invokeContinuation(fail);
+ ///
+ /// // Build the fail branch
+ /// cps.insideContinuation(fail)
+ /// ..invokeStaticThrower(...);
+ ///
+ /// // Go to the happy branch
+ /// cps.invokeContinuation(cont..)
+ ///
+ Continuation letCont([List<Parameter> parameters]) {
+ if (parameters == null) parameters = <Parameter>[];
+ Continuation cont = new Continuation(parameters);
+ LetCont let = new LetCont(cont, null);
+ put(let);
+ context = let;
+ return cont;
+ }
+
+ /// Returns a fragment whose context is the body of the given continuation.
+ ///
+ /// Does not change the state of this CPS fragment.
+ ///
+ /// Useful for building the body of a continuation created using [letCont].
+ CpsFragment insideContinuation(Continuation cont) {
+ return new CpsFragment(sourceInformation, cont);
+ }
+
+ /// Puts the given fragment into this one.
+ ///
+ /// If [other] was an open fragment, its hole becomes the new hole
+ /// in this fragment.
+ ///
+ /// [other] is reset to an empty fragment after this.
+ void append(CpsFragment other) {
+ if (other.root == null) return;
+ put(other.root);
+ context = other.context;
+ other.context = null;
+ other.root = null;
+ }
+}
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698