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

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: 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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. Otherwise, the fragment is "closed" and cannot be extended further.
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
103 /// Invoke a built-in operator.
104 Primitive applyBuiltin(BuiltinOperator op, List<Primitive> args) {
105 return letPrim(new ApplyBuiltinOperator(op, args));
106 }
107
108 /// Inserts an invocation. binds its continuation, and returns the
109 /// continuation parameter (i.e. the return value of the invocation).
110 ///
111 /// The continuation body becomes the new hole.
112 Parameter invokeMethod(Primitive receiver,
113 Selector selector,
114 TypeMask mask,
115 List<Primitive> arguments) {
116 Continuation cont = new Continuation(<Parameter>[new Parameter(null)]);
117 InvokeMethod invoke =
118 new InvokeMethod(receiver, selector, mask, arguments, cont,
119 sourceInformation);
120 put(new LetCont(cont, invoke));
121 context = cont;
122 return cont.parameters.single;
123 }
124
125 /// Inserts an invocation. binds its continuation, and returns the
126 /// continuation parameter (i.e. the return value of the invocation).
127 ///
128 /// The continuation body becomes the new hole.
129 Parameter invokeStatic(FunctionElement target, List<Primitive> arguments) {
130 Continuation cont = new Continuation(<Parameter>[new Parameter(null)]);
131 InvokeStatic invoke =
132 new InvokeStatic(target, new Selector.fromElement(target), arguments,
133 cont, sourceInformation);
134 put(new LetCont(cont, invoke));
135 context = cont;
136 return cont.parameters.single;
137 }
138
139 /// Inserts an invocation to a static function that throws an error.
140 ///
141 /// This closes the fragment; no more nodes may be added.
142 void invokeStaticThrower(FunctionElement target, List<Primitive> arguments) {
143 invokeStatic(target, arguments);
144 put(new Unreachable());
145 }
146
147 /// Invoke a non-recursive continuation.
148 ///
149 /// This closes the fragment; no more nodes may be inserted.
150 void invokeContinuation(Continuation cont, [List<Primitive> arguments]) {
151 if (arguments == null) arguments = <Primitive>[];
152 put(new InvokeContinuation(cont, arguments));
153 }
154
155 /// Build a loop with the given loop variables and initial values.
156 /// Call [continueLoop] with the returned continuation to iterate the loop.
157 ///
158 /// The loop body becomes the new hole.
159 Continuation beginLoop([List<Parameter> loopVars,
160 List<Primitive> initialValues]) {
161 if (initialValues == null) {
162 assert(loopVars == null);
163 loopVars = <Parameter>[];
164 initialValues = <Primitive>[];
165 }
166 Continuation cont = new Continuation(loopVars);
167 put(new LetCont(cont, new InvokeContinuation(cont, initialValues)));
168 context = cont;
169 return cont;
170 }
171
172 /// Continue a loop started by [beginLoop].
173 ///
174 /// This closes the fragment; no more nodes may be inserted.
175 void continueLoop(Continuation cont, [List<Primitive> updatedLoopVariables]) {
176 put(new InvokeContinuation(cont, updatedLoopVariables, isRecursive: true));
177 }
178
179 /// Branch on [condition].
180 ///
181 /// Returns a new fragment for the 'then' branch.
182 ///
183 /// The 'else' branch becomes the new hole.
184 CpsFragment ifTrue(Primitive condition) {
185 Continuation trueCont = new Continuation(<Parameter>[]);
186 Continuation falseCont = new Continuation(<Parameter>[]);
187 put(new LetCont.two(trueCont, falseCont,
188 new Branch(new IsTrue(condition), trueCont, falseCont)));
189 context = falseCont;
190 return new CpsFragment(sourceInformation, trueCont);
191 }
192
193 /// Branch on [condition].
194 ///
195 /// Returns a new fragment for the 'else' branch.
196 ///
197 /// The 'then' branch becomes the new hole.
198 CpsFragment ifFalse(Primitive condition) {
199 Continuation trueCont = new Continuation(<Parameter>[]);
200 Continuation falseCont = new Continuation(<Parameter>[]);
201 put(new LetCont.two(trueCont, falseCont,
202 new Branch(new IsTrue(condition), trueCont, falseCont)));
203 context = trueCont;
204 return new CpsFragment(sourceInformation, falseCont);
205 }
206
207 /// Create a new empty continuation and bind it here.
208 ///
209 /// Convenient for making a join point where multiple branches
210 /// meet later.
211 ///
212 /// The LetCont body becomes the new hole.
213 ///
214 /// Example use:
215 ///
216 /// Continuation fail = cps.letCont();
217 ///
218 /// // Fail if something
219 /// cps.ifTrue(<condition>)
220 /// ..invokeMethod(<method>)
221 /// ..invokeContinuation(fail);
222 ///
223 /// // Fail if something else
224 /// cps.ifTrue(<anotherCondition>)
225 /// ..invokeMethod(<anotherMethod>)
226 /// ..invokeContinuation(fail);
227 ///
228 /// // Build the fail branch
229 /// cps.insideContinuation(fail)
230 /// ..invokeStaticThrower(...);
231 ///
232 /// // Go to the happy branch
233 /// cps.invokeContinuation(cont..)
234 ///
235 Continuation letCont([List<Parameter> parameters]) {
236 if (parameters == null) parameters = <Parameter>[];
237 Continuation cont = new Continuation(parameters);
238 LetCont let = new LetCont(cont, null);
239 put(let);
240 context = let;
241 return cont;
242 }
243
244 /// Returns a fragment whose context is the body of the given continuation.
245 ///
246 /// Does not change the state of this CPS fragment.
247 ///
248 /// Useful for building the body of a continuation created using [letCont].
249 CpsFragment insideContinuation(Continuation cont) {
250 return new CpsFragment(sourceInformation, cont);
251 }
252
253 /// Puts the given fragment into this one.
254 ///
255 /// If [other] was an open fragment, its hole becomes the new hole
256 /// in this fragment.
257 ///
258 /// [other] is reset to an empty fragment after this.
259 void append(CpsFragment other) {
260 if (other.root == null) return;
261 put(other.root);
262 context = other.context;
263 other.context = null;
264 other.root = null;
265 }
266 }
OLDNEW
« 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