// PASS: COPY GRAPH // // Interface: // // #define ML(x) x##id e.g. _1 // #define ENTRY_LABEL copy_next_node * // #define ENTRY_LABEL_NODEP copy_next_node_in_nodeP * // #define EXIT_LABEL copy_done // #include "gts_copy.c" // #undef EXIT_LABEL // // COPY PASS: COPY_PASS #ifdef DYNAMIC_BLOCK #error "dynamic block not supported (gts_delete.c)" #endif #ifdef COPY_PASS #ifdef SHARE_PREFIXES #error "COPY_PASS and SHARE_PREFIXES cannot be used together" #endif #endif #ifdef UNFIXED_STACK #define PUSHL2 _pushl_gc #define RESERVE_STACK_BLOCK _reserve_stack_block_gc #define COPY_STACK_BLOCK _copy_stack_block_gc #define GARBAGE_COLLECTION GC_UNFIXED_STACK #else #define PUSHL2 _pushl_no_gc #define RESERVE_STACK_BLOCK _reserve_stack_block_no_gc #define COPY_STACK_BLOCK _copy_stack_block_no_gc #define GARBAGE_COLLECTION GC_FIXED_STACK #endif #ifdef GTS_COPY_ONLY_ENCODE_MACRO #undef GTS_COPY_ONLY_ENCODE_MACRO /* ** pre-conditions: ** - t1 contains to the encoded descP e.g. movl (stringP),t1 ** - stringP points to the encoded descriptor ** - t1 is not an indirection ** ** post condition: ** - (stringP) is changed ** - stringP is advanced with 4 ** ** identical code in: ** adjust_offset_per_block */ .macro ML(_adapt_encoded_graph) t12 #define stringP source #define t0 descP // %ebx #define t2 nodeP // %eax pushl t2 movl \t12,t2 andl $0x00ffffff,\t12 movl stackTop,t0 subl \t12,t0 // t0 = stackTop - offset movl 4(t0),\t12 // t12 = virtual base offset /* nop nop nop nop */ cmpl $0,\t12 jnz 9f // \virtual_base_offset_already_computed movl virtual_base_offset,\t12 // compute virtual base offset movl \t12,4(t0) // determine bitset size movl (t0),t2 // MAKE OFFSET DESCRIPTOR TABLE .. subl $1,free js GARBAGE_COLLECTION // gap between the string table and the intermediate data structure movl t2,(heapP) leal 4(heapP),heapP // .. MAKE OFFSET DESCRIPTOR TABLE andl $0xff000000,t2 shrl $24,t2 addl $n_bits,t2 movzbl (t2),t2 // t2 = #bitset leal (\t12,t2,4),t2 movl t2,virtual_base_offset // advance virtual base offset with #bitset * 4 movl (stringP),t2 9: // virtual base offset has already been computed andl $0xff000000,t2 shrl $29,t2 // t2 = prefix kind of encoded node addl $n_possible_prefixes_before_prefix,t2 movzbl (t2),t2 // t2 = set of prefixes which *can* occur before the desired prefix movl (t0),t0 andl $0xff000000,t0 shrl $24,t0 // t0 = set of needed prefixes andl t2,t0 // t0 = set of needed prefixes which *occur* before the desired prefix addl $n_bits,t0 movzbl (t0),t0 // t0 = #needed prefixes which *occur* before the desired prefix leal (\t12,t0,4),t0 // t0 = virtual_base_offset + (#needed prefixes * 4) andl $0x00ffffff,t0 movl (stringP),\t12 andl $0xff000000,\t12 // get prefix kind and arity orl t0,\t12 movl \t12,(stringP) // update encoded graph with just computed virtual offset for the prefix kind popl t2 #undef t0 #undef t2 /* ** precondition: stringP always points at a descP in the encoded graph ** ** Adapt the lower 24 bits to hold the virtual offset in the descriptor address table. The descriptor address ** table is generated by the linker at run-time. The order is important. Only the first four bytes of the ** intermediate structure are stored. ** */ leal 4(stringP),stringP // descriptor has been modified to point to the proper prefix // .. ADAPT ENCODED GRAPH .endm #else // GTS_COPY_ONLY_ENCODE_MACRO // mutally exclusive options #ifdef COPY_PASS //#define COPY_STACK_BLOCK N_copy_stack_block //#define RESERVE_STACK_BLOCK N_reserve_stack_block //#define PUSHL2 _pushl1 //#define COPY_HEAP_BLOCK _copy_heap_block #endif #ifdef SHARE_PREFIXES // stringP (%esi) = ptr in the encoded string //#define COPY_STACK_BLOCK N_copy_stack_block3 //#define RESERVE_STACK_BLOCK _reserve_stack_block2 //#define PUSHL2 _pushl3 #endif #include "gts_shared_macros.c" // Macros: #ifndef GTS_COPY_DEFINE_ONLY_ONCE #endif /* ** _copy_heap_block: ** ** call by: ** ** - source ** the source address ** - arity ** number of longs to copy */ #define COPY_HEAP_BLOCK ML(_copy_heap_block) .macro ML(_copy_heap_block) subl arity,free // free < length js GARBAGE_COLLECTION cld rep movsl .endm // Code: #ifdef COPY_PASS #ifdef COPY_BLOCK_PASS_WORDT_NIET_GEBRUIKT ENTRY_LABEL: _stack_empty EXIT_LABEL //ML(copy_done) _popl nodeP ENTRY_LABEL_NODEP: movl (nodeP),descP // get descriptor pointer #else ENTRY_LABEL: _stack_empty EXIT_LABEL //ML(copy_done) _popl nodeP ENTRY_LABEL_NODEP: movl (nodeP),descP // get descriptor pointer #ifdef COLOUR_GRAPH cmpl heapP,descP // descP <= heapP jbe ML(copy_indirection) // descP > heapP i.e. descP points in shared nodes table decl descP #ifdef COPY_BLOCK_PASS cmpl nodeP,mark_en_current_en_node je ML(copy_non_shared_node) #endif #define temp %ecx movl SN_COLOUR(descP),temp // get colour of node #ifdef COPY_BLOCK_PASS testl $ ENSN_COLOUR_SET_EN_BIT,temp jz ML(copy_non_shared_node) #endif #ifndef COPY_BLOCK_PASS andl $ ENSN_COLOUR_GET_COLOUR,temp cmpl current_colour,temp // node_colour == current_colour je ML(copy_possible_entry_node) incl n_references_to_entry_nodes // amount of external references // create external reference movl SN_COLOUR(descP),temp // get colour of node testl $ ENSN_COLOUR_SET_EN_BIT,temp jnz 2f // non first reference ML(_build_external_reference) // first reference to entry node jmp 3f 2: #endif movl EN_NODE_INDEX(descP),temp // at least the second reference #ifndef COPY_BLOCK_PASS 3: movl temp,ML(external_ref) #endif // encode external reference subl $1,free js GARBAGE_COLLECTION orl $3,temp movl temp,(heapP) addl $4,heapP #ifdef COPY_BLOCK_PASS jmp ENTRY_LABEL #undef temp #else // look if node has already been marked as an entry node movl SN_COLOUR(descP),temp // get colour of node testl $ ENSN_COLOUR_SET_EN_BIT,temp jnz ENTRY_LABEL // marked, ignore reference #undef temp // #else ML(_create_entry_node) // notice that the EN-node has not yet been copied in the string #define entry_node %ecx #define temp descP leal 1(entry_node),temp movl temp,(nodeP) // change descP of node to the created entry node #undef temp #undef entry_node pushl nodeP // visit different coloured node later jmp ENTRY_LABEL ML(copy_possible_entry_node): testl $ ENSN_COLOUR_SET_EN_BIT,SN_COLOUR(descP) jz ML(copy_non_shared_node) // a non-entry node // an entry node is being encoded, store its address (for now) // Later this should be the offset #define temp %ecx movl heapP,temp subl old_heap_pointer,temp movl temp,EN_BLOCK_OFFSET(descP) #undef temp #endif // COPY_BLOCK_PASS ML(copy_non_shared_node): #endif // COLOUR_GRAPH // #endif // COPY_BLOCK_PASS #ifndef COLOUR_GRAPH testl $1,descP // test bit#0 for indirection jne ML(copy_indirection) // if set then copy the indirection #endif // COLOUR_GRAPH // copy descriptor and make indirection subl $1,free // free < 1 js GARBAGE_COLLECTION leal 1(heapP),%ecx // indirection (%ecx) = heapP (heapP) + 1 movl %ecx,(nodeP) // update descriptor entry of node *in graph* movl descP,(heapP) // descP (descP) at location heapP *in string being encoded* addl $4,heapP // reserve space for descP #ifdef COLOUR_GRAPH // also for arrays movl SN_DESCP(descP),descP #endif // COLOUR_GRAPH #endif // COPY_BLOCK_PASS #endif // COPY_PASS testl $2,descP // test if in hnf (bit#1)? je ML(copy_closure) // no, copy closure // node in hnf movzwl -2(descP),arity // get arity (%cx) of descriptor testl arity,arity jne ML(copy_argument_pointers) // if not zero, the copy argument pointer cmpl $INT+2,descP je ML(copy_integer) cmpl $CHAR+2,descP je ML(copy_integer) cmpl $BOOL+2,descP je ML(copy_integer) cmpl $REAL+2,descP je ML(copy_real) cmpl $__STRING__+2,descP je ML(copy_string) cmpl $__ARRAY__+2,descP je ML(copy_array) jmp ENTRY_LABEL #ifdef COPY_PASS #define temp %eax ML(copy_indirection): // An indirection means that a certain node is referenced at least twice. All second // or later references to a particular node end up here. /* ** descP - 1 : pointer to an already encoded shared node in the string ** being built. ** heapP : pointer in the being built string which will contain the ** offset back to the node. */ decl descP #ifdef COLOUR_GRAPH /* ** descP -1 : contains a shared node pointer */ incl n_references_to_entry_nodes // #define sh_entry temp movl descP,sh_entry movl (sh_entry),sh_entry // pointer to shared entry #define node_colour %ecx movl SN_COLOUR(sh_entry),node_colour // get node colour // REF NAAR CURRENT EN-NODE MOET ALS INTERNE INDIRECTIE GECODEERD WORDEN #ifdef COPY_BLOCK_PASS testl $ ENSN_COLOUR_SET_EN_BIT,node_colour jnz ML(copy_external_indirection) #else andl $ ENSN_COLOUR_GET_COLOUR,node_colour cmpl current_colour,node_colour // current_colour <> node_colour i.e. external reference jne ML(copy_external_indirection) #undef sh_entry #endif // COPY_BLOCK_PASS #endif // COLOUR_GRAPH subl $1,free // free < 1 js GARBAGE_COLLECTION #ifdef COLOUR_GRAPH // internal references or indirections are difficult because the encoding // of a certain component may not occupy succesive space. This should be // compensated. Either by some additional administration or by implementing // the construction of the entry node tree // leal 1(heapP),temp movl heapP,temp subl descP,temp // offset = heapP - descP shll $2,temp orl $1,temp // internal indirection #else leal 1(heapP),temp // offset = heapP - descP + 1 subl descP,temp // heapP - descP + 1 #endif // COLOUR_GRAPH movl temp,(heapP) addl $4,heapP jmp ENTRY_LABEL #undef temp #ifdef COLOUR_GRAPH ML(copy_external_indirection): #ifdef COPY_BLOCK_PASS movl %ebx,ML(old_heapP) // backup old heap position movl SN_COLOUR(%eax),%ebx testl $ ENSN_COLOUR_SET_EN_BIT,%ebx jz ML(copy_indirection_unmarked) #endif // COPY_BLOCK_PASS // An entry node movl EN_NODE_INDEX(%eax),%ebx subl $1,free js GARBAGE_COLLECTION orl $3,%ebx movl %ebx,(heapP) addl $4,heapP jmp ENTRY_LABEL ML(copy_indirection_unmarked): // at old_heapP is the SN-pointer to be replaced. pushl %eax movl ML(old_heapP),%eax popl %eax // an unmarked entry node i.e. a sn-node has been discovered. Notice that %ecx // contains the node colour. // create external reference (similar to earlier case) #define temp %ecx ML(_build_external_reference) movl temp,ML(external_ref) // reference backup // store encoded external reference (identical to earlier case) subl $1,free js GARBAGE_COLLECTION orl $3,temp movl temp,(heapP) addl $4,heapP #undef temp movl %eax,descP // SN-pointer ML(_create_entry_node) // replace and initialise EN-pointer in node // EN_BLOCK_OFFSET berekenen #define temp %eax movl ML(old_heapP),temp movl %ecx,(temp) // replace SN-node by equivalent EN-node subl old_heap_pointer,temp movl temp,EN_BLOCK_OFFSET(%ecx) #undef temp // OLD_COMMENTS... // I assume that the highest significant bit is always set. For now I cannot make // up any case to handle the situation in which the significant bit is zero. Can // be added later. TEMPORARILY // ...OLD_COMMENTS jmp ENTRY_LABEL #endif // COLOUR_GRAPH #endif // COPY_PASS #define temp %ebx ML(copy_argument_pointers): /* #ifdef REPLACE_MODULE_ID_BY_DISK_ID1 #error "akakak" #ifdef OLD_COPY_PASS cmpl $e____SystemDynamic__dModuleID+10,descP jne ML(yyy) #define temp2 descP movl (nodeP),temp2 decl temp2 movl (temp2),temp2 movl $e____SystemDynamic__kDiskID+2,SN_DESCP(temp2) #undef temp2 subl $1,free js GARBAGE_COLLECTION movl $0x99999999,(heapP) movl $0x0,(heapP) addl $4,heapP jmp ENTRY_LABEL ML(yyy): #endif #ifdef SHARE_PREFIXES cmpl $e____SystemDynamic__dModuleID+10,descP jne ML(qqq) addl $4,heapP jmp ENTRY_LABEL ML(qqq): #endif // SHARE_PREFIXES #endif // REPLACE_MODULE_ID_BY_DISK_ID // HIERO */ cmpl $1,arity je ML(push_first_argument_pointer) cmpl $2,arity je ML(push_second_and_first) cmpl $256,arity jae ML(copy_record) // 2 < arity < 256 // (nodeP) descP // 4(nodeP) ptr to first arg // 8(nodeP) ptr to arg block #ifdef SHARE_PREFIXES pushl stringP // backup stringP #endif movl 8(nodeP),source decl arity COPY_STACK_BLOCK temp #ifdef SHARE_PREFIXES popl stringP // restore stringP #endif jmp ML(push_first_argument_pointer) #undef temp #define temp %ebx ML(push_second_and_first): movl 8(nodeP),temp PUSHL2 temp #undef temp ML(push_first_argument_pointer): #ifdef REPLACE_MODULE_ID_BY_DISK_ID #ifdef OLD_COPY_PASS cmpl $e____SystemDynamic__dModuleID+10,descP jne ML(yyy) // NEW ... #ifdef COMPUTE_TYPETABLE_ID_FROM_MODULE_ID subl $1,free js GARBAGE_COLLECTION pushl nodeP movl 4(nodeP),nodeP movl (nodeP),descP // int3 call find_type_table_id movl %eax,(heapP) popl nodeP #endif // COMPUTE_TYPETABLE_ID_FROM_MODULE_ID #define temp2 descP movl (nodeP),temp2 decl temp2 movl (temp2),temp2 // movl $e____SystemDynamic__kDiskID+2,SN_DESCP(temp2) movl $e____SystemDynamic__kRunTimeID+2,SN_DESCP(temp2) #undef temp2 #ifndef COMPUTE_TYPETABLE_ID_FROM_MODULE_ID subl $1,free js GARBAGE_COLLECTION movl $0x99999999,(heapP) #endif addl $4,heapP jmp ENTRY_LABEL ML(yyy): #endif // OLD_COPY_PASS #ifdef SHARE_PREFIXES2 cmpl $e____SystemDynamic__dModuleID+10,descP jne ML(qqq1) addl $4,stringP jmp ENTRY_LABEL ML(qqq1): #endif // SHARE_PREFIXES2 #endif // REPLACE_MODULE_ID_BY_DISK_ID movl 4(nodeP),nodeP jmp ENTRY_LABEL_NODEP // INT // (nodeP) descP to INT // 4(nodeP) integer value #define temp %ecx ML(copy_integer): #ifdef SHARE_PREFIXES leal 4(stringP),stringP #endif #ifdef COPY_PASS subl $1,free // free < 1 js GARBAGE_COLLECTION movl 4(nodeP),temp movl temp,(heapP) addl $4,heapP #endif jmp ENTRY_LABEL #undef temp // REAL // (nodeP) descP to REAL // 4(nodeP) least significant part of real // 8(nodeP) most significant part of real // encoding processor specific #define temp %ecx ML(copy_real): #ifdef SHARE_PREFIXES leal 8(stringP),stringP #endif #ifdef COPY_PASS subl $2,free // free < 2 js GARBAGE_COLLECTION movl 4(nodeP),temp movl temp,(heapP) movl 8(nodeP),temp movl temp,4(heapP) addl $8,heapP #endif jmp ENTRY_LABEL #undef temp // CLOSURE // -8(descP) descP // -4(descP) arity of closure // descP text ptr to code #define temp %ebx ML(copy_closure): movl -4(descP),arity cmpl $0,arity jl ML(copy_closure1) je ENTRY_LABEL cmpl $256,arity // arity >= 256 jae ML(copy_unboxed_closure) #ifdef LAZY_DYNAMICS #ifdef OLD_COPY_PASS cmpl $ e____SystemDynamic__nbuild__block,descP #ifdef LAZY_DYNAMICS_3 jne ML(continue) subl $2,free // free < 2 js GARBAGE_COLLECTION // store NodeIndex movl BUILD_DYNAMIC_NODE__INDEX_PTR(nodeP),temp // temp is an INT-node movl 4(temp),temp // get node-index movl temp,BUILD_LAZY_DYNAMIC_ON_DISK__NODE_INDEX(heapP) // store Dynamic // sharing equal pointer is not done. #ifdef DYNAMIC_STRINGS // call MAKE_ID_FDS(lb_alloc_entry) movl BUILD_DYNAMIC_GDID__PTR(nodeP),temp testl $2,(temp) jnz ML(no_closure) movl 4(temp),temp // argument of closure is GlobalDynamicInfo ML(no_closure): pushl temp movl 4(temp),temp cmpl $__STRING__+2,(temp) je ML(a_string) // not a string. how to get the dynamic string? popl temp int3 ML(a_string): call MAKE_ID_FDS(lb_alloc_entry) movl temp,LDR_SITE(%ecx) // field which will be put in ldr_site // get run-time id popl temp movl 8(temp),temp // arg block ptr movl GDI_ID(temp),temp // get ID pushl temp // backup dynamic ID // movl temp,LDR_ID(%ecx) // field will be put in ldr_id movl $ INVALID_DYNAMIC_ID,LDR_ID(%ecx) pushl %ecx call convert_dynamic_id_into_build_lazy_block_id popl %ecx movl %ebx,LDR_LAZY_DYNAMIC_INDEX(%ecx) // movl $1,%ebx movl %ebx,BUILD_LAZY_DYNAMIC_ON_DISK__DYNAMIC_ID(heapP) // *** popl temp // restore dynamic ID movl temp,LDR_ID(%ecx) // field will be put in ldr_id /* *** call MAKE_ID_FDS(lb_size) decl %ecx movl %ecx,BUILD_LAZY_DYNAMIC_ON_DISK__DYNAMIC_ID(heapP) // store dynamic index *** */ #endif // DYNAMIC_STRINGS addl $ BUILD_LAZY_DYNAMIC_ON_DISK__BSIZE,heapP jmp ENTRY_LABEL ML(continue): #else // LAZY_DYNAMICS_3 jne ML(no_build_block) #define temp2 descP movl (nodeP),temp2 decl temp2 movl (temp2),temp2 movl $ e____SystemDynamic__nbuild__lazy__block,SN_DESCP(temp2) #undef temp2 // movl 4(nodeP),nodeP // jmp ENTRY_LABEL_NODEP jmp ENTRY_LABEL ML(no_build_block): #endif // LAZY_DYNAMICS_3 #endif // OLD_COPY_PASS #ifdef SHARE_PREFIXES2 #ifdef LAZY_DYNAMICS_3 cmpl $ e____SystemDynamic__nbuild__block,descP // je ENTRY_LABEL jne ML(continue2) addl $8,stringP jmp ENTRY_LABEL ML(continue2): #else // not LAZY_DYNAMICS_3 cmpl $ e____SystemDynamic__nbuild__lazy__block,descP jne ML(doe) nop int3 nop jmp ENTRY_LABEL ML(doe): #endif // not LAZY_DYNAMICS_3 /* cmpl $e____SystemDynamic__dModuleID+10,descP jne ML(qqq1) addl $4,stringP jmp ENTRY_LABEL */ #endif // SHARE_PREFIXES2 // int3 #endif // LAZY_DYNAMICS #ifdef SHARE_PREFIXES pushl stringP // backup stringP #endif leal 4(nodeP),source COPY_STACK_BLOCK temp #ifdef SHARE_PREFIXES popl stringP // restore stringP #endif jmp ENTRY_LABEL ML(copy_closure1): movl 4(nodeP),nodeP jmp ENTRY_LABEL_NODEP #undef temp // UNBOXED CLOSURE // (descP) high byte, number of unboxed args // low_bytes, number of args // arity < 2: // 4(nodeP) 1st arg // 8(nodeP) 2nd arg if any // // arity > 2: // 4(nodeP) 1st arg // 8(nodeP) ptr to arg block // // Boxed args block if any precede unboxed args block #define nrUnboxed nodeP #define nrUnboxedL %al #define nrPointers arity #define nrPointersH %ch #define temp %ebx ML(copy_unboxed_closure): #ifdef SHARE_PREFIXES pushl stringP // backup stringP #endif leal 4(nodeP),source // set source xorl nrUnboxed,nrUnboxed movb nrPointersH,nrUnboxedL andl $255,arity sub nrUnboxed,arity // arity = # boxed arguments COPY_STACK_BLOCK temp #ifdef COPY_PASS movl nrUnboxed,arity // arity = # unboxed arguments COPY_HEAP_BLOCK #endif #ifdef SHARE_PREFIXES popl stringP // restore stringP leal (stringP,nrUnboxed,4),stringP // increase it with number of unboxed arguments #endif jmp ENTRY_LABEL #undef nrUnboxed #undef nrUnboxedL #undef nrPointers #undef nrPointersH #undef temp // RECORD // -2(descP) arity // (descP) # boxed args (ptrs) ML(copy_record): // cmpl $0x4205a0,%ebx // jne ML(copy_record_test) // int3 //ML(copy_record_test): //e____SystemDynamic__kRunTimeID // COPY_RECORD // temporary register assignments #ifdef COPY_PASS #define nrPointers %esi #endif // COPY_PASS #ifdef SHARE_PREFIXES #define nrPointers descP #endif // SHARE_PREFIXES // store descriptor pointer #ifdef OLD_COPY_PASS // klopt alleen COPY_PASS? #ifdef CONVERT_RUNTIME_ID_TO_RUNTIME_ID_ON_DISK movl descP,ML(stored_descp) // backup descP #endif #endif #ifdef OLD_COPY_PASS # ifdef COLLECT_TYPE_STRING_FOR_LAZY_RUN_TIME_IDS // arity is non-zero, used for lazy references in types cmpl $ e____SystemDynamic__kT__ypeConsSymbol + 2,%ebx jne 1f pushl %ebx movl 4(nodeP),%ebx // get type string movl %ebx,type_string_ptr popl %ebx #undef temp 1: # endif #endif movzwl (descP),nrPointers // nrPointers (boxed arguments) subl $256,arity // arity -= 256 (real arity) #ifdef COPY_PASS #define nrUnboxed %ebx movl arity,nrUnboxed subl nrPointers,nrUnboxed // nrUnboxed = arity - nrPointers #endif // COPY_PASS cmpl $0,arity je ENTRY_LABEL // arity == 0 cmpl $1,arity je ML(record_with_one_cell) // arity == 1 cmpl $2,arity je ML(record_with_two_cells) // arity == 2 #ifdef SHARE_PREFIXES #define nrUnboxed arity subl nrPointers,nrUnboxed #endif // SHARE_PREFIXES pushl nrPointers // arity contains total arity cmpl $0,nrPointers // nrPointers == 0 je ML(only_unboxed_args) decl nrPointers // 4(nodeP) is a boxed jmp ML(copy_args) // argument ML(only_unboxed_args): decl nrUnboxed // only unboxed, decrement // count ML(copy_args): #ifdef COPY_PASS movl nrPointers,arity // #boxed arguments in 8(nodeP) movl 8(nodeP),source // set source //ML(copy_boxed_args): jecxz ML(copy_unboxed_args) pushl nrUnboxed #define temp %ebx COPY_STACK_BLOCK temp #undef temp popl nrUnboxed ML(copy_unboxed_args): movl nrUnboxed,arity // #unboxed arguments in 8(nodeP) jecxz ML(copy_first_arg) COPY_HEAP_BLOCK #endif // COPY_PASS #ifdef SHARE_PREFIXES xchgl nrPointers,nrUnboxed // %ecx = nrPointers cmpl $0,%ecx je ML(copy_first_arg) pushl source // backup stringP movl 8(nodeP),source // set source #define temp descP pushl temp COPY_STACK_BLOCK temp popl temp #undef temp popl source // restore stringP #endif // SHARE_PREFIXES ML(copy_first_arg): #ifdef SHARE_PREFIXES leal (stringP,%ebx,4),stringP #endif popl nrPointers jmp ML(record_with_one_cell) #undef nrUnboxed // RECORD with two elements ML(record_with_two_cells): cmpl $1,nrPointers ja ML(second_is_pointer) // nrPointers > 1 #ifdef COPY_PASS // copy unboxed args subl $1,free // free < 1 js GARBAGE_COLLECTION #define temp %ebx movl 8(nodeP),temp movl temp,(heapP) addl $4,heapP #endif // COPY_PASS #ifdef SHARE_PREFIXES leal 4(stringP),stringP #endif jmp ML(record_with_one_cell) // two boxed args ML(second_is_pointer): #ifdef SHARE_PREFIXES #define temp arity #endif // SHARE_PREFIXES movl 8(nodeP),temp PUSHL2 temp #undef temp ML(record_with_one_cell): cmpl $0,nrPointers jne ML(first_arg_is_pointer) #ifdef OLD_COPY_PASS // implies COPY_PASS #ifdef CONVERT_RUNTIME_ID_TO_RUNTIME_ID_ON_DISK movl ML(stored_descp),descP cmpl $ e____SystemDynamic__kRunTimeID + 2,descP je ML(convert_runtime_id_to_runtime_id_on_disk) #endif #endif // one unboxed arg //ML(one_unboxed_argument): #ifdef COPY_PASS subl $1,free // free < 1 js GARBAGE_COLLECTION #define temp %ebx movl 4(nodeP),temp movl temp,(heapP) #undef temp addl $4,heapP #endif // COPY_PASS #ifdef SHARE_PREFIXES leal 4(stringP),stringP #endif // SHARE_PREFIXES jmp ENTRY_LABEL // ------------- #ifdef OLD_COPY_PASS #ifdef CONVERT_RUNTIME_ID_TO_RUNTIME_ID_ON_DISK ML(convert_runtime_id_to_runtime_id_on_disk): // int3 subl $1,free // free < 1 js GARBAGE_COLLECTION #define run_time_id nodeP #define run_time_id_on_disk %ecx movl 4(nodeP),run_time_id call convert_type_rt_to_disk_id //get_type_table_disk_id // convert to disk id movl run_time_id_on_disk,(heapP) addl $4,heapP jmp ENTRY_LABEL #endif #endif // -------------- ML(first_arg_is_pointer): //#define temp %ebx movl 4(nodeP),nodeP jmp ENTRY_LABEL_NODEP //#undef temp #undef nrPointers // STRING // (nodeP) descP to STRING // 4(nodeP) length // 8(nodeP) string #define temp %ebx #define length arity ML(copy_string): movl 4(nodeP),length #ifdef COPY_PASS test length,length je ML(string_length_zero) #endif // COPY_PASS addl $7,length // length = 4 + 4(nodeP) + 3 shrl $2,length // length in longs #ifdef COPY_PASS leal 4(nodeP),source // set source COPY_HEAP_BLOCK #endif // COPY_PASS #ifdef SHARE_PREFIXES leal (stringP,length,4),stringP #endif // SHARE_PREFIXES jmp ENTRY_LABEL #ifdef COPY_PASS ML(string_length_zero): subl $1,free js GARBAGE_COLLECTION movl length,(heapP) addl $4,heapP jmp ENTRY_LABEL #undef temp #undef length #endif // COPY_PASS // ARRAY // (nodeP) descP to ARRAY // 4(nodeP) size // 8(nodeP) 0, boxed array // otherwise, element descP // 12(nodeP) element block ML(copy_array): #ifdef COPY_PASS #define size arity subl $2,free js GARBAGE_COLLECTION movl 8(nodeP),descP movl descP,4(heapP) // store descriptor in string #ifdef COLOUR_GRAPH #endif cmpl $1,descP // indirection or boxed array? descP <= 1 jbe ML(copy_array2) // indirection; no boxed or already existing indirection #define temp arity leal 5(heapP),temp movl temp,8(nodeP) #undef temp #endif // COPY_PASS #ifdef SHARE_PREFIXES movl 8(nodeP),descP // get element descP #define t1 arity cmpl $0,descP je ML(share_prefixes_in_array2) leal 4(stringP),stringP // advance stringP movl (stringP),t1 ML(_adapt_encoded_graph) t1 #undef t1 movl 8(nodeP),descP // restore element descP jmp ML(copy_array2) ML(share_prefixes_in_array2): leal 8(stringP),stringP // advance stringP //ML(share_prefixes_in_array3): #define size arity #endif // SHARE_PREFIXES ML(copy_array2): movl 4(nodeP),size #ifdef COPY_PASS movl size,(heapP) addl $8,heapP #endif // COPY_PASS cmpl $0,size je ENTRY_LABEL // array size == 0 #ifdef COPY_PASS leal 12(nodeP),source // set source #endif // COPY_PASS cmpl $0,descP je ML(copy_array_pointers) // copy boxed array elements cmpl $INT+2,descP je ML(copy_int_array) // copy unboxed array of integers/chars cmpl $BOOL+2,descP je ML(copy_bool_array) // copy unboxed array of booleans #ifdef SHARE_PREFIXES cmpl $CHAR+2,descP je ML(copy_bool_array) #endif cmpl $REAL+2,descP je ML(copy_real_array) // copy unboxed array of reals jmp ML(copy_record_array) // copy array with records elements #define temp %ebx ML(copy_array_pointers): #ifdef SHARE_PREFIXES pushl stringP leal 12(nodeP),source #endif COPY_STACK_BLOCK temp #ifdef SHARE_PREFIXES popl stringP #endif jmp ENTRY_LABEL #undef temp ML(copy_int_array): #ifdef SHARE_PREFIXES leal (stringP,size,4),stringP #endif // SHARE_PREFIXES #ifdef COPY_PASS COPY_HEAP_BLOCK // copy size, elem. descriptor and elements #endif // COPY_PASS jmp ENTRY_LABEL ML(copy_bool_array): addl $3,size // size = size + 3 shrl $2,size // size /= 4 (in longs) #ifdef COPY_PASS jmp ML(copy_int_array) #endif // COPY_PASS #ifdef SHARE_PREFIXES leal (stringP,size,4),stringP jmp ENTRY_LABEL #endif // SHARE_PREFIXES ML(copy_real_array): #ifdef COPY_PASS shll $1,size // size *= 2 jmp ML(copy_int_array) #endif #ifdef SHARE_PREFIXES leal (stringP,size,8),stringP jmp ENTRY_LABEL #endif // RECORD ARRAY // (nodeP) descP to ARRAY // 4(nodeP) size // 8(nodeP) record element descP // 12(nodeP) record elements block // // -2(descP) #longs which is the recordsize // (descP) #a-fields in record (word,0) // // Purpose: // Copies an array containing records with at least one unboxed field. Other // records are handled by copy_record. If the record element type are unboxed // the copy_unboxed_record_array is called. .data .align 4 ML(t_stackP): .long 0 ML(unboxed_fields_size): .long 0 // copy indirection ML(old_heapP): .long 0 #ifdef OLD_COPY_PASS // klopt alleen COPY_PASS? #ifdef CONVERT_RUNTIME_ID_TO_RUNTIME_ID_ON_DISK ML(stored_descp): .long 0 #endif #endif .text ML(copy_record_array): #ifdef SHARE_PREFIXES pushl stringP // backup stringP #endif // SHARE_PREFIXES // compute boxed size part of the array and reserve stack memory movl stackP,ML(t_stackP) // backup stackP #define temp nodeP #define t_nodeP arity #define temp2 source // was: %esi movl nodeP,t_nodeP movzwl (descP),temp // #boxed fields per records cmpl $0,temp // any boxed arguments? je ML(copy_unboxed_record_array) // ok, copy only boxed mull 4(t_nodeP) // temp = size of boxed part of array (in longs) xchg nodeP,arity movl ML(t_stackP),stackP // restore stackP #ifdef SHARE_PREFIXES pushl stringP #endif // SHARE_PREFIXES nop RESERVE_STACK_BLOCK temp2 #ifdef SHARE_PREFIXES popl stringP #endif // SHARE_PREFIXES #undef temp #undef t_nodeP #undef temp2 #ifdef COPY_PASS // compute unboxed size part of the array and reserve heap memory movl stackP,ML(t_stackP) // backup stackP #define temp nodeP #define temp2 stackP #define t_nodeP arity movl nodeP,t_nodeP movzwl (descP),temp2 movzwl -2(descP),temp // total record size in bytes subl $256,temp subl temp2,temp // temp = total record size - nrFieldPointers movl temp,ML(unboxed_fields_size) mull 4(t_nodeP) subl %eax,free // free < unboxed record size js GARBAGE_COLLECTION movl t_nodeP,nodeP #undef temp #undef temp2 movl ML(t_stackP),stackP // restore stackP // assumption: amount of boxed and unboxed args is at least one #define nrBoxedFields %ebx movzwl (descP),nrBoxedFields // #boxed fields pushl free // backup free #define nrUnboxedFields free movl ML(unboxed_fields_size),nrUnboxedFields // #unboxed fields leal 12(nodeP),source // set source cld #define count nodeP movl 4(nodeP),count pushl stackP // backup tos ML(copy_boxed_fields): xchg heapP,stackP // exchange heapP and stackP movl nrBoxedFields,arity // amount of boxed fields to copy cld rep movsl xchg heapP,stackP // exchange ML(copy_unboxed_fields): movl nrUnboxedFields,arity // amount of unboxed fields to copy cld rep movsl ML(copied_one_array_record): decl count jne ML(copy_boxed_fields) popl stackP popl free jmp ENTRY_LABEL ML(copy_unboxed_record_array): leal 12(t_nodeP),source // set source #define s_unboxed_record_array %eax movzwl -2(descP),s_unboxed_record_array // total record size (in longs) subl $256,s_unboxed_record_array mull 4(t_nodeP) // get array size movl ML(t_stackP),stackP // restore stackP movl s_unboxed_record_array,arity // set arity #undef s_unboxed_record_array COPY_HEAP_BLOCK jmp ENTRY_LABEL #undef record_size #undef nrPointers #undef t_nodeP #endif // COPY_PASS #ifdef SHARE_PREFIXES // Copy the boxed part of the record array to stack leal 12(nodeP),source // set source pushl free #define nrPointers free movzwl (descP),nrPointers // boxed size of record #define s_unboxed_arguments descP movzwl -2(descP),s_unboxed_arguments // total record size subl $256,s_unboxed_arguments subl nrPointers,s_unboxed_arguments // s_unboxed_arguments = size of unboxed fields shll $2,s_unboxed_arguments // s_unboxed_arguments *= 4 (in bytes) #define count nodeP movl 4(nodeP),count // get array size pushl heapP movl stackP,heapP // set destination to stack start pushl count ML(share_prefixes_in_record_array2): movl nrPointers,arity // set arity to # boxed fields cld rep movsl addl s_unboxed_arguments,source // NEW!!! decl count jne ML(share_prefixes_in_record_array2) popl count popl heapP popl free // %ebx = unboxed record size (s_unboxed_arguments) // %eax = #array elements (count) pushl %edx mull %ebx popl %edx popl stringP leal (stringP,%eax),stringP jmp ENTRY_LABEL //share_next_prefix #undef nrPointers #undef s_unboxed_arguments #undef count ML(copy_unboxed_record_array): popl stringP #define temp %edx pushl temp movl 4(arity),temp #define s_unboxed_arguments nodeP movzwl -2(descP),s_unboxed_arguments // total record size subl $256,s_unboxed_arguments shll $2,s_unboxed_arguments // s_unboxed_arguments *= 4 (in bytes) mull temp popl temp leal (stringP,%eax),stringP jmp ENTRY_LABEL #undef s_unboxed_arguments #undef temp #endif // SHARE_PREFIXES #ifdef KAN_WEG #ifdef COLOUR_GRAPH .data .align 4 ML(external_ref): .long 0 #endif // COLOUR_GRAPH #endif #ifndef GTS_COPY_DEFINE_ONLY_ONCE #define GTS_COPY_DEFINE_ONLY_ONCE .data .align 4 // order r t c k d n // To compute the proper offset from the virtual base offset, it is necessary // to known what prefixes preceded the desired prefix e.g. suppose the offset // for k-prefix is desired, n_possible_prefixes_before_prefix: .byte 32+16+8+4+2 // n-prefix; 00|111110 .byte 32+16+8+4 // d-prefix; 00|111100 .byte 32+16+8 // k_prefix; 00|111000 .byte 32+16 // c_prefix; 00|110000 .byte 32 // t_prefix; 00|100000 .byte 0 // r_prefix; 00|000000 n_references_to_entry_nodes: .long 0 // kan weg #endif .text .align 4 #undef ML #endif // GTS_COPY_ONLY_ENCODE_MACRO #undef ENTRY_LABEL #undef ENTRY_LABEL_NODEP #undef COPY_STACK_BLOCK #undef RESERVE_STACK_BLOCK #undef PUSHL2 #undef COPY_HEAP_BLOCK #undef GARBAGE_COLLECTION #ifdef COPY_PASS #undef COPY_PASS #endif #ifdef OLD_COPY_PASS #undef OLD_COPY_PASS #endif #ifdef SHARE_PREFIXES2 #undef SHARE_PREFIXES2 #endif #ifdef UNFIXED_STACK #undef UNFIXED_STACK #endif //#undef ML