|
|
@ -5,6 +5,9 @@ var currentSelectedState = null; |
|
|
|
var currentDisplayedState = null; |
|
|
|
var debugData = null; |
|
|
|
var codeMap = null; |
|
|
|
var locations = []; |
|
|
|
var locationMap = {}; |
|
|
|
var breakpoints = {}; |
|
|
|
|
|
|
|
function init(data) |
|
|
|
{ |
|
|
@ -22,6 +25,8 @@ function init(data) |
|
|
|
currentSelectedState = null; |
|
|
|
currentDisplayedState = null; |
|
|
|
debugData = null; |
|
|
|
locations = []; |
|
|
|
locationMap = {}; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
@ -30,9 +35,59 @@ function init(data) |
|
|
|
currentDisplayedState = 0; |
|
|
|
setupInstructions(currentSelectedState); |
|
|
|
setupCallData(currentSelectedState); |
|
|
|
statesSlider.maximumValue = data.states.length - 1; |
|
|
|
initLocations(); |
|
|
|
initSlider(); |
|
|
|
selectState(currentSelectedState); |
|
|
|
} |
|
|
|
|
|
|
|
function updateMode() |
|
|
|
{ |
|
|
|
initSlider(); |
|
|
|
} |
|
|
|
|
|
|
|
function initLocations() |
|
|
|
{ |
|
|
|
locations = []; |
|
|
|
if (debugData.states.length === 0) |
|
|
|
return; |
|
|
|
|
|
|
|
var nullLocation = { start: -1, end: -1, documentId: "", state: 0 }; |
|
|
|
var prevLocation = nullLocation; |
|
|
|
|
|
|
|
for (var i = 0; i < debugData.states.length - 1; i++) { |
|
|
|
var code = debugData.states[i].code; |
|
|
|
var location = code.documentId ? code.locations[codeStr(i)] : nullLocation; |
|
|
|
if (location.start !== prevLocation.start || location.end !== prevLocation.end || code.documentId !== prevLocation.documentId) |
|
|
|
{ |
|
|
|
prevLocation = { start: location.start, end: location.end, documentId: code.documentId, state: i }; |
|
|
|
locations.push(prevLocation); |
|
|
|
} |
|
|
|
locationMap[i] = locations.length - 1; |
|
|
|
} |
|
|
|
locations.push({ start: -1, end: -1, documentId: code.documentId, state: i }); |
|
|
|
locationMap[debugData.states.length - 1] = locations.length - 1; |
|
|
|
} |
|
|
|
|
|
|
|
function setBreakpoints(bp) |
|
|
|
{ |
|
|
|
breakpoints = bp; |
|
|
|
} |
|
|
|
|
|
|
|
function srcMode() |
|
|
|
{ |
|
|
|
return !assemblyMode && locations.length; |
|
|
|
} |
|
|
|
|
|
|
|
function initSlider() |
|
|
|
{ |
|
|
|
if (!debugData) |
|
|
|
statesSlider.maximumValue = 0; |
|
|
|
else if (srcMode()) { |
|
|
|
statesSlider.maximumValue = locations.length - 1; |
|
|
|
} else { |
|
|
|
statesSlider.maximumValue = debugData.states.length - 1; |
|
|
|
} |
|
|
|
statesSlider.value = 0; |
|
|
|
select(currentSelectedState); |
|
|
|
} |
|
|
|
|
|
|
|
function setupInstructions(stateIndex) |
|
|
@ -54,11 +109,13 @@ function setupCallData(stateIndex) |
|
|
|
|
|
|
|
function moveSelection(incr) |
|
|
|
{ |
|
|
|
var prevState = currentSelectedState; |
|
|
|
if (currentSelectedState + incr >= 0) |
|
|
|
{ |
|
|
|
if (currentSelectedState + incr < debugData.states.length) |
|
|
|
select(currentSelectedState + incr); |
|
|
|
if (srcMode()) { |
|
|
|
var locationIndex = locationMap[currentSelectedState]; |
|
|
|
if (locationIndex + incr >= 0 && locationIndex + incr < locations.length) |
|
|
|
selectState(locations[locationIndex + incr].state); |
|
|
|
} else { |
|
|
|
if (currentSelectedState + incr >= 0 && currentSelectedState + incr < debugData.states.length) |
|
|
|
selectState(currentSelectedState + incr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -67,7 +124,7 @@ function display(stateIndex) |
|
|
|
if (stateIndex < 0) |
|
|
|
stateIndex = 0; |
|
|
|
if (stateIndex >= debugData.states.length) |
|
|
|
stateIndex = debugData.state.length - 1; |
|
|
|
stateIndex = debugData.states.length - 1; |
|
|
|
if (debugData.states[stateIndex].codeIndex !== debugData.states[currentDisplayedState].codeIndex) |
|
|
|
setupInstructions(stateIndex); |
|
|
|
if (debugData.states[stateIndex].dataIndex !== debugData.states[currentDisplayedState].dataIndex) |
|
|
@ -77,6 +134,9 @@ function display(stateIndex) |
|
|
|
highlightSelection(codeLine); |
|
|
|
completeCtxInformation(state); |
|
|
|
currentDisplayedState = stateIndex; |
|
|
|
var docId = debugData.states[stateIndex].code.documentId; |
|
|
|
if (docId) |
|
|
|
debugExecuteLocation(docId, locations[locationMap[stateIndex]]); |
|
|
|
} |
|
|
|
|
|
|
|
function displayFrame(frameIndex) |
|
|
@ -88,26 +148,39 @@ function displayFrame(frameIndex) |
|
|
|
display(state.levels[frameIndex - 1]); |
|
|
|
} |
|
|
|
|
|
|
|
function select(stateIndex) |
|
|
|
function select(index) |
|
|
|
{ |
|
|
|
if (srcMode()) |
|
|
|
selectState(locations[index].state); |
|
|
|
else |
|
|
|
selectState(index); |
|
|
|
} |
|
|
|
|
|
|
|
function selectState(stateIndex) |
|
|
|
{ |
|
|
|
display(stateIndex); |
|
|
|
currentSelectedState = stateIndex; |
|
|
|
var state = debugData.states[stateIndex]; |
|
|
|
statesSlider.value = stateIndex; |
|
|
|
jumpIntoForwardAction.enabled(stateIndex < debugData.states.length - 1) |
|
|
|
jumpIntoBackAction.enabled(stateIndex > 0); |
|
|
|
jumpOverForwardAction.enabled(stateIndex < debugData.states.length - 1); |
|
|
|
jumpOverBackAction.enabled(stateIndex > 0); |
|
|
|
jumpOutBackAction.enabled(state.levels.length > 1); |
|
|
|
jumpOutForwardAction.enabled(state.levels.length > 1); |
|
|
|
runForwardAction.enabled(stateIndex < debugData.states.length - 1) |
|
|
|
runBackAction.enabled(stateIndex > 0); |
|
|
|
|
|
|
|
var callStackData = []; |
|
|
|
for (var l = 0; l < state.levels.length; l++) { |
|
|
|
var address = debugData.states[state.levels[l] + 1].address; |
|
|
|
var address = debugData.states[state.levels[l] + 1].code.address; |
|
|
|
callStackData.push(address); |
|
|
|
} |
|
|
|
callStackData.push(debugData.states[0].address); |
|
|
|
callStackData.push(debugData.states[0].code.address); |
|
|
|
callStack.listModel = callStackData; |
|
|
|
if (srcMode()) |
|
|
|
statesSlider.value = locationMap[stateIndex]; |
|
|
|
else |
|
|
|
statesSlider.value = stateIndex; |
|
|
|
} |
|
|
|
|
|
|
|
function codeStr(stateIndex) |
|
|
@ -147,6 +220,24 @@ function isReturnInstruction(index) |
|
|
|
return state.instruction === "RETURN" |
|
|
|
} |
|
|
|
|
|
|
|
function locationsIntersect(l1, l2) |
|
|
|
{ |
|
|
|
return l1.start <= l2.end && l1.end >= l2.start; |
|
|
|
} |
|
|
|
|
|
|
|
function breakpointHit(i) |
|
|
|
{ |
|
|
|
var bpLocations = breakpoints[debugData.states[i].code.documentId]; |
|
|
|
if (bpLocations) { |
|
|
|
var location = locations[locationMap[i]]; |
|
|
|
if (location.start >= 0 && location.end >= location.start) |
|
|
|
for (var b = 0; b < bpLocations.length; b++) |
|
|
|
if (locationsIntersect(location, bpLocations[b])) |
|
|
|
return true; |
|
|
|
} |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
function stepIntoBack() |
|
|
|
{ |
|
|
|
moveSelection(-1); |
|
|
@ -173,25 +264,48 @@ function stepIntoForward() |
|
|
|
moveSelection(1); |
|
|
|
} |
|
|
|
|
|
|
|
function runBack() |
|
|
|
{ |
|
|
|
var i = currentSelectedState - 1; |
|
|
|
while (i > 0 && !breakpointHit(i)) { |
|
|
|
--i; |
|
|
|
} |
|
|
|
selectState(i); |
|
|
|
} |
|
|
|
|
|
|
|
function runForward() |
|
|
|
{ |
|
|
|
var i = currentSelectedState + 1; |
|
|
|
while (i < debugData.states.length - 1 && !breakpointHit(i)) { |
|
|
|
++i; |
|
|
|
} |
|
|
|
selectState(i); |
|
|
|
} |
|
|
|
|
|
|
|
function stepOutBack() |
|
|
|
{ |
|
|
|
var i = currentSelectedState - 1; |
|
|
|
var depth = 0; |
|
|
|
while (--i >= 0) |
|
|
|
while (--i >= 0) { |
|
|
|
if (breakpointHit(i)) |
|
|
|
break; |
|
|
|
if (isCallInstruction(i)) |
|
|
|
if (depth == 0) |
|
|
|
break; |
|
|
|
else depth--; |
|
|
|
else if (isReturnInstruction(i)) |
|
|
|
depth++; |
|
|
|
select(i); |
|
|
|
} |
|
|
|
selectState(i); |
|
|
|
} |
|
|
|
|
|
|
|
function stepOutForward() |
|
|
|
{ |
|
|
|
var i = currentSelectedState; |
|
|
|
var depth = 0; |
|
|
|
while (++i < debugData.states.length) |
|
|
|
while (++i < debugData.states.length) { |
|
|
|
if (breakpointHit(i)) |
|
|
|
break; |
|
|
|
if (isReturnInstruction(i)) |
|
|
|
if (depth == 0) |
|
|
|
break; |
|
|
@ -199,7 +313,8 @@ function stepOutForward() |
|
|
|
depth--; |
|
|
|
else if (isCallInstruction(i)) |
|
|
|
depth++; |
|
|
|
select(i + 1); |
|
|
|
} |
|
|
|
selectState(i + 1); |
|
|
|
} |
|
|
|
|
|
|
|
function jumpTo(value) |
|
|
|