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

Side by Side 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: Status files 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
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.
4
5 library cps_ir.cps_fragment;
6
7 import 'cps_ir_nodes.dart';
8 import '../constants/values.dart';
9 import '../universe/universe.dart' show Selector;
10 import '../types/types.dart' show TypeMask;
11 import '../io/source_information.dart';
12 import '../elements/elements.dart';
13
14 /// Builds a CPS fragment that can be plugged into another CPS term.
15 ///
16 /// A CPS fragment contains a CPS term, possibly with a "hole" in it denoting
17 /// where to insert new IR nodes. We say a fragment is "open" if it has such
18 /// a hole.
karlklose 2015/07/08 08:39:24 Maybe add: "Otherwise, the fragment is 'closed' an
asgerf 2015/07/08 10:28:37 Added comment about "closed". The return type isn
19 ///
20 /// This class is designed for building non-trivial CPS terms in a readable and
21 /// non-error prone manner. It is not designed to manipulate existing IR nodes,
22 /// nor is it intended to shield the user from every complexity in the IR.
23 ///
24 /// EXAMPLES:
25 ///
26 /// Call `cont` with `obj.field + 1` as argument:
27 ///
28 /// CpsFragment cps = new CpsFragment();
29 /// var fieldValue = cps.letPrim(new GetField(obj, field));
30 /// var plusOne = cps.applyBuiltin(BuiltinOperator.NumAdd,
31 /// [fieldValue, cps.makeOne()]);
32 /// cps.invokeContinuation(cont, [plusOne]);
33 ///
34 /// If `condition` is true then invoke `cont1`, else `cont2`.
35 ///
36 /// cps.ifTrue(condition).invokeContinuation(cont1, []);
37 /// cps.invokeContinuation(cont2, []);
38 ///
39 /// If `condition` is true then invoke `cont` with a bound primitive:
40 ///
41 /// CpsFragment branch = cps.ifTrue(condition);
42 /// branch.invokeContinuation(cont, [branch.letPrim(arg)]);
43 ///
44 /// Loop and call a method until it returns false:
45 ///
46 /// Continuation loop = cps.beginLoop();
47 /// var result = cps.invokeMethod(receiver, selector, ...);
48 /// cps.ifFalse(result).invokeContinuation(exit, []);
49 /// cps.continueLoop(loop);
50 ///
51 class CpsFragment {
52 /// The root of the IR built using this fragment.
53 Expression root;
54
55 /// Node whose body is the hole in this CPS fragment. May be null.
56 InteriorNode context;
57
58 /// Source information to attach to every IR node created in the fragment.
59 SourceInformation sourceInformation;
60
61 CpsFragment([this.sourceInformation, this.context]);
62
63 /// Asserts that the fragment is closed and returns the IR that was built.
64 Expression get result {
65 assert(context == null);
66 assert(root != null);
67 return root;
68 }
69
70 /// Put the given expression into the fragment's hole.
71 ///
72 /// Afterwards the fragment is closed and cannot be extended until a new
73 /// [context] is set.
74 void put(Expression node) {
75 assert(root == null || context != null); // We must put the node somewhere.
76 if (root == null) {
77 root = node;
78 }
79 if (context != null) {
80 context.body = node;
81 }
82 context = null;
83 }
84
85 /// Bind a primitive. Returns the same primitive for convenience.
86 Primitive letPrim(Primitive prim) {
87 assert(prim != null);
88 LetPrim let = new LetPrim(prim);
89 put(let);
90 context = let;
91 return prim;
92 }
93
94 /// Bind a constant value.
95 Primitive makeConstant(ConstantValue constant) {
96 return letPrim(new Constant(constant));
97 }
98
99 Primitive makeZero() => makeConstant(new IntConstantValue(0));
100 Primitive makeOne() => makeConstant(new IntConstantValue(1));
101 Primitive makeNull() => makeConstant(new NullConstantValue());
102 Primitive makeTrue() => makeConstant(new TrueConstantValue());
103 Primitive makeFalse() => makeConstant(new FalseConstantValue());
104
105 /// Invoke a built-in operator.
106 Primitive applyBuiltin(BuiltinOperator op, List<Primitive> args) {
107 return letPrim(new ApplyBuiltinOperator(op, args));
108 }
109
110 /// Inserts an invocation. binds its continuation, and returns the
111 /// continuation parameter (i.e. the return value of the invocation).
112 ///
113 /// The continuation body becomes the new hole.
114 Parameter invokeMethod(Primitive receiver,
115 Selector selector,
116 TypeMask mask,
117 List<Primitive> arguments) {
118 Continuation cont = new Continuation([new Parameter(null)]);
karlklose 2015/07/08 08:39:24 Add type arguments to list literals? (multiple pla
asgerf 2015/07/08 10:28:37 I've added some type arguments in places where it
119 InvokeMethod invoke =
120 new InvokeMethod(receiver, selector, mask, arguments, cont,
121 sourceInformation);
122 put(new LetCont(cont, invoke));
123 context = cont;
124 return cont.parameters.single;
125 }
126
127 /// Inserts an invocation. binds its continuation, and returns the
128 /// continuation parameter (i.e. the return value of the invocation).
129 ///
130 /// The continuation body becomes the new hole.
131 Parameter invokeStatic(FunctionElement target, List<Primitive> arguments) {
132 Continuation cont = new Continuation([new Parameter(null)]);
133 InvokeStatic invoke =
134 new InvokeStatic(target, new Selector.fromElement(target), arguments,
135 cont, sourceInformation);
136 put(new LetCont(cont, invoke));
137 context = cont;
138 return cont.parameters.single;
139 }
140
141 /// Inserts an invocation to a static function that throws an error.
142 ///
143 /// This closes the fragment; no more nodes may be added.
144 void invokeStaticThrower(FunctionElement target, List<Primitive> arguments) {
145 invokeStatic(target, arguments);
146 put(new Unreachable());
147 }
148
149 /// Invoke a non-recursive continuation.
150 ///
151 /// This closes the fragment; no more nodes may be inserted.
152 void invokeContinuation(Continuation cont, [List<Primitive> arguments]) {
153 if (arguments == null) arguments = <Primitive>[];
154 put(new InvokeContinuation(cont, arguments));
155 }
156
157 /// Build a loop with the given loop variables and initial values.
158 /// Call [continueLoop] with the returned continuation to iterate the loop.
159 ///
160 /// The loop body becomes the new hole.
161 Continuation beginLoop([List<Parameter> loopVars,
162 List<Primitive> initialValues]) {
163 if (initialValues == null) {
164 assert(loopVars == null);
165 loopVars = <Parameter>[];
166 initialValues = <Primitive>[];
167 }
168 Continuation cont = new Continuation(loopVars);
169 put(new LetCont(cont, new InvokeContinuation(cont, initialValues)));
170 context = cont;
171 return cont;
172 }
173
174 /// Continue a loop started by [beginLoop].
175 ///
176 /// This closes the fragment; no more nodes may be inserted.
177 void continueLoop(Continuation cont, [List<Primitive> updatedLoopVariables]) {
178 put(new InvokeContinuation(cont, updatedLoopVariables, isRecursive: true));
179 }
180
181 /// Branch on [condition].
182 ///
183 /// Returns a new fragment for the 'then' branch.
184 ///
185 /// The 'else' branch becomes the new hole.
186 CpsFragment ifTrue(Primitive condition) {
187 Continuation trueCont = new Continuation([]);
188 Continuation falseCont = new Continuation([]);
189 put(new LetCont.two(trueCont, falseCont,
190 new Branch(new IsTrue(condition), trueCont, falseCont)));
191 context = falseCont;
192 return new CpsFragment(sourceInformation, trueCont);
193 }
194
195 /// Branch on [condition].
196 ///
197 /// Returns a new fragment for the 'else' branch.
198 ///
199 /// The 'then' branch becomes the new hole.
200 CpsFragment ifFalse(Primitive condition) {
201 Continuation trueCont = new Continuation([]);
202 Continuation falseCont = new Continuation([]);
203 put(new LetCont.two(trueCont, falseCont,
204 new Branch(new IsTrue(condition), trueCont, falseCont)));
205 context = trueCont;
206 return new CpsFragment(sourceInformation, falseCont);
207 }
208
209 /// Create a new empty continuation and bind it here.
210 ///
211 /// Convenient for making a join point where multiple branches
212 /// meet later.
213 ///
214 /// The LetCont body becomes the new hole.
215 ///
216 /// Example use:
217 ///
218 /// Continuation fail = cps.letCont();
219 ///
220 /// // Fail if something
221 /// cps.ifTrue(<condition>)
222 /// ..invokeMethod(<method>)
223 /// ..invokeContinuation(fail);
224 ///
225 /// // Fail if something else
226 /// cps.ifTrue(<anotherCondition>)
227 /// ..invokeMethod(<anotherMethod>)
228 /// ..invokeContinuation(fail);
229 ///
230 /// // Build the fail branch
231 /// cps.insideContinuation(fail)
232 /// ..invokeStaticThrower(...);
233 ///
234 /// // Go to the happy branch
235 /// cps.invokeContinuation(cont..)
236 ///
237 Continuation letCont([List<Parameter> parameters]) {
238 if (parameters == null) parameters = <Parameter>[];
239 Continuation cont = new Continuation(parameters);
240 LetCont let = new LetCont(cont, null);
241 put(let);
242 context = let;
243 return cont;
244 }
245
246 /// Returns a fragment whose context is the body of the given continuation.
247 ///
248 /// Does not change the state of this CPS fragment.
249 ///
250 /// Useful for building the body of a continuation created using [letCont].
251 CpsFragment insideContinuation(Continuation cont) {
252 return new CpsFragment(sourceInformation, cont);
253 }
254
255 /// Puts the given fragment into this one.
256 ///
257 /// If [other] was an open fragment, its hole becomes the new hole
258 /// in this fragment.
259 ///
260 /// [other] is reset to an empty fragment after this.
261 void append(CpsFragment other) {
262 if (other.root == null) return;
263 put(other.root);
264 context = other.context;
265 other.context = null;
266 other.root = null;
267 }
268 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart » ('j') | pkg/compiler/lib/src/cps_ir/type_propagation.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698