Index: sdk/lib/_internal/compiler/implementation/ssa/ssa_tracer.dart |
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/ssa_tracer.dart b/sdk/lib/_internal/compiler/implementation/ssa/ssa_tracer.dart |
deleted file mode 100644 |
index 09d8069766eaba9cb227e1f1ae82953d0d1c6031..0000000000000000000000000000000000000000 |
--- a/sdk/lib/_internal/compiler/implementation/ssa/ssa_tracer.dart |
+++ /dev/null |
@@ -1,522 +0,0 @@ |
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-library ssa.tracer; |
- |
-import 'dart:async' show EventSink; |
- |
-import 'ssa.dart'; |
-import '../js_backend/js_backend.dart'; |
-import '../dart2jslib.dart'; |
-import '../tracer.dart'; |
- |
-/** |
- * Outputs SSA code in a format readable by Hydra IR. |
- * Tracing is disabled by default, see ../tracer.dart for how |
- * to enable it. |
- */ |
-class HTracer extends HGraphVisitor with TracerUtil { |
- Compiler compiler; |
- JavaScriptItemCompilationContext context; |
- final EventSink<String> output; |
- |
- HTracer(this.output, this.compiler, this.context); |
- |
- void traceGraph(String name, HGraph graph) { |
- DEBUG_MODE = true; |
- tag("cfg", () { |
- printProperty("name", name); |
- visitDominatorTree(graph); |
- }); |
- } |
- |
- void addPredecessors(HBasicBlock block) { |
- if (block.predecessors.isEmpty) { |
- printEmptyProperty("predecessors"); |
- } else { |
- addIndent(); |
- add("predecessors"); |
- for (HBasicBlock predecessor in block.predecessors) { |
- add(' "B${predecessor.id}"'); |
- } |
- add("\n"); |
- } |
- } |
- |
- void addSuccessors(HBasicBlock block) { |
- if (block.successors.isEmpty) { |
- printEmptyProperty("successors"); |
- } else { |
- addIndent(); |
- add("successors"); |
- for (HBasicBlock successor in block.successors) { |
- add(' "B${successor.id}"'); |
- } |
- add("\n"); |
- } |
- } |
- |
- void addInstructions(HInstructionStringifier stringifier, |
- HInstructionList list) { |
- for (HInstruction instruction = list.first; |
- instruction != null; |
- instruction = instruction.next) { |
- int bci = 0; |
- int uses = instruction.usedBy.length; |
- String changes = instruction.sideEffects.hasSideEffects() ? '!' : ' '; |
- String depends = instruction.sideEffects.dependsOnSomething() ? '?' : ''; |
- addIndent(); |
- String temporaryId = stringifier.temporaryId(instruction); |
- String instructionString = stringifier.visit(instruction); |
- add("$bci $uses $temporaryId $instructionString $changes $depends <|@\n"); |
- } |
- } |
- |
- void visitBasicBlock(HBasicBlock block) { |
- HInstructionStringifier stringifier = |
- new HInstructionStringifier(context, block, compiler); |
- assert(block.id != null); |
- tag("block", () { |
- printProperty("name", "B${block.id}"); |
- printProperty("from_bci", -1); |
- printProperty("to_bci", -1); |
- addPredecessors(block); |
- addSuccessors(block); |
- printEmptyProperty("xhandlers"); |
- printEmptyProperty("flags"); |
- if (block.dominator != null) { |
- printProperty("dominator", "B${block.dominator.id}"); |
- } |
- tag("states", () { |
- tag("locals", () { |
- printProperty("size", 0); |
- printProperty("method", "None"); |
- block.forEachPhi((phi) { |
- String phiId = stringifier.temporaryId(phi); |
- StringBuffer inputIds = new StringBuffer(); |
- for (int i = 0; i < phi.inputs.length; i++) { |
- inputIds.write(stringifier.temporaryId(phi.inputs[i])); |
- inputIds.write(" "); |
- } |
- println("${phi.id} $phiId [ $inputIds]"); |
- }); |
- }); |
- }); |
- tag("HIR", () { |
- addInstructions(stringifier, block.phis); |
- addInstructions(stringifier, block); |
- }); |
- }); |
- } |
-} |
- |
-class HInstructionStringifier implements HVisitor<String> { |
- final Compiler compiler; |
- final JavaScriptItemCompilationContext context; |
- final HBasicBlock currentBlock; |
- |
- HInstructionStringifier(this.context, this.currentBlock, this.compiler); |
- |
- visit(HInstruction node) => '${node.accept(this)} ${node.instructionType}'; |
- |
- String temporaryId(HInstruction instruction) { |
- String prefix; |
- if (instruction.isNull()) { |
- prefix = 'u'; |
- } else if (instruction.isConflicting()) { |
- prefix = 'c'; |
- } else if (instruction.isExtendableArray(compiler)) { |
- prefix = 'e'; |
- } else if (instruction.isFixedArray(compiler)) { |
- prefix = 'f'; |
- } else if (instruction.isMutableArray(compiler)) { |
- prefix = 'm'; |
- } else if (instruction.isReadableArray(compiler)) { |
- prefix = 'a'; |
- } else if (instruction.isString(compiler)) { |
- prefix = 's'; |
- } else if (instruction.isIndexablePrimitive(compiler)) { |
- prefix = 'r'; |
- } else if (instruction.isBoolean(compiler)) { |
- prefix = 'b'; |
- } else if (instruction.isInteger(compiler)) { |
- prefix = 'i'; |
- } else if (instruction.isDouble(compiler)) { |
- prefix = 'd'; |
- } else if (instruction.isNumber(compiler)) { |
- prefix = 'n'; |
- } else if (instruction.instructionType.containsAll(compiler.world)) { |
- prefix = 'v'; |
- } else { |
- prefix = 'U'; |
- } |
- return "$prefix${instruction.id}"; |
- } |
- |
- String visitBoolify(HBoolify node) { |
- return "Boolify: ${temporaryId(node.inputs[0])}"; |
- } |
- |
- String handleInvokeBinary(HInvokeBinary node, String op) { |
- String left = temporaryId(node.left); |
- String right= temporaryId(node.right); |
- return '$left $op $right'; |
- } |
- |
- String visitAdd(HAdd node) => handleInvokeBinary(node, '+'); |
- |
- String visitBitAnd(HBitAnd node) => handleInvokeBinary(node, '&'); |
- |
- String visitBitNot(HBitNot node) { |
- String operand = temporaryId(node.operand); |
- return "~$operand"; |
- } |
- |
- String visitBitOr(HBitOr node) => handleInvokeBinary(node, '|'); |
- |
- String visitBitXor(HBitXor node) => handleInvokeBinary(node, '^'); |
- |
- String visitBoundsCheck(HBoundsCheck node) { |
- String lengthId = temporaryId(node.length); |
- String indexId = temporaryId(node.index); |
- return "Bounds check: length = $lengthId, index = $indexId"; |
- } |
- |
- String visitBreak(HBreak node) { |
- HBasicBlock target = currentBlock.successors[0]; |
- if (node.label != null) { |
- return "Break ${node.label.labelName}: (B${target.id})"; |
- } |
- return "Break: (B${target.id})"; |
- } |
- |
- String visitConstant(HConstant constant) => "Constant ${constant.constant}"; |
- |
- String visitContinue(HContinue node) { |
- HBasicBlock target = currentBlock.successors[0]; |
- if (node.label != null) { |
- return "Continue ${node.label.labelName}: (B${target.id})"; |
- } |
- return "Continue: (B${target.id})"; |
- } |
- |
- String visitDivide(HDivide node) => handleInvokeBinary(node, '/'); |
- |
- String visitExit(HExit node) => "exit"; |
- |
- String visitFieldGet(HFieldGet node) { |
- if (node.isNullCheck) { |
- return 'null check on ${temporaryId(node.receiver)}'; |
- } |
- String fieldName = node.element.name; |
- return 'field get ${temporaryId(node.receiver)}.$fieldName'; |
- } |
- |
- String visitFieldSet(HFieldSet node) { |
- String valueId = temporaryId(node.value); |
- String fieldName = node.element.name; |
- return 'field set ${temporaryId(node.receiver)}.$fieldName to $valueId'; |
- } |
- |
- String visitReadModifyWrite(HReadModifyWrite node) { |
- String fieldName = node.element.name; |
- String receiverId = temporaryId(node.receiver); |
- String op = node.jsOp; |
- if (node.isAssignOp) { |
- String valueId = temporaryId(node.value); |
- return 'field-update $receiverId.$fieldName $op= $valueId'; |
- } else if (node.isPreOp) { |
- return 'field-update $op$receiverId.$fieldName'; |
- } else { |
- return 'field-update $receiverId.$fieldName$op'; |
- } |
- } |
- |
- String visitLocalGet(HLocalGet node) { |
- String localName = node.variable.name; |
- return 'local get ${temporaryId(node.local)}.$localName'; |
- } |
- |
- String visitLocalSet(HLocalSet node) { |
- String valueId = temporaryId(node.value); |
- String localName = node.variable.name; |
- return 'local set ${temporaryId(node.local)}.$localName to $valueId'; |
- } |
- |
- String visitGoto(HGoto node) { |
- HBasicBlock target = currentBlock.successors[0]; |
- return "Goto: (B${target.id})"; |
- } |
- |
- String visitGreater(HGreater node) => handleInvokeBinary(node, '>'); |
- String visitGreaterEqual(HGreaterEqual node) { |
- return handleInvokeBinary(node, '>='); |
- } |
- String visitIdentity(HIdentity node) => handleInvokeBinary(node, '==='); |
- |
- String visitIf(HIf node) { |
- HBasicBlock thenBlock = currentBlock.successors[0]; |
- HBasicBlock elseBlock = currentBlock.successors[1]; |
- String conditionId = temporaryId(node.inputs[0]); |
- return "If ($conditionId): (B${thenBlock.id}) else (B${elseBlock.id})"; |
- } |
- |
- String visitGenericInvoke(String invokeType, String functionName, |
- List<HInstruction> arguments) { |
- StringBuffer argumentsString = new StringBuffer(); |
- for (int i = 0; i < arguments.length; i++) { |
- if (i != 0) argumentsString.write(", "); |
- argumentsString.write(temporaryId(arguments[i])); |
- } |
- return "$invokeType: $functionName($argumentsString)"; |
- } |
- |
- String visitIndex(HIndex node) { |
- String receiver = temporaryId(node.receiver); |
- String index = temporaryId(node.index); |
- return "Index: $receiver[$index]"; |
- } |
- |
- String visitIndexAssign(HIndexAssign node) { |
- String receiver = temporaryId(node.receiver); |
- String index = temporaryId(node.index); |
- String value = temporaryId(node.value); |
- return "IndexAssign: $receiver[$index] = $value"; |
- } |
- |
- String visitInterceptor(HInterceptor node) { |
- String value = temporaryId(node.inputs[0]); |
- if (node.interceptedClasses != null) { |
- JavaScriptBackend backend = compiler.backend; |
- String cls = backend.namer.getInterceptorSuffix(node.interceptedClasses); |
- return "Intercept ($cls): $value"; |
- } |
- return "Intercept: $value"; |
- } |
- |
- String visitInvokeClosure(HInvokeClosure node) |
- => visitInvokeDynamic(node, "closure"); |
- |
- String visitInvokeDynamic(HInvokeDynamic invoke, String kind) { |
- String receiver = temporaryId(invoke.receiver); |
- String name = invoke.selector.name; |
- String target = "($kind) $receiver.$name"; |
- int offset = HInvoke.ARGUMENTS_OFFSET; |
- List arguments = invoke.inputs.sublist(offset); |
- return visitGenericInvoke("Invoke", target, arguments) + |
- "(${invoke.selector.mask})"; |
- } |
- |
- String visitInvokeDynamicMethod(HInvokeDynamicMethod node) |
- => visitInvokeDynamic(node, "method"); |
- String visitInvokeDynamicGetter(HInvokeDynamicGetter node) |
- => visitInvokeDynamic(node, "get"); |
- String visitInvokeDynamicSetter(HInvokeDynamicSetter node) |
- => visitInvokeDynamic(node, "set"); |
- |
- String visitInvokeStatic(HInvokeStatic invoke) { |
- String target = invoke.element.name; |
- return visitGenericInvoke("Invoke", target, invoke.inputs); |
- } |
- |
- String visitInvokeSuper(HInvokeSuper invoke) { |
- String target = invoke.element.name; |
- return visitGenericInvoke("Invoke super", target, invoke.inputs); |
- } |
- |
- String visitInvokeConstructorBody(HInvokeConstructorBody invoke) { |
- String target = invoke.element.name; |
- return visitGenericInvoke("Invoke constructor body", target, invoke.inputs); |
- } |
- |
- String visitForeign(HForeign foreign) { |
- return visitGenericInvoke("Foreign", "${foreign.codeTemplate.ast}", foreign.inputs); |
- } |
- |
- String visitForeignNew(HForeignNew node) { |
- return visitGenericInvoke("New", |
- "${node.element.name}", |
- node.inputs); |
- } |
- |
- String visitLess(HLess node) => handleInvokeBinary(node, '<'); |
- String visitLessEqual(HLessEqual node) => handleInvokeBinary(node, '<='); |
- |
- String visitLiteralList(HLiteralList node) { |
- StringBuffer elementsString = new StringBuffer(); |
- for (int i = 0; i < node.inputs.length; i++) { |
- if (i != 0) elementsString.write(", "); |
- elementsString.write(temporaryId(node.inputs[i])); |
- } |
- return "Literal list: [$elementsString]"; |
- } |
- |
- String visitLoopBranch(HLoopBranch branch) { |
- HBasicBlock bodyBlock = currentBlock.successors[0]; |
- HBasicBlock exitBlock = currentBlock.successors[1]; |
- String conditionId = temporaryId(branch.inputs[0]); |
- return "While ($conditionId): (B${bodyBlock.id}) then (B${exitBlock.id})"; |
- } |
- |
- String visitMultiply(HMultiply node) => handleInvokeBinary(node, '*'); |
- |
- String visitNegate(HNegate node) { |
- String operand = temporaryId(node.operand); |
- return "-$operand"; |
- } |
- |
- String visitNot(HNot node) => "Not: ${temporaryId(node.inputs[0])}"; |
- |
- String visitParameterValue(HParameterValue node) { |
- return "p${node.sourceElement.name}"; |
- } |
- |
- String visitLocalValue(HLocalValue node) { |
- return "l${node.sourceElement.name}"; |
- } |
- |
- String visitPhi(HPhi phi) { |
- StringBuffer buffer = new StringBuffer(); |
- buffer.write("Phi("); |
- for (int i = 0; i < phi.inputs.length; i++) { |
- if (i > 0) buffer.write(", "); |
- buffer.write(temporaryId(phi.inputs[i])); |
- } |
- buffer.write(")"); |
- return buffer.toString(); |
- } |
- |
- String visitReturn(HReturn node) => "Return ${temporaryId(node.inputs[0])}"; |
- |
- String visitShiftLeft(HShiftLeft node) => handleInvokeBinary(node, '<<'); |
- String visitShiftRight(HShiftRight node) => handleInvokeBinary(node, '>>'); |
- |
- String visitStatic(HStatic node) |
- => "Static ${node.element.name}"; |
- |
- String visitLazyStatic(HLazyStatic node) |
- => "LazyStatic ${node.element.name}"; |
- |
- String visitOneShotInterceptor(HOneShotInterceptor node) |
- => visitInvokeDynamic(node, "one shot interceptor"); |
- |
- String visitStaticStore(HStaticStore node) { |
- String lhs = node.element.name; |
- return "Static $lhs = ${temporaryId(node.inputs[0])}"; |
- } |
- |
- String visitStringConcat(HStringConcat node) { |
- var leftId = temporaryId(node.left); |
- var rightId = temporaryId(node.right); |
- return "StringConcat: $leftId + $rightId"; |
- } |
- |
- String visitStringify(HStringify node) { |
- return "Stringify ${temporaryId(node.inputs[0])}"; |
- } |
- |
- String visitSubtract(HSubtract node) => handleInvokeBinary(node, '-'); |
- |
- String visitSwitch(HSwitch node) { |
- StringBuffer buf = new StringBuffer(); |
- buf.write("Switch: ("); |
- buf.write(temporaryId(node.inputs[0])); |
- buf.write(") "); |
- for (int i = 1; i < node.inputs.length; i++) { |
- buf.write(temporaryId(node.inputs[i])); |
- buf.write(": B"); |
- buf.write(node.block.successors[i - 1].id); |
- buf.write(", "); |
- } |
- buf.write("default: B"); |
- buf.write(node.defaultTarget.id); |
- return buf.toString(); |
- } |
- |
- String visitThis(HThis node) => "this"; |
- |
- String visitThrow(HThrow node) => "Throw ${temporaryId(node.inputs[0])}"; |
- |
- String visitThrowExpression(HThrowExpression node) { |
- return "ThrowExpression ${temporaryId(node.inputs[0])}"; |
- } |
- |
- String visitTruncatingDivide(HTruncatingDivide node) { |
- return handleInvokeBinary(node, '~/'); |
- } |
- |
- String visitExitTry(HExitTry node) { |
- return "Exit try"; |
- } |
- |
- String visitTry(HTry node) { |
- List<HBasicBlock> successors = currentBlock.successors; |
- String tryBlock = 'B${successors[0].id}'; |
- String catchBlock = 'none'; |
- if (node.catchBlock != null) { |
- catchBlock = 'B${successors[1].id}'; |
- } |
- |
- String finallyBlock = 'none'; |
- if (node.finallyBlock != null) { |
- finallyBlock = 'B${node.finallyBlock.id}'; |
- } |
- |
- return "Try: $tryBlock, Catch: $catchBlock, Finally: $finallyBlock, " |
- "Join: B${successors.last.id}"; |
- } |
- |
- String visitIs(HIs node) { |
- String type = node.typeExpression.toString(); |
- return "TypeTest: ${temporaryId(node.expression)} is $type"; |
- } |
- |
- String visitIsViaInterceptor(HIsViaInterceptor node) { |
- String type = node.typeExpression.toString(); |
- return "TypeTest: ${temporaryId(node.inputs[0])} is $type"; |
- } |
- |
- String visitTypeConversion(HTypeConversion node) { |
- assert(node.inputs.length <= 2); |
- String otherInput = (node.inputs.length == 2) |
- ? temporaryId(node.inputs[1]) |
- : ''; |
- return "TypeConversion: ${temporaryId(node.checkedInput)} to " |
- "${node.instructionType} $otherInput"; |
- } |
- |
- String visitTypeKnown(HTypeKnown node) { |
- assert(node.inputs.length <= 2); |
- String result = |
- "TypeKnown: ${temporaryId(node.checkedInput)} is ${node.knownType}"; |
- if (node.witness != null) { |
- result += " witnessed by ${temporaryId(node.witness)}"; |
- } |
- return result; |
- } |
- |
- String visitRangeConversion(HRangeConversion node) { |
- return "RangeConversion: ${node.checkedInput}"; |
- } |
- |
- String visitReadTypeVariable(HReadTypeVariable node) { |
- return "ReadTypeVariable: ${node.dartType} ${node.hasReceiver}"; |
- } |
- |
- String visitFunctionType(HFunctionType node) { |
- return "FunctionType: ${node.dartType}"; |
- } |
- |
- String visitVoidType(HVoidType node) { |
- return "VoidType"; |
- } |
- |
- String visitInterfaceType(HInterfaceType node) { |
- return "InterfaceType: ${node.dartType}"; |
- } |
- |
- String visitDynamicType(HDynamicType node) { |
- return "DynamicType"; |
- } |
-} |