implementation module decode_dynamic; import StdEnv; import directory_structure; // Linker import DLState; import shared_buffer; import link_library_instance; import dynamics; import pdObjectToMem; import link_switches; from type_io_common import create_type_string; import ExtArray; import ExtString; import ExtInt; //import DynamicLinkerInterface; from DynamicLinkerInterface import ::GetBlockAddress_Out(..), instance EnDecode GetBlockAddress_Out,::RunTimeIDW(..), instance DefaultElem RunTimeIDW, instance EnDecode RunTimeIDW; // Compiler import utilities; import memory_mapped_files; from encode_dynamic import dereference_rt_lib_ref; // should be moved to Request.icl ComputeDescAddressTable2_n_args :== 4; ComputeDescAddressTable2_n_copy_request_args :== 6; init_lazy_dynamic :: !.Int !*DLClientState !*f -> *(Int,*DLClientState,!*f) | FileEnv f; init_lazy_dynamic id dl_client_state io = init_dynamic2 "LAZY DYNAMIC" True id dl_client_state io; // physically reads in file and initializes the administration for the dynamic by init_dynamic2 init_dynamic :: {#.Char} !Bool !Int !Int !{#String} !*DLClientState !*f -> *(!Int,!*DLClientState,!*f) | FileEnv f & FileSystem f; init_dynamic file_name False id block_i args dl_client_state io = (id,dl_client_state,io); init_dynamic file_name first_time id block_i args dl_client_state io // create a new id #! (id,dl_client_state) = new_dynamic_id dl_client_state; #! msg = "** Encoded a dynamic (e.g. from disk): " +++ toString id; #! (dl_client_state) = AddMessage (Verbose msg) dl_client_state; # (id,dl_client_state,io) = get_tables_from_dynamic args file_name id dl_client_state io; #! msg = "dynamic: '" +++ file_name +++ "' id: " +++ toString id +++" block: " +++ toString block_i; #! (dl_client_state) = AddMessage (Verbose msg) dl_client_state; = init_dynamic2 file_name first_time id dl_client_state io; where { get_tables_from_dynamic :: !{#String} !String !Int !*DLClientState *f -> *(Int,*DLClientState,*f) | FileSystem f; get_tables_from_dynamic args file_name id dl_client_state io #! dynamic_access = case (size args) of { ComputeDescAddressTable2_n_args -> "FILE"; // file containing dynamic is read by dynamic rts ComputeDescAddressTable2_n_copy_request_args -> "VIEW"; // view passed by the rts is read by dynamic rts }; #! dl_client_state = AddMessage (Verbose ("dynamic access: " +++ dynamic_access)) dl_client_state; | size args == ComputeDescAddressTable2_n_args // open dynamic #! (ok,dynamic_header,file,io) = open_dynamic_as_binary file_name io; | not ok #! (_,io) = close_dynamic_as_binary file io; #! msg = "could not open dynamic '" +++ file_name +++ "'"; #! dl_client_state = AddMessage (LinkerError msg) dl_client_state; = (0,dl_client_state,io); # (file,id,dl_client_state,io) = read_from_dynamic id file_name file dl_client_state io dynamic_header; # (_,io) = close_dynamic_as_binary file io; = (id,dl_client_state,io); | size args == ComputeDescAddressTable2_n_copy_request_args # file_mapping_handle = toInt args.[4]; # s_buffer = toInt args.[5]; # (ok,file) = OpenExistingSharedBuffer file_mapping_handle s_buffer | not ok = abort "get_tables_from_dynamic: OpenExistingSharedBuffer failed"; # (ok,dynamic_header,file) = read_dynamic_header file; | not ok = abort "get_tables_from_dynamic: error reading dynamic header"; # (file,id,dl_client_state,io) = read_from_dynamic id file_name file dl_client_state io dynamic_header; | CloseExistingSharedBuffer file = (id,dl_client_state,io); = abort "unreachable"; } // DynamicInfo init_dynamic2 file_name first_time id dl_client_state io #! (dl_client_state) = case first_time of { True -> AddMessage (Verbose ("init_dynamic2: dynamic id " +++ toString id)) dl_client_state; _ -> dl_client_state; }; #! ({di_disk_type_equivalent_classes,di_n_blocks},dl_client_state) = dl_client_state!cs_dynamic_info.[id]; | di_n_blocks <= 0 = abort "init_dynamic2; internal error; dynamic has no blocks"; #! (stringtable,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_string_table; #! (descriptor_usage_table,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_descriptor_usage_table; // lazy dynamics ... #! (di_lazy_dynamics_a,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_lazy_dynamics_a; #! (cs_n_lazy_dynamics,dl_client_state) = dl_client_state!cs_n_lazy_dynamics; #! n_lazy_disk_dynamics = size di_lazy_dynamics_a; #! di_disk_to_rt_dynamic_indices = createArray n_lazy_disk_dynamics 0; // allocate lazy dynamic ids for each lazy disk dynamic id #! dl_client_state = AddMessage (Verbose "Preallocation of its lazy dynamics") dl_client_state #! (di_disk_to_rt_dynamic_indices,cs_n_lazy_dynamics,dl_client_state) = loopAst ( \index (di_disk_to_rt_dynamic_indices,cs_n_lazy_dynamics,dl_client_state) -> let { cs_next_lazy_dynamic = inc cs_n_lazy_dynamics; msg = toString cs_n_lazy_dynamics +++ ": '" +++ di_lazy_dynamics_a.[index] } in ({di_disk_to_rt_dynamic_indices & [index] = cs_n_lazy_dynamics},cs_next_lazy_dynamic,AddMessage (Verbose msg) dl_client_state) ) (di_disk_to_rt_dynamic_indices,cs_n_lazy_dynamics,dl_client_state) n_lazy_disk_dynamics; // extend array to include new lazy dynamics #! (cs_lazy_dynamic_index_to_dynamic_id,dl_client_state) = get_lazy_dynamic_index_to_dynamic_id dl_client_state; #! (last_added_lazy_dynamic,cs_lazy_dynamic_index_to_dynamic_id) = extend_array_nu n_lazy_disk_dynamics cs_lazy_dynamic_index_to_dynamic_id; #! s_cs_lazy_dynamic_index_to_dynamic_id = inc last_added_lazy_dynamic; #! cs_lazy_dynamic_index_to_dynamic_id = ALLOW_LAZY_LIBRARY_REFERENCES (loopbAst (associate_lazy_dynamic_with_its_main_dynamic id) cs_lazy_dynamic_index_to_dynamic_id (s_cs_lazy_dynamic_index_to_dynamic_id - n_lazy_disk_dynamics) s_cs_lazy_dynamic_index_to_dynamic_id) cs_lazy_dynamic_index_to_dynamic_id ; #! dl_client_state = { dl_client_state & cs_lazy_dynamic_index_to_dynamic_id = cs_lazy_dynamic_index_to_dynamic_id }; #! dl_client_state = { dl_client_state & cs_n_lazy_dynamics = cs_n_lazy_dynamics }; # dl_client_state = { dl_client_state & cs_dynamic_info.[id].di_disk_to_rt_dynamic_indices = di_disk_to_rt_dynamic_indices }; // get info about the library instances used by the dynamic # (di_library_instance_to_library_index,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_library_instance_to_library_index; # (di_library_index_to_library_name,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_library_index_to_library_name; # s_library_instance_runtime_ids = size di_library_instance_to_library_index; # library_instance_runtime_ids // indexed by RunTimeID(diskID) to obtain library instance id = force_unboxed_int_array (createArray s_library_instance_runtime_ids (-1)); # (library_instance_runtime_ids,_,dl_client_state,io) = mapAiSt convert_string_id_to_runtime_id_for_a_library_instance di_library_instance_to_library_index (library_instance_runtime_ids,di_library_index_to_library_name,dl_client_state,io); # library_instance_runtime_ids = mapAiSt eliminate_library_redirections di_library_instance_to_library_index library_instance_runtime_ids; // ComputeDescAddress still contains diskIDs instead of real RunTimeIDs, so the conversion table // must be preserved. # dl_client_state = { dl_client_state & cs_dynamic_info.[id].di_disk_id_to_library_instance_i = library_instance_runtime_ids , cs_dynamic_info.[id].di_has_block_been_used = createArray di_n_blocks False }; // printing #! dl_client_state = AddMessage (Verbose "References to type-libraries i.e. type tables") dl_client_state; #! (type_tables,dl_client_state) = get_type_tables dl_client_state; #! (type_tables,dl_client_state) = loopAfill print_library_name type_tables dl_client_state; // updating #! dl_client_state = { dl_client_state & cs_type_tables = type_tables }; // Each dynamic has type equations which ensure that equivalent types have a single, unique representation // within a dynamic or even among several dynamics. It should be noted that by several does not imply all // dynamics: it depends upon the external types of dynamics which directly or indirectly could use the // dynamic being initialized here. // All lazy type equations are ignored here because the associated dynamics have not yet been initialized // let alone built which implies that the types implementations needed by these lazy dynamics can never // have been linked in already, so no type equations are needed to enforce this. Upon the first block built // of a lazy dynamic, the situation changes. // Hence only (eager) type equations will be stored in the type implementation table which is done below: // ... # (dl_client_state,io) = mapASt (enter_type_equations_in_type_implementation_table id) di_disk_type_equivalent_classes (dl_client_state,io); // # (dl_client_state,io) = case (COLLECT_AND_RENUMBER_EXTERNAL_TYPE_REFERENCES True False) of { False -> (dl_client_state,io); True #! (di_type_redirection_table,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_type_redirection_table; #! (x,(dl_client_state,io)) = real_mapAiSt convert_to_runtime_idw di_type_redirection_table (dl_client_state,io) #! dl_client_state = { dl_client_state & cs_dynamic_info.[id].di_rt_type_redirection_table = x }; -> (dl_client_state,io); }; = (id,dl_client_state,io); where { q :: {#RunTimeIDW} -> {#RunTimeIDW}; q a = a; convert_to_runtime_idw i type (dl_client_state,io) # (rt_type,(dl_client_state,io)) = convert_encoded_type_reference_to_rt_type_reference id type (dl_client_state,io); # ((type_name,module_name,_,_,_),dl_client_state) = get_info_library_instance_type_reference rt_type dl_client_state; # runtime_idw = { default_elem & rtid_type_string = create_type_string type_name module_name , rtid_runtime_id = encode_lib_ref rt_type }; = (runtime_idw,(dl_client_state,io)); associate_lazy_dynamic_with_its_main_dynamic main_dynamic_id i cs_lazy_dynamic_index_to_dynamic_id #! cs_lazy_dynamic_index_to_dynamic_id = { cs_lazy_dynamic_index_to_dynamic_id & [i] = {default_elem & ldi_parent_index = main_dynamic_id} }; = cs_lazy_dynamic_index_to_dynamic_id; eliminate_library_redirections i (LIK_LibraryRedirection disk_library_instance_i) library_instance_runtime_ids # no = abort "eliminate_library_redirections; lazy dynamics are unimplemented and turned off"; # (rt_library_instance_i,library_instance_runtime_ids) = library_instance_runtime_ids![disk_library_instance_i]; # library_instance_runtime_ids = { library_instance_runtime_ids & [i] = rt_library_instance_i }; # library_instance_runtime_ids = ALLOW_LAZY_LIBRARY_REFERENCES library_instance_runtime_ids no; | True <<- ("LIK_LibraryRedirection",disk_library_instance_i," to ",rt_library_instance_i) = ALLOW_LIBRARY_REDIRECTIONS library_instance_runtime_ids (abort "library redirections are not correctly implemented") ; eliminate_library_redirections i _ library_instance_runtime_ids = library_instance_runtime_ids; enter_type_equations_in_type_implementation_table id type_equations (dl_client_state,io) # type_equations = [ type \\ type <-: type_equations ]; # (types,(dl_client_state,io)) = mapSt (convert_encoded_type_reference_to_rt_type_reference id) type_equations (dl_client_state,io); #! (_,dl_client_state,io) = USE_ENTER_NEW_TYPE_EQUATIONS (enter_type_equation_new types dl_client_state io) (foo types dl_client_state io) ; = (dl_client_state,io); where { foo types dl_client_state io #! (Just (type_implementation_ref,created_new_type_equivalence_class),dl_client_state,io) = old_enter_type_equation (hd types) (hd (tl types)) dl_client_state io; #! dl_client_state = add_lazy_type_equations type_implementation_ref (tl (tl types)) dl_client_state; = (Nothing,dl_client_state,io); }; force_unboxed_int_array :: !*{#Int} -> !*{#Int}; force_unboxed_int_array i = i; convert_string_id_to_runtime_id_for_a_library_instance library_instance_string_id (LIK_LazyLibraryInstance {lik_library_instance_i,lik_dynamic_index_i}) s=:(library_instance_runtime_ids,di_library_index_to_library_name,dl_client_state,io) // skip reserved elements | library_instance_string_id < RTID_DISKID_RENUMBER_START = s //<<- (library_instance_string_id, "not accepted"); // name of lazy dynamic # (lazy_dynamic_name,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_lazy_dynamics_a // convert *disk* lazy library to *run-time* lazy library # (rt_lazy_dynamic_index,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_disk_to_rt_dynamic_indices.[lik_dynamic_index_i]; // consistency check # ({ldi_lazy_dynamic_index_to_dynamic=result},dl_client_state) = dl_client_state!cs_lazy_dynamic_index_to_dynamic_id.[rt_lazy_dynamic_index]; | isJust result // The lazy dynamics of the main dynamic being initialized here with identification id, are assigned numbers into // the cs_lazy_dynamic_index_to_dynamic_id-array which means that none of the code for the lazy dynamics has been // used yet and they therefore have not (yet) been initialized. = abort "encode_references_to_type_libraries; internal error; lazy dynamic has already been assigned a run-time id" # library_instance_runtime_ids = { library_instance_runtime_ids & [library_instance_string_id] = LLI_CREATE_LAZY_LIBRARY_INSTANCE lik_library_instance_i rt_lazy_dynamic_index }; = (library_instance_runtime_ids,di_library_index_to_library_name,dl_client_state,io); convert_string_id_to_runtime_id_for_a_library_instance library_instance_string_id (LIK_LibraryInstance {LIK_LibraryInstance | lik_index_in_di_library_index_to_library_name=library_name_i}) s=:(library_instance_runtime_ids,di_library_index_to_library_name,dl_client_state,io) // skip reserved elements | library_instance_string_id < RTID_DISKID_RENUMBER_START = s // convert string index for a library instance into a run-time index for that library instance # library_name = di_library_index_to_library_name.[library_name_i]; # (library_instance_i,_,dl_client_state,io) = RegisterLibrary (Just id) library_name dl_client_state io; # library_instance_runtime_ids = { library_instance_runtime_ids & [library_instance_string_id] = library_instance_i }; = (library_instance_runtime_ids,di_library_index_to_library_name,dl_client_state,io); convert_string_id_to_runtime_id_for_a_library_instance library_instance_string_id (LIK_LibraryRedirection _) s = s; print_library_name i a dl_client_state // printing #! (tt_name,a) = a![i].tt_name; #! (tt_loaded,a) = a![i].tt_loaded; #! msg = toString i +++ (if tt_loaded " (Loaded)" " (Not loaded)") +++ ": " +++ tt_name; #! dl_client_state = AddMessage (Verbose msg) dl_client_state; = (a,dl_client_state); }; read_from_dynamic :: !Int !String !*f !*DLClientState !.a !.DynamicHeader -> *(!*f,!Int,!*DLClientState,!.a) | BinaryDynamicIO f; read_from_dynamic id file_name file dl_client_state=:{cs_dlink_dir} io dynamic_header // read descriptor usage set table #! (ok,descriptor_usage_table,file) = read_descriptor_usage_table_from_dynamic dynamic_header file; | not ok #! msg = "could not read descriptor usage table '" +++ file_name +++ "'"; #! dl_client_state = AddMessage (LinkerError msg) dl_client_state; = (file,0,dl_client_state,io); // read string table #! (ok,stringtable,file) = read_string_table_from_dynamic dynamic_header file; #! dl_client_state = case ok of { True -> dl_client_state; False #! msg = "could not read string table from '" +++ file_name +++ "'"; -> AddMessage (LinkerError msg) dl_client_state; }; // read block table #! (ok,block_table,file) = read_block_table_from_dynamic dynamic_header file; #! dl_client_state = case ok of { True -> dl_client_state; False #! msg = "could not read block table from '" +++ file_name +++ "'"; -> AddMessage (LinkerError msg) dl_client_state; }; // read dynamic rts info #! (ok2,dynamic_info,file) = read_rts_info_from_dynamic dynamic_header file; #! dynamic_info = FILE_IDENTIFICATION { dynamic_info & di_library_index_to_library_name = { CONVERT_ENCODED_LIBRARY_IDENTIFICATION_INTO_RUN_TIME_LIBRARY_IDENTIFICATION cs_dlink_dir id \\ id <-: dynamic_info.di_library_index_to_library_name } , di_lazy_dynamics_a = { CONVERTED_ENCODED_DYNAMIC_FILE_NAME_INTO_PATH cs_dlink_dir lazy_dynamic_id \\ lazy_dynamic_id <-: dynamic_info.di_lazy_dynamics_a } } dynamic_info; // APPEND_LAZY_DYNAMIC_PATH // DynamicInfo #! dl_client_state = case ok2 of { True -> dl_client_state; False #! msg = "could not read dynamic rts info from '" +++ file_name +++ "'"; -> AddMessage (LinkerError msg) dl_client_state; }; # dynamic_info = { dynamic_info & di_string_table = stringtable , di_descriptor_usage_table = descriptor_usage_table , di_version = toVersion dynamic_header.version_number , di_file_name = file_name , di_n_blocks = size block_table }; # dl_client_state = UpdateDynamicInfo id dynamic_info dl_client_state = (file,id,dl_client_state,io); instance add_lazy_type_equations DLClientState where { add_lazy_type_equations index library_instance_type_references dl_client_state # (type_implementation_table,dl_client_state) = get_type_implementation_table dl_client_state; # type_implementation_table = add_lazy_type_equations index library_instance_type_references type_implementation_table; # dl_client_state = { dl_client_state & cs_type_implementation_table = type_implementation_table }; = dl_client_state; }; ComputeDescAddressTable2 :: !ProcessSerialNumber [String] !*DLServerState !*f -> !(!Bool,!ProcessSerialNumber,!*DLServerState, !*f) | FileSystem f & FileEnv f; ComputeDescAddressTable2 client_id [args] s io #! (client_exists,dl_client_state,s) = RemoveFromDLServerState client_id s; | not client_exists = internal_error "ComputeDescAddressTable2 (internal error): client not registered" client_id dl_client_state s io; #! (dl_client_state) = AddMessage (Verbose "ComputeDescAddressTable2") dl_client_state; #! args = ExtractArguments '\n' 0 args []; #! l_args = length args #! is_non_copy_request = (l_args == ComputeDescAddressTable2_n_args); #! is_copy_request = (l_args == ComputeDescAddressTable2_n_copy_request_args); | not (is_non_copy_request || is_copy_request) = internal_error ("ComputeDescAddressTable2 (internal error): didn't get expected arguments " +++ toString l_args) client_id dl_client_state s io; // extract arguments #! args = { arg \\ arg <- args }; #! file_name = args.[0]; #! first_time = args.[1] == "True"; #! id = toInt args.[2]; #! block_i = toInt args.[3]; #! (id,dl_client_state,io) = init_dynamic file_name first_time id block_i args dl_client_state io; // mark block as used ... #! (di_has_block_been_used,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_has_block_been_used; #! di_has_block_been_used = { x \\ x <-: di_has_block_been_used }; // make unique #! dl_client_state = { dl_client_state & cs_dynamic_info.[id].di_has_block_been_used = { di_has_block_been_used & [block_i] = True } }; // ... mark block as used # ({di_version,di_string_table,di_descriptor_usage_table,di_library_instance_to_library_index},dl_client_state) = dl_client_state!cs_dynamic_info.[id]; #! n_disk_libraries = size di_library_instance_to_library_index; #! used_disk_libraries = NewBitSet n_disk_libraries; #! (ok,latest_version,dl_client_state,s) = eager_read_version di_version dl_client_state s; // ... #! (dlink_dir,s) = GetDynamicLinkerDirectory s; #! module_name = dlink_dir +++ "\\" +++ copy_string_to_graph +++ "_" +++ (toFileNameSubString latest_version) +++ ".obj"; #! symbol_name = "e____SystemDynamic__d" +++ copy__string__to__graph +++ "__" +++ toFileNameSubString latest_version; #! (Just main_library_instance_i,dl_client_state) = dl_client_state!cs_main_library_instance_i; # conversion_dus_label = { default_elem & dusl_label_name = symbol_name , dusl_library_instance_i = main_library_instance_i , dusl_linked = False }; // ... # initial_labels = []; //conversion_dus_label]; # (do_dump_dynamic,dl_client_state) = dl_client_state!do_dump_dynamic; # (a,dl_client_state,s,io) = case do_dump_dynamic of { True -> (0,dl_client_state,s,io); _ # (maybe_to_graph_entry,dl_client_state) = get_to_graph_function_address2 (Just latest_version) dl_client_state; | isNothing maybe_to_graph_entry // Required conversion function not present -> abort ("ComputeDescAddressTable2: required conversion function not found >>" +++ toFileNameSubString latest_version); #! ({tafge_conversion},i) = fromJust maybe_to_graph_entry #! (a,dl_client_state,s,io) = case tafge_conversion of { Nothing # (dl_client_state,s,io) = add_object_module_to_library_instance module_name main_library_instance_i dl_client_state s io; # (_,[address:_],dl_client_state,io) = LoadLibraryInstance_new main_library_instance_i (Just [conversion_dus_label]) dl_client_state io; # dl_client_state = { dl_client_state & cs_to_and_from_graph.tafgt_to_graphs.[i].tafge_conversion = Just address }; -> (address,dl_client_state,s,io); Just address -> (address,dl_client_state,s,io); }; -> (a,dl_client_state,s,io); }; // address #! (n_addresses,used_disk_libraries) = mapAiSt (compute_used_libraries_in_current_block block_i) di_descriptor_usage_table (length initial_labels,used_disk_libraries); #! (used_disk_libraries,(dus_labels,dl_client_state,s,io)) = enum_setSt (link_library_instance di_string_table di_descriptor_usage_table block_i id n_addresses) used_disk_libraries (initial_labels,dl_client_state,s,io); // ----------------------------------------------- #! addresses = createArray n_addresses 0; #! dus_labels_a = createArray n_addresses default_elem; #! (addresses,dus_labels) = foldSt fill_addresses_and_dus_labels dus_labels (addresses,dus_labels_a); #! dus_labels = [conversion_dus_label : [ dus_label \\ dus_label <-: dus_labels ] ]; #! symbol_addresses = [ a : [ address \\ address <-: addresses ] ]; #! (dl_client_state,io) = case first_time of { False -> (dl_client_state,SendAddressToClient client_id (/* toString DYN_OK,*/ id,symbol_addresses) io); True #! (library_instance_runtime_ids,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_disk_id_to_library_instance_i; #! (di_disk_to_rt_dynamic_indices,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_disk_to_rt_dynamic_indices; #! (di_rt_type_redirection_table,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_rt_type_redirection_table; #! (di_rt_type_redirection_table,dl_client_state) = case COLLECT_AND_RENUMBER_EXTERNAL_TYPE_REFERENCES True False of { False -> ({},dl_client_state); True // | size di_rt_type_redirection_table == 0 // -> abort "RegisterLazyDynamic; internal error; null sized di_rt_type_redirection_table"; -> (di_rt_type_redirection_table,dl_client_state); }; #! msg = { gba_o_diskid_to_runtimeid = library_instance_runtime_ids , gba_o_disk_to_rt_dynamic_indices = di_disk_to_rt_dynamic_indices , gba_o_id = id , gba_o_addresses = (FromIntToString id) +++ foldl (\s i -> s +++ (FromIntToString i)) "" symbol_addresses , gba_o_rt_type_redirection_table = di_rt_type_redirection_table } -> (dl_client_state,SendAddressToClient client_id (encode msg) io); }; // check for errors #! (ok,dl_client_state) = IsErrorOccured dl_client_state; | not ok = (not ok,client_id,AddToDLServerState dl_client_state s,io); // verbose #! messages = if do_dump_dynamic (foldl2 produce_verbose_output2 [] (tl dus_labels) (tl symbol_addresses)) (foldl2 produce_verbose_output2 [] dus_labels symbol_addresses); #! dl_client_state = SetLinkerMessages messages dl_client_state ; = (not ok,client_id,AddToDLServerState dl_client_state s,io); where { fill_addresses_and_dus_labels:: !u:DusLabel !*(!*{#Int},!*{#DusLabel}) -> (!*{#Int},!*{#DusLabel}); fill_addresses_and_dus_labels dus_label=:{dusl_linked,dusl_ith_address,dusl_address} (addresses,dus_labels_a) #! addresses = { addresses & [dusl_ith_address] = dusl_address }; #! dus_labels_a = { dus_labels_a & [dusl_ith_address] = dus_label }; = (addresses,dus_labels_a); // computes which disk libraries are needed to build the current block compute_used_libraries_in_current_block :: !.Int .a !.DescriptorUsageEntry !*(!.Int,!*BitSet) -> (Int,.BitSet); compute_used_libraries_in_current_block block_i _ {bitset,prefix_set_and_string_ptr,dus_library_instance_nr_on_disk} (ith_address,used_disk_libraries) #! (prefixes,_,_) = determine_prefixes3 prefix_set_and_string_ptr; #! ith_address = if (fst (isBitSetMember bitset block_i)) (ith_address + length prefixes) ith_address; #! used_disk_libraries = AddBitSet used_disk_libraries dus_library_instance_nr_on_disk; = (ith_address,used_disk_libraries); lookup_library_id :: !Int (!*{#Int},!{#{String}},!*DLClientState) -> (!*{#Int},!{#{String}},!*DLClientState); lookup_library_id index (type_table_id_array,library_names,dl_client_state) # (type_table_id,dl_client_state) = AddReferenceToTypeTable library_names.[index] dl_client_state; # type_table_id_array = { type_table_id_array & [index] = type_table_id }; = (type_table_id_array,library_names,dl_client_state); Pl [] s = s; Pl [ModuleUnknown module_name symbol_name:xs] s = Pl xs ("(" +++ module_name +++ "," +++ symbol_name +++ ")\n " +++ s); }; link_library_instance stringtable descriptor_usage_table block_i id n_addresses disk_library_i (dus_labels,dl_client_state,s,io) #! (stringtable,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_string_table; #! (descriptor_usage_table,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_descriptor_usage_table; #! (library_instance_i,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_disk_id_to_library_instance_i.[disk_library_i]; #! (labels_linked,n_addresses2,labels,dl_client_state) = mapAiSt dus_entry_of_proper_library_instance_and_block descriptor_usage_table (True,0,[],dl_client_state); | n_addresses <> n_addresses2 = abort "link_library_instance; internal error; number of addresses should be the same"; # (dl_client_state,s,io) = case labels_linked of { True // all current library instance labels have already been linked. -> (dl_client_state,s,io); False #! (_,_,dl_client_state/*,s*/,io) = LoadLibraryInstance_new library_instance_i (Just labels) dl_client_state /*s*/ io; // what types have been linked in under water? #! (li_type_table_i,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_type_table_i; // If a type is eagerly linked i.e. all labels implementing the type have been linked, then // the LoadLibraryInstance_new-application is unnecessary because it is guaranteed that all // type labels have already been linked. // If lazy linking of type is to be supported, the unlinked_labels_of_types might become // handy. // // Note: // An efficiency improving technique might be to separate the actual link/relocation process // from the marking/module offset computation. Then all libraries required to satisfy a // request are linked at once. // #! (dl_client_state/*,s*/,io) // = LoadLibraryInstance_new library_instance_i (Just unlinked_labels_of_types) dl_client_state /*s*/ io; -> (dl_client_state,s,io); }; #! (new_dus_labels,dl_client_state) = mapSt compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class3 labels dl_client_state; = (dus_labels ++ new_dus_labels,dl_client_state,s,io); where { compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class3 :: !DusLabel !*DLClientState -> (!DusLabel,*DLClientState); compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class3 dus_label/*=:{dusl_linked=True}*/ dl_client_state #! (label_address,dl_client_state) = compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class2 dus_label /*(-89)*/ /*[]*/ dl_client_state; #! dus_label = { dus_label & dusl_address = label_address }; = (dus_label,dl_client_state); where { compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class2 :: !DusLabel !*DLClientState -> *(Int,*DLClientState); compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class2 {dusl_label_name,dusl_library_instance_i} dl_client_state #! (maybe_label,dl_client_state) = findLabel dusl_label_name dusl_library_instance_i dl_client_state; | isNothing maybe_label = abort ("compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class; internal error; label should exist '" +++ dusl_label_name +++ "'"); #! (file_n,symbol_n) = fromJust maybe_label; #! (maybe_label_address,dl_client_state) = isLabelImplemented file_n symbol_n dl_client_state; | isNothing maybe_label_address = abort ("compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class; internal error; label should exist (unmarked) '" +++ dusl_label_name +++ "'" +++ toString dusl_library_instance_i); = (fromJust maybe_label_address,dl_client_state); }; // compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class3 compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class3 dus_label dl_client_state = (dus_label,dl_client_state); dus_entry_of_proper_library_instance_and_block :: .a !.DescriptorUsageEntry !*(.Bool,.Int,u:[w:DusLabel],*DLClientState) -> *(Bool,Int,v:[x:DusLabel],*DLClientState), [w <= x, u <= v]; dus_entry_of_proper_library_instance_and_block _ dus_entry=:{bitset,prefix_set_and_string_ptr,dus_library_instance_nr_on_disk} (labels_linked,ith_address,labels,dl_client_state) #! is_entry_block_member = (fst (isBitSetMember bitset block_i)); | not is_entry_block_member = (labels_linked,ith_address,labels,dl_client_state); | disk_library_i == dus_library_instance_nr_on_disk // same library and in the same block = generate_label_name ith_address labels dl_client_state; #! (prefixes,_,_) = determine_prefixes3 prefix_set_and_string_ptr; = (labels_linked,ith_address + length prefixes,labels,dl_client_state); where { generate_label_name ith_address labels dl_client_state // get descriptor name #! (prefixes,string_offset,_) = determine_prefixes3 prefix_set_and_string_ptr; #! descriptor_module_table = []; // overbodig? #! (descriptor_and_module_name=:(descriptor_name,module_name),descriptor_module_table) = get_descriptor_and_module_name string_offset stringtable descriptor_module_table; #! used_library_instances = NewBitSet 0; // overbodig? #! (dus_implementation=:{dusi_linked},dl_client_state) = determine_implementation_for_dus_entry descriptor_name module_name dus_library_instance_nr_on_disk prefix_set_and_string_ptr id dl_client_state; // insert prefixes #! (l,(ith_address,_)) = mapSt generate_dus_label2 prefixes (ith_address,dus_implementation); = (labels_linked && dusi_linked,ith_address,labels ++ l,dl_client_state); where { generate_dus_label2 prefix (ith_address,dus_implementation) #! (dus_label,dus_implementation) = generate_dus_label prefix dus_implementation; #! dus_label = { dus_label & dusl_ith_address = ith_address }; = (dus_label,(inc ith_address,dus_implementation)); } // generate_label_name } // dus_entry_of_proper_library_instance_and_block } RegisterLazyDynamic :: !ProcessSerialNumber [String] !*DLServerState !*f -> !(!Bool,!ProcessSerialNumber,!*DLServerState, !*f) | FileEnv f; RegisterLazyDynamic client_id [args] s io #! (client_exists,dl_client_state,s) = RemoveFromDLServerState client_id s; | /*F "ComputeDescAddressTable2"*/ not client_exists = internal_error "RegisterLazyDynamic (internal error): client not registered" client_id dl_client_state s io; #! (dl_client_state) = AddMessage (Verbose "RegisterLazyDynamic") dl_client_state; #! args = ExtractArguments '\n' 0 args []; #! l_args = length args; #! rt_lazy_dynamic_index = FromStringToInt (hd args) 0; // run-time ptr // Using the run-time lazy dynamic index (rt_lazy_dynamic_index), the id of the main dynamic i.e. the // top-level dynamic is determined. #! (result,dl_client_state) = get_dynamic_id rt_lazy_dynamic_index dl_client_state | isNothing result = abort "RegisterLazyDynamic; get_dynamic_id; lazy_dynamic_index cannot be found"; // dynamic found // 1. map file // 2. initialize dynamic (using code in ComputeDescAddressTable2) #! (disk_lazy_dynamic_index,id) = fromJust result; #! main_dynamic_id = id; // run-time pointer // extract file name from dynamic containing the lazy dynamic # (file_name,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_lazy_dynamics_a.[disk_lazy_dynamic_index]; // assign the lazy dynamic a run-time id #! (id,dl_client_state) = new_dynamic_id dl_client_state; #! lazy_dynamic_id = id; #! (lazy_dynamic_info=:{ldi_lazy_dynamic_index_to_dynamic=has_lazy_dynamic_already_been_initialized},dl_client_state) = dl_client_state!cs_lazy_dynamic_index_to_dynamic_id.[rt_lazy_dynamic_index]; #! initialized_lazy_dynamic = isJust has_lazy_dynamic_already_been_initialized; // the dynamic associated from which the build_lazy_block wants to build a block has already // been initialized. #! dl_client_state = case initialized_lazy_dynamic of { True -> dl_client_state; _ # lazy_dynamic_info = { lazy_dynamic_info & ldi_lazy_dynamic_index_to_dynamic = Just id }; -> { dl_client_state & cs_lazy_dynamic_index_to_dynamic_id.[rt_lazy_dynamic_index] = lazy_dynamic_info }; }; // map file into memory of client ... # client_process_id = GetOSProcessSerialNumber client_id; # (dynamic_rts_process_handle,st) = OpenProcess (STANDARD_RIGHTS_REQUIRED bitor PROCESS_ALL_ACCESS) FALSE client_process_id initialState; # (ok,file,exported_handle) = CreateSharedBufferFromFile2 dynamic_rts_process_handle file_name; | not ok = abort "could not create memory mapped file"; // body ... # (file,id,dl_client_state,io) = case initialized_lazy_dynamic of { False # (ok,dynamic_header,file) = read_dynamic_header file; | not ok -> abort "get_tables_from_dynamic: error reading dynamic header"; # (file,id,dl_client_state,io) = read_from_dynamic id file_name file dl_client_state io dynamic_header; -> (file,id,dl_client_state,io); True -> (file,fromJust has_lazy_dynamic_already_been_initialized,dl_client_state,io); }; | not (CloseExistingSharedBuffer file) || not (CloseST st) = abort "stop"; // ... map file into memory of client // initialize dynamic #! (dl_client_state,io) = case initialized_lazy_dynamic of { False #! (_,dl_client_state,io) = init_lazy_dynamic id dl_client_state io; // lazy dynamic at rt_lazy_dynamic_index is assigned dynamic id, now type references must be // converted. Promotion of lazy dynamic to a dynamic #! (dl_client_state,io) = update_type_implementation_table rt_lazy_dynamic_index id dl_client_state io; -> (dl_client_state,io); True -> (dl_client_state,io); }; # (di_string_table,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_string_table; // msg ... #! (library_instance_runtime_ids,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_disk_id_to_library_instance_i; #! (di_disk_to_rt_dynamic_indices,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_disk_to_rt_dynamic_indices; #! (di_rt_type_redirection_table,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_rt_type_redirection_table; #! (di_rt_type_redirection_table,dl_client_state) = case COLLECT_AND_RENUMBER_EXTERNAL_TYPE_REFERENCES True False of { False -> ({},dl_client_state); True // | size di_rt_type_redirection_table == 0 // -> abort "RegisterLazyDynamic; internal error; null sized di_rt_type_redirection_table"; -> (di_rt_type_redirection_table,dl_client_state); }; // due to 1.3 bug, a six tuple cannot be exported. Therefore I pack the file_name // with the exported handle. #! msg = ((exported_handle, file_name), library_instance_runtime_ids, // lazy dynamics... di_disk_to_rt_dynamic_indices, // ... lazy dynamics id ,di_rt_type_redirection_table ); // ... msg #! io = SendAddressToClient client_id (encode msg) io; #! ok = True = (not ok,client_id,AddToDLServerState dl_client_state s,io); where { // Converts LibRefViaLazyDynamic into LibRef. This means that a lazy dynamic is promoted to a dynamic // because all its library instances have been assigned a run-time library instance number because the // evaluation needs some part of the lazy dynamic. // // rt_lazy_dynamic_index = index in cs_lazy_dynamic_index_to_dynamic_id of DLClientState // rt_dynamic_index = just allocated id for (lazy) dynamic update_type_implementation_table rt_lazy_dynamic_index rt_dynamic_index dl_client_state io #! (n_type_equivalent_classes,dl_client_state) = dl_client_state!cs_type_implementation_table.teit_n_type_implementations; #! (dl_client_state,io) = loopAst convert_type_equivalent_class (dl_client_state,io) n_type_equivalent_classes; = (dl_client_state,io); where { convert_type_equivalent_class ith_type_equivalent_class (dl_client_state,io) #! (type_equivalent_class=:{tei_type_implementations},dl_client_state) = dl_client_state!cs_type_implementation_table.teit_type_implementations_a.[ith_type_equivalent_class]; #! (converted_type_references,(changed,dl_client_state,io)) = mapSt convert_type_reference tei_type_implementations (False,dl_client_state,io); | not changed = (dl_client_state,io); #! dl_client_state = AddMessage (Verbose "something has changed") dl_client_state; #! dl_client_state = { dl_client_state & cs_type_implementation_table.teit_type_implementations_a.[ith_type_equivalent_class].tei_type_implementations = converted_type_references }; #! (_,dl_client_state,io) = enter_type_equation_new [hd tei_type_implementations] dl_client_state io; = (dl_client_state,io); where { convert_type_reference type_reference=:(LIT_TypeReference (LibRefViaLazyDynamic disk_library_instance_i rt_offered_lazy_dynamic_index _) tio_type_ref) (changed,dl_client_state,io) | IS_COLLECT_AND_RENUMBER_EXTERNAL_TYPE_REFERENCES = abort "convert_type_reference: not yet implemented"; #! (result,lazy_dynamic_reference_path,dl_client_state) = dereference_lazy_reference disk_library_instance_i rt_offered_lazy_dynamic_index [] dl_client_state; #! lazy_dynamic_reference_path_as_a_string = convert_lazy_dynamic_reference_path_to_string lazy_dynamic_reference_path ""; #! dl_client_state = AddMessage (Verbose lazy_dynamic_reference_path_as_a_string) dl_client_state; | isJust result # disk_library_instance_i = fromJust result; // promote lazy dynamic to a dynamic by converting the LibRefViaLazyDynamic to LibRef. The // library instances used by the lazy dynamic have been assigned an unique number by init_ // dynamic2. Now the type implementation table must be converted accordingly. Note that the // RunTimeIDs still contain references to the lazy dynamic index. #! (rt_library_instance,dl_client_state) = dl_client_state!cs_dynamic_info.[rt_dynamic_index].di_disk_id_to_library_instance_i.[disk_library_instance_i]; #! converted_type_reference = LIT_TypeReference (LibRef rt_library_instance) tio_type_ref; #! dl_client_state = AddMessage (Verbose (lazy_dynamic_reference_path_as_a_string +++ ": converted to " +++ toString rt_dynamic_index)) dl_client_state; = (converted_type_reference,(True,dl_client_state,io)); = (type_reference,(changed,dl_client_state,io)); where { // rt_lazy_dynamic_index = index in cs_lazy_dynamic_index_to_dynamic_id of DLClientState // rt_dynamic_index = just allocated id for (lazy) dynamic // //(LibRefViaLazyDynamic disk_library_instance_i rt_offered_lazy_dynamic_index _) // DynamicInfo dereference_lazy_reference disk_library_instance_i rt_offered_lazy_dynamic_index lazy_dynamic_reference_path dl_client_state #! lazy_dynamic_reference_path = [(disk_library_instance_i,rt_offered_lazy_dynamic_index):lazy_dynamic_reference_path] #! (maybe_lazy_dynamic_to_dynamic_index,dl_client_state) = dl_client_state!cs_lazy_dynamic_index_to_dynamic_id.[rt_offered_lazy_dynamic_index].ldi_lazy_dynamic_index_to_dynamic; | isNothing maybe_lazy_dynamic_to_dynamic_index <<- ("***",rt_offered_lazy_dynamic_index,disk_library_instance_i) // lazy dynamic not (yet) allocated = (Nothing,lazy_dynamic_reference_path,dl_client_state); # rt_dynamic_index_of_lazy_dynamic = fromJust maybe_lazy_dynamic_to_dynamic_index; # (library_instance_kind,dl_client_state) = dl_client_state!cs_dynamic_info.[rt_dynamic_index_of_lazy_dynamic].di_library_instance_to_library_index.[disk_library_instance_i]; | rt_lazy_dynamic_index == rt_offered_lazy_dynamic_index && (not (isLazyLibraryInstance library_instance_kind)) = (Just disk_library_instance_i,lazy_dynamic_reference_path,dl_client_state); # (LIK_LazyLibraryInstance {lik_library_instance_i=new_disk_library_instance_i,lik_dynamic_index_i}) = library_instance_kind; # (new_rt_offered_lazy_dynamic_index,dl_client_state) = dl_client_state!cs_dynamic_info.[rt_dynamic_index_of_lazy_dynamic].di_disk_to_rt_dynamic_indices.[lik_dynamic_index_i]; = dereference_lazy_reference new_disk_library_instance_i new_rt_offered_lazy_dynamic_index lazy_dynamic_reference_path dl_client_state; convert_lazy_dynamic_reference_path_to_string :: [(!Int,!Int)] !String -> !String; convert_lazy_dynamic_reference_path_to_string [] converted_lazy_dynamic_reference_path = converted_lazy_dynamic_reference_path; convert_lazy_dynamic_reference_path_to_string [(disk_library_instance_i,rt_offered_lazy_dynamic_index):lazy_dynamic_reference_path] converted_lazy_dynamic_reference_path # converted_lazy_dynamic_reference = "(" +++ toString disk_library_instance_i +++ "," +++ toString rt_offered_lazy_dynamic_index +++ ")"; = convert_lazy_dynamic_reference_path_to_string lazy_dynamic_reference_path (converted_lazy_dynamic_reference_path +++ converted_lazy_dynamic_reference +++ (if (isEmpty lazy_dynamic_reference_path) "" " -> ") ); } convert_type_reference type_reference=:(LIT_TypeReference lib_ref=:(LazyLibRef rt_type_redirection_i rt_lazy_dynamic_i type_table_i) tio_type_ref) (changed,dl_client_state,io) | not IS_COLLECT_AND_RENUMBER_EXTERNAL_TYPE_REFERENCES <<- ("???",lib_ref) = abort "convert_type_reference: switch COLLECT_AND_RENUMBER_EXTERNAL_TYPE_REFERENCES on!"; #! (lib_ref_chain,dl_client_state,io) = dereference_rt_lib_ref lib_ref [] dl_client_state io; | isLibRef lib_ref_chain<<- ("&&&", type_reference,lib_ref_chain) #! converted_type_reference = LIT_TypeReference (hd lib_ref_chain) tio_type_ref; = (converted_type_reference,(True,dl_client_state,io)); = (type_reference,(changed,dl_client_state,io)); where { isLibRef ([LibRef _:_]) = True; isLibRef _ = False; }; convert_type_reference type_reference s = (type_reference,s); } } // update_type_implementation_table }; class convert_encoded_type_reference_to_rt_type_reference a :: !Int !a !(!*DLClientState,*f) -> *(!a,!(!*DLClientState,!*f)) | FileEnv f; instance convert_encoded_type_reference_to_rt_type_reference LibRef where { convert_encoded_type_reference_to_rt_type_reference id lit_type_reference st = convert_encoded_type_reference_to_rt_type_reference_LibRef id lit_type_reference st; }; convert_encoded_type_reference_to_rt_type_reference_LibRef :: !.Int !.LibRef !*(!*DLClientState,*a) -> *(.LibRef,*(*DLClientState,*a))| FileEnv a; convert_encoded_type_reference_to_rt_type_reference_LibRef id (LibRef disk_library_instance) (dl_client_state,io) #! ({di_disk_id_to_library_instance_i},dl_client_state) = dl_client_state!cs_dynamic_info.[id]; = (LibRef (di_disk_id_to_library_instance_i.[disk_library_instance]),(dl_client_state,io)); convert_encoded_type_reference_to_rt_type_reference_LibRef id (LibRefViaLazyDynamic disk_library_instance disk_dynamic_index type_library_reference) (dl_client_state,io) #! ({di_disk_to_rt_dynamic_indices},dl_client_state) = dl_client_state!cs_dynamic_info.[id]; #! (library_name,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_library_index_to_library_name.[type_library_reference]; // allocate & load required type table #!(type_table_i,dl_client_state) = AddReferenceToTypeTable library_name dl_client_state; #! (dl_client_state,io) = LoadTypeTable type_table_i dl_client_state io; #! type_table_reference = type_table_i; = (LibRefViaLazyDynamic disk_library_instance (di_disk_to_rt_dynamic_indices.[disk_dynamic_index]) type_table_reference,(dl_client_state,io)); convert_encoded_type_reference_to_rt_type_reference_LibRef id (LazyLibRef type_redirection_table_i disk_dynamic_index type_library_reference) (dl_client_state,io) #! ({di_disk_to_rt_dynamic_indices},dl_client_state) = dl_client_state!cs_dynamic_info.[id]; | not IS_COLLECT_AND_RENUMBER_EXTERNAL_TYPE_REFERENCES <<- ("&&&",id) = abort "convert_encoded_type_reference_to_rt_type_reference; switch COLLECT_AND_RENUMBER_EXTERNAL_TYPE_REFERENCES on"; // same as above ... # (library_name,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_library_index_to_library_name.[type_library_reference]; // allocate & load required type table # (type_table_i,dl_client_state) = AddReferenceToTypeTable library_name dl_client_state; # (dl_client_state,io) = LoadTypeTable type_table_i dl_client_state io; # type_table_reference = type_table_i; = (LazyLibRef type_redirection_table_i (di_disk_to_rt_dynamic_indices.[disk_dynamic_index]) type_table_reference,(dl_client_state,io)); // ... same as above instance convert_encoded_type_reference_to_rt_type_reference LibraryInstanceTypeReference where { convert_encoded_type_reference_to_rt_type_reference id lit_type_reference st = convert_encoded_type_reference_to_rt_type_reference_LibraryInstanceTypeReference id lit_type_reference st; }; convert_encoded_type_reference_to_rt_type_reference_LibraryInstanceTypeReference :: !.Int !.LibraryInstanceTypeReference !*(!*DLClientState,*a) -> *(.LibraryInstanceTypeReference,*(!*DLClientState,!*a)) | FileEnv a; convert_encoded_type_reference_to_rt_type_reference_LibraryInstanceTypeReference id (LIT_TypeReference lib_ref tio_type_reference) st #! (lib_ref,st) = convert_encoded_type_reference_to_rt_type_reference id lib_ref st; = (LIT_TypeReference lib_ref tio_type_reference,st);