Skip to content

Commit 690fd7d

Browse files
authored
Hot-Reload prepare: use Pointer as asmPos (#138)
* Hot-Reload prepare: jit resolveAsmPos take Pointer * Hot-Reload prepare: remove dependency on jit.codeStart * Hot-Reload prepare: use Pointer for start, use class StackRawInfo * Hot-Reload prepare: move some typedef to class * Hot-Reload prepare: improve code and fix pointer compare * Hot-Reload prepare: fix compilation on hl (use explicit i64)
1 parent 71f13e6 commit 690fd7d

File tree

5 files changed

+132
-81
lines changed

5 files changed

+132
-81
lines changed

hld/Debugger.hx

Lines changed: 64 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,34 @@ enum StepMode {
66
Into;
77
}
88

9-
typedef Address = { ptr : Pointer, t : format.hl.Data.HLType };
9+
@:publicFields @:structInit
10+
class Address {
11+
var ptr : Pointer;
12+
var t : format.hl.Data.HLType;
13+
}
1014

11-
typedef WatchPoint = {
15+
@:publicFields @:structInit
16+
class WatchPoint {
1217
var addr : Address;
1318
var regs : Array<{ offset : Int, bits : Int, r : Api.Register }>;
1419
var forReadWrite : Bool;
1520
}
1621

17-
typedef StackRawInfo = { fidx : Int, fpos : Int, codePos : Int, ebp : hld.Pointer };
22+
@:publicFields @:structInit
23+
class StackRawInfo {
24+
var fidx : Int;
25+
var fpos : Int;
26+
var codePos : Pointer;
27+
var ebp : Null<hld.Pointer>;
28+
}
1829

19-
typedef StackInfo = { file : String, line : Int, ebp : Pointer, ?context : { obj : format.hl.Data.ObjPrototype, field : String } };
30+
@:publicFields @:structInit
31+
class StackInfo {
32+
var file : String;
33+
var line : Int;
34+
var ebp : Pointer;
35+
var context : Null<{ obj : format.hl.Data.ObjPrototype, field : String }>;
36+
}
2037

2138
class Debugger {
2239

@@ -49,8 +66,8 @@ class Debugger {
4966
var processExit : Bool;
5067
var ignoredRoots : Map<String,Bool>;
5168

52-
var breakPoints : Array<{ fid : Int, pos : Int, codePos : Int, oldByte : Int, condition : String }>;
53-
var nextStep(default,set): Int = -1;
69+
var breakPoints : Array<{ fid : Int, pos : Int, codePos : Pointer, oldByte : Int, condition : String }>;
70+
var nextStep(default,set): Pointer = Pointer.make(0,0);
5471
var currentStack : Array<StackRawInfo>;
5572
var watches : Array<WatchPoint>;
5673
var threads : Map<Int,{ id : Int, stackTop : Pointer, exception : Pointer, ?exceptionStack: Array<StackRawInfo>, ?exceptionTrap: Pointer, name : String }>;
@@ -75,8 +92,8 @@ class Debugger {
7592
watches = [];
7693
}
7794

78-
function set_nextStep(v:Int) {
79-
if( DEBUG ) trace("NEXT STEP "+v);
95+
function set_nextStep(v:Pointer) {
96+
if( DEBUG ) trace("NEXT STEP "+jit.codePtrToString(v));
8097
return nextStep = v;
8198
}
8299

@@ -295,14 +312,14 @@ class Debugger {
295312
return fields;
296313
}
297314

298-
function wait( onStep = false, onEvalCall = false, onPause = false ) : Api.WaitResult {
315+
function wait( onSingleStep = false, onEvalCall = false, onPause = false ) : Api.WaitResult {
299316
var cmd = null;
300317
var condition : String = null;
301318
watchBreak = null;
302319
while( true ) {
303320
cmd = api.wait(customTimeout == null ? 1000 : Math.ceil(customTimeout * 1000));
304321

305-
if( cmd.r == Breakpoint && !onEvalCall && (nextStep >= 0 || onStep) ) {
322+
if( cmd.r == Breakpoint && !onEvalCall && (jit.isCodePtr(nextStep) || onSingleStep) ) {
306323
// On Linux, singlestep is not reset
307324
cmd.r = SingleStep;
308325
singleStep(cmd.tid,false);
@@ -330,7 +347,7 @@ class Debugger {
330347
return cmd.r;
331348

332349
case Breakpoint:
333-
var codePos = getCodePos(tid) - 1;
350+
var codePos = getCodePos(tid).offset(-1);
334351
for( b in breakPoints ) {
335352
if( b.codePos == codePos ) {
336353
condition = b.condition;
@@ -346,9 +363,9 @@ class Debugger {
346363
break;
347364
case SingleStep:
348365
// restore our breakpoint
349-
if( nextStep >= 0 ) {
366+
if( jit.isCodePtr(nextStep) ) {
350367
setAsm(nextStep, INT3);
351-
nextStep = -1;
368+
nextStep = Pointer.make(0, 0);
352369
} else if( watches.length > 0 ) {
353370

354371
// check if we have a break on a watchpoint
@@ -370,7 +387,7 @@ class Debugger {
370387

371388
}
372389
stoppedThread = tid;
373-
if( onStep )
390+
if( onSingleStep )
374391
return SingleStep;
375392
resume();
376393
case Exit:
@@ -401,7 +418,7 @@ class Debugger {
401418
eval.onBeforeBreak();
402419

403420
// if breakpoint has a condition, try to evaluate and do not actually break on false
404-
if( !onStep && !onEvalCall && !onPause && condition != null ) {
421+
if( !onSingleStep && !onEvalCall && !onPause && condition != null ) {
405422
try {
406423
var value = getValue(condition);
407424
if( value != null ) {
@@ -473,11 +490,9 @@ class Debugger {
473490
return stack;
474491
for( i in 0...count ) {
475492
var codePtr = eval.readPointer(base.offset(i * jit.align.ptr));
476-
if( codePtr < jit.codeStart || codePtr > jit.codeEnd)
477-
continue;
478-
var codePos = codePtr.sub(jit.codeStart);
479-
var e = jit.resolveAsmPos(codePos);
480-
stack.push(e);
493+
var e = jit.resolveAsmPos(codePtr);
494+
if( e != null )
495+
stack.push(e);
481496
}
482497
return [for( s in stack ) if( module.isValid(s.fidx, s.fpos) ) s];
483498
}
@@ -528,15 +543,14 @@ class Debugger {
528543

529544
// Add trap breakpoint if current trap is not in current function
530545
var trap = threads.get(tid).exceptionTrap;
531-
if( trap != null && jit.codeStart < trap && trap < jit.codeEnd ) {
532-
var codePos = trap.sub(jit.codeStart);
533-
var e = jit.resolveAsmPos(codePos);
534-
if( e.fidx != s.fidx ) {
535-
var old = getAsm(codePos);
536-
var bp = { fid : -4, pos : e.fpos, codePos : codePos, oldByte : old, condition : null };
546+
if( trap != null ) {
547+
var e = jit.resolveAsmPos(trap);
548+
if( e != null && e.fidx != s.fidx ) {
549+
var old = getAsm(trap);
550+
var bp = { fid : -4, pos : e.fpos, codePos : trap, oldByte : old, condition : null };
537551
breakPoints.push(bp);
538552
marked.set(-1, bp);
539-
setAsm(codePos, INT3);
553+
setAsm(trap, INT3);
540554
}
541555
}
542556

@@ -665,9 +679,9 @@ class Debugger {
665679
var mem = readMem(esp.offset(-jit.align.ptr), size);
666680

667681
var eip = getReg(tid, Eip);
668-
var asmPos = eip.sub(jit.codeStart);
682+
var asmPos = eip;
669683
if( isWatchbreak )
670-
asmPos -= 1;
684+
asmPos = asmPos.offset(-1);
671685
var e = jit.resolveAsmPos(asmPos);
672686
var inProlog = false;
673687
var exc = getException();
@@ -702,7 +716,7 @@ class Debugger {
702716
e = null;
703717
} else if( e.fpos < 0 ) {
704718
// we are in function prolog
705-
var delta = jit.getFunctionPos(e.fidx) - asmPos;
719+
var delta = jit.getFunctionPos(e.fidx).sub(asmPos);
706720
e.fpos = 0;
707721
if( delta == 0 )
708722
e.ebp = esp.offset(-jit.align.ptr); // not yet pushed ebp
@@ -727,10 +741,7 @@ class Debugger {
727741
var val = mem.getPointer(i << 3, jit.align);
728742
if( (val > esp && val < tinf.stackTop) || (inProlog && i == 0) || skipFirstCheck ) {
729743
var codePtr = skipFirstCheck ? val : mem.getPointer((i + 1) << 3, jit.align);
730-
if( codePtr < jit.codeStart || codePtr > jit.codeEnd )
731-
continue;
732-
var codePos = codePtr.sub(jit.codeStart);
733-
var e = jit.resolveAsmPos(codePos);
744+
var e = jit.resolveAsmPos(codePtr);
734745
if( e != null && e.fpos >= 0 ) {
735746
if( skipFirstCheck ) {
736747
e.ebp = ebp;
@@ -757,7 +768,7 @@ class Debugger {
757768
var val = mem.getPointer((k--) << 3, jit.align);
758769
if( val > validEsp && val < tinf.stackTop ) {
759770
var code = readMem(val.offset(jit.align.ptr),jit.align.ptr).getPointer(0, jit.align);
760-
if( code < jit.codeStart || code > jit.codeEnd ) continue;
771+
if( !jit.isCodePtr(code) ) continue;
761772
if( first || val < e.ebp ) {
762773
e.ebp = val;
763774
first = false;
@@ -779,8 +790,8 @@ class Debugger {
779790
for( i in 0...size >> 2 ) {
780791
var val = mem.getI32(i << 2);
781792
if( val > stackBottom && val < stackTop || (inProlog && i == 0) ) {
782-
var codePos = mem.getI32((i + 1) << 2) - jit.codeStart.toInt();
783-
var e = jit.resolveAsmPos(codePos);
793+
var codePtr = mem.getPointer((i + 1) << 2, jit.align);
794+
var e = jit.resolveAsmPos(codePtr);
784795
if( e != null && e.fpos >= 0 ) {
785796
e.ebp = Pointer.make(val,0);
786797
stack.push(e);
@@ -803,23 +814,22 @@ class Debugger {
803814
if( frame == null ) frame = currentStackFrame;
804815
var f = currentStack[frame];
805816
if( f == null )
806-
return {file:"???", line:0, ebp:Pointer.make(0, 0)};
817+
return { file : "???", line : 0, ebp : Pointer.make(0, 0), context : null };
807818
return stackInfo(f);
808819
}
809820

810821
public function getClosureStack( value ) : Array<StackInfo> {
811822
var stack = @:privateAccess eval.getClosureStack(value);
812823
var out = [];
813824
for( ptr in stack ) {
814-
var codePos = ptr.sub(jit.codeStart);
815-
var e = jit.resolveAsmPos(codePos);
825+
var e = jit.resolveAsmPos(ptr);
816826
if( e == null || !module.isValid(e.fidx,e.fpos) || e.fpos < 0 ) continue;
817827
out.push(stackInfo({ fidx : e.fidx, fpos : e.fpos, ebp: null }));
818828
}
819829
return out;
820830
}
821831

822-
function stackInfo( f ) {
832+
function stackInfo( f ) : StackInfo {
823833
var s = module.resolveSymbol(f.fidx, f.fpos);
824834
return { file : s.file, line : s.line, ebp : f.ebp, context : module.getMethodContext(f.fidx) };
825835
}
@@ -918,13 +928,13 @@ class Debugger {
918928

919929
function getCodePos(tid) {
920930
var eip = getReg(tid, Eip);
921-
return eip.sub(jit.codeStart);
931+
return eip;
922932
}
923933

924934
public function resume() {
925935
if( stoppedThread == null )
926936
throw "No thread stopped";
927-
if( DEBUG ) trace("RUN "+getCodePos(currentThread));
937+
if( DEBUG ) trace("RUN " + jit.codePtrToString(getCodePos(currentThread)));
928938
if( !api.resume(stoppedThread) && !processExit )
929939
throw "Could not resume "+stoppedThread;
930940
stoppedThread = null;
@@ -946,14 +956,18 @@ class Debugger {
946956
return mem;
947957
}
948958

949-
function getAsm( pos : Int ) {
950-
return api.readByte(jit.codeStart,pos);
959+
function getAsm( ptr : Pointer ) {
960+
if( !jit.isCodePtr(ptr) )
961+
throw "Assert invalid ptr " + ptr;
962+
return api.readByte(ptr, 0);
951963
}
952964

953-
function setAsm( pos : Int, byte : Int ) {
954-
if( DEBUG ) trace("Set "+pos+"="+byte);
955-
api.writeByte(jit.codeStart, pos, byte);
956-
api.flush(jit.codeStart.offset(pos),1);
965+
function setAsm( ptr : Pointer, byte : Int ) {
966+
if( !jit.isCodePtr(ptr) )
967+
throw "Assert invalid ptr " + ptr;
968+
if( DEBUG ) trace('Set ${jit.codePtrToString(ptr)}=$byte');
969+
api.writeByte(ptr, 0, byte);
970+
api.flush(ptr, 1);
957971
}
958972

959973
function getReg(tid, reg) {
@@ -1012,7 +1026,7 @@ class Debugger {
10121026
setAsm(bp.codePos, bp.oldByte);
10131027
if( nextStep == bp.codePos ) {
10141028
singleStep(currentThread, false);
1015-
nextStep = -1;
1029+
nextStep = Pointer.make(0, 0);
10161030
}
10171031
}
10181032

hld/Eval.hx

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1670,16 +1670,3 @@ class Eval {
16701670
}
16711671

16721672
}
1673-
1674-
// Map<Int64, V> does not work on JS, see https://github.com/HaxeFoundation/haxe/issues/9872
1675-
class Int64Map<T> extends haxe.ds.BalancedTree<haxe.Int64, T> {
1676-
override function compare(k1:haxe.Int64, k2:haxe.Int64):Int {
1677-
return if( k1 == k2 ) {
1678-
0;
1679-
} else if( k1 > k2 ) {
1680-
1;
1681-
} else {
1682-
-1;
1683-
}
1684-
}
1685-
}

hld/Int64Map.hx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package hld;
2+
3+
// Map<Int64, V> does not work on JS, see https://github.com/HaxeFoundation/haxe/issues/9872
4+
class Int64Map<T> extends haxe.ds.BalancedTree<haxe.Int64, T> {
5+
override function compare(k1:haxe.Int64, k2:haxe.Int64):Int {
6+
return if( k1 == k2 ) {
7+
0;
8+
} else if( k1 > k2 ) {
9+
1;
10+
} else {
11+
-1;
12+
}
13+
}
14+
}

0 commit comments

Comments
 (0)