OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library ssa.tracer; | 5 library ssa.tracer; |
6 | 6 |
7 import 'dart:async' show EventSink; | 7 import 'dart:async' show EventSink; |
8 | 8 |
9 import '../compiler.dart' show Compiler; | 9 import '../compiler.dart' show Compiler; |
10 import '../diagnostics/invariant.dart' show DEBUG_MODE; | 10 import '../diagnostics/invariant.dart' show DEBUG_MODE; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 } else { | 52 } else { |
53 addIndent(); | 53 addIndent(); |
54 add("successors"); | 54 add("successors"); |
55 for (HBasicBlock successor in block.successors) { | 55 for (HBasicBlock successor in block.successors) { |
56 add(' "B${successor.id}"'); | 56 add(' "B${successor.id}"'); |
57 } | 57 } |
58 add("\n"); | 58 add("\n"); |
59 } | 59 } |
60 } | 60 } |
61 | 61 |
62 void addInstructions(HInstructionStringifier stringifier, | 62 void addInstructions( |
63 HInstructionList list) { | 63 HInstructionStringifier stringifier, HInstructionList list) { |
64 for (HInstruction instruction = list.first; | 64 for (HInstruction instruction = list.first; |
65 instruction != null; | 65 instruction != null; |
66 instruction = instruction.next) { | 66 instruction = instruction.next) { |
67 int bci = 0; | 67 int bci = 0; |
68 int uses = instruction.usedBy.length; | 68 int uses = instruction.usedBy.length; |
69 String changes = instruction.sideEffects.hasSideEffects() ? '!' : ' '; | 69 String changes = instruction.sideEffects.hasSideEffects() ? '!' : ' '; |
70 String depends = instruction.sideEffects.dependsOnSomething() ? '?' : ''; | 70 String depends = instruction.sideEffects.dependsOnSomething() ? '?' : ''; |
71 addIndent(); | 71 addIndent(); |
72 String temporaryId = stringifier.temporaryId(instruction); | 72 String temporaryId = stringifier.temporaryId(instruction); |
73 String instructionString = stringifier.visit(instruction); | 73 String instructionString = stringifier.visit(instruction); |
74 add("$bci $uses $temporaryId $instructionString $changes $depends <|@\n"); | 74 add("$bci $uses $temporaryId $instructionString $changes $depends <|@\n"); |
75 } | 75 } |
76 } | 76 } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 } | 155 } |
156 return "$prefix${instruction.id}"; | 156 return "$prefix${instruction.id}"; |
157 } | 157 } |
158 | 158 |
159 String visitBoolify(HBoolify node) { | 159 String visitBoolify(HBoolify node) { |
160 return "Boolify: ${temporaryId(node.inputs[0])}"; | 160 return "Boolify: ${temporaryId(node.inputs[0])}"; |
161 } | 161 } |
162 | 162 |
163 String handleInvokeBinary(HInvokeBinary node, String opcode) { | 163 String handleInvokeBinary(HInvokeBinary node, String opcode) { |
164 String left = temporaryId(node.left); | 164 String left = temporaryId(node.left); |
165 String right= temporaryId(node.right); | 165 String right = temporaryId(node.right); |
166 return '$opcode: $left $right'; | 166 return '$opcode: $left $right'; |
167 } | 167 } |
168 | 168 |
169 String visitAdd(HAdd node) => handleInvokeBinary(node, 'Add'); | 169 String visitAdd(HAdd node) => handleInvokeBinary(node, 'Add'); |
170 | 170 |
171 String visitBitAnd(HBitAnd node) => handleInvokeBinary(node, 'BitAnd'); | 171 String visitBitAnd(HBitAnd node) => handleInvokeBinary(node, 'BitAnd'); |
172 | 172 |
173 String visitBitNot(HBitNot node) { | 173 String visitBitNot(HBitNot node) { |
174 String operand = temporaryId(node.operand); | 174 String operand = temporaryId(node.operand); |
175 return "BitNot: $operand"; | 175 return "BitNot: $operand"; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 | 248 |
249 String visitGoto(HGoto node) { | 249 String visitGoto(HGoto node) { |
250 HBasicBlock target = currentBlock.successors[0]; | 250 HBasicBlock target = currentBlock.successors[0]; |
251 return "Goto: (B${target.id})"; | 251 return "Goto: (B${target.id})"; |
252 } | 252 } |
253 | 253 |
254 String visitGreater(HGreater node) => handleInvokeBinary(node, 'Greater'); | 254 String visitGreater(HGreater node) => handleInvokeBinary(node, 'Greater'); |
255 String visitGreaterEqual(HGreaterEqual node) { | 255 String visitGreaterEqual(HGreaterEqual node) { |
256 return handleInvokeBinary(node, 'GreaterEqual'); | 256 return handleInvokeBinary(node, 'GreaterEqual'); |
257 } | 257 } |
| 258 |
258 String visitIdentity(HIdentity node) => handleInvokeBinary(node, 'Identity'); | 259 String visitIdentity(HIdentity node) => handleInvokeBinary(node, 'Identity'); |
259 | 260 |
260 String visitIf(HIf node) { | 261 String visitIf(HIf node) { |
261 HBasicBlock thenBlock = currentBlock.successors[0]; | 262 HBasicBlock thenBlock = currentBlock.successors[0]; |
262 HBasicBlock elseBlock = currentBlock.successors[1]; | 263 HBasicBlock elseBlock = currentBlock.successors[1]; |
263 String conditionId = temporaryId(node.inputs[0]); | 264 String conditionId = temporaryId(node.inputs[0]); |
264 return "If ($conditionId): (B${thenBlock.id}) else (B${elseBlock.id})"; | 265 return "If ($conditionId): (B${thenBlock.id}) else (B${elseBlock.id})"; |
265 } | 266 } |
266 | 267 |
267 String handleGenericInvoke(String invokeType, String functionName, | 268 String handleGenericInvoke( |
268 List<HInstruction> arguments) { | 269 String invokeType, String functionName, List<HInstruction> arguments) { |
269 StringBuffer argumentsString = new StringBuffer(); | 270 StringBuffer argumentsString = new StringBuffer(); |
270 for (int i = 0; i < arguments.length; i++) { | 271 for (int i = 0; i < arguments.length; i++) { |
271 if (i != 0) argumentsString.write(", "); | 272 if (i != 0) argumentsString.write(", "); |
272 argumentsString.write(temporaryId(arguments[i])); | 273 argumentsString.write(temporaryId(arguments[i])); |
273 } | 274 } |
274 return "$invokeType: $functionName($argumentsString)"; | 275 return "$invokeType: $functionName($argumentsString)"; |
275 } | 276 } |
276 | 277 |
277 String visitIndex(HIndex node) { | 278 String visitIndex(HIndex node) { |
278 String receiver = temporaryId(node.receiver); | 279 String receiver = temporaryId(node.receiver); |
(...skipping 12 matching lines...) Expand all Loading... |
291 String value = temporaryId(node.inputs[0]); | 292 String value = temporaryId(node.inputs[0]); |
292 if (node.interceptedClasses != null) { | 293 if (node.interceptedClasses != null) { |
293 JavaScriptBackend backend = compiler.backend; | 294 JavaScriptBackend backend = compiler.backend; |
294 String cls = | 295 String cls = |
295 backend.namer.suffixForGetInterceptor(node.interceptedClasses); | 296 backend.namer.suffixForGetInterceptor(node.interceptedClasses); |
296 return "Interceptor ($cls): $value"; | 297 return "Interceptor ($cls): $value"; |
297 } | 298 } |
298 return "Interceptor: $value"; | 299 return "Interceptor: $value"; |
299 } | 300 } |
300 | 301 |
301 String visitInvokeClosure(HInvokeClosure node) | 302 String visitInvokeClosure(HInvokeClosure node) => |
302 => handleInvokeDynamic(node, "InvokeClosure"); | 303 handleInvokeDynamic(node, "InvokeClosure"); |
303 | 304 |
304 String handleInvokeDynamic(HInvokeDynamic invoke, String kind) { | 305 String handleInvokeDynamic(HInvokeDynamic invoke, String kind) { |
305 String receiver = temporaryId(invoke.receiver); | 306 String receiver = temporaryId(invoke.receiver); |
306 String name = invoke.selector.name; | 307 String name = invoke.selector.name; |
307 String target = "$receiver.$name"; | 308 String target = "$receiver.$name"; |
308 int offset = HInvoke.ARGUMENTS_OFFSET; | 309 int offset = HInvoke.ARGUMENTS_OFFSET; |
309 List arguments = invoke.inputs.sublist(offset); | 310 List arguments = invoke.inputs.sublist(offset); |
310 return handleGenericInvoke(kind, target, arguments) + | 311 return handleGenericInvoke(kind, target, arguments) + "(${invoke.mask})"; |
311 "(${invoke.mask})"; | |
312 } | 312 } |
313 | 313 |
314 String visitInvokeDynamicMethod(HInvokeDynamicMethod node) | 314 String visitInvokeDynamicMethod(HInvokeDynamicMethod node) => |
315 => handleInvokeDynamic(node, "InvokeDynamicMethod"); | 315 handleInvokeDynamic(node, "InvokeDynamicMethod"); |
316 String visitInvokeDynamicGetter(HInvokeDynamicGetter node) | 316 String visitInvokeDynamicGetter(HInvokeDynamicGetter node) => |
317 => handleInvokeDynamic(node, "InvokeDynamicGetter"); | 317 handleInvokeDynamic(node, "InvokeDynamicGetter"); |
318 String visitInvokeDynamicSetter(HInvokeDynamicSetter node) | 318 String visitInvokeDynamicSetter(HInvokeDynamicSetter node) => |
319 => handleInvokeDynamic(node, "InvokeDynamicSetter"); | 319 handleInvokeDynamic(node, "InvokeDynamicSetter"); |
320 | 320 |
321 String visitInvokeStatic(HInvokeStatic invoke) { | 321 String visitInvokeStatic(HInvokeStatic invoke) { |
322 String target = invoke.element.name; | 322 String target = invoke.element.name; |
323 return handleGenericInvoke("InvokeStatic", target, invoke.inputs); | 323 return handleGenericInvoke("InvokeStatic", target, invoke.inputs); |
324 } | 324 } |
325 | 325 |
326 String visitInvokeSuper(HInvokeSuper invoke) { | 326 String visitInvokeSuper(HInvokeSuper invoke) { |
327 String target = invoke.element.name; | 327 String target = invoke.element.name; |
328 return handleGenericInvoke("InvokeSuper", target, invoke.inputs); | 328 return handleGenericInvoke("InvokeSuper", target, invoke.inputs); |
329 } | 329 } |
330 | 330 |
331 String visitInvokeConstructorBody(HInvokeConstructorBody invoke) { | 331 String visitInvokeConstructorBody(HInvokeConstructorBody invoke) { |
332 String target = invoke.element.name; | 332 String target = invoke.element.name; |
333 return handleGenericInvoke("InvokeConstructorBody", target, invoke.inputs); | 333 return handleGenericInvoke("InvokeConstructorBody", target, invoke.inputs); |
334 } | 334 } |
335 | 335 |
336 String visitForeignCode(HForeignCode foreign) { | 336 String visitForeignCode(HForeignCode foreign) { |
337 return handleGenericInvoke("ForeignCode", "${foreign.codeTemplate.ast}", | 337 return handleGenericInvoke( |
338 foreign.inputs); | 338 "ForeignCode", "${foreign.codeTemplate.ast}", foreign.inputs); |
339 } | 339 } |
340 | 340 |
341 String visitForeignNew(HForeignNew node) { | 341 String visitForeignNew(HForeignNew node) { |
342 return handleGenericInvoke("ForeignNew", | 342 return handleGenericInvoke( |
343 "${node.element.name}", | 343 "ForeignNew", "${node.element.name}", node.inputs); |
344 node.inputs); | |
345 } | 344 } |
346 | 345 |
347 String visitLess(HLess node) => handleInvokeBinary(node, 'Less'); | 346 String visitLess(HLess node) => handleInvokeBinary(node, 'Less'); |
348 String visitLessEqual(HLessEqual node) => | 347 String visitLessEqual(HLessEqual node) => |
349 handleInvokeBinary(node, 'LessEqual'); | 348 handleInvokeBinary(node, 'LessEqual'); |
350 | 349 |
351 String visitLiteralList(HLiteralList node) { | 350 String visitLiteralList(HLiteralList node) { |
352 StringBuffer elementsString = new StringBuffer(); | 351 StringBuffer elementsString = new StringBuffer(); |
353 for (int i = 0; i < node.inputs.length; i++) { | 352 for (int i = 0; i < node.inputs.length; i++) { |
354 if (i != 0) elementsString.write(", "); | 353 if (i != 0) elementsString.write(", "); |
355 elementsString.write(temporaryId(node.inputs[i])); | 354 elementsString.write(temporaryId(node.inputs[i])); |
356 } | 355 } |
357 return "LiteralList: [$elementsString]"; | 356 return "LiteralList: [$elementsString]"; |
358 } | 357 } |
359 | 358 |
360 String visitLoopBranch(HLoopBranch branch) { | 359 String visitLoopBranch(HLoopBranch branch) { |
361 HBasicBlock bodyBlock = currentBlock.successors[0]; | 360 HBasicBlock bodyBlock = currentBlock.successors[0]; |
362 HBasicBlock exitBlock = currentBlock.successors[1]; | 361 HBasicBlock exitBlock = currentBlock.successors[1]; |
363 String conditionId = temporaryId(branch.inputs[0]); | 362 String conditionId = temporaryId(branch.inputs[0]); |
364 return | 363 return "LoopBranch ($conditionId): (B${bodyBlock.id}) then (B${exitBlock.id}
)"; |
365 "LoopBranch ($conditionId): (B${bodyBlock.id}) then (B${exitBlock.id})"; | |
366 } | 364 } |
367 | 365 |
368 String visitMultiply(HMultiply node) => handleInvokeBinary(node, 'Multiply'); | 366 String visitMultiply(HMultiply node) => handleInvokeBinary(node, 'Multiply'); |
369 | 367 |
370 String visitNegate(HNegate node) { | 368 String visitNegate(HNegate node) { |
371 String operand = temporaryId(node.operand); | 369 String operand = temporaryId(node.operand); |
372 return "Negate: $operand"; | 370 return "Negate: $operand"; |
373 } | 371 } |
374 | 372 |
375 String visitNot(HNot node) => "Not: ${temporaryId(node.inputs[0])}"; | 373 String visitNot(HNot node) => "Not: ${temporaryId(node.inputs[0])}"; |
(...skipping 20 matching lines...) Expand all Loading... |
396 return 'Ref: ${temporaryId(node.value)}'; | 394 return 'Ref: ${temporaryId(node.value)}'; |
397 } | 395 } |
398 | 396 |
399 String visitReturn(HReturn node) => "Return: ${temporaryId(node.inputs[0])}"; | 397 String visitReturn(HReturn node) => "Return: ${temporaryId(node.inputs[0])}"; |
400 | 398 |
401 String visitShiftLeft(HShiftLeft node) => | 399 String visitShiftLeft(HShiftLeft node) => |
402 handleInvokeBinary(node, 'ShiftLeft'); | 400 handleInvokeBinary(node, 'ShiftLeft'); |
403 String visitShiftRight(HShiftRight node) => | 401 String visitShiftRight(HShiftRight node) => |
404 handleInvokeBinary(node, 'ShiftRight'); | 402 handleInvokeBinary(node, 'ShiftRight'); |
405 | 403 |
406 String visitStatic(HStatic node) | 404 String visitStatic(HStatic node) => "Static: ${node.element.name}"; |
407 => "Static: ${node.element.name}"; | |
408 | 405 |
409 String visitLazyStatic(HLazyStatic node) | 406 String visitLazyStatic(HLazyStatic node) => |
410 => "LazyStatic: ${node.element.name}"; | 407 "LazyStatic: ${node.element.name}"; |
411 | 408 |
412 String visitOneShotInterceptor(HOneShotInterceptor node) | 409 String visitOneShotInterceptor(HOneShotInterceptor node) => |
413 => handleInvokeDynamic(node, "OneShotInterceptor"); | 410 handleInvokeDynamic(node, "OneShotInterceptor"); |
414 | 411 |
415 String visitStaticStore(HStaticStore node) { | 412 String visitStaticStore(HStaticStore node) { |
416 String lhs = node.element.name; | 413 String lhs = node.element.name; |
417 return "StaticStore: $lhs = ${temporaryId(node.inputs[0])}"; | 414 return "StaticStore: $lhs = ${temporaryId(node.inputs[0])}"; |
418 } | 415 } |
419 | 416 |
420 String visitStringConcat(HStringConcat node) { | 417 String visitStringConcat(HStringConcat node) { |
421 var leftId = temporaryId(node.left); | 418 var leftId = temporaryId(node.left); |
422 var rightId = temporaryId(node.right); | 419 var rightId = temporaryId(node.right); |
423 return "StringConcat: $leftId + $rightId"; | 420 return "StringConcat: $leftId + $rightId"; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
483 return "Is: ${temporaryId(node.expression)} is $type"; | 480 return "Is: ${temporaryId(node.expression)} is $type"; |
484 } | 481 } |
485 | 482 |
486 String visitIsViaInterceptor(HIsViaInterceptor node) { | 483 String visitIsViaInterceptor(HIsViaInterceptor node) { |
487 String type = node.typeExpression.toString(); | 484 String type = node.typeExpression.toString(); |
488 return "IsViaInterceptor: ${temporaryId(node.inputs[0])} is $type"; | 485 return "IsViaInterceptor: ${temporaryId(node.inputs[0])} is $type"; |
489 } | 486 } |
490 | 487 |
491 String visitTypeConversion(HTypeConversion node) { | 488 String visitTypeConversion(HTypeConversion node) { |
492 assert(node.inputs.length <= 2); | 489 assert(node.inputs.length <= 2); |
493 String otherInput = (node.inputs.length == 2) | 490 String otherInput = |
494 ? temporaryId(node.inputs[1]) | 491 (node.inputs.length == 2) ? temporaryId(node.inputs[1]) : ''; |
495 : ''; | |
496 return "TypeConversion: ${temporaryId(node.checkedInput)} to " | 492 return "TypeConversion: ${temporaryId(node.checkedInput)} to " |
497 "${node.instructionType} $otherInput"; | 493 "${node.instructionType} $otherInput"; |
498 } | 494 } |
499 | 495 |
500 String visitTypeKnown(HTypeKnown node) { | 496 String visitTypeKnown(HTypeKnown node) { |
501 assert(node.inputs.length <= 2); | 497 assert(node.inputs.length <= 2); |
502 String result = | 498 String result = |
503 "TypeKnown: ${temporaryId(node.checkedInput)} is ${node.knownType}"; | 499 "TypeKnown: ${temporaryId(node.checkedInput)} is ${node.knownType}"; |
504 if (node.witness != null) { | 500 if (node.witness != null) { |
505 result += " witnessed by ${temporaryId(node.witness)}"; | 501 result += " witnessed by ${temporaryId(node.witness)}"; |
506 } | 502 } |
507 return result; | 503 return result; |
(...skipping 24 matching lines...) Expand all Loading... |
532 } | 528 } |
533 | 529 |
534 String visitAwait(HAwait node) { | 530 String visitAwait(HAwait node) { |
535 return "Await: ${temporaryId(node.inputs[0])}"; | 531 return "Await: ${temporaryId(node.inputs[0])}"; |
536 } | 532 } |
537 | 533 |
538 String visitYield(HYield node) { | 534 String visitYield(HYield node) { |
539 return "Yield${node.hasStar ? "*" : ""}: ${temporaryId(node.inputs[0])}"; | 535 return "Yield${node.hasStar ? "*" : ""}: ${temporaryId(node.inputs[0])}"; |
540 } | 536 } |
541 } | 537 } |
OLD | NEW |