// Problems: // - check that an internal reference is created for reference to an entry node if // it is the current entry node. // - garbage collection with DETERMINE_ENTRY_NODES has not been test. #define COLLECT_TYPE_STRING_FOR_LAZY_RUN_TIME_IDS #define CONVERT_LAZY_RUN_TIME_ID // handles lazy type references #define LAZY_DYNAMICS // handles build__block and build_lazy_block closures // #define LAZY_DYNAMICS_1 #define LAZY_DYNAMICS_2 // compute descriptor replaces build_blocks by build_lazy_blocks #define LAZY_DYNAMICS_3 // ignore build_blocks (should also ignore build_lazy_blocks) #define COPIED_DYNAMICS // #define UNBOXED_DYNAMIC // call convention; DynamicTemp is passed unboxed. #define DYNAMIC_STRINGS // store dynamic strings #define USE_CGTSA_AND_CGTSR #define USE_USED_CODE_LIBRARY_INSTANCE_ARRAY //#define DEBUG // includes //#define COMPUTE_LIBRARY_NUMBER #define MAKE_DUS_SYMBOLIC // should be *always* be defined #define EXTEND_DUS_WITH_LIBARY_NUMBER #define CONVERT_RUNTIME_ID_TO_RUNTIME_ID_ON_DISK #include "globals.c" #include "global_registers.c" #include "gts_stack.c" #include "extra_heap.c" #include "colour.c" #include "descriptor_usage.c" #include "gts_need_debug.c" #include "gts_build_block.c" #include "gts_gdi.c" // #define DETERMINE_ENTRY_NODES // extra pass to determine entry nodes // TODO: // - small changes to support REPLACE_MODULE_ID_BY_DISK_ID #define DETERMINE_ENTRY_NODES // Macro's which should always be defined. #define EXTRA_HEAP_ENTRY #define EXTRA_ARG #define REPLACE_MODULE_ID_BY_DISK_ID #define COMPUTE_TYPETABLE_ID_FROM_MODULE_ID // obsolete #define BUILD_DISK_ID // Some checks //#ifdef DETERMINE_ENTRY_NODES //#ifdef REPLACE_MODULE_ID_BY_DISK_ID //#error "graph_to_string.c: DETERMINE_ENTRY_NODES and REPLACE_MODULE_ID_BY_DISK_ID should not be defined at the same time" //#endif //#ifdef CONVERT_RUNTIME_ID_TO_RUNTIME_ID_ON_DISK //#error "graph_to_string.c: DETERMINE_ENTRY_NODES and CONVERT_RUNTIME_ID_TO_RUNTIME_ID_ON_DISK cannot (yet) be defined at the same time" //#endif //#endif //#ifdef CONVERT_RUNTIME_ID_TO_RUNTIME_ID_ON_DISK //#ifdef DETERMINE_ENTRY_NODES //#error "graph_to_string.c: DETERMINE_ENTRY_NODES and CONVERT_RUNTIME_ID_TO_RUNTIME_ID_ON_DISK cannot (yet) be defined at the same time" //#endif //#endif /* #ifdef REPLACE_MODULE_ID_BY_DISK_ID #ifdef DETERMINE_ENTRY_NODES #error "graph_to_string.c: DETERMINE_ENTRY_NODES and REPLACE_MODULE_ID_BY_DISK_ID should not be defined at the same time" #endif #endif */ #ifdef COLOUR_GRAPH // User definable #define N_LB_ENTRIES 8 // n entries = 2 ^ N_LB_ENTRIES_EXP #define N_LB_ENTRIES_EXP 3 #define LB_ENTRY_BSIZE 4 // entry size = 2 ^ LB_ENTRY_BSIZE_EXP (in bytes) #define LB_ENTRY_BSIZE_EXP 2 #define MAKE_ID(x) x##_DL // data // NEW ... #define MAKE_ID_NDL(x) x##_fixed_DL // no stack #define MAKE_ID_UDL(x) x##_unfixed_DL // unfixed stack #define MAKE_ID_FDL(x) x##_fixed_DL // fixed stack #define SPECIAL // To be removed #define BOTH_FIXEDNESS // ... NEW //#define MAKE_ID_DL(x) x##_DL #include "LinkedBlock.c" // User definable #define N_LB_ENTRIES 8 // n entries = 2 ^ N_LB_ENTRIES_EXP #define N_LB_ENTRIES_EXP 3 #define NOT_A_POWER_OF_TWO_ENTRY_SIZE #define LB_ENTRY_WSIZE 5 //5 //#define LB_ENTRY_BSIZE 32 // 16 // entry size = 2 ^ LB_ENTRY_BSIZE_EXP (in bytes) //#define LB_ENTRY_BSIZE_EXP 5 // 4 #define MAKE_ID(x) x##_EN // data // NEW ... #define MAKE_ID_NEN(x) x##_fixed_EN // no stack #define MAKE_ID_UEN(x) x##_unfixed_EN // unfixed stack #define MAKE_ID_FEN(x) x##_fixed_EN // fixed stack #define SPECIAL // To be removed #define BOTH_FIXEDNESS // used in both unfixed and fixed contents // ... NEW #define MAKE_ID_EN(x) x##_EN #include "LinkedBlock.c" // Format EN: // word 0: descP // word 1 (1234): // - 12 offset array index i.e. id of entry node // - 34 except for two least significant bits represents the block_id in offset array // word 2: // Offset from block start to the entry node // word 3: unused (might come in handy for nodeP) #define EN_DESCP 0 #define EN_COLOUR 4 // EN/SN-node, EN_COLOUR (1234): 1 = reserved #define ENSN_COLOUR_GET_COLOUR 0x00ffffff // 0x3fffffff// 1234, 12 reserverd, 34 = colour // byte 1, bit 4: set iff EN-node otherwise it is an SN-node #define ENSN_COLOUR_SET_EN_BIT 0x80000000 #ifdef DETERMINE_ENTRY_NODES // byte 1, bit 3: set iff EN/SN-node has already been visited, used in 2nd pass (determination of EN-nodes) #define ENSN_COLOUR_ALREADY_VISITED_MASK 0x40000000 // Multiple combinations of bits #define ENSN_COLOUR_EN_BIT_AND_COLOUR 0xbfffffff #endif #define EN_NODE_INDEX 8 #define EN_BLOCK_OFFSET 12 #define EN_NODEP 12 // used in pass 2 (determine en nodes) #define EN_NODE_LIST 16 // used in pass 3 (copying) #define EN_NODE 16 // first used in pass 4 //3 #define INITIAL_BLOCK_N 4 // 0 is reservered for top-level dynamic; two least significant bits are unused #define BLOCK_INCREASEMENT 4 // User definable #define N_LB_ENTRIES 8 // n entries = 2 ^ N_LB_ENTRIES_EXP #define N_LB_ENTRIES_EXP 3 #define LB_ENTRY_BSIZE 8 /*4 */ // entry size = 2 ^ LB_ENTRY_BSIZE_EXP (in bytes) #define LB_ENTRY_BSIZE_EXP 3 /* 2 */ #define MAKE_ID(x) x##_BI #define BI_INFO 0 #define BI_N_EN_NODES 4 // NEW ... //#define MAKE_ID_NBI(x) MAKE_ID_NEN_error //#define MAKE_ID_UBI(x) MAKE_ID_UEN_error #define MAKE_ID_FBI(x) x##_fixed_BI // fixed stack #define SPECIAL #define FIXED // ... NEW #define MAKE_ID_BI(x) x##_BI #include "LinkedBlock.c" #ifdef DYNAMIC_STRINGS // User definable #define N_LB_ENTRIES 8 // n entries = 2 ^ N_LB_ENTRIES_EXP #define N_LB_ENTRIES_EXP 3 //#define LB_ENTRY_BSIZE 8 // entry size = 2 ^ LB_ENTRY_BSIZE_EXP (in bytes) //#define LB_ENTRY_BSIZE_EXP 3 #define NOT_A_POWER_OF_TWO_ENTRY_SIZE #define LB_ENTRY_WSIZE 3 //5 #define MAKE_ID(x) x##_DS // data // NEW ... #define MAKE_ID_NDS(x) x##_fixed_DS // no stack #define MAKE_ID_UDS(x) x##_unfixed_DS // unfixed stack #define MAKE_ID_FDS(x) x##_fixed_DS // fixed stack #define SPECIAL // To be removed #define BOTH_FIXEDNESS // ... NEW #define MAKE_ID_DS(x) x##_DS #include "LinkedBlock.c" #endif // DYNAMIC_STRINGS #include "gts_undo.c" # ifdef CONVERT_LAZY_RUN_TIME_ID // also change RunTimeIDW in DynamicLinkerInterface #define RTID_TYPE_STRING 0 #define RTID_RUNTIME_ID 4 // must have been ored with LAZY_DYNAMIC_INSTANCE #define RTID_ASSIGNED_DISK_ID 8 // id on disk #define RTID_LAST_FIELD RTID_ASSIGNED_DISK_ID #define RTID_SIZE (RTID_LAST_FIELD + 4) // User definable #define N_LB_ENTRIES 8 // n entries = 2 ^ N_LB_ENTRIES_EXP #define N_LB_ENTRIES_EXP 3 #define NOT_A_POWER_OF_TWO_ENTRY_SIZE #define LB_ENTRY_WSIZE 3 //#define LB_ENTRY_BSIZE 8 // entry size = 2 ^ LB_ENTRY_BSIZE_EXP (in bytes) //#define LB_ENTRY_BSIZE_EXP 3 #define MAKE_ID(x) x##_RTID // data // NEW ... #define MAKE_ID_NRTID(x) x##_fixed_RTID // no stack #define MAKE_ID_URTID(x) x##_unfixed_RTID // unfixed stack #define MAKE_ID_FRTID(x) x##_fixed_RTID // fixed stack #define SPECIAL // To be removed #define BOTH_FIXEDNESS // ... NEW #define MAKE_ID_RTID(x) x##_RTID #include "LinkedBlock.c" # include "gts_runtime_id.c" # endif #ifdef COMPUTE_TYPETABLE_ID_FROM_MODULE_ID #include "gts_range_id.c" #endif #endif #include "gts_lazy_dynamic_reference.c" #include "gts_build_lazy_block_id.c" # ifdef USE_CGTSA_AND_CGTSR # include "gts_copy_graph_to_string_arguments.c" # include "gts_copy_graph_to_string_results.c" # endif // USE_CGTSA_AND_CGTSR // ------------------------------------------------------------------------------------------- // HEADER // // Notice that part of the header is shared by different applications // // To add a new field: // 1. add the field either in the common section or just for dumpDynamic // 2. if its the last field, then mention it as the last field by replacing it in the // HEADER_SIZE-macro. (just below) // Shared by: // StdDynamicLowLevelInterface.{icl,dcl}; build_dynamic_header // in application dumpDynamic & dynamic linker // OBSOLETE: // - StdDynamic.icl (StdEnv) // - read_dynamic.icl (dumpDynamic) // - dynamics.icl (dumpDynamic,dynamic linker) // // Probably only by StdDynamicLowLevelInterface.icl #define HEADER_SIZE_OFFSET 8 // header size (in bytes) #define VERSION_NUMBER_OFFSET 12 // version (major,minor) // little or big endian format? #define GRAPH_OFFSET 16 // graph offset #define GRAPH_SIZE 20 // graph size #define BLOCK_TABLE_OFFSET 24 #define BLOCK_TABLE_SIZE 28 #define DYNAMIC_RTS_INFO_OFFSET 32 // info from dynamic rts; filled in by StdDynamic.icl #define DYNAMIC_RTS_INFO_SIZE 36 // End sharing for StdDynamic.icl #define STRINGTABLE_OFFSET 40 // stringtable offset #define STRINGTABLE_SIZE 44 // stringtable size #define DESCADDTRESTABLE_OFFSET 48 // descriptor address table offset #define DESCADDRESSTABLE_SIZE 52 // descriptor address table size #define N_NODES 56 // n_dynamics #define HEADER_SIZE (N_NODES-4) //((last_field + 4) - 8)=last_field-4 //32 #define HEADER_SIZE_IN_WORDS (HEADER_SIZE / 4) // in words #define INITIAL_EXTRA_HEAP_SIZE 0 // in words (each word is 4 bytes) #define INITIAL_EXTRA_HEAP_SIZE_IN_BYTES (INITIAL_EXTRA_HEAP_SIZE * 4) // Descriptor for graph_to_string function // called by writeDynamic .data #ifdef DEBUG nth_call: .long 0 #endif # ifdef COLLECT_TYPE_STRING_FOR_LAZY_RUN_TIME_IDS type_string_ptr: .long 0 # endif m__StdDynamic: .long 10 .ascii "StdDynamic" .byte 0,0 .align 4 #ifdef EXTRA_ARG // e____SystemDynamic__dcopy__graph__to__string__0x00010101 .long m__StdDynamic .align 4 .long e____SystemDynamic__dcopy__graph__to__string__0x00010101+2 .word 0 .word 1 .globl e____SystemDynamic__dcopy__graph__to__string__0x00010101 e____SystemDynamic__dcopy__graph__to__string__0x00010101: .word 0 .word 0 .long e____SystemDynamic__lcopy__graph__to__string__0x00010101 .word 1 .word 8 i_133: l_39: .long 23 .ascii "copy_graph_to_st" .ascii "ring_OK" .byte 0 #else // EXTRA_ARG .long m__StdDynamic .align 4 .long e____SystemDynamic__dcopy__graph__to__string__0x00010101+2 .word 0 .word 1 .globl e____SystemDynamic__dcopy__graph__to__string__0x00010101 e____SystemDynamic__dcopy__graph__to__string__0x00010101: .word 0 .word 0 .long e____SystemDynamic__lcopy__graph__to__string__0x00010101 .word 1 .word 8 i_24: l_7: .long 4 .ascii "test" #endif // Global variables across passes .align 4 t_stackP: .long 0 initfree: .long 0 // initial free words (4 bytes) // backup variables ecx_backup: .long 0 edx_backup: .long 0 old_heap_pointer: .long 0 // %edi before encoding started root_node: .long 0 // graph to be encoded #ifdef EXTRA_ARG type_table_usage: .long 0 range_table: .long 0 # ifdef USE_USED_CODE_LIBRARY_INSTANCE_ARRAY used_code_library_instance_array: .long 0 # endif #endif esp_backup: .long 0 // ------------------------------------------------------------------------------------------- // .text .align 4 .text .align 4 #ifdef EXTRA_ARG e____SystemDynamic__lcopy__graph__to__string__0x00010101: cmpl end_b_stack,%esp jb stack_overflow call ea11 cmpl end_heap,%edi jae i_408 i_409: movl $e____SystemDynamic__rWrap+2,(%edi) movl %ecx,4(%edi) movl %edi,%ecx addl $8,%edi ret i_408: call collect_1 jmp i_409 ea11: testb $2,(%ecx) jne e_44 cmpl end_a_stack,%esi jae stack_overflow call (%ecx) e_44: movl 4(%ecx),%ecx /* nop nop nop nop int3 */ // ********************* #else // EXTRA_ARG e____SystemDynamic__lcopy__graph__to__string__0x00010101: #ifdef UNBOXED_DYNAMIC call copy__graph__to__string__0x00010101_save_args #else call copy__graph__to__string__0x00010101 #endif cmpl end_heap,%edi jae i_102 i_103: movl $ARRAY+10,(%edi) movl %ecx,4(%edi) movl %edi,%ecx addl $8,%edi ret i_102: call collect_1 jmp i_103 #endif // ************************ // pass1 //.align 4 #ifdef UNBOXED_DYNAMIC copy__graph__to__string__0x00010101_save_args: movl %edx,edx_backup // value movl %ecx,ecx_backup // type #endif // .globl copy__graph__to__string__0x00010101 copy__graph__to__string__0x00010101: // int3 #ifdef UNBOXED_DYNAMIC cmpl end_heap,%edi jb box_toplevel_dynamic // collect without l because less than 32 bytes allocated movl edx_backup,%edx movl ecx_backup,%ecx call collect_2 movl %edx,edx_backup movl %ecx,ecx_backup box_toplevel_dynamic: movl $e____SystemDynamic__rDynamicTemp+2,8(%edi) movl ecx_backup,%eax // type movl %eax,16(%edi) movl edx_backup,%eax // value movl %eax,12(%edi) leal 8(%edi),%eax movl %eax,root_node #endif #ifdef DEBUG incl nth_call #endif #ifdef DYNAMIC_STRINGS call init_lazy_block_id #endif /* ** Warning: ** This function needs at least some space to operate. Because the run-time system ** probably uses memory both before and after the call, not enough memory will ** cause an access violation. ** called by the Clean and the garbage collector */ // backup state; DO_NOT_CHANGE ... #ifdef EXTRA_ARG #ifdef UNBOXED_DYNAMIC #define temp %eax movl -4(%esi),temp movl temp,type_table_usage movl -8(%esi),temp movl temp,range_table #undef temp #else // not UNBOXED_DYNAMIC #ifdef USE_CGTSA_AND_CGTSR movl %ecx,ecx_backup #define temp %eax movl CGTSA_DYNAMIC(%ecx),temp // find root movl temp,root_node movl 8(%ecx),%edx // get arg block movl CGTSA_TYPE_LIBRARY_INSTANCES(%edx),temp // copy type library instances array movl temp,type_table_usage # ifdef USE_USED_CODE_LIBRARY_INSTANCE_ARRAY movl CGTSA_CODE_LIBRARY_INSTANCES(%edx),temp // copy type library instances array movl temp,used_code_library_instance_array # endif movl CGTSA_RANGE_TABLE(%edx),temp // copy range table movl temp,range_table #undef temp #else // not USE_CGTSA_AND_CGTSR movl %ecx,type_table_usage movl %edx,root_node #define temp %eax movl -4(%esi),temp movl temp,range_table #undef temp #endif // not USE_CGTSA_AND_CGTSR #endif // not UNBOXED_DYNAMIC #else // not EXTRA_ARG #error "not EXTRA ARG" movl %ecx,root_node // backup root node, MUST BE FIRST #endif // not EXTRA_ARG pushl %esi // backup A-stack pointer movl %esp,esp_backup // backup esp movl heapP,old_heap_pointer // backup heap pointer // compute free space movl end_heap,free leal 32(free),free subl heapP,free // free = stackP - heapP (in bytes) shrl $2,free // free /= 4 (in longs) movl free,initfree // initfree = initial amount of memory available // ... DO_NOT_CHANGE (The garbage collector handler depends upon correct initialization) #ifdef COLOUR_GRAPH _set_default_undo_handler // After the first pass, the stack size will be fixed but the second pass which deletes // indirections in SN-nodes traverses the graph as a whole in contrast to the first // colouring pass which traverses the graph on a dynamic base. // However, the graph has almost been traversed completely because the top-level dynamic // has been traversed. Additional 8 bytes for its two arguments are needed, to increase // the maximum stack size. // At label copy_done_colouring_finished the stack is enlarged by the size of the two // arguments of the top-level dynamic by subtracting 2 * 4 bytes from the StackTop. In // this way the stack is always big enough. subl $2,free js GC_NO_STACK #endif // COLOUR_GRAPH // initialize stack subl $ INITIAL_EXTRA_HEAP_SIZE,free // try to reserve INITIAL_EXTRA_HEAP_SIZE js GC_NO_STACK movl end_heap,stackP leal 32(stackP),stackP // end_heap + 32 is invalid; thus 32 - 4 = 28 movl stackP,extraheapBottom movl stackP,extraP subl $ INITIAL_EXTRA_HEAP_SIZE_IN_BYTES,stackP movl stackP,stackBottom movl stackP,stackTop subl $(2 + HEADER_SIZE_IN_WORDS),free js GC_NO_STACK movl $__STRING__+2,(heapP) // store STRING descriptor movl $0,4(heapP) // string length is zero leal ((2 * 4) + HEADER_SIZE)(heapP),heapP movl %ecx,nodeP // top node of graph to be encoded # ifdef CONVERT_LAZY_RUN_TIME_ID call MAKE_ID_NRTID(lb_init) # endif #ifdef COLOUR_GRAPH call MAKE_ID_NSN(lb_init) call MAKE_ID_NDL(lb_init) jmp copy_done #else #define ML_COPY(x) x##_1 jmp ML_COPY(copy_next_node_in_nodeP) // pass 1; COPY #define ML(x) x##_1 #define EXIT_LABEL copy_done #define ENTRY_LABEL copy_next_node_1 #define ENTRY_LABEL_NODEP copy_next_node_in_nodeP_1 #define UNFIXED_STACK #define COPY_PASS #include "gts_copy.c" #undef COPY_PASS #undef EXIT_LABEL #endif // -------------------------------------------------------------------------------------------------------- // 2nd pass function_name_list: .long 0 module_name_list: .long 0 n_nodes: .long 0 .align 4 #include "prefixes.c" #ifdef COLOUR_GRAPH .align 4 .data .align 4 s_copy_done: .long __STRING__+2 .long 9 .ascii "copy_done" // 012345678901234567890123456789012345678901234567890123456 .byte 0 .byte 0 .byte 0 .byte 0 s_interleaved_subcomponents: .long __STRING__+2 .long 66 .ascii "graph_to_string ERROR: interleaved subcomponents are unimplemented" // 012345678901234567890123456789012345678901234567890123456789012345 .byte 0 .byte 0 .byte 0 .byte 0 .align 4 debug_count: .long 0 counter: .long 0 en_list_base_address: .long 0 .data .align 4 blocks_are_not_successive: .long __STRING__+2 .long 117 // .ascii "aap" // .ascii "(graph_to_string; internal error) blocks are not successive" // 012345678901234567890123456789012345678901234567890123456789012345 // 0 1 2 3 4 5 .ascii "(graph_to_string.c; internal error; blocks are not successive): pa" .ascii "ss the HyperStrictEvaluation-option to WriteDynamic" .byte 0 .byte 0 .byte 0 .byte 0 .align 4 build_block_cannot_be_stored: .long __STRING__+2 .long 72 // 012345678901234567890123456789012345678901234567890123456789012345 // 0 1 2 3 4 5 .ascii "(graph_to_string.c; internal error; build_block-closure cannot be " .ascii "stored." .byte 0 .byte 0 .byte 0 .byte 0 .align 4 counter_backup: .long 0 .align 4 current_colour: .long 0 block_n: .long 0 // points to free block number old_heapP: .long 0 // point to start address of block #ifdef EXTEND_DESCRIPTOR_USAGE_TABLE dus_entry_bsize: // size of descriptor usage set-entry .long 0 // adapt also function read_descriptor_usage_table in StdDynamicLowLevelInterface.icl #ifdef EXTEND_DUS_WITH_LIBARY_NUMBER // fixed part: #define DUS_DESC_ADDRESS_ENTRY 0 #define DUS_LIBRARY_NUMBER 4 #define DUS_FIXED_ENTRY_BSIZE (DUS_LIBRARY_NUMBER + 4) #define DUS_FIXED_ENTRY_WSIZE (DUS_FIXED_ENTRY_BSIZE / MACHINE_WORD_BSIZE) // variable part: #define DUS_SET 8 #else // fixed part: #define DUS_DESC_ADDRESS_ENTRY 0 #define DUS_FIXED_ENTRY_BSIZE (DUS_DESC_ADDRESS_ENTRY + 4) #define DUS_FIXED_ENTRY_WSIZE (DUS_FIXED_ENTRY_BSIZE / MACHINE_WORD_BSIZE) // variable part: #define DUS_SET 4 #endif // EXTEND_DUS_WITH_LIBARY_NUMBER #endif // EXTEND_DESCRIPTOR_USAGE_TABLE #endif // COLOUR_GRAPH // ------------------------------------------------------------- // pass2 .data keer: .long 0 ptr_to_dynamic_to_be_added: .long 0 stored_ptr_to_dynamic: .long 0 #ifdef COPIED_DYNAMICS current_dynamic_node: .long 0 #endif .text #ifdef COLOUR_GRAPH is_dynamic_in_list: movl (%ecx),%ecx // get ptr to stored Dynamic-node #define ptr_to_dynamic %ecx #define ptr_to_searched_dynamic %eax #define temp %ebx movl ptr_to_dynamic_to_be_added,ptr_to_searched_dynamic // retrieve searched dynamic movl 4(ptr_to_dynamic),temp // compare 1st fields cmpl temp,4(ptr_to_searched_dynamic) jne is_dynamic_in_list_end movl 8(ptr_to_dynamic),temp // compare 2nd fields cmpl temp,8(ptr_to_searched_dynamic) jne is_dynamic_in_list_end movl $0,ptr_to_dynamic_to_be_added movl ptr_to_dynamic,stored_ptr_to_dynamic #undef temp #undef ptr_to_dynamic is_dynamic_in_list_end: ret /* ** Disadvantages: ** - equally nodes can have several entries in the shared nodes array. ** A node is equal if: ** 1) the descPs exactly match ** 2) the nodes have the same colour ** (A hash-table could be used to search whether or not the array already ** contains such an element. There is always the possibility that a node ** has to be split because a colouring might change. If colours change a ** lot the table grows rapidly. It is probably not a good solution.) ** The current solution guarantees: ** - each node there is exactly one sn entry ** - element descriptors of arrays are also entered */ /* colour_copied_dynamics_with_colour_of_original: // nodeP - ptr to copy dynamic node // descP - pt movl stored_ptr_to_dynamic,%ebx // ptr to original dynamic // is die al opgeslagen? eigenlijk moet hetzelfde dynamic zijn. nop nop nop */ visit_nodes: _stack_empty visit_nodes_done _popl nodeP visit_nodes_from_nodeP: // nodeP contains the candidate node to colour #define sh_entry %ebx movl (nodeP),sh_entry // (nodeP) is always an indirection testl $1,sh_entry // test bit#0 for indirection jne visit_nodes_with_indirection // if set then copy the indirection call MAKE_ID_USN(lb_alloc_entry) // alloc for node and colour index movl sh_entry,SN_DESCP(%ecx) // store descP movl $ TOPLEVEL_COLOUR,SN_COLOUR(%ecx) // alloc node leal 1(%ecx),%ecx // make an indirection into movl %ecx,(nodeP) // shared nodes table // a dynamic? cmpl $e____SystemDynamic__rDynamicTemp+2,sh_entry jne visit_nodes_update_sh_entry #ifdef COPIED_DYNAMICS // A dynamic is the same iff the value and type-field are the same pointers. movl nodeP,ptr_to_dynamic_to_be_added pushl %ebx pushl %ecx movl $ is_dynamic_in_list,%ecx call MAKE_ID_UDL(lb_map_array) popl %ecx popl %ebx cmpl $0,ptr_to_dynamic_to_be_added je visit_nodes_update_sh_entry // dynamic is unique within list, add it. movl ptr_to_dynamic_to_be_added,nodeP pushl %ecx call MAKE_ID_UDL(lb_alloc_entry) // alloc for dynamic movl nodeP,(%ecx) popl %ecx #endif visit_nodes_update_sh_entry: movl %ecx,sh_entry // indirection to sh_entry decl sh_entry movl $ TOPLEVEL_COLOUR,%ecx // jmp visit_nodes_initial_colour visit_nodes_with_indirection: decl sh_entry // undo indirection, sh_entry is ptr in shared node #define node_colour %ecx movl SN_COLOUR(sh_entry),node_colour // get node colour /* // test ... cmpl $1,node_colour jne w int3 int3 w: // ... test */ visit_nodes_initial_colour: cmpl previous_colour_combinations,node_colour // node_colour >= previous_colour_combinations jae visit_nodes // skip colouring the current node because it has already been visited // node_colour < previous_colour_combinations i.e. node has not yet been coloured call MAKE_ID_UCT(lb_index_of_entry) #undef node_colour #define colour_entry %ecx cmpl $0,(colour_entry) // get colour table index at node_colour of the colour table jne visit_nodes_already_assigned_a_new_colour // a new colour has already been assigned to the old colour // int3 // nop // nop // nop pushl sh_entry // back up sh_entry #define temp2 sh_entry pushl colour_entry // backup colour entry call MAKE_ID_UCT(lb_size) // get new colour to be allocated movl %ecx,temp2 // temp2 contains new colour popl colour_entry // restore colour entry movl temp2,(colour_entry) // set new node colour in table by using colour_entry popl temp2 // restore sh_entry #undef temp2 pushl %ecx call MAKE_ID_UCT(lb_alloc_entry) // allocate new colour popl %ecx visit_nodes_already_assigned_a_new_colour: #define temp2 %ecx movl (colour_entry),temp2 // replace (old) node colour by new colour movl temp2,SN_COLOUR(sh_entry) #ifdef COLOUR_GRAPH movl temp2,array_colour #endif // COLOUR_GRAPH #undef temp2 #undef colour_entry // node has been recoloured, now its children are put on the stack movl SN_DESCP(sh_entry),descP // get descriptor pointer of node #undef sh_entry visit_nodes_push_args: #define ML(x) x##_vs #define ENTRY_LABEL visit_nodes #define ENTRY_LABEL_NODEP visit_nodes_from_nodeP #define PUSH_BOXED_ARGS #define UNFIXED_STACK #define COLOUR_PASS #define IGNORE_MODULE_ID #define IGNORE_BUILD_BLOCK // debug ... // incl keer // cmpl $9,keer // jne debug // int3 //debug: // ... debug testl $2,descP je ML(resolve_closure_indirection) #include "gts_delete.c" // PASS1: COLOURING visit_nodes_done: // int3 ret #endif // COLOUR_GRAPH reset_colour_table_entry: movl $0,(%ecx) // should be initialized at zero ret reset_colour_table_entry2: // movl $0,(%ecx) // should be initialized at zero ret copy_done_no_top_level_dynamic: int3 int3 nop nop jmp copy_done_no_top_level_dynamic // PASS 1: colour graph copy_done: // delete_indirections #ifdef DEBUG call need_debug movl root_node,nodeP #endif #ifdef COLOUR_GRAPH call MAKE_ID_NEN(lb_init) // initialize Entry Node (EN) array #define en_node %ecx movl root_node,nodeP // int3 call MAKE_ID_NEN(lb_alloc_entry) movl (nodeP),descP movl descP,EN_DESCP(en_node) movl $ TOPLEVEL_COLOUR,EN_COLOUR(en_node) _set_undo_handler $undo_colouring // update root node (from this point on: only U and F permitted) leal 1(en_node),en_node movl en_node,(nodeP) #undef en_node // colour rest of graph cmpl $e____SystemDynamic__rDynamicTemp+2,descP jne copy_done_no_top_level_dynamic copy_done_top_level_dynamic: call MAKE_ID_UDL(lb_alloc_entry) // add top level dynamic to dynamic list movl nodeP,(%ecx) call init_colour_table // initialize colour table #define counter %ecx #define limit %ebx movl $1,limit movl $0,counter // counter initialized at zero // int3 copy_done_loop: pushl limit movl counter,counter_backup // body ... call MAKE_ID_UDL(lb_index_of_entry) movl (%ecx),nodeP // nodeP is a DynamicTemp node #ifdef COPIED_DYNAMICS movl nodeP,current_dynamic_node #endif // colour value call MAKE_ID_UCT(lb_size) movl %ecx,previous_colour_combinations pushl 8(nodeP) // backup type node movl 4(nodeP),nodeP // current node is value node movl $ reset_colour_table_entry,%ecx call MAKE_ID_UCT(lb_map_array) // reset colour table nop nop nop call visit_nodes_from_nodeP // colour it // colour type call MAKE_ID_UCT(lb_size) movl %ecx,previous_colour_combinations popl nodeP movl $ reset_colour_table_entry,%ecx call MAKE_ID_UCT(lb_map_array) // reset colour table nop nop nop call visit_nodes_from_nodeP // colour it // ... body movl counter_backup,counter popl limit cmpl $0,counter jne limit_does_not_change_any_more pushl counter call MAKE_ID_UDL(lb_size) // n_dynamics movl %ecx,limit popl counter limit_does_not_change_any_more: incl counter cmpl counter,limit jne copy_done_loop #undef counter #undef limit // int3 movl MAKE_ID_SN(lb_root),%eax #ifdef DEBUG call need_debug #endif /* i: int3 jmp i */ // -------------------------------------------------------------------------------------- // PASS 2: copying & determing entry nodes copy_done_colouring_finished: // The 8 bytes have already been reserved during initialization. It is mainly // done for making the undo_colouring-routine more simple. subl $8,stackTop #define sh_entry descP #undef sh_entry movl $ reset_colour_table_entry,%ecx call MAKE_ID_FCT(lb_map_array) // reset colour table movl $ 0,%ecx call MAKE_ID_FEN(lb_index_of_entry) #define entry_node %ecx #define temp nodeP movl SN_COLOUR(entry_node),temp orl $ ENSN_COLOUR_SET_EN_BIT,temp movl temp,EN_COLOUR(entry_node) // mark as entry node #undef temp movl $0,EN_NODE_INDEX(entry_node) #ifndef DETERMINE_ENTRY_NODES movl $ ((2 * 4) + HEADER_SIZE),EN_BLOCK_OFFSET(entry_node) #else #define temp nodeP movl root_node,nodeP movl nodeP,EN_NODEP(entry_node) // NEW!!! set nodeP to be used in pass 2 #undef temp #endif #undef entry_node movl $ INITIAL_BLOCK_N,block_n // initialize block_n call MAKE_ID_FBI(lb_init) // assumption: at least one dynamic #define temp2 %ecx movl root_node,nodeP // nodeP = root nodeP // set colour of root dynamic movl $ 0,temp2 call MAKE_ID_FEN(lb_index_of_entry) movl EN_COLOUR(temp2),temp2 andl $ ENSN_COLOUR_GET_COLOUR,temp2 movl temp2,current_colour #ifdef DETERMINE_ENTRY_NODES #ifdef COMPUTE_TYPETABLE_ID_FROM_MODULE_ID call init_range_id #endif #include "gts_determine_entry_nodes.c" #else // not DETERMINE_ENTRY_NODES //// OLD_COPY_PASS #ifdef COMPUTE_TYPETABLE_ID_FROM_MODULE_ID call init_range_id #endif _set_undo_handler $undo_copying // Each node now has a colour associated with it. // // For the moment it is assumed that pieces graph are allocated in successive // space. // // Each site in the code where descP are copied in the string should be // changed e.g. arrays. Look for '// also for array'. #undef temp2 movl heapP,graph_start // backup start of encoded graph #define ML(x) x##_ccn #define ENTRY_LABEL copy_next_node_ccn #define ENTRY_LABEL_NODEP copy_next_node_in_nodeP_ccn #define OLD_COPY_PASS copy_nodes_with_current_colour: /* int3 pushl %eax movl current_colour,%eax popl %eax nop nop */ movl heapP,old_heapP jmp ML(copy_next_node_in_nodeP) // encode nodes having current colour #define EXIT_LABEL copy_done_current_colour_copied #define COPY_PASS #include "gts_copy.c" #undef COPY_PASS EXIT_LABEL: #define newHeapP descP movl heapP,newHeapP // new heap pointer subl old_heapP,newHeapP // newHeapP = newHeapP - old_heapP #define block_size newHeapP shll $16,block_size movl current_colour,%ecx call MAKE_ID_FCT(lb_index_of_entry) movl (%ecx),%ecx andl $0x0000fffc,%ecx orl %ecx,block_size // 1234; 12 = (partial) block size, 34 = block index #define block_info block_size call MAKE_ID_FBI(lb_alloc_entry) // alloc block info entry movl block_info,(%ecx) #undef newHeapP #undef block_size cmpl esp_backup,%esp je copy_equally_coloured_nodes_finished // assumption: // - the stack contains only nodes which colour has not yet been // current_colour NIET WAAR. Furthermore the copy algorithm leaves different // colours than the current colour unmodified. Thus it is always // a pointer to a sn. popl nodeP movl (nodeP),descP cmpl heapP,descP // descP <= heapP; can be removed once assumption holds jbe EXIT_LABEL // node has already been encoded #define new_current_colour %ecx decl descP movl SN_COLOUR(descP),new_current_colour // get new current colour andl $ ENSN_COLOUR_GET_COLOUR,new_current_colour movl new_current_colour,current_colour #undef temp jmp copy_nodes_with_current_colour #undef EXIT_LABEL #endif // DETERMINE_ENTRY_NODES // -------------------------------------------------------------------------------------- copy_equally_coloured_nodes_finished: #ifdef DEBUG2 int3 int3 int3 int3 #endif // int3 #ifdef COMPUTE_TYPETABLE_ID_FROM_MODULE_ID call restore__Module_descriptors #endif nop nop nop movl heapP,graph_end // backup end of graph encoding nop nop nop #define temp nodeP call MAKE_ID_FBI(lb_size) // # blocks allocated + allocated root block // int3 movl block_n,temp shrl $2,temp cmpl %ecx,temp je 0f // I think blocks are never interleaved because after the first pass it is // known which nodes belong to a block. Equally coloured nodes are encoded // together. // Using DETERMINE_ENTRY_NODES blocks are never interspersed with other // blocks 1: int3 // movl block_n,%esp movl MAKE_ID_EN(lb_root),%ebx nop nop nop nop movl root_node,%eax // block are not successive // jmp 1b movl $ blocks_are_not_successive,%ecx jmp abort 0: #undef temp #define temp nodeP // The associated descriptors of a block are computed here and stored just after the // stringtable. movl block_n,temp shrl $2,temp addl $31,temp shrl $5,temp // temp = set size (in words) movl temp,usage_bit_set_size #ifdef MAKE_DUS_SYMBOLIC addl $ DUS_FIXED_ENTRY_WSIZE,temp // temp = set size + size of fixed part #else incl temp // temp = set size + backup first characters of string #endif movl temp,set_entry_size_in_words // store entry size in words shll $2,temp movl temp,set_entry_size_in_bytes // store entry size in bytes #ifdef EXTEND_DESCRIPTOR_USAGE_TABLE movl temp,dus_entry_bsize movl heapP,dus_start #endif #define STORE_USAGE_BIT_SET_SIZE #ifdef STORE_USAGE_BIT_SET_SIZE #define DUS_USAGE_BIT_SIZE 0 #define DUS_N_USAGE_ENTRIES 4 #define DUS_HEADER_BSIZE (DUS_N_USAGE_ENTRIES + 4) #define DUS_HEADER_WSIZE (DUS_N_USAGE_ENTRIES / MACHINE_WORD_BSIZE) subl $2,free js garbage_collection2 #define temp2 %ecx movl usage_bit_set_size,temp2 // store entry size in words movl temp2,DUS_USAGE_BIT_SIZE(heapP) movl $0,n_usage_entries // intilialize usage entry counter addl $ DUS_HEADER_BSIZE,heapP #undef temp2 #endif _set_undo_handler $undo_descriptor_usage #ifdef LAZY_DYNAMICS_1 // test ... movl $ replace_build_block_by_build_lazy_block,%ecx call MAKE_ID_FSN(lb_map_array) // ... test #endif movl $ compute_descriptor_usage,%ecx call MAKE_ID_FSN(lb_map_array) // The top-level dynamic is only inserted in the EN-table and not in the SN-table. Thus // compute_descriptor_usage movl $ 0,%ecx call MAKE_ID_FEN(lb_index_of_entry) // int3 call compute_descriptor_usage // test ... movl $ compute_descriptor_usage,%ecx call MAKE_ID_FEN(lb_map_array) // ... test #ifdef EXTEND_DESCRIPTOR_USAGE_TABLE #define dus_n_usage_entries %eax movl dus_start,dus_n_usage_entries #define temp3 %ebx movl n_usage_entries,temp3 movl temp3,DUS_N_USAGE_ENTRIES(dus_n_usage_entries) #undef temp3 #undef dus_n_usage_entries movl heapP,dus_end #endif jmp delete_indirections #undef temp #ifdef LAZY_DYNAMICS_1 // HACK: replace each build_block by lazy_block replace_build_block_by_build_lazy_block: cmpl $ e____SystemDynamic__nbuild__block,SN_DESCP(%ecx) jne replace_build_block_by_build_lazy_block_end movl $ e____SystemDynamic__nbuild__lazy__block,SN_DESCP(%ecx) replace_build_block_by_build_lazy_block_end: ret #endif // compute_descriptor_usage: // // the descriptor usage table is constructed for each SN-node. The algorithm can // be divided in: // - creating a dus-entry // - marking a dus-entry as used by a colour // // A dus entry looks like this: // 0 first four characters, backuped from the descriptor name // 4 library instance number // 12 marking set. Size is number of colours. // ? // // dynamicTemp voor root dynamic moet ook een entry in EN krijgen // call MAKE_ID_EN (het aflopen van SN is genoeg moet alleen nog root toevoegen) // descriptors van arrays 'inherit // TODO: // - descriptors van arrays (gaat goed) compute_descriptor_usage: // int3 #define sn_entry %ecx // compute pointer to descriptor name (similar to fragment in _copy_name) #define temp nodeP movl SN_COLOUR(sn_entry),temp andl $ ENSN_COLOUR_GET_COLOUR,temp pushl temp #ifdef ARRAY_DESCP movl temp,array_colour // backup array colour for its elements #endif movl SN_DESCP(sn_entry),descP #define LAZY_DYNAMICS_3 #ifdef LAZY_DYNAMICS_3 cmpl $ e____SystemDynamic__nbuild__block,descP jne hiero movl $ e____SystemDynamic__nbuild__lazy__block,descP hiero: #endif #undef sn_entry #ifdef ARRAY_DESCP // descP = descriptor pointer // tos = colour of parent node compute_descriptor_usage_got_descP: movl descP,descP_backup #endif call compute_label_name_ptr #define desc_nameP source #define setP descP movl 4(desc_nameP),setP testl setP,setP jns 3f // allocate space for four characters and set shll $1,setP jmp compute_descriptor_usage_got_space_for_set // allocate space 3: subl set_entry_size_in_words,free js GC_FIXED_STACK // initialize new block #ifdef STORE_USAGE_BIT_SET_SIZE incl n_usage_entries // count usage table entries #endif movl setP,(heapP) // backup first four characters #define setP_backup arity movl heapP,setP_backup // backup pointer #define temp nodeP movl heapP,temp stc rcrl $1,temp movl temp,4(desc_nameP) // first four characters of descriptor are marked and are pointer to dus-entry #undef temp #define counter nodeP #define limit descP movl $0,counter movl set_entry_size_in_words,limit decl limit addl $4,heapP 4: movl $0,(heapP) addl $4,heapP incl counter cmpl counter,limit jne 4b // empty descriptor usage set #undef counter #undef limit #ifdef EXTEND_DUS_WITH_LIBARY_NUMBER pushl setP_backup // backup ptr to dus entry movl desc_nameP,%ebx // load address in library call find_code_library_instance_nr // %eax = library instance number // movl $1,%eax popl setP // restore ptr to dus_entry // movl $9,%eax movl %eax,DUS_LIBRARY_NUMBER(setP) // store library number #else movl setP_backup,setP // restore setP #endif // EXTEND_DUS_WITH_LIBARY_NUMBER #undef setP_backup compute_descriptor_usage_got_space_for_set: // setP = address of set entry // tos = current colour #define current_colour arity popl current_colour call MAKE_ID_FCT(lb_index_of_entry) #define associated_block current_colour movl (associated_block),associated_block andl $0x0000fffc,associated_block shrl $2,associated_block // get block_n #define word_index_in_set nodeP movl associated_block,word_index_in_set shrl $5,word_index_in_set // word index in set #define bit_index_in_set_word associated_block movl associated_block,bit_index_in_set_word // index of bit to be set in that word andl $31,bit_index_in_set_word #define temp source movl $1,temp shll %cl,temp // build proper mask #undef associated_block #undef bit_index_in_set_word #define set_word arity movl DUS_FIXED_ENTRY_BSIZE(setP,word_index_in_set,4),set_word orl temp,set_word movl set_word,DUS_FIXED_ENTRY_BSIZE(setP,word_index_in_set,4) #undef set_word #undef setP #undef temp #undef current_colour #undef desc_nameP #ifdef ARRAY_DESCP movl descP_backup,descP cmpl $__ARRAY__+2,descP jne 0f /* nop nop nop int3 nop nop nop */ movl 8(nodeP),descP pushl array_colour jmp compute_descriptor_usage_got_descP 0: #endif ret #endif // COLOUR_GRAPH #ifdef COLOUR_GRAPH // **** // compute_label_name_ptr // precondition: // - descP contains a valid (unmodified) descriptor pointer // postcondition: // - source contains the descName compute_label_name_ptr: testl $2,descP je 0f // closure detected movzwl -2(descP),arity cmpl $256,arity jb 1f #define desc_nameP source movl -6(descP),desc_nameP // get descriptor name jmp compute_descriptor_usage_got_name 1: #define temp nodeP movzwl (descP),temp // temp = partial arity * 8 leal -2(descP),desc_nameP // desc_nameP = descP - 2 subl temp,desc_nameP // desc_nameP = descP - arity * 8 movzwl -2(desc_nameP),temp // temp = total arity of descriptor leal 4(desc_nameP,temp,8),desc_nameP // desc_nameP = ptr to descriptor name jmp compute_descriptor_usage_got_name // closures 0: movl -8(descP),desc_nameP // get descP movl -4(descP),arity cmpl $256,arity jae 2f movzwl -2(desc_nameP),temp leal 4(desc_nameP,temp,8),desc_nameP jmp compute_descriptor_usage_got_name #undef temp 2: leal -8(desc_nameP),desc_nameP compute_descriptor_usage_got_name: #undef desc_nameP ret #endif // COLOUR_GRAPH // **** // ----------------------------------------------------------------------------------------- // Heap situation: // - the modified descriptors i.e. first four characters have been backup and replaced by a pointer in the // descriptor address table. // - (nodeP) has bit#0 set. Two cases: // 1) (nodeP) < heapP i.e. an indirection via the encoded graph // 2) otherwise i.e. (nodeP) is a SN/EN-pointer // pass 1; DELETE #define ML(x) x##_1 #define ENTRY_LABEL delete_next_indirection_1 #define ENTRY_LABEL_NODEP delete_next_indirection_in_nodeP_1 #define EXIT_LABEL deletion_done_1 #define DELETE_PASS #define RESTORE_MODULE_ID #define RESTORE_BUILD_BLOCK // define stack behaviour //#define PUSHL _pushl_no_gc delete_indirections: #ifdef DEBUG2 int3 nop nop nop int3 #endif movl $0,n_nodes #define t0 %eax movl stackTop,t0 movl t0,descStackTop #undef t0 movl root_node,nodeP // descriptor prefix table may never start at offset 0 movl $0,function_name_list movl $0,module_name_list movl heapP,string_table_base jmp ML(delete_next_indirection_in_nodeP) #include "gts_delete.c" #undef EXIT_LABEL // -------------------------------------------------------------------------------------------------- // called from the first pass garbage_collection: nop nop nop nop nop nop nop nop // int3 // int3 // reset pointers movl stackBottom,stackP movl esp_backup,%esp jmp delete_indirections .data .align 4 virtual_base_offset: .long 0 descriptor_address_table_base: .long 0 #ifdef COLOUR_GRAPH descP_backup: .long 0 //array_colour: // .long 0 #endif // COLOUR_GRAPH n_bits: .byte /* 0-15 */ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 .byte /* 16-31 */ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5 .byte /* 32-47 */ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5 .byte /* 48-63 */ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6 .byte /* 64-79 */ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5 .byte /* 80-95 */ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6 .byte /* 96-111 */ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6 .byte /* 112-127 */ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7 .byte /* 128-143 */ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5 .byte /* 144-159 */ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6 .byte /* 160-175 */ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6 .byte /* 176-191 */ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7 .byte /* 192-207 */ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6 .byte /* 208-223 */ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7 .byte /* 224-239 */ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7 .byte /* 240-255 */ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 .align 4 #ifdef COLOUR_GRAPH current_block_index: .long 0 current_block_index_word: .long 0 current_block_index_bit: .long 0 current_block_n_en_nodes: .long 0 //current_block_bi_ptr: // .long 0 #endif // COLOUR_GRAPH .text #ifdef COLOUR_GRAPH // loops over block infos // computes offsets only for used descriptors and sets the current block in // current_block_index. adjust_offset_per_block: movl $0,current_block_n_en_nodes // count amount of entry nodes in a block pushl %ecx // backup BI-ptr // determine block index #define block_index nodeP movl (%ecx),block_index andl $0x0000fffc,block_index shrl $2,block_index // convert block number to set index movl block_index,current_block_index // compute proper word in set #define temp descP movl block_index,temp shrl $5,temp movl temp,current_block_index_word #undef temp // compute proper bit within that word andl $31,block_index movl block_index,%ecx // %cl = number of bits to shift #define temp descP movl $1,temp // make mask shll %cl,temp movl temp,current_block_index_bit #undef temp #undef block_index // initialize block #define desc_prefix_entry descP #ifdef EXTEND_DESCRIPTOR_USAGE_TABLE // _debug // TODO: // - stackP should re-initialized for each stack. In this way routines executing // between passes does not need to save it. pushl stackP #define dus_p stackP movl dus_start,dus_p #ifdef STORE_USAGE_BIT_SET_SIZE leal DUS_HEADER_BSIZE(dus_p),dus_p // skip usage entry size #endif // STORE_USAGE_BIT_SET_SIZE #else movl stackTop,desc_prefix_entry #endif // EXTEND_DESCRIPTOR_USAGE_TABLE movl $4,virtual_base_offset // initial virtual base offset // there is always at least one descriptor adjust_offset_per_block_end_initialize_loop: #ifdef EXTEND_DESCRIPTOR_USAGE_TABLE movl DUS_DESC_ADDRESS_ENTRY(dus_p),desc_prefix_entry #else subl $ DESCRIPTOR_PREFIX_ENTRY_BSIZE, desc_prefix_entry // do { #endif // determine whether the descriptor is used by the current block #define setP arity // later movl DPT_DESCP_USAGE_SET_PTR(desc_prefix_entry),setP addl current_block_index_word,setP // compute proper word in set and #ifdef MAKE_DUS_SYMBOLIC movl DUS_SET(setP),setP // load it (4 means first four characters) #else movl 4(setP),setP // load it (4 means first four characters) #endif // MAKE_DUS_SYMBOLIC testl current_block_index_bit,setP jz adjust_offset_per_block_skip_descriptor // descriptor is used by block #undef setP // identical with _adapt_encoded_graph ... #define temp nodeP movl virtual_base_offset,temp // set virtual base offset movl temp,DPT_VIRTUAL_BASE(desc_prefix_entry) #ifdef COMPUTE_LIBRARY_NUMBER_WEG int3 pushl %eax movl $0xffffffff,%eax movl %eax,DPT_LIBRARY_NUMBER(desc_prefix_entry) popl %eax #endif #define temp2 arity movl DPT_PREFIX_SET_AND_STRING_PTR(desc_prefix_entry),temp2 andl $0xff000000,temp2 shrl $24,temp2 addl $n_bits,temp2 movzbl (temp2),temp2 // bitset length leal (temp,temp2,4),temp2 movl temp2,virtual_base_offset #undef temp2 #undef temp // ... identical with _adapt_encoded_graph adjust_offset_per_block_skip_descriptor: #ifdef EXTEND_DESCRIPTOR_USAGE_TABLE addl dus_entry_bsize,dus_p cmpl dus_end,dus_p jb adjust_offset_per_block_end_initialize_loop #undef dus_p popl stackP #else cmpl desc_prefix_entry,descStackTop jb adjust_offset_per_block_end_initialize_loop // } while descStackTop < desc_prefix_entry #endif adjust_offset_per_block_end_initialize: // The following is valid at this point: // - offsets of *used* descriptor have been computed // - current_block_index contains the block being adjusted // // block = piece of encoded graph // // Now all references to descriptors in the block have to // be adjusted. movl $ adjust_offsets_in_EN_block,%ecx call MAKE_ID_FEN(lb_map_array) popl %ecx // restore BI-ptr #define temp nodeP movl current_block_n_en_nodes,temp movl temp,BI_N_EN_NODES(%ecx) // update BI #undef temp ret // adjust_offsets_in_EN_block // // The conditions above must be valid. This routine partially adapts the // block with which the EN-node is associated. adjust_offsets_in_EN_block: #define en_node %ecx #define en_block nodeP movl EN_NODE_INDEX(en_node),en_block andl $0x0000fffc,en_block shrl $2,en_block // convert block number to set index cmpl current_block_index,en_block jne adjust_offsets_in_EN_block_share_prefixes_done #undef en_block incl current_block_n_en_nodes // count amount of entry nodes in the current block // compute string offset for the EN-node #define string_start nodeP #define en_block_offset descP movl old_heap_pointer,string_start movl EN_BLOCK_OFFSET(en_node),en_block_offset leal (string_start,en_block_offset),%esi #undef string_start #undef en_block_offset movl EN_NODE(en_node),nodeP // make EN-node root node #undef en_node // start adjusting movl heapP,descriptor_address_table_base // to be removed (?) movl (stringP),%ecx // get encoded descP // determine descP of entry node movl (nodeP),descP leal -1(descP),descP pushl (descP) jmp adjust_offsets_in_EN_block_share_next_prefixes_skip_root_EN //adjust_offsets_in_EN_block_share_prefixes_in_nodeP // ----------------- // An entry node has been found. If it belongs to another colour i.e. block as the current // colour i.e. current block, then it is external to the block being adjusted. // If both entries belong to the same colour i.e. block, then it is unknown if this pass // can continue adjusting offsets. If the next address at which to adjust does not equal // the address at which the found entry node starts, then the remaining nodes can be // adjusted. // If not and the stack is empty i.e. no more nodes to adjust then we have arrived at the // true end of the subcomponent of the current entry. We can then safely quit the process. // Otherwise the current subcomponent is interleaved with other components. // At the moment is not quite clear for me if this can happen, but I detect it. A solution // could be to change the copying algoritm to terminate copying a subcomponent if an entry // node of the same colour is encountered. In this case an internal indirection is needed // to refer to the other subcomponent. This has not been implemented yet. adjust_offsets_in_EN_block_entry_node_found: // nodeP is an entry node #define en_node descP movl (nodeP),en_node decl en_node // undo EN-indirection #define en_block_n arity movl EN_NODE_INDEX(en_node),en_block_n andl $0x0000fffc,en_block_n shrl $2,en_block_n // test .. movl $0,times // ... test cmpl current_block_index,en_block_n // equally coloured? jne adjust_offsets_in_EN_block_share_next_prefixes // no // determine whether to continue adjusting offsets for the current entry node #define temp nodeP movl EN_BLOCK_OFFSET(en_node),temp addl old_heap_pointer,temp cmpl temp,stringP jne adjust_offsets_in_EN_block_share_next_prefixes // continue adjusting offsets #undef temp _stack_empty adjust_offsets_in_EN_block_share_next_prefixes movl $ s_interleaved_subcomponents,%ecx jmp abort #undef en_block_n #undef en_node // ----------------- // HIER .data times: .long 0 .text kk: int3 adjust_offsets_in_EN_block_share_next_prefixes: _stack_empty adjust_offsets_in_EN_block_share_prefixes_done _popl nodeP cmpl $0,nodeP je kk adjust_offsets_in_EN_block_share_prefixes_in_nodeP: // incl times // cmpl $7,times // jne ll // int3 //ll: // Anne // pruning ... ; indirections; order is important #define temp arity movl (stringP),temp testl $1,temp jne adjust_offsets_in_EN_block_share_prefixes_indirection // entry_nodes testl $1,(nodeP) jnz adjust_offsets_in_EN_block_entry_node_found // ... pruning // no indirection or entry node movl (nodeP),descP // get descP pushl descP adjust_offsets_in_EN_block_share_next_prefixes_skip_root_EN: // The test whether an offset has already been computed can be eliminated because // all offsets are precomputed. #define ML(x) x##_ao_en #define GTS_COPY_ONLY_ENCODE_MACRO #include "gts_copy.c" // @@@@@@@@@@@@ ML(_adapt_encoded_graph) temp #undef temp popl descP #define SHARE_PREFIXES #define SHARE_PREFIXES2 //#define ML(x) x##_ao_en #define ENTRY_LABEL adjust_offsets_in_EN_block_share_next_prefixes #define ENTRY_LABEL_NODEP adjust_offsets_in_EN_block_share_prefixes_in_nodeP #define EXIT_LABEL adjust_offsets_in_EN_block_share_prefixes_done // define stack behaviour //#define PUSHL _pushl_no_gc #include "gts_copy.c" #undef EXIT_LABEL adjust_offsets_in_EN_block_share_prefixes_done: ret adjust_offsets_in_EN_block_share_prefixes_indirection: addl $4,stringP jmp adjust_offsets_in_EN_block_share_next_prefixes mark_EN_nodes_as_such: #define en_node %ecx movl EN_NODE(en_node),nodeP // get Entry Node #define temp descP leal 1(%ecx),temp movl temp,(nodeP) // replace descriptor by indirection to Entry Node #undef temp ret #undef en_node unmark_EN_nodes_as_such: #define en_node %ecx movl EN_NODE(en_node),nodeP movl EN_DESCP(en_node),descP movl descP,(nodeP) ret #undef en_node #endif // COLOUR_GRAPH .align 4 deletion_done_1: #ifdef DEBUG2 int3 nop nop nop nop int3 #endif movl heapP,string_table_end #define name_p arity #define temp nodeP #define temp2 descP removing_forwarding_pointers_in_strings: movl function_name_list,name_p #define t0 stackP #define t1 source #define t2 heapP pushl t0 pushl t1 pushl t2 movl stackTop,t0 movl string_table_base,t2 remove_function_names: jecxz end_remove_function_names movl (name_p),temp // temp = address function name in descriptor shll $1,temp movl (temp),temp andl $0x00ffffff,temp nop leal (t2,temp),temp // temp = address in string table nop movl -4(temp),temp2 // get length movl temp2,(name_p) // restore length in descriptor string movl (temp),temp2 // get 1st four characters xchg temp2,4(name_p) // exchange name_p with 1st four chars movl temp2,name_p jmp remove_function_names end_remove_function_names: popl t2 popl t1 popl t0 #undef t2 #undef t1 #undef t0 movl module_name_list,name_p remove: jecxz end_remove_forwarding_pointers movl (name_p),temp shll $1,temp // temp = pointer to name of function movl -4(temp),temp2 // get length movl temp2,(name_p) // restore length in descriptor string movl (temp),temp2 // get 1st four characters xchg temp2,4(name_p) // exchange name_p with 1st four chars movl temp2,name_p jmp remove end_remove_forwarding_pointers: #undef temp #undef name_p #undef temp2 #ifdef COLOUR_GRAPH testl free,free js garbage_collection2 // graph has been restored, do a gc (graph has been restored) _set_default_undo_handler movl $ mark_EN_nodes_as_such,%ecx // EN-nodes are marked by setting bit#0 call MAKE_ID_FEN(lb_map_array) // computing the proper descP offset within a single component. The dynamic linker // will use the order of the descriptor address table to build a table for each block // separately. // // First the entry nodes of a particular block are traversed and marked as having been // visited, offsets are adapted accordingly. // int3 // int3 // movl MAKE_ID_EN(lb_root),%ebx pushl %edi movl $ adjust_offset_per_block,%ecx call MAKE_ID_FBI(lb_map_array) movl $ unmark_EN_nodes_as_such,%ecx call MAKE_ID_FEN(lb_map_array) popl %edi // encode descriptor prefix table ... #define dus_p arity #define dus_end_p descP movl dus_start,dus_p #ifdef STORE_USAGE_BIT_SET_SIZE leal DUS_HEADER_BSIZE(dus_p),dus_p // skip usage entry size #endif // STORE_USAGE_BIT_SET_SIZE movl dus_end,dus_end_p 0: #define temp nodeP movl (dus_p),temp // get descriptor prefix table ptr movl DPT_PREFIX_SET_AND_STRING_PTR(temp),temp movl temp,(dus_p) #undef temp addl dus_entry_bsize,dus_p cmpl dus_end_p,dus_p jb 0b #undef dus_p #undef dus_end_p // ... encode descriptor prefix table /* movl MAKE_ID_BI(lb_root),%eax qqq: int3 jmp qqq ret ret ret ret ret ret */ // #endif // COLOUR_GRAPH #else #error "test" // ******************************************************************************************* // PASS 3: // // Task: // establish sharing of prefixes within one descriptor. The following subtasks are performed: // 1) compute base offsets for each descriptor (within the descriptor address table) // 2) modify the encoded graph to virtual offsets (within the descriptor address table) // ******************************************************************************************* // pass3 //#define stringP source share_prefixes: cmpl $0,free // free >= 0 jle GC_FIXED_STACK #define temp %eax movl stackTop,temp subl descStackTop,temp // temp shrl $1,temp subl temp,free // reserve for descriptor address table js GC_FIXED_STACK #undef temp movl heapP,descriptor_address_table_base // init movl $4,virtual_base_offset // initial virtual base offset movl root_node,nodeP // root of graph movl old_heap_pointer,stringP leal ((2 * 4) + HEADER_SIZE)(stringP),stringP jmp share_prefixes_in_nodeP share_next_prefix: _stack_empty share_prefixes_done _popl nodeP share_prefixes_in_nodeP: #define t1 arity // %ecx movl (stringP),t1 // t1 = encoded node testl $1,t1 jne share_prefixes_indirection // an indirection; share_next_prefix; advance stringP #define ML(x) x##_sp #define GTS_COPY_ONLY_ENCODE_MACRO #include "gts_copy.c" ML(_adapt_encoded_graph) t1 //l2137 #undef t1 movl (nodeP),descP #define SHARE_PREFIXES #define ENTRY_LABEL share_next_prefix #define ENTRY_LABEL_NODEP share_prefixes_in_nodeP #define EXIT_LABEL share_prefixes_done #include "gts_copy.c" #undef EXIT_LABEL #ifdef SHARE_PREFIXES share_prefixes_indirection: leal 4(stringP),stringP jmp share_next_prefix #endif share_prefixes_done: #endif // COLOUR_GRAPH finished: // ******************************************************************************************* cmpl $0,free // free >= 0 jg prepare_to_return garbage_collection2: movl old_heap_pointer,heapP // release string memory #define usedCells %eax movl initfree,usedCells subl free,usedCells leal -32(heapP,usedCells,4),free // reserve usedCells * 4 from old heap start, gebruik l-entry # ifdef UNBOXED_DYNAMIC // A dynamic moved from an abstract representation to a concrete record representation. As records // are passed unboxed. The dynamic is splitted over edx (value) and %ecx (type). popl %esi movl esp_backup,%esp movl edx_backup,%edx movl ecx_backup,%ecx # else // not UNBOXED_DYNAMIC # ifdef EXTRA_ARG # ifdef USE_CGTSA_AND_CGTSR movl ecx_backup,%ecx # else movl type_table_usage,%ecx movl root_node,%edx # endif # else // not EXTRA_ARG movl root_node,%ecx # endif // not EXTRA_ARG movl esp_backup,%esp // restore B/C stackpointer popl %esi # endif // not UNBOXED_DYNAMIC #ifdef EXTRA_ARG # ifdef USE_CGTSA_AND_CGTSR call collect_1l # else call collect_2l # endif #else call collect_1l #endif #undef usedCells nop nop nop nop nop // ret jmp copy__graph__to__string__0x00010101 // -------------------------------------------------------------------------------------- /* ** string format: */ prepare_to_return: // int3 // movl esp_backup,%esp #define temp %eax prepare_to_return2: #ifdef COLOUR_GRAPH // misschien vooraf alles tussen heapP en end_heap vrijgeven. #define BK_BLOCK_N 0 #define BK_START_OFFSET 4 // offset (in bytes) from encoding start #define BK_SIZE 8 // block size (in bytes) #define BK_N_EN_NODES 12 // # EN-nodes in block #define BK_BASIC_BSIZE (BK_N_EN_NODES + 4) #define BK_BASIC_WSIZE (BK_BASIC_BSIZE / MACHINE_WORD_BSIZE) // in bytes // block table // store # blocks call MAKE_ID_FBI(lb_size) #define n_blocks %ecx // create index array for quick block array access subl n_blocks,free js garbage_collection2 // int3 // nop // int3 movl n_blocks,temp shll $2,temp movl temp,index_array_size // size of index array (in bytes) movl heapP,index_array_ptr // backup index array_pointer leal (heapP,n_blocks,4),heapP // create index array for blocks // create block array movl heapP,block_table_start // backup block table start subl $1,free js garbage_collection2 movl n_blocks,(heapP) // amount of blocks #undef n_blocks addl $4,heapP movl $ create_block_table,%ecx // create block table call MAKE_ID_FBI(lb_map_array) movl $ insert_en_nodes_in_block_table,%ecx call MAKE_ID_FEN(lb_map_array) // overwrite index_array with block table /* #define s_block_table nodeP movl heapP,s_block_table subl block_table_ptr,s_block_table // s_block_table = size of block table movl s_block_table,block_table_size #undef s_block_table */ #define block_table_p nodeP #define index_array_p descP #define block_table_end heapP movl block_table_start,block_table_p // load start address of block table movl index_array_ptr,index_array_p // load start address of index array movl index_array_p,block_table_start // new start address of block table 1: cmpl block_table_end,block_table_p jae 0f // block_table_p >= block_table_end #define temp2 arity movl (block_table_p),temp2 movl temp2,(index_array_p) #undef temp2 addl $4,block_table_p addl $4,index_array_p jmp 1b 0: subl index_array_size,heapP // free index array movl heapP,block_table_end2 #undef block_table_end #undef index_array_p #undef block_table_p #endif // COLOUR_GRAPH movl old_heap_pointer,%ecx movl heapP,%eax subl %ecx,%eax subl $8,%eax movl %eax,4(%ecx) // length (%eax) = heapP - old_heap_pointer - 8 #define t2 descP #define t3 stackP movl old_heap_pointer,temp leal 8(temp),temp // temp = ptr to string start #ifdef COLOUR_GRAPH // set header size movl $ HEADER_SIZE,t3 subl $4,t3 movl t3,HEADER_SIZE_OFFSET(%ecx) // header size // set version number of encoding routine movl $ VERSION_NUMBER,t2 movl t2,VERSION_NUMBER_OFFSET(%ecx) // set graph offset and size movl graph_start,t2 movl graph_end,t3 subl t2,t3 // t3 = graph_end - graph_start movl t3,GRAPH_SIZE(%ecx) subl temp,t2 // t2 = graph_start - string start movl t2,GRAPH_OFFSET(%ecx) // set block table offset and size movl block_table_start,t2 movl block_table_end2,t3 subl t2,t3 // t3 = graph_end - graph_start movl t3,BLOCK_TABLE_SIZE(%ecx) subl temp,t2 // t2 = graph_start - string start movl t2,BLOCK_TABLE_OFFSET(%ecx) movl $0x0,DYNAMIC_RTS_INFO_OFFSET(%ecx) movl $0x0,DYNAMIC_RTS_INFO_SIZE(%ecx) // End sharing for StdDynamic.icl // set string table offset and size movl string_table_start,t2 movl string_table_end,t3 subl t2,t3 movl t3,STRINGTABLE_SIZE(%ecx) subl temp,t2 movl t2,STRINGTABLE_OFFSET(%ecx) // set descriptor usage set offset and size movl dus_start,t2 movl dus_end,t3 subl t2,t3 movl t3,DESCADDRESSTABLE_SIZE(%ecx) subl temp,t2 movl t2,DESCADDTRESTABLE_OFFSET(%ecx) // set nodes movl n_nodes,t3 movl t3,N_NODES(%ecx) nop nop nop #else movl $ HEADER_SIZE,t3 subl $4,t3 movl t3,HEADER_SIZE_OFFSET(%ecx) // header size movl $ HEADER_SIZE,t3 movl t3,GRAPH_OFFSET(%ecx) // in future there may be a gap between header and graph offset movl $ VERSION_NUMBER,t2 movl t2,VERSION_NUMBER_OFFSET(%ecx) movl string_table_base,t2 subl temp,t2 movl t2,STRINGTABLE_OFFSET(%ecx) // set stringtable offset (t2_ subl t3,t2 movl t2,GRAPH_SIZE(%ecx) movl descriptor_address_table_base,t2 subl temp,t2 movl t2,DESCADDTRESTABLE_OFFSET(%ecx) movl STRINGTABLE_OFFSET(%ecx),t3 subl t3,t2 movl t2,STRINGTABLE_SIZE(%ecx) movl heapP,t3 subl temp,t3 subl DESCADDTRESTABLE_OFFSET(%ecx),t3 movl t3,DESCADDRESSTABLE_SIZE(%ecx) movl n_nodes,t3 movl t3,N_NODES(%ecx) #endif // COLOUR_GRAPH #ifdef COLOUR_GRAPH //#error "COLOUR_GRAPH: adapting header not yet implemented" /* #define BLOCK_TABLE_OFFSET 24 #define BLOCK_TABLE_SIZE 28 */ #else movl $0,BLOCK_TABLE_OFFSET(%ecx) movl $0,BLOCK_TABLE_SIZE(%ecx) #endif #undef temp // #undef t2 #undef t3 // movl esp_backup,%esp // restore B/C stackpointer popl %esi #ifdef EXTRA_ARG // OLD: leal -4(%esi),%esi #ifdef DYNAMIC_STRINGS pushl %ecx // backup ptr to encoded dynamic call MAKE_ID_FDS(lb_size) movl %ecx,%eax // %eax = n_elements to store addl %eax,%ecx addl %eax,%ecx addl $3,%ecx pushl %esi subl %ecx,free // reserve heap js garbage_collection2 popl %esi movl %eax,%ecx #ifdef USE_CGTSA_AND_CGTSR movl %edi,backup_lazy_dynamic_index_array #else // not USE_CGTSA_AND_CGTSR movl %edi,-8(%esi) #endif movl $__ARRAY__+2,(%edi) // fill array header movl %ecx,4(%edi) movl $e__StdDynamicLowLevelInterface__rLazyDynamicReference+2,8(%edi) addl $12,%edi pushl %esi movl $ fill_dynamic_string,%ecx call MAKE_ID_FDS(lb_map_array) popl %esi # ifdef CONVERT_LAZY_RUN_TIME_ID // int3 call MAKE_ID_FRTID(lb_size) movl %ecx,%eax // n_elements to store addl %eax,%ecx addl %eax,%ecx addl $3,%ecx // shll $1,%ecx // n_elements * 2 + 3 words // addl $3,%ecx pushl %esi subl %ecx,free js garbage_collection2 popl %esi movl %eax,%ecx // get n_elements back movl %edi,backup_runtime_ids movl $__ARRAY__+2,(%edi) movl %ecx,4(%edi) movl $e__DynamicLinkerInterface__rRunTimeIDW+2,8(%edi) addl $12,%edi pushl %esi movl $ fill_runtime_ids,%ecx call MAKE_ID_FRTID(lb_map_array) popl %esi // movl backup_runtime_ids,temp // movl temp,CGTSR_RUNTIME_IDS(heap) # endif popl %ecx // restore ptr to encoded dynamic #ifndef USE_CGTSA_AND_CGTSR subl $4,%esi #endif // not USE_CGTSA_AND_CGTSR #else // not DYNAMIC_STRINGS // aanname: genoeg geheugen movl $__ARRAY__+2,(%edi) movl $0,4(%edi) movl $0,8(%edi) movl %edi,-8(%esi) addl $12,%edi subl $4,%esi #endif // int3 #ifdef USE_CGTSA_AND_CGTSR subl $ 12+CGTSR_ARG_BLOCK_SIZE,free js garbage_collection2 // int3 pushl heapP #define temp %eax // Node // (%edi) : CopyGraphToStringResults-descriptor // 4(%edi) : string containing encoded dynamic (%ecx) // 8(%edi) : ptr to arg block movl $ e____SystemDynamic__rCopyGraphToStringResults+2,(heapP) movl %ecx,CGTSR_ENCODED_DYNAMIC(heapP) // ptr to encoded dynamic leal 12(heapP),temp movl temp,8(heapP) // ptr to arg block addl $12,heapP // Arg block // layout of argument block // movl %ecx,12(heapP) // cgtsr_encoded_dynamic #define cgtsa %ebx movl ecx_backup,cgtsa movl 8(cgtsa),cgtsa // ptr to arg block movl CGTSA_CODE_LIBRARY_INSTANCES(cgtsa),temp movl temp,CGTSR_CODE_LIBRARY_INSTANCES(heapP) movl CGTSA_TYPE_LIBRARY_INSTANCES(cgtsa),temp movl temp,CGTSR_TYPE_LIBRARY_INSTANCES(heapP) movl backup_lazy_dynamic_index_array,temp movl temp,CGTSR_LAZY_DYNAMIC_REFERENCES(heapP) # ifdef CONVERT_LAZY_RUN_TIME_ID movl backup_runtime_ids,temp movl temp,CGTSR_RUNTIME_IDS(heapP) # endif addl $ CGTSR_ARG_BLOCK_SIZE,heapP #undef cgtsa popl %ecx // ptr to CGTSR-node #undef temp #else // not USE_CGTSA_AND_CGTSR movl %ecx,%edx movl type_table_usage,%ecx #endif // not USE_CGTSA_AND_CGTSR #endif ret #ifdef DYNAMIC_STRINGS fill_dynamic_string: /* OLD ... movl (%ecx),%eax movl %eax,(heapP) // addl $4,heapP OLD ... OLD */ // new ... movl (%ecx),%eax // movl %eax,4(heapP) movl %eax,(heapP) movl 4(%ecx),%eax movl %eax,4(heapP) // NEW3... movl 8(%ecx),%eax movl %eax,8(heapP) // ...NEW3 // addl $8,heapP OLD addl $12,heapP // NEW3 // ... new ret #endif // DYNAMIC_STRINGS #ifdef COLOUR_GRAPH // insert en-nodes in block table // Two tasks: // 1. fill variable sized part of block table // 2. min (BK_START_OFFSET,current offset) (en-nodes of a block are encoded succesive) insert_en_nodes_in_block_table: // int3 #define en_node %ecx #define temp descP movl EN_NODE_INDEX(en_node),temp // get node index pushl temp // backup node index andl $0x0000ffff,temp shrl $2,temp // temp = block index #define block_table_entry nodeP movl index_array_ptr,block_table_entry leal (block_table_entry,temp,4),block_table_entry movl (block_table_entry),block_table_entry #undef temp #define en_offset descP movl EN_BLOCK_OFFSET(en_node),en_offset // get offset in subl $ (HEADER_SIZE + 8),en_offset #undef en_node // store minimum offset of EN-nodes in block table #define current_block_offset arity movl ((- BK_BASIC_BSIZE) + BK_START_OFFSET)(block_table_entry),current_block_offset // get current block offset cmpl en_offset,current_block_offset jbe 0f // current_block_offset <= en_offset movl en_offset,((- BK_BASIC_BSIZE) + BK_START_OFFSET)(block_table_entry) // store smaller offset #undef current_block_offset 0: #define en_index arity popl en_index // restore node index // _debug cmpl $0,((- BK_BASIC_BSIZE) + BK_N_EN_NODES)(block_table_entry) je 1f shrl $16,en_index // extract entry node index /* cmpl $1,en_index cmpl $0,en_index je 1f decl en_index */ movl en_offset,(block_table_entry,en_index,4) #undef en_offset 1: #undef block_table_entry ret // creates the block table create_block_table: // int3 #define bi_block %ecx subl $ BK_BASIC_WSIZE,free // allocate basic block js garbage_collection2 // get & store block number #define block_n nodeP movl BI_INFO(bi_block),block_n andl $0x0000ffff,block_n shrl $2,block_n movl block_n,BK_BLOCK_N(heapP) #define temp descP movl index_array_ptr,temp leal (temp,block_n,4),temp // temp = address in index_array for block_n leal BK_BASIC_BSIZE(heapP),block_n movl block_n,(temp) // store address to variable sized of block_n #undef temp #undef block_n movl $0xffffffff,BK_START_OFFSET(heapP) // minimum of start offsets of the block EN-nodes // extract & store block size #define temp nodeP movl BI_INFO(bi_block),temp shrl $16,temp movl temp,BK_SIZE(heapP) #undef temp // store amount of block entry nodes #define n_en_nodes nodeP movl BI_N_EN_NODES(bi_block),n_en_nodes cmpl $1,n_en_nodes jne 0f decl n_en_nodes // n_en_nodes is zero 0: // decl n_en_nodes // each block has at least one entry node movl n_en_nodes,BK_N_EN_NODES(heapP) addl $ BK_BASIC_BSIZE,heapP // reserve heap memory for the block entry nodes subl n_en_nodes,free // reserve a machine word for each entry node js garbage_collection2 shll $2,n_en_nodes addl n_en_nodes,heapP #undef n_en_nodes #undef bi_block ret # ifdef CONVERT_LAZY_RUN_TIME_ID fill_runtime_ids: #define temp %eax movl RTID_TYPE_STRING(%ecx),temp movl temp,RTID_TYPE_STRING(heapP) movl RTID_RUNTIME_ID(%ecx),temp movl temp,RTID_RUNTIME_ID(heapP) movl RTID_ASSIGNED_DISK_ID(%ecx),temp movl temp,RTID_ASSIGNED_DISK_ID(heapP) addl $ RTID_SIZE,heapP ret // CONVERT_LAZY_RUN_TIME_ID #undef temp # endif .data .align 4 index_array_ptr: .long 0 index_array_size: .long 0 // general graph_start: .long 0 graph_end: .long 0 block_table_start: .long 0 block_table_end2: .long 0 dus_start: .long 0 dus_end: .long 0 usage_bit_set_size: .long 0 n_usage_entries: .long 0 #endif // COLOUR_GRAPH .data .align 4 string_table_start: string_table_base: .long 0 string_table_end: .long 0 backup_lazy_dynamic_index_array: .long 0 # ifdef CONVERT_LAZY_RUN_TIME_ID backup_runtime_ids: .long 0 # endif