| 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 tracer; | 5 library tracer; |
| 6 | 6 |
| 7 import 'dart:async' show EventSink; | 7 import 'dart:async' show EventSink; |
| 8 | 8 |
| 9 import 'ssa.dart'; | 9 import 'ssa.dart'; |
| 10 import '../js_backend/js_backend.dart'; | 10 import '../js_backend/js_backend.dart'; |
| 11 import '../dart2jslib.dart'; | 11 import '../dart2jslib.dart'; |
| 12 | 12 |
| 13 const bool GENERATE_SSA_TRACE = false; | 13 const bool GENERATE_SSA_TRACE = false; |
| 14 const String SSA_TRACE_FILTER = null; | 14 const String SSA_TRACE_FILTER = null; |
| 15 | 15 |
| 16 class HTracer extends HGraphVisitor implements Tracer { | 16 class HTracer extends HGraphVisitor implements Tracer { |
| 17 Compiler compiler; |
| 17 JavaScriptItemCompilationContext context; | 18 JavaScriptItemCompilationContext context; |
| 18 int indent = 0; | 19 int indent = 0; |
| 19 final EventSink<String> output; | 20 final EventSink<String> output; |
| 20 final bool enabled = GENERATE_SSA_TRACE; | 21 final bool enabled = GENERATE_SSA_TRACE; |
| 21 bool traceActive = false; | 22 bool traceActive = false; |
| 22 | 23 |
| 23 HTracer(this.output); | 24 HTracer(this.output); |
| 24 | 25 |
| 25 void close() { | 26 void close() { |
| 26 if (enabled) output.close(); | 27 if (enabled) output.close(); |
| 27 } | 28 } |
| 28 | 29 |
| 29 void traceCompilation(String methodName, | 30 void traceCompilation(String methodName, |
| 30 JavaScriptItemCompilationContext compilationContext) { | 31 JavaScriptItemCompilationContext compilationContext, |
| 32 Compiler compiler) { |
| 31 if (!enabled) return; | 33 if (!enabled) return; |
| 32 this.context = compilationContext; | 34 this.context = compilationContext; |
| 35 this.compiler = compiler; |
| 33 traceActive = | 36 traceActive = |
| 34 SSA_TRACE_FILTER == null || methodName.contains(SSA_TRACE_FILTER); | 37 SSA_TRACE_FILTER == null || methodName.contains(SSA_TRACE_FILTER); |
| 35 if (!traceActive) return; | 38 if (!traceActive) return; |
| 36 tag("compilation", () { | 39 tag("compilation", () { |
| 37 printProperty("name", methodName); | 40 printProperty("name", methodName); |
| 38 printProperty("method", methodName); | 41 printProperty("method", methodName); |
| 39 printProperty("date", new DateTime.now().millisecondsSinceEpoch); | 42 printProperty("date", new DateTime.now().millisecondsSinceEpoch); |
| 40 }); | 43 }); |
| 41 } | 44 } |
| 42 | 45 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 String depends = instruction.sideEffects.dependsOnSomething() ? '?' : ''; | 88 String depends = instruction.sideEffects.dependsOnSomething() ? '?' : ''; |
| 86 addIndent(); | 89 addIndent(); |
| 87 String temporaryId = stringifier.temporaryId(instruction); | 90 String temporaryId = stringifier.temporaryId(instruction); |
| 88 String instructionString = stringifier.visit(instruction); | 91 String instructionString = stringifier.visit(instruction); |
| 89 add("$bci $uses $temporaryId $instructionString $changes $depends <|@\n"); | 92 add("$bci $uses $temporaryId $instructionString $changes $depends <|@\n"); |
| 90 } | 93 } |
| 91 } | 94 } |
| 92 | 95 |
| 93 void visitBasicBlock(HBasicBlock block) { | 96 void visitBasicBlock(HBasicBlock block) { |
| 94 HInstructionStringifier stringifier = | 97 HInstructionStringifier stringifier = |
| 95 new HInstructionStringifier(context, block); | 98 new HInstructionStringifier(context, block, compiler); |
| 96 assert(block.id != null); | 99 assert(block.id != null); |
| 97 tag("block", () { | 100 tag("block", () { |
| 98 printProperty("name", "B${block.id}"); | 101 printProperty("name", "B${block.id}"); |
| 99 printProperty("from_bci", -1); | 102 printProperty("from_bci", -1); |
| 100 printProperty("to_bci", -1); | 103 printProperty("to_bci", -1); |
| 101 addPredecessors(block); | 104 addPredecessors(block); |
| 102 addSuccessors(block); | 105 addSuccessors(block); |
| 103 printEmptyProperty("xhandlers"); | 106 printEmptyProperty("xhandlers"); |
| 104 printEmptyProperty("flags"); | 107 printEmptyProperty("flags"); |
| 105 if (block.dominator != null) { | 108 if (block.dominator != null) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 } | 161 } |
| 159 | 162 |
| 160 void addIndent() { | 163 void addIndent() { |
| 161 for (int i = 0; i < indent; i++) { | 164 for (int i = 0; i < indent; i++) { |
| 162 add(" "); | 165 add(" "); |
| 163 } | 166 } |
| 164 } | 167 } |
| 165 } | 168 } |
| 166 | 169 |
| 167 class HInstructionStringifier implements HVisitor<String> { | 170 class HInstructionStringifier implements HVisitor<String> { |
| 168 JavaScriptItemCompilationContext context; | 171 final Compiler compiler; |
| 169 HBasicBlock currentBlock; | 172 final JavaScriptItemCompilationContext context; |
| 173 final HBasicBlock currentBlock; |
| 170 | 174 |
| 171 HInstructionStringifier(this.context, this.currentBlock); | 175 HInstructionStringifier(this.context, this.currentBlock, this.compiler); |
| 172 | 176 |
| 173 visit(HInstruction node) => node.accept(this); | 177 visit(HInstruction node) => node.accept(this); |
| 174 | 178 |
| 175 String temporaryId(HInstruction instruction) { | 179 String temporaryId(HInstruction instruction) { |
| 176 String prefix; | 180 String prefix; |
| 177 HType type = instruction.instructionType; | 181 HType type = instruction.instructionType; |
| 178 if (type == HType.MUTABLE_ARRAY) { | 182 if (type.isMutableArray(compiler)) { |
| 179 prefix = 'm'; | 183 prefix = 'm'; |
| 180 } else if (type == HType.READABLE_ARRAY) { | 184 } else if (type.isReadableArray(compiler)) { |
| 181 prefix = 'a'; | 185 prefix = 'a'; |
| 182 } else if (type == HType.EXTENDABLE_ARRAY) { | 186 } else if (type.isExtendableArray(compiler)) { |
| 183 prefix = 'e'; | 187 prefix = 'e'; |
| 184 } else if (type == HType.BOOLEAN) { | 188 } else if (type == HType.BOOLEAN) { |
| 185 prefix = 'b'; | 189 prefix = 'b'; |
| 186 } else if (type == HType.INTEGER) { | 190 } else if (type == HType.INTEGER) { |
| 187 prefix = 'i'; | 191 prefix = 'i'; |
| 188 } else if (type == HType.DOUBLE) { | 192 } else if (type == HType.DOUBLE) { |
| 189 prefix = 'd'; | 193 prefix = 'd'; |
| 190 } else if (type == HType.NUMBER) { | 194 } else if (type == HType.NUMBER) { |
| 191 prefix = 'n'; | 195 prefix = 'n'; |
| 192 } else if (type == HType.STRING) { | 196 } else if (type.isString(compiler)) { |
| 193 prefix = 's'; | 197 prefix = 's'; |
| 194 } else if (type == HType.UNKNOWN) { | 198 } else if (type == HType.UNKNOWN) { |
| 195 prefix = 'v'; | 199 prefix = 'v'; |
| 196 } else if (type == HType.CONFLICTING) { | 200 } else if (type == HType.CONFLICTING) { |
| 197 prefix = 'c'; | 201 prefix = 'c'; |
| 198 } else if (type == HType.INDEXABLE_PRIMITIVE) { | 202 } else if (type.isIndexable(compiler)) { |
| 199 prefix = 'r'; | 203 prefix = 'r'; |
| 200 } else if (type == HType.NULL) { | 204 } else if (type == HType.NULL) { |
| 201 prefix = 'u'; | 205 prefix = 'u'; |
| 202 } else { | 206 } else { |
| 203 prefix = 'U'; | 207 prefix = 'U'; |
| 204 } | 208 } |
| 205 return "$prefix${instruction.id}"; | 209 return "$prefix${instruction.id}"; |
| 206 } | 210 } |
| 207 | 211 |
| 208 String visitBailoutTarget(HBailoutTarget node) { | 212 String visitBailoutTarget(HBailoutTarget node) { |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 finallyBlock = 'B${node.finallyBlock.id}'; | 502 finallyBlock = 'B${node.finallyBlock.id}'; |
| 499 } | 503 } |
| 500 | 504 |
| 501 return "Try: $tryBlock, Catch: $catchBlock, Finally: $finallyBlock, " | 505 return "Try: $tryBlock, Catch: $catchBlock, Finally: $finallyBlock, " |
| 502 "Join: B${successors.last.id}"; | 506 "Join: B${successors.last.id}"; |
| 503 } | 507 } |
| 504 | 508 |
| 505 String visitTypeGuard(HTypeGuard node) { | 509 String visitTypeGuard(HTypeGuard node) { |
| 506 String type; | 510 String type; |
| 507 HType guardedType = node.guardedType; | 511 HType guardedType = node.guardedType; |
| 508 if (guardedType == HType.MUTABLE_ARRAY) { | 512 if (guardedType.isExtendableArray(compiler)) { |
| 513 type = "extendable_array"; |
| 514 } else if (guardedType.isMutableArray(compiler)) { |
| 509 type = "mutable_array"; | 515 type = "mutable_array"; |
| 510 } else if (guardedType == HType.READABLE_ARRAY) { | 516 } else if (guardedType.isReadableArray(compiler)) { |
| 511 type = "readable_array"; | 517 type = "readable_array"; |
| 512 } else if (guardedType == HType.EXTENDABLE_ARRAY) { | |
| 513 type = "extendable_array"; | |
| 514 } else if (guardedType == HType.BOOLEAN) { | 518 } else if (guardedType == HType.BOOLEAN) { |
| 515 type = "bool"; | 519 type = "bool"; |
| 516 } else if (guardedType == HType.INTEGER) { | 520 } else if (guardedType == HType.INTEGER) { |
| 517 type = "integer"; | 521 type = "integer"; |
| 518 } else if (guardedType == HType.DOUBLE) { | 522 } else if (guardedType == HType.DOUBLE) { |
| 519 type = "double"; | 523 type = "double"; |
| 520 } else if (guardedType == HType.NUMBER) { | 524 } else if (guardedType == HType.NUMBER) { |
| 521 type = "number"; | 525 type = "number"; |
| 522 } else if (guardedType == HType.STRING) { | 526 } else if (guardedType.isString(compiler)) { |
| 523 type = "string"; | 527 type = "string"; |
| 524 } else if (guardedType == HType.INDEXABLE_PRIMITIVE) { | 528 } else if (guardedType.isIndexable(compiler)) { |
| 525 type = "string_or_array"; | 529 type = "string_or_array"; |
| 526 } else if (guardedType == HType.UNKNOWN) { | 530 } else if (guardedType == HType.UNKNOWN) { |
| 527 type = 'unknown'; | 531 type = 'unknown'; |
| 528 } else { | 532 } else { |
| 529 throw new CompilerCancelledException('Unexpected type guard: $type'); | 533 throw new CompilerCancelledException('Unexpected type guard: $type'); |
| 530 } | 534 } |
| 531 HInstruction guarded = node.guarded; | 535 HInstruction guarded = node.guarded; |
| 532 HInstruction bailoutTarget = node.bailoutTarget; | 536 HInstruction bailoutTarget = node.bailoutTarget; |
| 533 StringBuffer envBuffer = new StringBuffer(); | 537 StringBuffer envBuffer = new StringBuffer(); |
| 534 List<HInstruction> inputs = node.inputs; | 538 List<HInstruction> inputs = node.inputs; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 556 ? temporaryId(node.inputs[1]) | 560 ? temporaryId(node.inputs[1]) |
| 557 : ''; | 561 : ''; |
| 558 return "TypeConversion: ${temporaryId(node.checkedInput)} to " | 562 return "TypeConversion: ${temporaryId(node.checkedInput)} to " |
| 559 "${node.instructionType} $otherInput"; | 563 "${node.instructionType} $otherInput"; |
| 560 } | 564 } |
| 561 | 565 |
| 562 String visitRangeConversion(HRangeConversion node) { | 566 String visitRangeConversion(HRangeConversion node) { |
| 563 return "RangeConversion: ${node.checkedInput}"; | 567 return "RangeConversion: ${node.checkedInput}"; |
| 564 } | 568 } |
| 565 } | 569 } |
| OLD | NEW |