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

Side by Side Diff: pkg/compiler/lib/src/ssa/builder_kernel.dart

Issue 2338093002: Build entire program with kernel for conversion to ssa. (Closed)
Patch Set: Created 4 years, 3 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
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'package:kernel/ast.dart' as ir; 5 import 'package:kernel/ast.dart' as ir;
6 6
7 import '../common.dart'; 7 import '../common.dart';
8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; 8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
9 import '../common/tasks.dart' show CompilerTask; 9 import '../common/tasks.dart' show CompilerTask;
10 import '../compiler.dart'; 10 import '../compiler.dart';
11 import '../dart_types.dart';
11 import '../elements/elements.dart'; 12 import '../elements/elements.dart';
12 import '../io/source_information.dart'; 13 import '../io/source_information.dart';
13 import '../js_backend/backend.dart' show JavaScriptBackend; 14 import '../js_backend/backend.dart' show JavaScriptBackend;
14 import '../kernel/kernel.dart'; 15 import '../kernel/kernel.dart';
15 import '../kernel/kernel_visitor.dart';
16 import '../resolution/tree_elements.dart';
17 import '../tree/dartstring.dart'; 16 import '../tree/dartstring.dart';
18 import '../types/masks.dart'; 17 import '../types/masks.dart';
18 import '../universe/selector.dart';
19 19
20 import 'graph_builder.dart'; 20 import 'graph_builder.dart';
21 import 'kernel_ast_adapter.dart'; 21 import 'kernel_ast_adapter.dart';
22 import 'locals_handler.dart'; 22 import 'locals_handler.dart';
23 import 'nodes.dart'; 23 import 'nodes.dart';
24 import 'ssa_branch_builder.dart'; 24 import 'ssa_branch_builder.dart';
25 25
26 class SsaKernelBuilderTask extends CompilerTask { 26 class SsaKernelBuilderTask extends CompilerTask {
27 final JavaScriptBackend backend; 27 final JavaScriptBackend backend;
28 final SourceInformationStrategy sourceInformationFactory; 28 final SourceInformationStrategy sourceInformationFactory;
29 29
30 String get name => 'SSA kernel builder'; 30 String get name => 'SSA kernel builder';
31 31
32 SsaKernelBuilderTask(JavaScriptBackend backend, this.sourceInformationFactory) 32 SsaKernelBuilderTask(JavaScriptBackend backend, this.sourceInformationFactory)
33 : backend = backend, 33 : backend = backend,
34 super(backend.compiler.measurer); 34 super(backend.compiler.measurer);
35 35
36 HGraph build(CodegenWorkItem work) { 36 HGraph build(CodegenWorkItem work) {
37 return measure(() { 37 return measure(() {
38 AstElement element = work.element.implementation; 38 AstElement element = work.element.implementation;
39 Kernel kernel = backend.kernelTask.kernel; 39 Kernel kernel = backend.kernelTask.kernel;
40 ir.Procedure function = kernel.functions[element]; 40 KernelSsaBuilder builder = new KernelSsaBuilder(element, work.resolvedAst,
41 KernelSsaBuilder builder = new KernelSsaBuilder( 41 backend.compiler, work.registry, sourceInformationFactory, kernel);
42 function,
43 element,
44 work.resolvedAst,
45 backend.compiler,
46 work.registry,
47 sourceInformationFactory,
48 kernel);
49 return builder.build(); 42 return builder.build();
50 }); 43 });
51 } 44 }
52 } 45 }
53 46
54 class KernelSsaBuilder extends ir.Visitor with GraphBuilder { 47 class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
55 final ir.Procedure function; 48 ir.Node target;
56 final FunctionElement functionElement; 49 final AstElement targetElement;
57 final ResolvedAst resolvedAst; 50 final ResolvedAst resolvedAst;
58 final Compiler compiler; 51 final Compiler compiler;
59 final CodegenRegistry registry; 52 final CodegenRegistry registry;
60 53
61 JavaScriptBackend get backend => compiler.backend; 54 JavaScriptBackend get backend => compiler.backend;
62 55
63 SourceInformationBuilder sourceInformationBuilder; 56 SourceInformationBuilder sourceInformationBuilder;
64 KernelAstAdapter astAdapter; 57 KernelAstAdapter astAdapter;
65 58
66 KernelSsaBuilder( 59 KernelSsaBuilder(
67 this.function, 60 this.targetElement,
68 this.functionElement,
69 this.resolvedAst, 61 this.resolvedAst,
70 this.compiler, 62 this.compiler,
71 this.registry, 63 this.registry,
72 SourceInformationStrategy sourceInformationFactory, 64 SourceInformationStrategy sourceInformationFactory,
73 Kernel kernel) { 65 Kernel kernel) {
74 graph.element = functionElement; 66 graph.element = targetElement;
75 // TODO(het): Should sourceInformationBuilder be in GraphBuilder? 67 // TODO(het): Should sourceInformationBuilder be in GraphBuilder?
76 this.sourceInformationBuilder = 68 this.sourceInformationBuilder =
77 sourceInformationFactory.createBuilderForContext(resolvedAst); 69 sourceInformationFactory.createBuilderForContext(resolvedAst);
78 graph.sourceInformation = 70 graph.sourceInformation =
79 sourceInformationBuilder.buildVariableDeclaration(); 71 sourceInformationBuilder.buildVariableDeclaration();
80 this.localsHandler = 72 this.localsHandler = new LocalsHandler(this, targetElement, null, compiler);
81 new LocalsHandler(this, functionElement, null, compiler);
82 this.astAdapter = new KernelAstAdapter( 73 this.astAdapter = new KernelAstAdapter(
83 compiler.backend, 74 compiler.backend,
84 resolvedAst, 75 resolvedAst,
85 kernel.nodeToAst, 76 kernel.nodeToAst,
86 kernel.nodeToElement, 77 kernel.nodeToElement,
78 kernel.fields,
87 kernel.functions, 79 kernel.functions,
88 kernel.classes, 80 kernel.classes,
89 kernel.libraries); 81 kernel.libraries);
82 Element originTarget = targetElement;
83 if (originTarget.isPatch) {
84 originTarget = originTarget.origin;
85 }
86 if (originTarget is FunctionElement) {
87 target = kernel.functions[originTarget];
88 } else if (originTarget is FieldElement) {
89 target = kernel.fields[originTarget];
90 }
90 } 91 }
91 92
92 HGraph build() { 93 HGraph build() {
93 // TODO(het): no reason to do this here... 94 // TODO(het): no reason to do this here...
94 HInstruction.idCounter = 0; 95 HInstruction.idCounter = 0;
95 if (function.kind == ir.ProcedureKind.Method || 96 if (target is ir.Procedure) {
96 function.kind == ir.ProcedureKind.Operator) { 97 buildProcedure(target);
97 buildMethod(function, functionElement); 98 } else if (target is ir.Field) {
98 } else { 99 buildField(target);
99 compiler.reporter.internalError( 100 } else if (target is ir.Constructor) {
100 functionElement, 101 // TODO(het): Actually handle this correctly
101 "Unable to convert this kind of Kernel " 102 HBasicBlock block = graph.addNewBlock();
102 "procedure to SSA: ${function.kind}"); 103 open(graph.entry);
104 close(new HGoto()).addSuccessor(block);
105 open(block);
106 closeAndGotoExit(new HGoto());
107 graph.finalize();
103 } 108 }
104 assert(graph.isValid()); 109 assert(graph.isValid());
105 return graph; 110 return graph;
106 } 111 }
107 112
113 void buildProcedure(ir.Procedure procedure) {
114 if (procedure.kind == ir.ProcedureKind.Method ||
115 procedure.kind == ir.ProcedureKind.Operator ||
116 procedure.kind == ir.ProcedureKind.Getter ||
117 procedure.kind == ir.ProcedureKind.Factory) {
118 buildMethod(procedure);
119 } else {
120 compiler.reporter.internalError(
121 targetElement,
122 "Unable to convert this kind of Kernel "
123 "procedure to SSA: ${procedure.kind}");
124 }
125 }
126
127 void buildField(ir.Field field) {
128 openFunction();
129 field.initializer.accept(this);
130 HInstruction value = pop();
131 closeAndGotoExit(new HReturn(value, null));
132 closeFunction();
133 }
134
108 @override 135 @override
109 HInstruction popBoolified() { 136 HInstruction popBoolified() {
110 HInstruction value = pop(); 137 HInstruction value = pop();
111 // TODO(het): add boolean conversion type check 138 // TODO(het): add boolean conversion type check
112 HInstruction result = new HBoolify(value, backend.boolType); 139 HInstruction result = new HBoolify(value, backend.boolType);
113 add(result); 140 add(result);
114 return result; 141 return result;
115 } 142 }
116 143
117 // TODO(het): This implementation is shared with [SsaBuilder]. Should we just 144 // TODO(het): This implementation is shared with [SsaBuilder]. Should we just
118 // allow [GraphBuilder] to access `compiler`? 145 // allow [GraphBuilder] to access `compiler`?
119 @override 146 @override
120 pushCheckNull(HInstruction expression) { 147 pushCheckNull(HInstruction expression) {
121 push(new HIdentity( 148 push(new HIdentity(
122 expression, graph.addConstantNull(compiler), null, backend.boolType)); 149 expression, graph.addConstantNull(compiler), null, backend.boolType));
123 } 150 }
124 151
125 /// Builds a SSA graph for [method]. 152 /// Builds a SSA graph for [method].
126 void buildMethod(ir.Procedure method, FunctionElement functionElement) { 153 void buildMethod(ir.Procedure method) {
127 openFunction(functionElement); 154 openFunction();
128 method.function.body.accept(this); 155 method.function.body.accept(this);
129 closeFunction(); 156 closeFunction();
130 } 157 }
131 158
132 // TODO(het): get function element from astAdapter? 159 void openFunction() {
133 void openFunction(FunctionElement functionElement) {
134 HBasicBlock block = graph.addNewBlock(); 160 HBasicBlock block = graph.addNewBlock();
135 open(graph.entry); 161 open(graph.entry);
136 localsHandler.startFunction(functionElement, resolvedAst.node); 162 localsHandler.startFunction(targetElement, resolvedAst.node);
137 close(new HGoto()).addSuccessor(block); 163 close(new HGoto()).addSuccessor(block);
138 164
139 open(block); 165 open(block);
140 } 166 }
141 167
142 void closeFunction() { 168 void closeFunction() {
143 if (!isAborted()) closeAndGotoExit(new HGoto()); 169 if (!isAborted()) closeAndGotoExit(new HGoto());
144 graph.finalize(); 170 graph.finalize();
145 } 171 }
146 172
147 @override 173 @override
174 void defaultExpression(ir.Expression expression) {
175 // TODO(het): This is only to get tests working
176 stack.add(graph.addConstantNull(compiler));
177 }
178
179 @override
148 void visitBlock(ir.Block block) { 180 void visitBlock(ir.Block block) {
149 assert(!isAborted()); 181 assert(!isAborted());
150 for (ir.Statement statement in block.statements) { 182 for (ir.Statement statement in block.statements) {
151 statement.accept(this); 183 statement.accept(this);
152 if (!isReachable) { 184 if (!isReachable) {
153 // The block has been aborted by a return or a throw. 185 // The block has been aborted by a return or a throw.
154 if (stack.isNotEmpty) { 186 if (stack.isNotEmpty) {
155 compiler.reporter.internalError( 187 compiler.reporter.internalError(
156 NO_LOCATION_SPANNABLE, 'Non-empty instruction stack.'); 188 NO_LOCATION_SPANNABLE, 'Non-empty instruction stack.');
157 } 189 }
158 return; 190 return;
159 } 191 }
160 } 192 }
161 assert(!current.isClosed()); 193 assert(!current.isClosed());
162 if (stack.isNotEmpty) { 194 if (stack.isNotEmpty) {
163 compiler.reporter 195 compiler.reporter
164 .internalError(NO_LOCATION_SPANNABLE, 'Non-empty instruction stack'); 196 .internalError(NO_LOCATION_SPANNABLE, 'Non-empty instruction stack');
165 } 197 }
166 } 198 }
167 199
168 @override 200 @override
169 visitExpressionStatement(ir.ExpressionStatement exprStatement) { 201 void visitExpressionStatement(ir.ExpressionStatement exprStatement) {
170 exprStatement.expression.accept(this); 202 exprStatement.expression.accept(this);
171 pop(); 203 pop();
172 } 204 }
173 205
174 @override 206 @override
175 void visitReturnStatement(ir.ReturnStatement returnStatement) { 207 void visitReturnStatement(ir.ReturnStatement returnStatement) {
176 HInstruction value; 208 HInstruction value;
177 if (returnStatement.expression == null) { 209 if (returnStatement.expression == null) {
178 value = graph.addConstantNull(compiler); 210 value = graph.addConstantNull(compiler);
179 } else { 211 } else {
180 returnStatement.expression.accept(this); 212 returnStatement.expression.accept(this);
181 value = pop(); 213 value = pop();
182 // TODO(het): Check or trust the type of value 214 // TODO(het): Check or trust the type of value
183 } 215 }
184 // TODO(het): Add source information 216 // TODO(het): Add source information
185 // TODO(het): Set a return value instead of closing the function when we 217 // TODO(het): Set a return value instead of closing the function when we
186 // support inlining. 218 // support inlining.
187 closeAndGotoExit(new HReturn(value, null)); 219 closeAndGotoExit(new HReturn(value, null));
188 } 220 }
189 221
190 @override 222 @override
191 void visitIfStatement(ir.IfStatement ifStatement) { 223 void visitIfStatement(ir.IfStatement ifStatement) {
192 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, compiler); 224 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler);
193 branchBuilder.handleIf( 225 brancher.handleIf(
194 () => ifStatement.condition.accept(this), 226 () => ifStatement.condition.accept(this),
195 () => ifStatement.then.accept(this), 227 () => ifStatement.then.accept(this),
196 () => ifStatement.otherwise?.accept(this)); 228 () => ifStatement.otherwise?.accept(this));
197 } 229 }
198 230
199 @override 231 @override
232 void visitConditionalExpression(ir.ConditionalExpression conditional) {
233 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler);
234 brancher.handleConditional(
235 () => conditional.condition.accept(this),
236 () => conditional.then.accept(this),
237 () => conditional.otherwise.accept(this));
238 }
239
240 @override
241 void visitLogicalExpression(ir.LogicalExpression logicalExpression) {
242 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler);
243 brancher.handleLogicalBinary(() => logicalExpression.left.accept(this),
244 () => logicalExpression.right.accept(this),
245 isAnd: logicalExpression.operator == '&&');
246 }
247
248 @override
200 void visitIntLiteral(ir.IntLiteral intLiteral) { 249 void visitIntLiteral(ir.IntLiteral intLiteral) {
201 stack.add(graph.addConstantInt(intLiteral.value, compiler)); 250 stack.add(graph.addConstantInt(intLiteral.value, compiler));
202 } 251 }
203 252
204 @override 253 @override
205 visitDoubleLiteral(ir.DoubleLiteral doubleLiteral) { 254 void visitDoubleLiteral(ir.DoubleLiteral doubleLiteral) {
206 stack.add(graph.addConstantDouble(doubleLiteral.value, compiler)); 255 stack.add(graph.addConstantDouble(doubleLiteral.value, compiler));
207 } 256 }
208 257
209 @override 258 @override
210 visitBoolLiteral(ir.BoolLiteral boolLiteral) { 259 void visitBoolLiteral(ir.BoolLiteral boolLiteral) {
211 stack.add(graph.addConstantBool(boolLiteral.value, compiler)); 260 stack.add(graph.addConstantBool(boolLiteral.value, compiler));
212 } 261 }
213 262
214 @override 263 @override
215 visitStringLiteral(ir.StringLiteral stringLiteral) { 264 void visitStringLiteral(ir.StringLiteral stringLiteral) {
216 stack.add(graph.addConstantString( 265 stack.add(graph.addConstantString(
217 new DartString.literal(stringLiteral.value), compiler)); 266 new DartString.literal(stringLiteral.value), compiler));
218 } 267 }
219 268
220 @override 269 @override
221 visitSymbolLiteral(ir.SymbolLiteral symbolLiteral) { 270 void visitSymbolLiteral(ir.SymbolLiteral symbolLiteral) {
222 stack.add(graph.addConstant( 271 stack.add(graph.addConstant(
223 astAdapter.getConstantForSymbol(symbolLiteral), compiler)); 272 astAdapter.getConstantForSymbol(symbolLiteral), compiler));
224 registry?.registerConstSymbol(symbolLiteral.value); 273 registry?.registerConstSymbol(symbolLiteral.value);
225 } 274 }
226 275
227 @override 276 @override
228 visitNullLiteral(ir.NullLiteral nullLiteral) { 277 void visitNullLiteral(ir.NullLiteral nullLiteral) {
229 stack.add(graph.addConstantNull(compiler)); 278 stack.add(graph.addConstantNull(compiler));
230 } 279 }
231 280
232 @override 281 @override
233 visitVariableGet(ir.VariableGet variableGet) { 282 void visitStaticGet(ir.StaticGet staticGet) {
283 Element element = astAdapter.getElement(staticGet.target);
Siggi Cherem (dart-lang) 2016/09/13 23:48:19 nit: consider adding a variable for target Membe
Harry Terkelsen 2016/09/14 00:07:24 Done.
284 if (staticGet.target is ir.Procedure) {
285 element = element.declaration;
286 ir.Procedure target = staticGet.target;
Siggi Cherem (dart-lang) 2016/09/13 23:48:19 (with a variable above, type promotion would work
Harry Terkelsen 2016/09/14 00:07:24 Done.
287 if (target.kind == ir.ProcedureKind.Getter) {
288 // We must invoke the getter
289 _pushStaticInvocation(
290 target, const <HInstruction>[], astAdapter.returnTypeOf(target));
291 } else {
292 push(new HStatic(element, astAdapter.inferredTypeOf(staticGet.target)));
Siggi Cherem (dart-lang) 2016/09/13 23:48:19 nit: maybe add a comment that this is a tear-off?
Harry Terkelsen 2016/09/14 00:07:24 Done.
293 }
294 } else {
295 push(new HStatic(element, astAdapter.inferredTypeOf(staticGet.target)));
Siggi Cherem (dart-lang) 2016/09/13 23:48:19 A couple questions here: (a) shouldn't this elemen
Harry Terkelsen 2016/09/14 00:07:24 a) Yes. Done b) Yes, there are more cases that ne
296 }
297 }
298
299 @override
300 void visitStaticSet(ir.StaticSet staticSet) {
301 VariableElement field = astAdapter.getElement(staticSet.target);
302 staticSet.value.accept(this);
303 HInstruction value = pop();
304 add(new HStaticStore(field, value));
305 stack.add(value);
306 }
307
308 @override
309 void visitPropertyGet(ir.PropertyGet propertyGet) {
310 propertyGet.receiver.accept(this);
311 HInstruction receiver = pop();
312
313 List<HInstruction> inputs = <HInstruction>[];
314 bool isIntercepted = astAdapter.isIntercepted(propertyGet);
315 if (isIntercepted) {
316 HInterceptor interceptor = _interceptorFor(receiver);
317 inputs.add(interceptor);
318 }
319 inputs.add(receiver);
320
321 TypeMask type = astAdapter.selectorGetterTypeOf(propertyGet);
322
323 push(new HInvokeDynamicGetter(astAdapter.getGetterSelector(propertyGet),
324 astAdapter.typeOfGet(propertyGet), null, inputs, type));
325 }
326
327 @override
328 void visitVariableGet(ir.VariableGet variableGet) {
234 LocalElement local = astAdapter.getElement(variableGet.variable); 329 LocalElement local = astAdapter.getElement(variableGet.variable);
235 stack.add(localsHandler.readLocal(local)); 330 stack.add(localsHandler.readLocal(local));
236 } 331 }
237 332
333 @override
334 void visitVariableSet(ir.VariableSet variableSet) {
335 variableSet.value.accept(this);
336 HInstruction value = pop();
337 _visitLocalSetter(variableSet.variable, value);
338 }
339
340 @override
341 void visitVariableDeclaration(ir.VariableDeclaration declaration) {
342 LocalElement local = astAdapter.getElement(declaration);
343 if (declaration.initializer == null) {
344 HInstruction initialValue = graph.addConstantNull(compiler);
345 localsHandler.updateLocal(local, initialValue);
346 } else {
347 // TODO(het): handle case where the variable is top-level or static
348 declaration.initializer.accept(this);
349 HInstruction initialValue = pop();
350
351 _visitLocalSetter(declaration, initialValue);
352
353 // Ignore value
354 pop();
355 }
356 }
357
358 void _visitLocalSetter(ir.VariableDeclaration variable, HInstruction value) {
359 // TODO(het): handle case where the variable is top-level or static
360 LocalElement local = astAdapter.getElement(variable);
361
362 // Give the value a name if it doesn't have one already.
363 if (value.sourceElement == null) {
364 value.sourceElement = local;
365 }
366
367 stack.add(value);
368 // TODO(het): check or trust type
369 localsHandler.updateLocal(local, value);
370 }
371
238 // TODO(het): Also extract type arguments 372 // TODO(het): Also extract type arguments
239 /// Extracts the list of instructions for the expressions in the arguments. 373 /// Extracts the list of instructions for the expressions in the arguments.
240 List<HInstruction> _visitArguments(ir.Arguments arguments) { 374 List<HInstruction> _visitArguments(ir.Arguments arguments) {
241 List<HInstruction> result = <HInstruction>[]; 375 List<HInstruction> result = <HInstruction>[];
242 376
243 for (ir.Expression argument in arguments.positional) { 377 for (ir.Expression argument in arguments.positional) {
244 argument.accept(this); 378 argument.accept(this);
245 result.add(pop()); 379 result.add(pop());
246 } 380 }
247 for (ir.NamedExpression argument in arguments.named) { 381 for (ir.NamedExpression argument in arguments.named) {
248 argument.value.accept(this); 382 argument.value.accept(this);
249 result.add(pop()); 383 result.add(pop());
250 } 384 }
251 385
252 return result; 386 return result;
253 } 387 }
254 388
255 @override 389 @override
256 visitStaticInvocation(ir.StaticInvocation invocation) { 390 void visitStaticInvocation(ir.StaticInvocation invocation) {
257 ir.Procedure target = invocation.target; 391 ir.Procedure target = invocation.target;
258 bool targetCanThrow = astAdapter.getCanThrow(target);
259 TypeMask typeMask = astAdapter.returnTypeOf(target); 392 TypeMask typeMask = astAdapter.returnTypeOf(target);
260 393
261 var arguments = _visitArguments(invocation.arguments); 394 List<HInstruction> arguments = _visitArguments(invocation.arguments);
395
396 _pushStaticInvocation(target, arguments, typeMask);
397 }
398
399 void _pushStaticInvocation(
400 ir.Node target, List<HInstruction> arguments, TypeMask typeMask) {
401 bool targetCanThrow = astAdapter.getCanThrow(target);
262 402
263 HInstruction instruction = new HInvokeStatic( 403 HInstruction instruction = new HInvokeStatic(
264 astAdapter.getElement(target).declaration, arguments, typeMask, 404 astAdapter.getElement(target).declaration, arguments, typeMask,
265 targetCanThrow: targetCanThrow); 405 targetCanThrow: targetCanThrow);
266 instruction.sideEffects = astAdapter.getSideEffects(target); 406 instruction.sideEffects = astAdapter.getSideEffects(target);
267 407
268 push(instruction); 408 push(instruction);
269 } 409 }
270 410
271 // TODO(het): Decide when to inline 411 // TODO(het): Decide when to inline
272 @override 412 @override
273 visitMethodInvocation(ir.MethodInvocation invocation) { 413 void visitMethodInvocation(ir.MethodInvocation invocation) {
274 invocation.receiver.accept(this); 414 invocation.receiver.accept(this);
275 HInstruction receiver = pop(); 415 HInstruction receiver = pop();
276 416
277 List<HInstruction> arguments = <HInstruction>[receiver] 417 List<HInstruction> arguments = <HInstruction>[receiver]
278 ..addAll(_visitArguments(invocation.arguments)); 418 ..addAll(_visitArguments(invocation.arguments));
279 419
280 List<HInstruction> inputs = <HInstruction>[]; 420 List<HInstruction> inputs = <HInstruction>[];
281 421
282 bool isIntercepted = astAdapter.isIntercepted(invocation); 422 bool isIntercepted = astAdapter.isIntercepted(invocation);
283 if (isIntercepted) { 423 if (isIntercepted) {
284 HInterceptor interceptor = 424 HInterceptor interceptor = _interceptorFor(receiver);
285 new HInterceptor(receiver, backend.nonNullType);
286 add(interceptor);
287 inputs.add(interceptor); 425 inputs.add(interceptor);
288 } 426 }
289 inputs.addAll(arguments); 427 inputs.addAll(arguments);
290 428
291 TypeMask type = astAdapter.selectorTypeOf(invocation); 429 TypeMask type = astAdapter.selectorTypeOf(invocation);
292 430
293 push(new HInvokeDynamicMethod(astAdapter.getSelector(invocation), 431 push(new HInvokeDynamicMethod(astAdapter.getSelector(invocation),
294 astAdapter.typeOfInvocation(invocation), inputs, type, isIntercepted)); 432 astAdapter.typeOfInvocation(invocation), inputs, type, isIntercepted));
295 } 433 }
296 434
435 HInterceptor _interceptorFor(HInstruction intercepted) {
436 HInterceptor interceptor =
437 new HInterceptor(intercepted, backend.nonNullType);
438 add(interceptor);
439 return interceptor;
440 }
441
442 ir.Class containingClass(ir.TreeNode node) {
Siggi Cherem (dart-lang) 2016/09/13 23:48:19 nit => make static and private?
Harry Terkelsen 2016/09/14 00:07:24 Done.
443 while (node != null) {
444 if (node is ir.Class) return node;
445 node = node.parent;
446 }
447 return null;
448 }
449
297 @override 450 @override
298 visitThisExpression(ir.ThisExpression thisExpression) { 451 void visitSuperMethodInvocation(ir.SuperMethodInvocation invocation) {
452 List<HInstruction> arguments = _visitArguments(invocation.arguments);
453 HInstruction receiver = localsHandler.readThis();
454 Selector selector = astAdapter.getSelector(invocation);
455 ir.Class surroundingClass = containingClass(invocation);
456
457 List<HInstruction> inputs = <HInstruction>[];
458 if (astAdapter.isIntercepted(invocation)) {
459 inputs.add(_interceptorFor(receiver));
460 }
461 inputs.add(receiver);
462 inputs.addAll(arguments);
463
464 HInstruction instruction = new HInvokeSuper(
465 astAdapter.getElement(invocation.interfaceTarget),
466 astAdapter.getElement(surroundingClass),
467 selector,
468 inputs,
469 astAdapter.returnTypeOf(invocation.interfaceTarget),
470 null,
471 isSetter: selector.isSetter || selector.isIndexSet);
472 instruction.sideEffects =
473 compiler.world.getSideEffectsOfSelector(selector, null);
474 push(instruction);
475 }
476
477 @override
478 void visitConstructorInvocation(ir.ConstructorInvocation invocation) {
479 ir.Constructor target = invocation.target;
480 List<HInstruction> arguments = _visitArguments(invocation.arguments);
481 TypeMask typeMask = new TypeMask.nonNullExact(
482 astAdapter.getElement(target.enclosingClass), compiler.world);
483 _pushStaticInvocation(target, arguments, typeMask);
484 }
485
486 @override
487 void visitIsExpression(ir.IsExpression isExpression) {
488 isExpression.operand.accept(this);
489 HInstruction expression = pop();
490
491 DartType type = astAdapter.getDartType(isExpression.type);
492
493 if (backend.hasDirectCheckFor(type)) {
494 push(new HIs.direct(type, expression, backend.boolType));
495 return;
496 }
497
498 // The interceptor is not always needed. It is removed by optimization
499 // when the receiver type or tested type permit.
500 HInterceptor interceptor = _interceptorFor(expression);
501 push(new HIs.raw(type, expression, interceptor, backend.boolType));
502 }
503
504 @override
505 void visitThrow(ir.Throw throwNode) {
506 throwNode.expression.accept(this);
507 HInstruction expression = pop();
508 if (isReachable) {
509 push(new HThrowExpression(expression, null));
510 isReachable = false;
511 }
512 }
513
514 @override
515 void visitThisExpression(ir.ThisExpression thisExpression) {
299 stack.add(localsHandler.readThis()); 516 stack.add(localsHandler.readThis());
300 } 517 }
301 518
302 @override 519 @override
303 visitNot(ir.Not not) { 520 void visitNot(ir.Not not) {
304 not.operand.accept(this); 521 not.operand.accept(this);
305 push(new HNot(popBoolified(), backend.boolType)); 522 push(new HNot(popBoolified(), backend.boolType));
306 } 523 }
307 } 524 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698