use cached source location

pull/5370/head
yann300 2 years ago
parent f30a4582ed
commit dd00d1d13b
  1. 3
      apps/debugger/src/app/debugger-api.ts
  2. 2
      libs/remix-debug/src/debugger/debugger.ts
  3. 27
      libs/remix-debug/src/solidity-decoder/internalCallTree.ts
  4. 15
      libs/remix-debug/src/source/sourceLocationTracker.ts
  5. 2
      libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
  6. 2
      libs/remix-ui/debugger-ui/src/lib/idebugger-api.ts

@ -41,8 +41,9 @@ export const DebuggerApiMixin = (Base) => class extends Base {
await this.call('editor', 'discardHighlight') await this.call('editor', 'discardHighlight')
} }
async highlight (lineColumnPos, path) { async highlight (lineColumnPos, path, rawLocation) {
await this.call('editor', 'highlight', lineColumnPos, path, '', { focus: true }) await this.call('editor', 'highlight', lineColumnPos, path, '', { focus: true })
this.call('')
} }
async getFile (path) { async getFile (path) {

@ -76,7 +76,7 @@ export class Debugger {
return return
} }
this.debugger.callTree.sourceLocationTracker.getValidSourceLocationFromVMTraceIndex(address, index, compilationResultForAddress.data.contracts).then(async (rawLocation) => { this.debugger.callTree.getValidSourceLocationFromVMTraceIndexFromCache(address, index, compilationResultForAddress.data.contracts).then(async (rawLocation) => {
if (compilationResultForAddress && compilationResultForAddress.data) { if (compilationResultForAddress && compilationResultForAddress.data) {
const generatedSources = this.debugger.callTree.sourceLocationTracker.getGeneratedSourcesFromAddress(address) const generatedSources = this.debugger.callTree.sourceLocationTracker.getGeneratedSourcesFromAddress(address)
const astSources = Object.assign({}, compilationResultForAddress.data.sources) const astSources = Object.assign({}, compilationResultForAddress.data.sources)

@ -6,6 +6,17 @@ import { EventManager } from '../eventManager'
import { parseType } from './decodeInfo' import { parseType } from './decodeInfo'
import { isContractCreation, isCallInstruction, isCreateInstruction, isJumpDestInstruction } from '../trace/traceHelper' import { isContractCreation, isCallInstruction, isCreateInstruction, isJumpDestInstruction } from '../trace/traceHelper'
import { extractLocationFromAstVariable } from './types/util' import { extractLocationFromAstVariable } from './types/util'
import { Uint } from './types/Uint'
export type StepDetail = {
depth: number,
gas: number,
gasCost: number,
memory: number[],
op: string,
pc: number,
stack: number[],
}
/** /**
* Tree representing internal jump into function. * Tree representing internal jump into function.
@ -27,6 +38,9 @@ export class InternalCallTree {
functionDefinitionByFile functionDefinitionByFile
astWalker astWalker
reducedTrace reducedTrace
locationAndOpcodePerVMTraceIndex: {
[Key: number]: any
}
/** /**
* constructor * constructor
@ -89,6 +103,7 @@ export class InternalCallTree {
this.functionDefinitionByFile = {} this.functionDefinitionByFile = {}
this.astWalker = new AstWalker() this.astWalker = new AstWalker()
this.reducedTrace = [] this.reducedTrace = []
this.locationAndOpcodePerVMTraceIndex = {}
} }
/** /**
@ -145,6 +160,7 @@ export class InternalCallTree {
try { try {
const address = this.traceManager.getCurrentCalledAddressAt(step) const address = this.traceManager.getCurrentCalledAddressAt(step)
const location = await this.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, step, this.solidityProxy.contracts) const location = await this.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, step, this.solidityProxy.contracts)
return location return location
} catch (error) { } catch (error) {
throw new Error('InternalCallTree - Cannot retrieve sourcelocation for step ' + step + ' ' + error) throw new Error('InternalCallTree - Cannot retrieve sourcelocation for step ' + step + ' ' + error)
@ -160,6 +176,10 @@ export class InternalCallTree {
throw new Error('InternalCallTree - Cannot retrieve valid sourcelocation for step ' + step + ' ' + error) throw new Error('InternalCallTree - Cannot retrieve valid sourcelocation for step ' + step + ' ' + error)
} }
} }
async getValidSourceLocationFromVMTraceIndexFromCache (address: string, step: number, contracts: any) {
return await this.sourceLocationTracker.getValidSourceLocationFromVMTraceIndexFromCache(address, step, contracts, this.locationAndOpcodePerVMTraceIndex)
}
} }
async function buildTree (tree, step, scopeId, isExternalCall, isCreation) { async function buildTree (tree, step, scopeId, isExternalCall, isCreation) {
@ -201,8 +221,11 @@ async function buildTree (tree, step, scopeId, isExternalCall, isCreation) {
if (!sourceLocation) { if (!sourceLocation) {
return { outStep: step, error: 'InternalCallTree - No source Location. ' + step } return { outStep: step, error: 'InternalCallTree - No source Location. ' + step }
} }
const isCallInstrn = isCallInstruction(tree.traceManager.trace[step]) const stepDetail: StepDetail = tree.traceManager.trace[step]
const isCreateInstrn = isCreateInstruction(tree.traceManager.trace[step]) tree.locationAndOpcodePerVMTraceIndex[step] = { ...sourceLocation, ...stepDetail }
console.log('locationAndOpcodePerVMTraceIndex', stepDetail)
const isCallInstrn = isCallInstruction(stepDetail)
const isCreateInstrn = isCreateInstruction(stepDetail)
// we are checking if we are jumping in a new CALL or in an internal function // we are checking if we are jumping in a new CALL or in an internal function
if (isCallInstrn || sourceLocation.jump === 'i') { if (isCallInstrn || sourceLocation.jump === 'i') {
try { try {

@ -94,6 +94,21 @@ export class SourceLocationTracker {
return map return map
} }
async getValidSourceLocationFromVMTraceIndexFromCache (address: string, vmtraceStepIndex: number, contracts: any, cache: Map<number, any>) {
const amountOfSources = this.getTotalAmountOfSources(address, contracts)
let map: Record<string, number> = { file: -1 }
/*
(map.file === -1) this indicates that it isn't associated with a known source code
(map.file > amountOfSources - 1) this indicates the current file index exceed the total number of files.
this happens when generated sources should not be considered.
*/
while (vmtraceStepIndex >= 0 && (map.file === -1 || map.file > amountOfSources - 1)) {
map = cache[vmtraceStepIndex]
vmtraceStepIndex = vmtraceStepIndex - 1
}
return map
}
clearCache () { clearCache () {
this.sourceMapByAddress = {} this.sourceMapByAddress = {}
} }

@ -158,7 +158,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
return { ...prevState, sourceLocationStatus: '' } return { ...prevState, sourceLocationStatus: '' }
}) })
await debuggerModule.discardHighlight() await debuggerModule.discardHighlight()
await debuggerModule.highlight(lineColumnPos, path) await debuggerModule.highlight(lineColumnPos, path, rawLocation)
} }
} }
}) })

@ -44,7 +44,7 @@ export interface IDebuggerApi {
onEditorContentChanged: (listener: onEditorContentChanged) => void onEditorContentChanged: (listener: onEditorContentChanged) => void
onEnvChanged: (listener: onEnvChangedListener) => void onEnvChanged: (listener: onEnvChangedListener) => void
discardHighlight: () => Promise<void> discardHighlight: () => Promise<void>
highlight: (lineColumnPos: LineColumnLocation, path: string) => Promise<void> highlight: (lineColumnPos: LineColumnLocation, path: string, rawLocation: any) => Promise<void>
fetchContractAndCompile: (address: string, currentReceipt: TransactionReceipt) => Promise<CompilerAbstract> fetchContractAndCompile: (address: string, currentReceipt: TransactionReceipt) => Promise<CompilerAbstract>
getFile: (path: string) => Promise<string> getFile: (path: string) => Promise<string>
setFile: (path: string, content: string) => Promise<void> setFile: (path: string, content: string) => Promise<void>

Loading…
Cancel
Save