...
This commit is contained in:
@@ -1,13 +1,19 @@
|
|||||||
global gc_init, gc_alloc
|
global gc_init, gc_alloc
|
||||||
extern alloc, free
|
extern alloc, free, printint, printstr, endl
|
||||||
|
|
||||||
section .bss
|
section .bss
|
||||||
alloc_list: resq 1 ; head of alloc list
|
alloc_list_head: resq 1
|
||||||
stack_start: resq 1 ; start of stack
|
free_list_head: resq 1
|
||||||
|
stack_start: resq 1
|
||||||
|
|
||||||
section .data
|
section .data
|
||||||
gc_threshold_c: dq 1024 ; default of 1024 allocations
|
gc_bytes_allocated: dq 0 ; bytes allocated since the last gc cycle
|
||||||
total_alloc_c: dq 0 ; count the amount of allocations
|
gc_trigger_threshold: dq 1024 * 1024 * 8 ; initial gc trigger threshold in bytes (adjusts dynamically)
|
||||||
|
gc_start_text: db "Running gc after ", 0
|
||||||
|
gc_sweep_done_text: db " Sweep done. We no have ", 0
|
||||||
|
gc_next_threshold: db " The next threshold is ", 0
|
||||||
|
gc_allocated_bytes: db " allocated bytes", 0
|
||||||
|
gc_mark_done_text: db " Marking done", 0
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
gc_init:
|
gc_init:
|
||||||
@@ -15,30 +21,65 @@ gc_init:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
gc_alloc:
|
gc_alloc:
|
||||||
add rdi, 24 ; add space for metadata
|
add rdi, 24
|
||||||
mov rdx, [total_alloc_c] ; load total allocation count
|
mov rdx, [gc_bytes_allocated]
|
||||||
cmp rdx, [gc_threshold_c] ; has count exceeded threshold?
|
cmp rdx, [gc_trigger_threshold]
|
||||||
jb .skip_collect ; yes? run gc
|
jb .skip_collect ; if allocated bytes since last collect has exceeded threshold, trigger collect
|
||||||
push rdi
|
push rdi
|
||||||
call gc_collect
|
call gc_collect
|
||||||
pop rdi
|
pop rdi
|
||||||
.skip_collect:
|
.skip_collect:
|
||||||
inc qword [total_alloc_c] ; update total allocation count
|
add [gc_bytes_allocated], rdi
|
||||||
push rdi
|
push rdi
|
||||||
call alloc ; allocate size + metadata
|
call alloc ; allocate size + metadata
|
||||||
pop rdi
|
pop rdi
|
||||||
mov byte [rax], 0 ; set mark to 0
|
mov byte [rax], 0 ; set mark to 0
|
||||||
mov qword [rax + 8], rdi ; set total size of object (including metadata)
|
mov qword [rax + 8], rdi ; set total size of object (including metadata)
|
||||||
mov rsi, [alloc_list] ; load first item in allocation list
|
mov rsi, [alloc_list_head] ; load first item in allocation list
|
||||||
mov qword [rax + 16], rsi ; make current head of allocation list the next item in this object
|
mov qword [rax + 16], rsi ; make current head of allocation list the next item in this object
|
||||||
mov [alloc_list], rax ; update head of allocation list so it points to this object
|
mov [alloc_list_head], rax ; update head of allocation list so it points to this object
|
||||||
add rax, 24 ; skip metadata for return value
|
add rax, 24 ; skip metadata for return value
|
||||||
ret
|
ret
|
||||||
|
|
||||||
gc_collect:
|
gc_collect:
|
||||||
|
mov rdi, gc_start_text
|
||||||
|
call printstr
|
||||||
|
mov rdi, [gc_bytes_allocated]
|
||||||
|
call printint
|
||||||
|
mov rdi, gc_allocated_bytes
|
||||||
|
call printstr
|
||||||
|
call endl
|
||||||
|
|
||||||
call gc_mark_stack
|
call gc_mark_stack
|
||||||
|
|
||||||
|
mov rdi, gc_mark_done_text
|
||||||
|
call printstr
|
||||||
|
call endl
|
||||||
|
|
||||||
call gc_sweep
|
call gc_sweep
|
||||||
mov qword [total_alloc_c], 0 ; reset allocation count
|
|
||||||
|
mov rdi, gc_sweep_done_text
|
||||||
|
call printstr
|
||||||
|
mov rdi, [gc_bytes_allocated]
|
||||||
|
call printint
|
||||||
|
mov rdi, gc_allocated_bytes
|
||||||
|
call printstr
|
||||||
|
call endl
|
||||||
|
|
||||||
|
mov rdi, [gc_bytes_allocated]
|
||||||
|
shl rdi, 1
|
||||||
|
mov rsi, 1024 * 1024 * 8
|
||||||
|
call max
|
||||||
|
mov [gc_trigger_threshold], rax
|
||||||
|
mov qword [gc_bytes_allocated], 0
|
||||||
|
|
||||||
|
mov rdi, gc_next_threshold
|
||||||
|
call printstr
|
||||||
|
mov rdi, [gc_trigger_threshold]
|
||||||
|
call printint
|
||||||
|
mov rdi, gc_allocated_bytes
|
||||||
|
call printstr
|
||||||
|
call endl
|
||||||
ret
|
ret
|
||||||
|
|
||||||
gc_mark_stack:
|
gc_mark_stack:
|
||||||
@@ -57,7 +98,7 @@ gc_mark_stack:
|
|||||||
gc_mark:
|
gc_mark:
|
||||||
test rdi, rdi ; is input null?
|
test rdi, rdi ; is input null?
|
||||||
jz .done ; yes? return
|
jz .done ; yes? return
|
||||||
mov rsi, [alloc_list] ; load start of allocation list
|
mov rsi, [alloc_list_head] ; load start of allocation list
|
||||||
.loop:
|
.loop:
|
||||||
test rsi, rsi ; reached end of list?
|
test rsi, rsi ; reached end of list?
|
||||||
jz .done ; yes? return
|
jz .done ; yes? return
|
||||||
@@ -85,32 +126,43 @@ gc_mark:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
gc_sweep:
|
gc_sweep:
|
||||||
mov rdi, [alloc_list]
|
mov rdi, [alloc_list_head]
|
||||||
xor rsi, rsi
|
xor rsi, rsi
|
||||||
.loop:
|
.loop:
|
||||||
test rdi, rdi ; reached end of list?
|
test rdi, rdi ; reached end of list?
|
||||||
jz .done ; yes? return
|
jz .done ; yes? return
|
||||||
mov al, [rdi]
|
mov al, [rdi]
|
||||||
test al, al ; is object marked?
|
test al, al ; is object marked?
|
||||||
jz .free ; no? free it
|
jz .unmarked ; no? free it
|
||||||
mov byte [rdi], 0 ; yes? clear mark for next marking
|
mov byte [rdi], 0 ; yes? clear mark for next marking
|
||||||
mov rsi, rdi
|
mov rsi, rdi
|
||||||
mov rdi, [rdi + 16] ; load the next object in the list
|
mov rdi, [rdi + 16] ; load the next object in the list
|
||||||
jmp .loop ; repeat
|
jmp .loop ; repeat
|
||||||
.free:
|
.unmarked:
|
||||||
mov rdx, [rdi + 16] ; save address of next object in list
|
mov rdx, [rdi + 16] ; save address of next object in list
|
||||||
test rsi, rsi
|
test rsi, rsi
|
||||||
jz .remove_head
|
jz .remove_head
|
||||||
mov [rsi + 16], rdx ; unlink the current node by setting the previous node's next to the next node's address
|
mov [rsi + 16], rdx ; unlink the current node by setting the previous node's next to the next node's address
|
||||||
jmp .free_memory
|
jmp .free
|
||||||
.remove_head:
|
.remove_head:
|
||||||
mov [alloc_list], rdx ; update head node to be the next node
|
mov [alloc_list_head], rdx ; update head node to be the next node
|
||||||
.free_memory:
|
.free:
|
||||||
push rsi ; save previous node since it will also be the previous node for the next item
|
push rsi ; save previous node since it will also be the previous node for the next item
|
||||||
push rdx ; save next node
|
push rdx ; save next node
|
||||||
call free ; free the memory
|
mov rdx, [rdi + 8] ; load the size of the object
|
||||||
pop rdi ; input for next iteration
|
sub [gc_bytes_allocated], rdx ; adjust allocated bytes
|
||||||
pop rsi ; prev node for next iteration
|
call free ; free the memory
|
||||||
|
pop rdi ; input for next iteration
|
||||||
|
pop rsi ; prev node for next iteration
|
||||||
jmp .loop
|
jmp .loop
|
||||||
.done:
|
.done:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
max:
|
||||||
|
cmp rdi, rsi
|
||||||
|
jae .left
|
||||||
|
mov rax, rsi
|
||||||
|
ret
|
||||||
|
.left:
|
||||||
|
mov rax, rdi
|
||||||
|
ret
|
||||||
|
|||||||
@@ -6,11 +6,9 @@ func main() {
|
|||||||
let x = new Human
|
let x = new Human
|
||||||
{
|
{
|
||||||
name = "test",
|
name = "test",
|
||||||
age = i
|
age = 34958743
|
||||||
};
|
};
|
||||||
|
|
||||||
println(x.age);
|
|
||||||
|
|
||||||
i = i + 1;
|
i = i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
311
input/util.asm
Normal file
311
input/util.asm
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
;*********************************************************************
|
||||||
|
; util.asm
|
||||||
|
; Version: 1.2
|
||||||
|
; Author: mjbrusso
|
||||||
|
; Contributors: AlessandroFonseca
|
||||||
|
; Licensed under the MIT license (see "license.txt").
|
||||||
|
;*********************************************************************
|
||||||
|
global exit, exit0, strlen, atoi, endl, printstr, printint, readstr, readint
|
||||||
|
|
||||||
|
SYS_READ: equ 0
|
||||||
|
SYS_WRITE: equ 1
|
||||||
|
SYS_EXIT: equ 60
|
||||||
|
|
||||||
|
STDIN: equ 0
|
||||||
|
STDOUT: equ 1
|
||||||
|
|
||||||
|
LINEFEED: equ 0x0A
|
||||||
|
|
||||||
|
section .text
|
||||||
|
|
||||||
|
;*********************************************************************
|
||||||
|
; void exit(int64 code)
|
||||||
|
;
|
||||||
|
; Description:
|
||||||
|
; Quit program
|
||||||
|
;
|
||||||
|
; Arguments:
|
||||||
|
; rdi: int64 code: Exit code (0=Success, >0=Error)
|
||||||
|
;
|
||||||
|
; Returns:
|
||||||
|
; This function does not return
|
||||||
|
;
|
||||||
|
;*********************************************************************
|
||||||
|
exit:
|
||||||
|
mov rax, SYS_EXIT ; rax: system call number
|
||||||
|
syscall
|
||||||
|
;*********************************************************************
|
||||||
|
|
||||||
|
;*********************************************************************
|
||||||
|
; void exit0()
|
||||||
|
;
|
||||||
|
; Description:
|
||||||
|
; Quit program with status code = 0
|
||||||
|
;
|
||||||
|
; Arguments:
|
||||||
|
; None
|
||||||
|
;
|
||||||
|
; Returns:
|
||||||
|
; This function does not return
|
||||||
|
;
|
||||||
|
;*********************************************************************
|
||||||
|
exit0:
|
||||||
|
xor rdi, rdi ; rdi = 0
|
||||||
|
jmp exit ; TCO: tail call optimization
|
||||||
|
;*********************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
;*********************************************************************
|
||||||
|
; int64 strlen(char *s)
|
||||||
|
;
|
||||||
|
; Description:
|
||||||
|
; Calculates the length of string ( excluding the terminating null)
|
||||||
|
;
|
||||||
|
; Arguments:
|
||||||
|
; rdi: char *s: address of a null-terminated string (array of chars terminated by 0)
|
||||||
|
;
|
||||||
|
; Returns:
|
||||||
|
; rax: int64: string size
|
||||||
|
;
|
||||||
|
;*********************************************************************
|
||||||
|
strlen:
|
||||||
|
xor rax, rax ; rax=0; // reset counter
|
||||||
|
.loop: ; do{
|
||||||
|
cmp byte [rdi], 0 ; if (*s==0); // If zero, skip loop
|
||||||
|
je strlen.end ; break;
|
||||||
|
inc rax ; rax++; // increment counter
|
||||||
|
inc rdi ; s++; // advance to the next char
|
||||||
|
jmp strlen.loop ; }while(true);
|
||||||
|
.end:
|
||||||
|
ret ; return rax;
|
||||||
|
;*********************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
;*********************************************************************
|
||||||
|
; void itoa(int64 value, char *s)
|
||||||
|
;
|
||||||
|
; Description:
|
||||||
|
; Converts an integer to a null-terminated string.
|
||||||
|
;
|
||||||
|
; Arguments:
|
||||||
|
; rdi: int64 value: Integer value to convert.
|
||||||
|
; rsi: char *s: Memory address where to store the resulting string.
|
||||||
|
;
|
||||||
|
; Returns:
|
||||||
|
; rax: int64: string size
|
||||||
|
;
|
||||||
|
;*********************************************************************
|
||||||
|
itoa:
|
||||||
|
test rdi, rdi ; value = rdi
|
||||||
|
jz itoa.iszero ; value==0 has a direct solution
|
||||||
|
jns itoa.notneg ; if(value <0 )
|
||||||
|
mov byte [rsi], '-' ; *s = '-'
|
||||||
|
neg rdi ; value = -value
|
||||||
|
inc rsi ; s++
|
||||||
|
.notneg:
|
||||||
|
mov r9b, 1 ; bool leftzero=true
|
||||||
|
mov r10, 10 ; base = 10
|
||||||
|
mov rcx, 1000000000000000000 ; divisor = 1000000000000000000
|
||||||
|
mov r8, 19 ; cont = 19 // Will repeat 19 times
|
||||||
|
.loop: ; do{
|
||||||
|
mov rax, rdi ; dividend[0..31] = value
|
||||||
|
xor rdx, rdx ; dividend[32..63] = 0
|
||||||
|
idiv rcx ; rax=(rdx:rax)/rcx ; rdx=(rdx:rax)%rcx
|
||||||
|
test al, al ; digit = rax[0..7]
|
||||||
|
jnz itoa.notdigit0 ; if(digit!=0)
|
||||||
|
test r9b, r9b ; if(leftzero)
|
||||||
|
jnz itoa.nextdigit ; continue
|
||||||
|
jmp itoa.digit0
|
||||||
|
.notdigit0:
|
||||||
|
xor r9b, r9b ; leftzero = false
|
||||||
|
.digit0:
|
||||||
|
add eax, 48 ; digit = '0' + digit
|
||||||
|
mov rdi, rdx ; value %= divisor
|
||||||
|
mov byte [rsi], al ; *p = digit
|
||||||
|
inc rsi ; p++
|
||||||
|
.nextdigit:
|
||||||
|
mov rax, rcx ; dividend[0..31] = value
|
||||||
|
xor rdx, rdx ; dividend[32..63] = 0
|
||||||
|
idiv r10 ; rax=(rdx:rax)/10 ; rdx=(rdx:rax)%10
|
||||||
|
mov rcx, rax ; divisor /= 10
|
||||||
|
dec r8 ; cont--
|
||||||
|
jne itoa.loop ; }while(cont!=0)
|
||||||
|
.end:
|
||||||
|
mov byte [rsi], 0 ; *p = '\0'
|
||||||
|
ret
|
||||||
|
.iszero:
|
||||||
|
mov word [rsi], 0x0030 ; *p = "0" (x86 is little endian)
|
||||||
|
ret
|
||||||
|
;*********************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
;*********************************************************************
|
||||||
|
; int64 atoi(char *s)
|
||||||
|
;
|
||||||
|
; Description:
|
||||||
|
; Convert string to integer.
|
||||||
|
;
|
||||||
|
; Arguments:
|
||||||
|
; rdi: char *s: Address of a null-terminated string (array of chars terminated by 0)
|
||||||
|
;
|
||||||
|
; Returns:
|
||||||
|
; rax: int64: integer value
|
||||||
|
;*********************************************************************
|
||||||
|
atoi:
|
||||||
|
push r12 ; r12 is callee saved
|
||||||
|
mov r12, rdi ; rdi is caller saved
|
||||||
|
call strlen
|
||||||
|
lea rdi, [r12+rax-1] ; char *p = &s[strlen(string)]; //scans string backward
|
||||||
|
xor rax, rax ; result value
|
||||||
|
mov rdx, 1 ; multiplier
|
||||||
|
.beginloop:
|
||||||
|
cmp rdi, r12 ; while(p>=s){
|
||||||
|
jl atoi.end ;
|
||||||
|
xor rcx, rcx ;
|
||||||
|
mov cl, byte [rdi] ; cl = current char
|
||||||
|
cmp cl, '-' ; if(cl=='-')
|
||||||
|
jne atoi.notneg ;
|
||||||
|
neg rax ; rax=-rax
|
||||||
|
jmp atoi.end ;
|
||||||
|
.notneg:
|
||||||
|
cmp cl, '9' ; if(!isdigit(cl)) nextdigit
|
||||||
|
jg atoi.endloop ;
|
||||||
|
sub cl, '0' ;
|
||||||
|
jl atoi.endloop ;
|
||||||
|
imul rcx, rdx ; digit_value = current_char * multiplier
|
||||||
|
add rax, rcx ; result += digit_value
|
||||||
|
imul rdx, 10 ; multiplier *= 10
|
||||||
|
.endloop:
|
||||||
|
dec rdi ; previous char //scans string backward
|
||||||
|
jmp atoi.beginloop ; }
|
||||||
|
.end:
|
||||||
|
pop r12 ; restore r12
|
||||||
|
ret
|
||||||
|
;*********************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
;*********************************************************************
|
||||||
|
; void endl()
|
||||||
|
;
|
||||||
|
; Description:
|
||||||
|
; Prints a newline (line break)
|
||||||
|
;
|
||||||
|
; Arguments:
|
||||||
|
; None
|
||||||
|
;
|
||||||
|
; Returns:
|
||||||
|
; Nothing
|
||||||
|
;
|
||||||
|
;*********************************************************************
|
||||||
|
endl:
|
||||||
|
lea rdi, [endl.str] ; print the string
|
||||||
|
call printstr
|
||||||
|
ret
|
||||||
|
|
||||||
|
;*********************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
;*********************************************************************
|
||||||
|
; void printstr(char *s)
|
||||||
|
;
|
||||||
|
; Description:
|
||||||
|
; Print a string
|
||||||
|
;
|
||||||
|
; Arguments:
|
||||||
|
; rdi: char *s: address of a null-terminated string (array of chars terminated by 0)
|
||||||
|
;
|
||||||
|
; Returns:
|
||||||
|
; Nothing
|
||||||
|
;
|
||||||
|
;*********************************************************************
|
||||||
|
printstr:
|
||||||
|
push r15 ; r15 is callee saved
|
||||||
|
mov r15, rdi ; save copy (rdi should be caller saved)
|
||||||
|
call strlen
|
||||||
|
mov rdx, rax ; string size
|
||||||
|
mov rsi, r15 ; string
|
||||||
|
mov rax, SYS_WRITE ; system call number
|
||||||
|
mov rdi, STDOUT ; file descriptor
|
||||||
|
syscall ; system call
|
||||||
|
pop r15
|
||||||
|
ret
|
||||||
|
;*********************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
;*********************************************************************
|
||||||
|
; void printint(int64 n)
|
||||||
|
;
|
||||||
|
; Description:
|
||||||
|
; Print integer number (decimal)
|
||||||
|
;
|
||||||
|
; Arguments:
|
||||||
|
; rdi: int64 n: Value to print
|
||||||
|
;
|
||||||
|
; Returns:
|
||||||
|
; Nothing
|
||||||
|
;
|
||||||
|
;*********************************************************************
|
||||||
|
printint:
|
||||||
|
sub rsp, 40 ; stack allocate a temp string
|
||||||
|
mov rsi, rsp ; rdi=value, rsi=&str[0]
|
||||||
|
call itoa
|
||||||
|
mov rdi, rsp ; rdi=&str[0]
|
||||||
|
call printstr ; print number
|
||||||
|
add rsp, 40 ; deallocate the string
|
||||||
|
ret
|
||||||
|
;*********************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
;*********************************************************************
|
||||||
|
; int64 readstr(char *s, int64 maxsize)
|
||||||
|
;
|
||||||
|
; Description:
|
||||||
|
; Read up to *maxsize* chars from standard input into a string.
|
||||||
|
;
|
||||||
|
; Arguments:
|
||||||
|
; rdi: char *s: address of a string (array of chars)
|
||||||
|
; rsi: int64 maxsize: input size limit
|
||||||
|
;
|
||||||
|
; Returns:
|
||||||
|
; rax: int64: Number of characters read
|
||||||
|
;
|
||||||
|
;*********************************************************************
|
||||||
|
readstr:
|
||||||
|
mov r8, rdi ; copy of buffer address
|
||||||
|
mov rax, SYS_READ ; system call number
|
||||||
|
mov rdx, rsi ; pointer to buffer
|
||||||
|
mov rsi, rdi ; max size
|
||||||
|
mov rdi, STDIN ; file descriptor
|
||||||
|
syscall ; system call
|
||||||
|
dec rax ; removing trailing newline char
|
||||||
|
mov byte [r8+rax], 0 ; replace with '\0'
|
||||||
|
ret
|
||||||
|
;*********************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
;*********************************************************************
|
||||||
|
; int64 readint()
|
||||||
|
;
|
||||||
|
; Description:
|
||||||
|
; Read int64 from standard input
|
||||||
|
;
|
||||||
|
; Arguments:
|
||||||
|
; None
|
||||||
|
;
|
||||||
|
; Returns:
|
||||||
|
; rax: int64: The value entered
|
||||||
|
;
|
||||||
|
;*********************************************************************
|
||||||
|
readint:
|
||||||
|
sub rsp, 40 ; char s[40]
|
||||||
|
mov rdi, rsp ; rdi = &s[0]
|
||||||
|
mov rsi, 21 ; max input size
|
||||||
|
call readstr ; read number as string
|
||||||
|
mov rdi, rsp ;
|
||||||
|
call atoi ; rax = atoi(s)
|
||||||
|
add rsp, 40 ; deallocate s from stack
|
||||||
|
ret
|
||||||
|
;*********************************************************************
|
||||||
|
|
||||||
|
section .data
|
||||||
|
endl.str: db LINEFEED, 0
|
||||||
@@ -13,4 +13,7 @@ nasm -g -felf64 ../input/core/itoa.asm -o itoa.o
|
|||||||
# program
|
# program
|
||||||
nasm -g -felf64 out.asm -o out.o
|
nasm -g -felf64 out.asm -o out.o
|
||||||
|
|
||||||
ld -o out str_len.o arr_size.o itoa.o alloc.o gc.o str_cmp.o out.o
|
# tmp
|
||||||
|
nasm -g -felf64 ../input/util.asm -o util.o
|
||||||
|
|
||||||
|
ld -o out out.o gc.o alloc.o str_cmp.o str_len.o arr_size.o itoa.o util.o
|
||||||
|
|||||||
Reference in New Issue
Block a user