#ifndef GTS_STACK #define GTS_STACK #ifdef COLOUR_GRAPH #else # error "NEVER" #endif // Note: // - pushl_gc and pushl_no_gc are wrongly chosen because in both cases garbage collection can occur. // In the former case indirections have to be restored and then code which pushl_no_gc would call // is called. Should be changed. // - STACK_CHECKS are no option. The normal algorithm depends upon stack being checked as a means to // determine when all indirections have been undone. // - After the first pass the stack is FIXED // gts_stack.c // General: // - stackP (tos) points to occupied stackcell // precondition: // - maximum stack size is unknown .macro _pushl_gc reg cmpl stackTop,stackP // stackP > stackTop ja 0f //jae \label subl $1,free js undo_handler // \gc subl $4,stackTop // stackTop -= 4 0: subl $4,stackP // stackP -= 4 movl \reg,(stackP) .endm // precondition: // - maximum stack size is known .macro _pushl_no_gc reg #ifdef STACK_CHECKS // check for stack overflow cmpl stackTop,stackP jbe undo_handler // stackP <= stackTop i.e. internal error #endif // STACK_CHECKS subl $4,stackP // stackP -= 4 movl \reg,(stackP) .endm .macro _stack_empty label cmpl stackBottom,stackP je \label .endm .macro _popl reg #ifdef STACK_CHECKS cmpl stackBottom,stackP je stack_underflow // internal error #endif movl (stackP),\reg addl $4,stackP .endm .macro _try_popl reg label cmpl stackBottom,stackP je \label movl (stackP),\reg addl $4,stackP .endm .macro _reserve_stack_block_gc t movl stackP,\t subl stackTop,\t // temp = stackP - stackTop shrl $2,\t cmpl \t,arity // arity < temp jbe 0f // \l1 // enough space between stackTop and stackP // arity > temp // arity = arity - temp subl \t,arity // arity - available space between stackTop and stackP subl arity,free // free -= rest of arity js undo_handler addl \t,arity shll $2,arity subl arity,stackP // stackP -= arity movl stackP,stackTop shrl $2,arity // arity /= 4 jmp 1f //\l2 0: movl arity,\t shll $2,arity // arity *= 4 subl arity,stackP // reserve space between stackTop and stackP movl \t,arity 1: .endm .macro _reserve_stack_block_no_gc t #ifdef STACK_CHECKS cmpl stackTop,stackP // stackP <= stackTop jbe undo_handler // stackP > stackTop movl stackP,\t subl stackTop,\t // free_stack_space = stackP - stackTop shrl $2,\t // free_stack_space in longs cmpl \t,arity // arity > free_stack_space ja undo_handler // out of memory, garbage collect #endif // STACK_CHECKS // Enough space available movl arity,\t shll $2,\t // temp = arity * 4 subl \t,stackP // stackP -= arity * 4 .endm .macro _copy_stack_block_gc t // N_reserve_stack_block \t movl stackP,\t subl stackTop,\t // temp = stackP - stackTop shrl $2,\t cmpl \t,arity // arity < temp jbe 0f // enough space between stackTop and stackP // arity > temp // arity = arity - temp subl \t,arity // arity - available space between stackTop and stackP subl arity,free // free -= rest of arity js undo_handler addl \t,arity shll $2,arity subl arity,stackP // stackP -= arity movl stackP,stackTop shrl $2,arity // arity /= 4 jmp 1f 0: movl arity,\t shll $2,arity // arity *= 4 subl arity,stackP // reserve space between stackTop and stackP movl \t,arity 1: // copy part movl heapP,\t movl stackP,heapP cld rep movsl movl \t,heapP .endm .macro _copy_stack_block_no_gc t #ifdef STACK_CHECKS cmpl stackTop,stackP // stackP <= stackTop jbe undo_handler // stackP > stackTop movl stackP,\t subl stackTop,\t // free_stack_space = stackP - stackTop shrl $2,\t // free_stack_space in longs cmpl \t,arity // arity > free_stack_space ja undo_handler // out of memory, stack overflow #endif // STACK_CHECKS // Enough space available, reserve stack memory movl arity,\t shll $2,\t // temp = arity * 4 subl \t,stackP // stackP -= arity * 4 // Copy to reserved memory area movl heapP,\t // backup heapP movl stackP,heapP // set destination cld rep movsl movl \t,heapP // restore heapP .endm /* // stack_overflow // This is a serious error because the stack size as computed in the very first // pass is too small. Mainly caused by a different traversal of the graph. stack_overflow: int3 jmp stack_overflow */ stack_underflow: int3 jmp stack_underflow // (user) stack .data .align 4 stackTop: .long 0 stackBottom: .long 0 descStackTop: .long 0 // extra heap (between (user) stack and end_heap + 32) extraheapBottom: .long 0 extraP: .long 0 #define FIXED #include "gts_alloc_from_extra_heap.c" #define UNFIXED #include "gts_alloc_from_extra_heap.c" // ------------------------------------------------------------------------------------------ // support for a moveable stack // ecx = amount of bytes to move; preserves all registers except for status move_stack_downwards: #define n_bytes %ecx pushl %esi pushl %edi pushl %eax pushl %ebx #define newStackP %eax #define temp %ebx movl stackP,newStackP subl n_bytes,newStackP // newStackP = stackP - n_bytes pushl newStackP movl stackBottom,%esi cmpl stackP,%esi je move_stack_downwards2 move_stack_loop: movl (stackP),temp addl $4,stackP movl temp,(newStackP) addl $4,newStackP cmpl stackP,%esi jne move_stack_loop move_stack_downwards2: popl stackP subl n_bytes,stackBottom // stackBotom -= n_words subl n_bytes,stackTop // stackTop -= n_words #undef temp #undef newStackP popl %ebx popl %eax popl %edi popl %esi ret #undef n_bytes .macro _debug int3 nop nop nop .endm //#else //#error "al defined" #endif // GTS_STACK