Skip to content
Snippets Groups Projects
Commit d1855e80 authored by Loïc Correnson's avatar Loïc Correnson
Browse files

[ivette/eva] callstacks cache & selection

parent 45ab3e31
No related branches found
No related tags found
No related merge requests found
...@@ -50,23 +50,35 @@ function ProbeEditor() { ...@@ -50,23 +50,35 @@ function ProbeEditor() {
const label = probe?.label; const label = probe?.label;
const code = probe?.code; const code = probe?.code;
const rank = probe?.rank; const rank = probe?.rank;
const byCS = probe?.byCallstacks;
const stmt = rank ? `@S${rank}` : undefined; const stmt = rank ? `@S${rank}` : undefined;
const stacks = model.getStacks(probe).length;
const { cols, rows } = sizeof(code); const { cols, rows } = sizeof(code);
const width = WSIZER.dimension(cols) + 4;
const height = HSIZER.dimension(rows) + 3;
const visible = probe ? !!code : model.getRowCount() > 0; const visible = probe ? !!code : model.getRowCount() > 0;
const visibility = visible ? 'visible' : 'hidden'; const visibility = visible ? 'visible' : 'hidden';
return ( return (
<Hpack style={{ visibility }} className="eva-probe"> <Hpack style={{ visibility }} className="eva-probe">
<Label className="eva-probe-label">{label && `${label}:`}</Label> <Label className="eva-probe-label">{label && `${label}:`}</Label>
<div className="eva-probe-code"> <div style={{ width, height }} className="eva-probe-code">
<SizedArea cols={cols} rows={rows}>{code}</SizedArea> <SizedArea cols={cols} rows={rows}>{code}</SizedArea>
</div> </div>
<Code className="eva-probe-stmt">{stmt}</Code> <Code className="eva-probe-stmt">{stmt}</Code>
<IconButton
className="eva-probe-button"
visible={byCS || stacks > 0}
selected={byCS}
icon="ITEMS.LIST"
title={`Details by callstack (${stacks})`}
onClick={() => { if (probe) probe.setByCallstacks(!byCS); }}
/>
<IconButton <IconButton
className="eva-probe-button" className="eva-probe-button"
kind={transient ? 'selected' : 'warning'} kind={transient ? 'selected' : 'warning'}
icon={transient ? 'CIRC.CHECK' : 'CIRC.CLOSE'} icon={transient ? 'CIRC.CHECK' : 'CIRC.CLOSE'}
onClick={() => { if (probe) probe.setTransient(!transient); }}
title={transient ? 'Make the probe persistent' : 'Release the probe'} title={transient ? 'Make the probe persistent' : 'Release the probe'}
onClick={() => { if (probe) probe.setTransient(!transient); }}
/> />
<Filler /> <Filler />
</Hpack> </Hpack>
...@@ -93,22 +105,26 @@ function TableCell(props: TableCellProps) { ...@@ -93,22 +105,26 @@ function TableCell(props: TableCellProps) {
const style = { width: minWidth, maxWidth }; const style = { width: minWidth, maxWidth };
let styling = 'dome-text-code'; let styling = 'dome-text-code';
let contents: React.ReactNode = props.probe.marker; let contents: React.ReactNode = props.probe.marker;
const { transient, label, code } = probe; const { transient } = probe;
switch (kind) { switch (kind) {
case 'probes': case 'probes':
if (transient) { if (transient) {
styling = 'dome-text-label'; styling = 'dome-text-label';
contents = '« Probe »'; contents = '« Probe »';
} else if (label) {
styling = 'dome-text-label';
contents = label;
} else { } else {
contents = <>{code}</>; const { rank, code, label } = probe;
const atpoint = rank && (
<span className='dome-text-code eva-probe-stmt'>@S{probe.rank}</span>
);
styling = 'dome-text-label';
contents = (
<>{label ?? code}{atpoint}</>
);
} }
break; break;
case 'values': case 'values':
{ {
const { values } = model.cache.getValues(probe.marker); const { values } = model.values.getValues(probe.marker);
const { cols, rows } = sizeof(values); const { cols, rows } = sizeof(values);
contents = ( contents = (
<SizedArea cols={cols} rows={rows}> <SizedArea cols={cols} rows={rows}>
......
...@@ -65,7 +65,7 @@ export function leq(a: Size, b: Size): boolean { ...@@ -65,7 +65,7 @@ export function leq(a: Size, b: Size): boolean {
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// --- Value Cache // --- Data
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
export type EvaStatus = 'True' | 'False' | 'Unknown'; export type EvaStatus = 'True' | 'False' | 'Unknown';
...@@ -81,6 +81,10 @@ export interface EvaValues { ...@@ -81,6 +81,10 @@ export interface EvaValues {
size: Size; size: Size;
} }
// --------------------------------------------------------------------------
// --- Value Cache
// --------------------------------------------------------------------------
export class ValueCache { export class ValueCache {
private readonly state: StateCallbacks; private readonly state: StateCallbacks;
......
...@@ -13,6 +13,7 @@ import * as Ast from 'frama-c/api/kernel/ast'; ...@@ -13,6 +13,7 @@ import * as Ast from 'frama-c/api/kernel/ast';
// Model // Model
import { Probe } from './probes'; import { Probe } from './probes';
import { StacksCache } from './stacks';
import { callback, StateCallbacks, ValueCache } from './cells'; import { callback, StateCallbacks, ValueCache } from './cells';
import { LayoutProps, LayoutEngine, Row } from './layout'; import { LayoutProps, LayoutEngine, Row } from './layout';
...@@ -59,9 +60,15 @@ export class Model implements StateCallbacks { ...@@ -59,9 +60,15 @@ export class Model implements StateCallbacks {
return p; return p;
} }
// --- Values getStacks(p: Probe | undefined): Values.callstack[] {
const stmt = p?.stmt;
return stmt ? this.stacks.getStacks(stmt) : [];
}
// --- Caches
readonly cache = new ValueCache(this); readonly stacks = new StacksCache(this);
readonly values = new ValueCache(this);
// --- Rows // --- Rows
...@@ -91,7 +98,7 @@ export class Model implements StateCallbacks { ...@@ -91,7 +98,7 @@ export class Model implements StateCallbacks {
toLayout.push(p); toLayout.push(p);
} }
}); });
const engine = new LayoutEngine(this.cache, this.layout); const engine = new LayoutEngine(this.values, this.layout);
toLayout.sort(Probe.order).forEach(engine.push); toLayout.sort(Probe.order).forEach(engine.push);
this.rows = engine.flush(); this.rows = engine.flush();
this.forceUpdate(); this.forceUpdate();
...@@ -128,14 +135,12 @@ export class Model implements StateCallbacks { ...@@ -128,14 +135,12 @@ export class Model implements StateCallbacks {
// --- Force Reload (empty caches) // --- Force Reload (empty caches)
forceReload() { forceReload() {
this.probes.forEach((p) => { this.focused = undefined;
if (p.transient && p !== this.focused) { this.remanent = undefined;
this.probes.delete(p.marker); this.selected = undefined;
} else { this.probes.clear();
p.requestProbeInfo(); this.stacks.clear();
} this.values.clear();
});
this.cache.clear();
this.forceLayout(); this.forceLayout();
} }
......
...@@ -53,6 +53,7 @@ export class Probe { ...@@ -53,6 +53,7 @@ export class Probe {
rank?: number; rank?: number;
minCols: number = LabelSize; minCols: number = LabelSize;
maxCols: number = LabelSize; maxCols: number = LabelSize;
byCallstacks = false;
constructor(state: StateCallbacks, marker: Ast.marker) { constructor(state: StateCallbacks, marker: Ast.marker) {
this.marker = marker; this.marker = marker;
...@@ -98,6 +99,13 @@ export class Probe { ...@@ -98,6 +99,13 @@ export class Probe {
} }
} }
setByCallstacks(byCS: boolean) {
if (byCS !== this.byCallstacks) {
this.byCallstacks = byCS;
this.state.forceLayout();
}
}
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// --- Ordering // --- Ordering
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
......
// --------------------------------------------------------------------------
// --- CallStacks
// --------------------------------------------------------------------------
import * as Server from 'frama-c/server';
import * as Values from 'frama-c/api/plugins/eva/values';
import { StateCallbacks } from './cells';
// --------------------------------------------------------------------------
// --- Callstack infos
// --------------------------------------------------------------------------
export type callstacks = Values.callstack[];
// --------------------------------------------------------------------------
// --- CallStacks Cache
// --------------------------------------------------------------------------
export class StacksCache {
private readonly state: StateCallbacks;
private readonly stacks = new Map<string, callstacks>();
// --------------------------------------------------------------------------
// --- LifeCycle
// --------------------------------------------------------------------------
constructor(state: StateCallbacks) {
this.state = state;
}
clear() {
this.stacks.clear();
}
// --------------------------------------------------------------------------
// --- Getters
// --------------------------------------------------------------------------
getStacks(stmt: string): callstacks {
const cs = this.stacks.get(stmt);
if (cs !== undefined) return cs;
this.stacks.set(stmt, []);
this.requestCallstacks(stmt);
return [];
}
// --------------------------------------------------------------------------
// --- Fetchers
// --------------------------------------------------------------------------
private requestCallstacks(stmt: string) {
Server
.send(Values.getCallstacks, stmt)
.then((cs: callstacks) => {
this.stacks.set(stmt, cs);
this.state.forceLayout();
});
}
}
// --------------------------------------------------------------------------
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
.eva-probe { .eva-probe {
margin: 4px; margin: 8px;
width: 100%; width: 100%;
display: flex; display: flex;
} }
...@@ -40,13 +40,14 @@ ...@@ -40,13 +40,14 @@
.eva-probe-stmt { .eva-probe-stmt {
flex: 0 0 auto; flex: 0 0 auto;
color: grey; color: grey;
margin-left: 3px; margin-left: 2px;
margin-right: 3px; margin-right: 0px;
margin-top: 3px; margin-top: 2px;
} }
.eva-probe-button { .eva-probe-button {
flex: 0 0 auto; flex: 0 0 auto;
margin: 1px;
min-width: 16px; min-width: 16px;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment