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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ir/inode_builder.dart

Issue 57873002: Build new IR for functions returning a constant (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 1 month 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 part of ir;
kasperl 2013/11/06 08:30:04 Add copyright header. I'd make the IrBuilder live
lukas 2013/11/06 11:36:08 Done.
2
3 class IrBuilderTask extends CompilerTask {
4 final Map<Element, INode> iNodes = new Map<Element, INode>();
5
6 IrBuilderTask(Compiler compiler) : super(compiler);
7
8 String get name => 'IR builder';
9
10 void buildNodes() {
11 Map<Element, TreeElements> resolved =
12 compiler.enqueuer.resolution.resolvedElements;
13 resolved.forEach((Element element, TreeElements elementsMapping) {
14 element = element.implementation;
15
16 // @lry debug
17 if (element.name == 'noInline')
18 print(0);
19
20 SourceFile sourceFile = elementSourceFile(element);
21 INodeBuilderVisitor visitor =
22 new INodeBuilderVisitor(elementsMapping, compiler, sourceFile);
23 INode iNode;
24 ElementKind kind = element.kind;
25 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
26 // iNode = compileConstructor(builder, work);
27 } else if (kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY ||
28 kind == ElementKind.FUNCTION ||
29 kind == ElementKind.GETTER ||
30 kind == ElementKind.SETTER) {
31 iNode = visitor.buildMethod(element);
32 } else if (kind == ElementKind.FIELD) {
33 // @lry the below assertion holds in the ssa-builder, but not here.
34 // are instance fields never enqueued in the backend?
35 // compare to inferrer, which is not worklist-based but runs over all
36 // resolved elements
37 // assert(!element.isInstanceMember());
38 // iNode = builder.buildLazyInitializer(element);
39 } else {
40 compiler.internalErrorOnElement(element,
41 'unexpected element kind $kind');
42 }
43
44 if (iNode != null) {
45 iNodes[element] = iNode;
46 }
47
48 // @lry debug
49 if (element.name == 'noInline') {
50 (element as dynamic).beginToken.next = null;
51 (element as dynamic).cachedNode = null;
52 print(iNode);
53 }
54
55 });
56 }
57
58 SourceFile elementSourceFile(Element element) {
59 if (element is FunctionElement) {
60 FunctionElement functionElement = element;
61 if (functionElement.patch != null) element = functionElement.patch;
62 }
63 return element.getCompilationUnit().script.file;
64 }
65 }
66
67
68 class INodeBuilderVisitor extends ResolvedVisitor<INode> {
69 SourceFile sourceFile;
70
71 Context context;
72
73 INodeBuilderVisitor(TreeElements elements, Compiler compiler,
74 this.sourceFile) : super(elements, compiler) {
75 context = new Context(this);
76 }
77
78 INode buildMethod(FunctionElement functionElement) {
79 assert(invariant(functionElement, functionElement.isImplementation));
80 FunctionExpression function = functionElement.parseNode(compiler);
81 assert(function != null);
82 assert(!function.modifiers.isExternal());
83 assert(elements[function] != null);
84 return buildNode(function);
85 }
86
87 INode buildNode(Node node) {
88 try {
89 return node.accept(this);
90 } catch(e) {
91 if (e == ABORT_INODE_BUILDER) return null;
92 throw e;
93 }
94 }
95
96 ConstantSystem get constantSystem => compiler.backend.constantSystem;
97
98 Position nodePos(Node node) {
99 return new Position(sourceFile, node.getBeginToken().charOffset);
100 }
101
102 INode visitFunctionExpression(FunctionExpression node) {
103 IFunction result = new IFunction(nodePos(node), const<INode>[]);
ngeoffray 2013/11/05 12:58:35 Should we create that at the end of the visit, onc
lukas 2013/11/05 17:10:50 It's done here for now because the "IrReturn" poin
104 context.openFunction(result);
105 INode body = node.body.accept(this);
106 if (context.statements.isNotEmpty) {
107 result.statements =
108 <INode>[]..addAll(context.constants)..addAll(context.statements);
109 }
110 context.closeFunction();
111 if (!context.isTopLevel()) {
112 context.enterStatement(result);
113 }
114 return result;
115 }
116
117 INode visitBlock(Block node) {
118 for (Node n in node.statements.nodes) {
119 n.accept(this);
120 }
121 return new NoValue();
122 }
123
124 INode visitReturn(Return node) {
125 INode value = node.expression.accept(this);
126 return context.enterStatement(
127 new IReturn(nodePos(node), context.returnFunction, value));
128 }
129
130 IConstant visitLiteralBool(LiteralBool node) =>
131 context.enterConstant(constantSystem.createBool(node.value), node);
132
133 IConstant visitLiteralDouble(LiteralDouble node) =>
134 context.enterConstant(constantSystem.createDouble(node.value), node);
135
136 IConstant visitLiteralInt(LiteralInt node) =>
137 context.enterConstant(constantSystem.createInt(node.value), node);
138
139 IConstant visitLiteralString(LiteralString node) =>
140 context.enterConstant(
141 constantSystem.createString(node.dartString, node), node);
142
143 IConstant visitLiteralNull(LiteralNull node) =>
144 context.enterConstant(constantSystem.createNull(), node);
145
146 // INode visitLiteralList(LiteralList node) => visitExpression(node);
147 // INode visitLiteralMap(LiteralMap node) => visitExpression(node);
148 // INode visitLiteralMapEntry(LiteralMapEntry node) => visitNode(node);
149 // INode visitLiteralSymbol(LiteralSymbol node) => visitExpression(node);
150
151
152 INode visitAssert(Send node) {
153 return giveup();
154 }
155
156 INode visitClosureSend(Send node) {
157 return giveup();
158 }
159
160 INode visitDynamicSend(Send node) {
161 return giveup();
162 }
163
164 INode visitGetterSend(Send node) {
165 return giveup();
166 }
167
168 INode visitOperatorSend(Send node) {
169 return giveup();
170 }
171
172 INode visitStaticSend(Send node) {
173 return giveup();
174 }
175
176 INode visitSuperSend(Send node) {
177 return giveup();
178 }
179
180 INode visitTypeReferenceSend(Send node) {
181 return giveup();
182 }
183
184 static final String ABORT_INODE_BUILDER = "INode builder aborted";
185
186 INode giveup() => throw ABORT_INODE_BUILDER;
187
188 void internalError(String reason, {Node node}) {
189 giveup();
190 }
191 }
192
193 class Context {
194 INodeBuilderVisitor visitor;
195 Context(this.visitor);
196
197 List<IFunction> returnFunctionList = <IFunction>[];
198 IFunction get returnFunction => returnFunctionList.last;
ngeoffray 2013/11/05 12:58:35 Are you anticipating inlining?
lukas 2013/11/05 17:10:50 Yes - again, depends on the IR we use.
199
200 List<List<INode>> statementsList = <List<INode>>[];
201 List<INode> get statements => statementsList.last;
202
203 List<List<IConstant>> constantsList = <List<IConstant>>[];
ngeoffray 2013/11/05 12:58:35 I think we'll just have one giant list/set of cons
lukas 2013/11/05 17:10:50 We have one list per function here. The reason it'
204 List<IConstant> get constants => constantsList.last;
205
206 IConstant enterConstant(Constant value, Node node) {
207 return constants.firstWhere((c) => c.value == value, orElse: () {
208 IConstant c = new IConstant(visitor.nodePos(node), value);
209 constants.add(c);
210 return c;
211 });
212 }
213
214 INode enterStatement(INode statement) {
215 statements.add(statement);
216 return statement;
217 }
218
219 void openFunction(IFunction function) {
220 returnFunctionList.add(function);
221 statementsList.add(<INode>[]);
222 constantsList.add(<IConstant>[]);
223 }
224
225 void closeFunction() {
226 returnFunctionList.removeLast();
227 statementsList.removeLast();
228 constantsList.removeLast();
229 }
230
231 void openContinuation() {
232 statementsList.add(<INode>[]);
233 }
234
235 void closeContinuation() {
236 statementsList.removeLast();
237 }
238
239 isTopLevel() => returnFunctionList.isEmpty;
240 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698