| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file | |
| 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.md file. | |
| 4 | |
| 5 part of fletch.debug_state; | |
| 6 | |
| 7 class BackTraceFrame { | |
| 8 final FletchFunction function; | |
| 9 final int bytecodePointer; | |
| 10 final IncrementalCompiler compiler; | |
| 11 final DebugState debugState; | |
| 12 | |
| 13 BackTraceFrame(this.function, this.bytecodePointer, this.compiler, | |
| 14 this.debugState); | |
| 15 | |
| 16 bool get inPlatformLibrary => function.element.library.isPlatformLibrary; | |
| 17 | |
| 18 bool get isInternal => function.isInternal || inPlatformLibrary; | |
| 19 | |
| 20 String invokeString(Bytecode bytecode) { | |
| 21 if (bytecode is InvokeMethod) { | |
| 22 String name = | |
| 23 compiler.lookupFunctionNameBySelector(bytecode.uint32Argument0); | |
| 24 return ' ($name)'; | |
| 25 } | |
| 26 return ''; | |
| 27 } | |
| 28 | |
| 29 bool get isVisible => debugState.showInternalFrames || !isInternal; | |
| 30 | |
| 31 DebugInfo get debugInfo => debugState.getDebugInfo(function); | |
| 32 | |
| 33 String list(SessionState state, {int contextLines: 5}) { | |
| 34 return debugInfo.sourceListStringFor( | |
| 35 bytecodePointer - 1, state, contextLines: contextLines); | |
| 36 } | |
| 37 | |
| 38 String disasm() { | |
| 39 StringBuffer buffer = new StringBuffer(); | |
| 40 var bytecodes = function.bytecodes; | |
| 41 var offset = 0; | |
| 42 for (var bytecode in bytecodes) offset += bytecode.size; | |
| 43 int offsetLength = '$offset'.length; | |
| 44 offset = 0; | |
| 45 for (var i = 0; i < bytecodes.length; i++) { | |
| 46 var source = debugInfo.astStringFor(offset); | |
| 47 var current = bytecodes[i]; | |
| 48 var byteNumberString = '$offset:'.padLeft(offsetLength); | |
| 49 var invokeInfo = invokeString(current); | |
| 50 var bytecodeString = '$byteNumberString $current$invokeInfo'; | |
| 51 var sourceString = '// $source'; | |
| 52 var printString = bytecodeString.padRight(30) + sourceString; | |
| 53 offset += current.size; | |
| 54 var marker = (offset == bytecodePointer) ? '* ' : ' '; | |
| 55 buffer.writeln("$marker$printString"); | |
| 56 } | |
| 57 return buffer.toString(); | |
| 58 } | |
| 59 | |
| 60 String shortString([int namePadding = 0]) { | |
| 61 String name = compiler.lookupFunctionName(function); | |
| 62 String astString = debugInfo.astStringFor(bytecodePointer - 1); | |
| 63 astString = (astString != null) ? '@$astString' : ''; | |
| 64 | |
| 65 String paddedName = name.padRight(namePadding); | |
| 66 String spaces = ''; | |
| 67 if (astString.isNotEmpty) { | |
| 68 int missingSpaces = 4 - (paddedName.length % 4); | |
| 69 spaces = ' ' * missingSpaces; | |
| 70 } | |
| 71 | |
| 72 return '$paddedName$spaces$astString'; | |
| 73 } | |
| 74 | |
| 75 SourceLocation sourceLocation() { | |
| 76 return debugInfo.sourceLocationFor(bytecodePointer - 1); | |
| 77 } | |
| 78 | |
| 79 ScopeInfo scopeInfo() { | |
| 80 return debugInfo.scopeInfoFor(bytecodePointer - 1); | |
| 81 } | |
| 82 | |
| 83 bool isSameSourceLocation(int offset, | |
| 84 SourceLocation current) { | |
| 85 SourceLocation location = debugInfo.sourceLocationFor(offset); | |
| 86 // Treat locations for which we have no source information as the same | |
| 87 // as the previous location. | |
| 88 if (location == null || location.node == null) return true; | |
| 89 return location.isSameSourceLevelLocationAs(current); | |
| 90 } | |
| 91 | |
| 92 int stepBytecodePointer(SourceLocation current) { | |
| 93 var bytecodes = function.bytecodes; | |
| 94 // Zip forward to the current bytecode. The bytecode pointer in the stack | |
| 95 // frame is the return address which is one bytecode after the current one. | |
| 96 var offset = 0; | |
| 97 var i = 0; | |
| 98 for (; i < bytecodes.length; i++) { | |
| 99 var currentSize = bytecodes[i].size; | |
| 100 if (offset + currentSize == bytecodePointer) break; | |
| 101 offset += currentSize; | |
| 102 } | |
| 103 // Move forward while we know step should not stop. | |
| 104 while (!bytecodes[i].isBranching && | |
| 105 isSameSourceLocation(offset, current)) { | |
| 106 offset += bytecodes[i++].size; | |
| 107 } | |
| 108 return offset <= bytecodePointer ? -1 : offset; | |
| 109 } | |
| 110 | |
| 111 int get functionId => function.functionId; | |
| 112 } | |
| 113 | |
| 114 class BackTrace { | |
| 115 final List<BackTraceFrame> frames; | |
| 116 final DebugState debugState; | |
| 117 | |
| 118 List<int> visibleFrameMapping; | |
| 119 int framesToGo; | |
| 120 int maxNameLength = 0; | |
| 121 | |
| 122 BackTrace(int framesToGo, this.debugState) | |
| 123 : this.framesToGo = framesToGo, | |
| 124 frames = new List(framesToGo); | |
| 125 | |
| 126 int get length => frames.length; | |
| 127 | |
| 128 int get visibleFrames { | |
| 129 ensureVisibleFrameMap(); | |
| 130 return visibleFrameMapping.length; | |
| 131 } | |
| 132 | |
| 133 void addFrame(IncrementalCompiler compiler, BackTraceFrame frame) { | |
| 134 frames[--framesToGo] = frame; | |
| 135 String name = compiler.lookupFunctionName(frame.function); | |
| 136 var nameLength = name == null ? 0 : name.length; | |
| 137 if (nameLength > maxNameLength) maxNameLength = nameLength; | |
| 138 } | |
| 139 | |
| 140 String format([int frame]) { | |
| 141 int currentFrame = frame != null ? frame : debugState.currentFrame; | |
| 142 StringBuffer buffer = new StringBuffer(); | |
| 143 assert(framesToGo == 0); | |
| 144 int frameNumber = 0; | |
| 145 int frameNumberLength = '$frameNumber'.length; | |
| 146 for (var i = 0; i < frames.length; i++) { | |
| 147 if (!frames[i].isVisible) continue; | |
| 148 var marker = currentFrame == frameNumber ? '* ' : ' '; | |
| 149 var line = frames[i].shortString(maxNameLength); | |
| 150 String frameNumberString = '${frameNumber++}: '.padLeft(frameNumberLength)
; | |
| 151 buffer.writeln('$marker$frameNumberString$line'); | |
| 152 } | |
| 153 return buffer.toString(); | |
| 154 } | |
| 155 | |
| 156 void ensureVisibleFrameMap() { | |
| 157 if (visibleFrameMapping == null) { | |
| 158 visibleFrameMapping = []; | |
| 159 for (int i = 0; i < frames.length; i++) { | |
| 160 if (frames[i].isVisible) visibleFrameMapping.add(i); | |
| 161 } | |
| 162 } | |
| 163 } | |
| 164 | |
| 165 // Map user visible frame numbers to actual frame numbers. | |
| 166 int actualFrameNumber(int visibleFrameNumber) { | |
| 167 ensureVisibleFrameMap(); | |
| 168 return (visibleFrameNumber < visibleFrameMapping.length) | |
| 169 ? visibleFrameMapping[visibleFrameNumber] | |
| 170 : -1; | |
| 171 } | |
| 172 | |
| 173 BackTraceFrame visibleFrame(int frame) { | |
| 174 int frameNumber = actualFrameNumber(frame); | |
| 175 if (frameNumber == -1) return null; | |
| 176 return frames[frameNumber]; | |
| 177 } | |
| 178 | |
| 179 void visibilityChanged() { | |
| 180 visibleFrameMapping = null; | |
| 181 } | |
| 182 | |
| 183 String list(SessionState state, [int frame]) { | |
| 184 if (frame == null) frame = debugState.currentFrame; | |
| 185 BackTraceFrame visibleStackFrame = visibleFrame(frame); | |
| 186 if (visibleStackFrame == null) return null; | |
| 187 return visibleStackFrame.list(state); | |
| 188 } | |
| 189 | |
| 190 String disasm([int frame]) { | |
| 191 if (frame == null) frame = debugState.currentFrame; | |
| 192 BackTraceFrame visibleStackFrame = visibleFrame(frame); | |
| 193 if (visibleStackFrame == null) return null; | |
| 194 return visibleStackFrame.disasm(); | |
| 195 } | |
| 196 | |
| 197 SourceLocation sourceLocation() { | |
| 198 return frames[0].sourceLocation(); | |
| 199 } | |
| 200 | |
| 201 ScopeInfo scopeInfo(int frame) { | |
| 202 BackTraceFrame visibleStackFrame = visibleFrame(frame); | |
| 203 if (visibleStackFrame == null) return null; | |
| 204 return visibleStackFrame.scopeInfo(); | |
| 205 } | |
| 206 | |
| 207 ScopeInfo get scopeInfoForCurrentFrame => scopeInfo(debugState.currentFrame); | |
| 208 | |
| 209 int stepBytecodePointer(SourceLocation location) { | |
| 210 return frames[0].stepBytecodePointer(location); | |
| 211 } | |
| 212 } | |
| OLD | NEW |