mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-07 15:28:49 +00:00
add stack roots scanning
This commit is contained in:
parent
98f9cc0254
commit
16d3f839ce
6 changed files with 1784 additions and 27 deletions
|
|
@ -1,6 +1,12 @@
|
||||||
all:
|
all: gc_runtime.o runtime.o
|
||||||
gcc -m32 -c runtime.c
|
ar rc runtime.a gc_runtime.o runtime.o
|
||||||
|
|
||||||
|
gc_runtime.o: gc_runtime.s
|
||||||
|
gcc -g -m32 -c gc_runtime.s
|
||||||
|
|
||||||
|
runtime.o: runtime.c
|
||||||
|
gcc -g -m32 -c runtime.c
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f runtime.o *~
|
rm -f *.a *.o *~
|
||||||
|
|
||||||
|
|
|
||||||
68
runtime/gc_runtime.s
Normal file
68
runtime/gc_runtime.s
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
.data
|
||||||
|
printf_format: .string "Stack root: %lx\n"
|
||||||
|
printf_format2: .string "BOT: %lx\n"
|
||||||
|
printf_format3: .string "TOP: %lx\n"
|
||||||
|
printf_format4: .string "EAX: %lx\n"
|
||||||
|
printf_format5: .string "LOL\n"
|
||||||
|
__gc_stack_bottom: .long 0
|
||||||
|
__gc_stack_top: .long 0
|
||||||
|
|
||||||
|
.globl L__gc_init
|
||||||
|
.globl __gc_root_scan_stack
|
||||||
|
|
||||||
|
.text
|
||||||
|
L__gc_init: movl %esp, __gc_stack_bottom
|
||||||
|
addl $4, __gc_stack_bottom
|
||||||
|
ret
|
||||||
|
|
||||||
|
__gc_root_scan_stack:
|
||||||
|
movl %esp, __gc_stack_top
|
||||||
|
movl %esp, %eax
|
||||||
|
jmp next
|
||||||
|
|
||||||
|
loop:
|
||||||
|
movl (%eax), %ebx
|
||||||
|
|
||||||
|
// check that it is not a pointer to code section
|
||||||
|
// i.e. the following is not true:
|
||||||
|
// __executable_start <= (%eax) <= __etext
|
||||||
|
check11:
|
||||||
|
leal __executable_start, %edx
|
||||||
|
cmpl %ebx, %edx
|
||||||
|
jna check12
|
||||||
|
jmp check21
|
||||||
|
|
||||||
|
check12:
|
||||||
|
leal __etext, %edx
|
||||||
|
cmpl %ebx, %edx
|
||||||
|
jnb next
|
||||||
|
|
||||||
|
// check that it is not a pointer into the program stack
|
||||||
|
// i.e. the following is not true:
|
||||||
|
// __gc_stack_bottom <= (%eax) <= __gc_stack_top
|
||||||
|
check21:
|
||||||
|
cmpl %ebx, __gc_stack_top
|
||||||
|
jna check22
|
||||||
|
jmp loop2
|
||||||
|
|
||||||
|
check22:
|
||||||
|
cmpl %ebx, __gc_stack_bottom
|
||||||
|
jnb next
|
||||||
|
|
||||||
|
// check if it a valid pointer
|
||||||
|
// i.e. the lastest bit is set to zero
|
||||||
|
loop2:
|
||||||
|
andl $0x00000001, %ebx
|
||||||
|
jnz next
|
||||||
|
pushl %eax
|
||||||
|
pushl (%eax)
|
||||||
|
pushl $printf_format
|
||||||
|
call printf
|
||||||
|
addl $8, %esp
|
||||||
|
popl %eax
|
||||||
|
|
||||||
|
next:
|
||||||
|
addl $4, %eax
|
||||||
|
cmpl %eax, __gc_stack_bottom
|
||||||
|
jne loop
|
||||||
|
ret
|
||||||
|
|
@ -351,18 +351,24 @@ extern int Lwrite (int n) {
|
||||||
/* GC starts here */
|
/* GC starts here */
|
||||||
|
|
||||||
extern const size_t __gc_data_end, __gc_data_start;
|
extern const size_t __gc_data_end, __gc_data_start;
|
||||||
|
extern size_t __gc_stack_bottom, __gc_stack_top;
|
||||||
|
|
||||||
|
extern void L__gc_init ();
|
||||||
|
|
||||||
extern void __gc_root_scan_data () {
|
extern void __gc_root_scan_data () {
|
||||||
size_t * p = &__gc_data_start;
|
size_t * p = &__gc_data_start;
|
||||||
|
|
||||||
printf ("Start, end: %d, %d\n", &__gc_data_start, &__gc_data_end);
|
printf ("Start, end: %lx, %lx\n", &__gc_data_start, &__gc_data_end);
|
||||||
|
|
||||||
while (p != &__gc_data_end) {
|
while (p != &__gc_data_end) {
|
||||||
if (!UNBOXED(*p)) printf ("Root: %d\n", p);
|
if (!UNBOXED(*p)) printf ("Root: %lx\n", *p);
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void __gc_root_scan_stack ();
|
||||||
|
|
||||||
|
|
||||||
/* extern const void * __gc_data_end, * __gc_data_start; */
|
/* extern const void * __gc_data_end, * __gc_data_start; */
|
||||||
|
|
||||||
/* extern void __gc_root_scan_data () { */
|
/* extern void __gc_root_scan_data () { */
|
||||||
|
|
@ -376,6 +382,17 @@ extern void __gc_root_scan_data () {
|
||||||
/* } */
|
/* } */
|
||||||
/* } */
|
/* } */
|
||||||
|
|
||||||
|
extern char __executable_start;
|
||||||
|
extern char __etext;
|
||||||
|
|
||||||
extern void Ltest () {
|
extern void Ltest () {
|
||||||
|
printf("\n");
|
||||||
|
printf("STA 0x%lx\n", (unsigned long)&__executable_start);
|
||||||
|
printf("END 0x%lx\n", (unsigned long)&__etext);
|
||||||
__gc_root_scan_data ();
|
__gc_root_scan_data ();
|
||||||
|
__gc_root_scan_stack ();
|
||||||
|
|
||||||
|
// printf("STA 0x%lx\n", (unsigned long)&__executable_start);
|
||||||
|
// printf("END 0x%lx\n", (unsigned long)&__etext);
|
||||||
|
// printf("RET 0x%lx\n\n", __builtin_return_address(0));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1640
runtime/runtime.s
Normal file
1640
runtime/runtime.s
Normal file
File diff suppressed because it is too large
Load diff
33
src/X86.ml
33
src/X86.ml
|
|
@ -19,6 +19,8 @@ let word_size = 4;;
|
||||||
| L of int (* an immediate operand *)
|
| L of int (* an immediate operand *)
|
||||||
with show
|
with show
|
||||||
|
|
||||||
|
let show_opnd = show(opnd)
|
||||||
|
|
||||||
(* For convenience we define the following synonyms for the registers: *)
|
(* For convenience we define the following synonyms for the registers: *)
|
||||||
let ebx = R 0
|
let ebx = R 0
|
||||||
let ecx = R 1
|
let ecx = R 1
|
||||||
|
|
@ -164,7 +166,7 @@ let compile env code =
|
||||||
(env, Mov (M ("$" ^ s), l) :: call)
|
(env, Mov (M ("$" ^ s), l) :: call)
|
||||||
|
|
||||||
| LD x ->
|
| LD x ->
|
||||||
let s, env' = (env#global x)#allocate in
|
let s, env' = (env#variable x)#allocate in
|
||||||
env',
|
env',
|
||||||
(match s with
|
(match s with
|
||||||
| S _ | M _ -> [Mov (env'#loc x, eax); Mov (eax, s)]
|
| S _ | M _ -> [Mov (env'#loc x, eax); Mov (eax, s)]
|
||||||
|
|
@ -172,7 +174,7 @@ let compile env code =
|
||||||
)
|
)
|
||||||
|
|
||||||
| STA (x, n) ->
|
| STA (x, n) ->
|
||||||
let s, env = (env#global x)#allocate in
|
let s, env = (env#variable x)#allocate in
|
||||||
let push =
|
let push =
|
||||||
match s with
|
match s with
|
||||||
| S _ | M _ -> [Mov (env#loc x, eax); Mov (eax, s)]
|
| S _ | M _ -> [Mov (env#loc x, eax); Mov (eax, s)]
|
||||||
|
|
@ -182,7 +184,7 @@ let compile env code =
|
||||||
env, push @ code
|
env, push @ code
|
||||||
|
|
||||||
| ST x ->
|
| ST x ->
|
||||||
let s, env' = (env#global x)#pop in
|
let s, env' = (env#variable x)#pop in
|
||||||
env',
|
env',
|
||||||
(match s with
|
(match s with
|
||||||
| S _ | M _ -> [Mov (s, eax); Mov (eax, env'#loc x)]
|
| S _ | M _ -> [Mov (s, eax); Mov (eax, env'#loc x)]
|
||||||
|
|
@ -458,8 +460,11 @@ class env =
|
||||||
done;
|
done;
|
||||||
!h
|
!h
|
||||||
|
|
||||||
(* registers a global variable in the environment *)
|
(* registers a variable in the environment *)
|
||||||
method global x = {< globals = S.add ("global_" ^ x) globals >}
|
method variable x =
|
||||||
|
match self#loc x with
|
||||||
|
| M name -> {< globals = S.add name globals >}
|
||||||
|
| _ -> self
|
||||||
|
|
||||||
(* registers a string constant *)
|
(* registers a string constant *)
|
||||||
method string x =
|
method string x =
|
||||||
|
|
@ -515,14 +520,24 @@ class env =
|
||||||
the stack code, then generates x86 assember code, then prints the assembler file
|
the stack code, then generates x86 assember code, then prints the assembler file
|
||||||
*)
|
*)
|
||||||
let genasm (ds, stmt) =
|
let genasm (ds, stmt) =
|
||||||
let stmt = Language.Stmt.Seq (stmt, Language.Stmt.Return (Some (Language.Expr.Call ("raw", [Language.Expr.Const 0])))) in
|
let stmt =
|
||||||
|
Language.Stmt.Seq (
|
||||||
|
Language.Stmt.Call ("__gc_init", []),
|
||||||
|
Language.Stmt.Seq (stmt, Language.Stmt.Return (Some (Language.Expr.Call ("raw", [Language.Expr.Const 0]))))
|
||||||
|
)
|
||||||
|
in
|
||||||
let env, code =
|
let env, code =
|
||||||
compile
|
compile
|
||||||
(new env)
|
(new env)
|
||||||
((LABEL "main") :: (BEGIN ("main", [], [])) :: SM.compile (ds, stmt))
|
((LABEL "main") :: (BEGIN ("main", [], [])) :: SM.compile (ds, stmt))
|
||||||
in
|
in
|
||||||
let data = Meta "\t.data" :: (List.map (fun s -> Meta (Printf.sprintf "%s:\t.int\t0" s )) env#globals) @
|
let gc_start, gc_end = "__gc_data_start", "__gc_data_end" in
|
||||||
(List.map (fun (s, v) -> Meta (Printf.sprintf "%s:\t.string\t\"%s\"" v s)) env#strings) in
|
let data = [Meta "\t.data"; Meta (Printf.sprintf "\t.globl\t%s" gc_start); Meta (Printf.sprintf "\t.globl\t%s" gc_end)] @
|
||||||
|
[Meta (Printf.sprintf "%s:" gc_start)] @
|
||||||
|
(List.map (fun s -> Meta (Printf.sprintf "%s:\t.int\t1" s )) env#globals) @
|
||||||
|
[Meta (Printf.sprintf "%s:" gc_end)] @
|
||||||
|
(List.map (fun (s, v) -> Meta (Printf.sprintf "%s:\t.string\t\"%s\"" v s)) env#strings)
|
||||||
|
in
|
||||||
let asm = Buffer.create 1024 in
|
let asm = Buffer.create 1024 in
|
||||||
List.iter
|
List.iter
|
||||||
(fun i -> Buffer.add_string asm (Printf.sprintf "%s\n" @@ show i))
|
(fun i -> Buffer.add_string asm (Printf.sprintf "%s\n" @@ show i))
|
||||||
|
|
@ -535,5 +550,5 @@ let build prog name =
|
||||||
Printf.fprintf outf "%s" (genasm prog);
|
Printf.fprintf outf "%s" (genasm prog);
|
||||||
close_out outf;
|
close_out outf;
|
||||||
let inc = try Sys.getenv "RC_RUNTIME" with _ -> "../runtime" in
|
let inc = try Sys.getenv "RC_RUNTIME" with _ -> "../runtime" in
|
||||||
Sys.command (Printf.sprintf "gcc -m32 -o %s %s/runtime.o %s.s" name inc name)
|
Sys.command (Printf.sprintf "gcc -g -m32 -o %s %s/gc_runtime.o %s/runtime.o %s.s" name inc inc name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,22 @@
|
||||||
x := 0;
|
fun f () local b {
|
||||||
y := 0;
|
b := 7;
|
||||||
z := 0;
|
|
||||||
t := 0;
|
|
||||||
test ();
|
test ();
|
||||||
|
b := y;
|
||||||
|
test ();
|
||||||
|
b := 9;
|
||||||
|
test ();
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
--x := 0;
|
||||||
|
--y := 0;
|
||||||
|
--z := 0;
|
||||||
|
--t := 0;
|
||||||
|
--test ();
|
||||||
y := "abc";
|
y := "abc";
|
||||||
test ();
|
test ();
|
||||||
t := [];
|
t := [];
|
||||||
test ();
|
test ();
|
||||||
t := 0;
|
t := 0;
|
||||||
test ()
|
test ();
|
||||||
|
f ()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue