| Index: pkg/compiler/lib/src/ssa/ssa_tracer.dart
|
| diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
|
| deleted file mode 100644
|
| index 09d8069766eaba9cb227e1f1ae82953d0d1c6031..0000000000000000000000000000000000000000
|
| --- a/pkg/compiler/lib/src/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";
|
| - }
|
| -}
|
|
|