mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-16 14:25:56 +00:00
This change introduces instrumentation that tracks sparks as well as parallel
conjunctions and their conjuncts. This should hopefully give us more
information to diagnose runtime performance issues.
As of this date the ThreadScope program hasn't been updated to read or
understand these new events.
runtime/mercury_threadscope.[ch]:
Added a function and types to register all the threadscope strings from an
array.
Add functions to post the new events (see below).
runtime/mercury_threadscope.c:
Added support for 5 new threadscope events.
Registering a string so that other messages may refer to a constant
string.
Marking the beginning and ends of parallel conjunctions.
Creating a spark for a parallel conjunct.
Finishing a parallel conjunct.
Re-arranged event IDs, I've started allocating IDs from 38 onwards for
general purposes and 100 onwards for mercury specific events after talking
with Duncan Coutts.
Trimmed excess whitespace from the end of lines.
runtime/mercury_context.h:
Post a beginning parallel conjunction message when the sync term for the
parallel conjunction is initialized.
Post an event when creating a spark for a parallel conjunction.
Add a MR_spark_id field to the MR_Spark structure, these identify sparks to
threadscope.
runtime/mercury_context.c:
Post threadscope messages when a spark is about to be executed.
Post a threadscope event when a parallel conjunct is completed.
Add a missing memory barrier.
runtime/mercury_wrapper.[ch]:
Create a global function pointer for the code that registers strings in the
threadscope string table, this is filled in by mkinit.
Call this function pointer immediatly after setting up threadscope.
runtime/mercury_wsdeque.[ch]:
Modify MR_wsdeque_pop_bottom to return the spark pointer (which points onto
the queue) rather then returning a result through a pointer and bool if the
operation was successful. This pointer is safe to dereference until
MR_wsdeque_push_bottom is used.
runtime/mercury_wsdeque.c:
Corrected a code comment.
runtime/mercury_engine.h:
Documented some of the fields of the engine structure that hadn't been
documented.
Add a next spark ID field to the engine structure.
Change the type of the engine ID field to MR_uint_least16_t
compiler/llds.m:
Add a third field to the init_sync_term instruction that stores the index
into the threadscope string table of the static conjunction ID.
Add a field to the c_file structure containing the threadscope string
table.
compiler/layout.m:
Added a new layout array name for the threadscope string table.
compiler/layout_out.m:
Implement code to write out the threadscope string table.
compiler/llds_out_file.m:
Write out the threadscope string table when writing out the c_file.
compiler/par_conj_gen.m:
Create strings that statically identify parallel conjunctions for each
init_sync_term LLDS instruction. These strings are added to a table in the
!CodeInfo and the index of the string is added to the init_sync_term
instruction.
Add an extra instruction after a parallel conjunction to post the message
that the parallel conjunction has completed.
compiler/global_data.m:
Add fields to the global data structure to represent the threadscope string
table and its current size.
Add predicates to update and retrieve the table.
Handle merging of threadscope string tables in global data by allowing the
references to the strings to be remapped.
Refactored remapping code so that a caller such as proc_gen only needs to
call one remapping predicate after merging global data..
compiler/code_info.m:
Add a table of strings for use with threadscope to the code_info_persistent
type.
Modify the code_info_init to initialise the threadscope string table fields.
Add a predicate to get the string table and another to update it.
compiler/proc_gen.m:
Build the containing goal map before code generation for procedures with
parallel conjunctions in a parallel grade. par_conj_gen.m depends on this.
Conform to changes in code_info.m and global_data.m
compiler/llds_out_instr.m:
Write out the extra parameter in the init_sync_term instruction.
compiler/dupelim.m:
compiler/dupproc.m:
compiler/exprn_aux.m:
compiler/global_data.m:
compiler/jumpopt.m:
compiler/livemap.m:
compiler/llds_to_x86_64.m:
compiler/mercury_compile_llds_back_end.m:
compiler/middle_rec.m:
compiler/opt_debug.m:
compiler/opt_util.m:
compiler/peephole.m:
compiler/reassign.m:
compiler/use_local_vars.m:
Conform to changes in llds.m
compiler/opt_debug.m:
Conform to changes in layout.m
compiler/mercury_compile_llds_back_end.m:
Fix some trailing whitespace.
util/mkinit.c:
Build an initialisation function that registers all the strings in
threadscope string tables.
Correct the layout of a comment.
390 lines
15 KiB
Mathematica
390 lines
15 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2001-2009, 2011 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% File: layout.m.
|
|
% Author: zs.
|
|
%
|
|
% Definitions of Mercury types for representing layout structures within
|
|
% the compiler. Layout structures are generated by the compiler, and are
|
|
% used by the parts of the runtime system that need to look at the stacks
|
|
% (and sometimes the registers) and make sense of their contents. The parts
|
|
% of the runtime system that need to do this include exception handling,
|
|
% the debugger, the deep profiler and (eventually) the accurate garbage
|
|
% collector.
|
|
%
|
|
% When output by layout_out.m, values of most these types will correspond
|
|
% to the C types defined in runtime/mercury_stack_layout.h or
|
|
% runtime/mercury_deep_profiling.h; the documentation of those types
|
|
% can be found there. The names of the C types are listed next to the
|
|
% function symbol whose arguments represent their contents.
|
|
%
|
|
% The code to generate values of these types is in stack_layout.m and
|
|
% deep_profiling.m.
|
|
%
|
|
% This module should be, but as yet isn't, independent of whether we are
|
|
% compiling to LLDS or MLDS.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module ll_backend.layout.
|
|
:- interface.
|
|
|
|
:- import_module hlds.hlds_pred.
|
|
:- import_module hlds.hlds_rtti.
|
|
:- import_module libs.trace_params.
|
|
:- import_module ll_backend.llds.
|
|
:- import_module mdbcomp.prim_data.
|
|
:- import_module parse_tree.prog_data.
|
|
|
|
:- import_module assoc_list.
|
|
:- import_module bool.
|
|
:- import_module list.
|
|
:- import_module map.
|
|
:- import_module maybe.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Closure layouts.
|
|
%
|
|
|
|
:- type closure_proc_id_data
|
|
---> closure_proc_id_data(
|
|
% defines MR_ClosureId
|
|
caller_proc_label :: proc_label,
|
|
caller_closure_seq_no :: int,
|
|
closure_proc_label :: proc_label,
|
|
closure_module_name :: module_name,
|
|
closure_file_name :: string,
|
|
closure_line_number :: int,
|
|
closure_origin :: pred_origin,
|
|
closure_goal_path :: string
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Proc layouts and their components.
|
|
%
|
|
|
|
:- type user_event_data
|
|
---> user_event_data(
|
|
user_event_number :: int,
|
|
user_event_locns :: rval,
|
|
user_event_var_nums :: layout_slot_name
|
|
).
|
|
|
|
:- type basic_label_layout
|
|
---> basic_label_layout(
|
|
proc_label :: proc_label,
|
|
label_num :: int,
|
|
proc_layout_name :: layout_name,
|
|
maybe_port :: maybe(trace_port),
|
|
maybe_is_hidden :: maybe(bool),
|
|
label_num_in_module :: int,
|
|
maybe_goal_path :: maybe(int), % offset
|
|
maybe_user_info :: maybe(layout_slot_name)
|
|
).
|
|
|
|
:- type label_short_var_info
|
|
---> label_short_var_info(
|
|
% part of MR_LabelLayout
|
|
lsvi_encoded_var_count :: int, % encodes #Long=0 and #Short
|
|
lsvi_type_params :: rval,
|
|
lsvi_ptis :: int, % -1 if none, otherwise slot#
|
|
lsvi_hlds_var_nums :: int, % -1 if none, otherwise slot#
|
|
lsvi_short_locns :: int % -1 if none, otherwise slot#
|
|
).
|
|
|
|
:- type label_long_var_info
|
|
---> label_long_var_info(
|
|
% part of MR_LabelLayout
|
|
llvi_encoded_var_count :: int, % encodes #Long>0 and #Short
|
|
llvi_type_params :: rval,
|
|
llvi_ptis :: int, % -1 if none, otherwise slot#
|
|
llvi_hlds_var_nums :: int, % -1 if none, otherwise slot#
|
|
llvi_short_locns :: int, % -1 if none, otherwise slot#
|
|
llvi_long_locns :: int % -1 if none, otherwise slot#
|
|
).
|
|
|
|
:- type label_layout_no_vars
|
|
---> label_layout_no_vars(
|
|
% defines MR_LabelLayoutNoVarInfo
|
|
basic_label_layout
|
|
).
|
|
|
|
:- type label_layout_short_vars
|
|
---> label_layout_short_vars(
|
|
% defines MR_LabelLayout
|
|
basic_label_layout,
|
|
label_short_var_info
|
|
).
|
|
|
|
:- type label_layout_long_vars
|
|
---> label_layout_long_vars(
|
|
% defines MR_LabelLayout
|
|
basic_label_layout,
|
|
label_long_var_info
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Proc layouts and their components.
|
|
%
|
|
|
|
:- type proc_layout_stack_traversal
|
|
---> proc_layout_stack_traversal(
|
|
% defines MR_StackTraversal
|
|
% The proc entry label will be `no' if we don't have
|
|
% static code addresses.
|
|
plst_entry_label :: maybe(label),
|
|
|
|
plst_succip_slot :: maybe(int),
|
|
plst_stack_slot_count :: int,
|
|
plst_detism :: determinism
|
|
).
|
|
|
|
% The deep_slot_info gives the stack slot numbers that hold
|
|
% the values returned by the call port code, which are needed to let
|
|
% exception.throw perform the work we need to do at the excp port.
|
|
% The old_outermost slot is needed only with the save/restore approach;
|
|
% the old_outermost field contain -1 otherwise. All fields will contain
|
|
% -1 if the variables are never saved on the stack because the
|
|
% predicate makes no calls (in which case it cannot throw exceptions,
|
|
% because to do that it would need to call exception.throw, directly or
|
|
% indirectly.)
|
|
:- type deep_excp_slots
|
|
---> deep_excp_slots(
|
|
top_csd :: int,
|
|
middle_csd :: int,
|
|
old_outermost :: int
|
|
).
|
|
|
|
:- type proc_layout_proc_static
|
|
---> proc_layout_proc_static(
|
|
plps_file_name :: string,
|
|
plps_line_number :: int,
|
|
plps_is_in_interface :: bool,
|
|
plps_excp_slots :: deep_excp_slots,
|
|
plps_call_site_statics :: maybe({int, int}),
|
|
plps_coverage_points :: maybe({int, int})
|
|
).
|
|
|
|
:- type table_io_decl_data
|
|
---> table_io_decl_data(
|
|
% defines MR_TableIoDecl
|
|
tid_proc_ptr :: layout_name,
|
|
tid_num_ptis :: int,
|
|
|
|
% pseudo-typeinfos for headvars
|
|
tid_ptis :: rval,
|
|
|
|
tid_type_params :: rval
|
|
).
|
|
|
|
:- type data_or_slot_id
|
|
---> data_or_slot_is_data(data_id)
|
|
; data_or_slot_is_slot(layout_slot_name).
|
|
|
|
:- type proc_layout_exec_trace
|
|
---> proc_layout_exec_trace(
|
|
% defines MR_ExecTrace
|
|
plet_maybe_call_label_slot :: maybe(layout_slot_name),
|
|
|
|
% The label layouts of the events in the predicate.
|
|
plet_proc_event_layouts :: layout_slot_name,
|
|
plet_num_proc_event_layouts :: int,
|
|
|
|
plet_maybe_table_info :: maybe(data_or_slot_id),
|
|
|
|
% The variable numbers of the head variables, including the
|
|
% ones added by the compiler, in order. The length of the list
|
|
% must be the same as the procedure's arity. The maybe will be
|
|
% `no' if the procedure has no head variables.
|
|
plet_head_var_nums :: maybe(layout_slot_name),
|
|
plet_num_head_var_nums :: int,
|
|
|
|
% Each variable name is an offset into the module's
|
|
% string table. The maybe will be `no' if the procedure
|
|
% has no variables.
|
|
plet_var_names :: maybe(layout_slot_name),
|
|
|
|
plet_max_var_num :: int,
|
|
plet_max_r_num :: int,
|
|
plet_maybe_from_full_slot :: maybe(int),
|
|
plet_maybe_io_seq_slot :: maybe(int),
|
|
plet_maybe_trail_slot :: maybe(int),
|
|
plet_maybe_maxfr_slot :: maybe(int),
|
|
plet_eval_method :: eval_method,
|
|
plet_maybe_call_table_slot :: maybe(int),
|
|
plet_maybe_tail_rec_slot :: maybe(int),
|
|
plet_eff_trace_level :: trace_level,
|
|
plet_exec_trace_flags :: int
|
|
).
|
|
|
|
:- type maybe_proc_id_and_more
|
|
---> no_proc_id_and_more
|
|
; proc_id_and_more(
|
|
maybe_proc_static :: maybe(layout_slot_name),
|
|
maybe_exec_trace :: maybe(layout_slot_name),
|
|
|
|
% The procedure body represented as a list of bytecodes.
|
|
proc_body_bytes :: maybe(layout_slot_name),
|
|
|
|
% The name of the module_common_layout structure.
|
|
proc_module_common :: layout_name
|
|
).
|
|
|
|
:- type proc_layout_data
|
|
---> proc_layout_data(
|
|
% defines MR_ProcLayout
|
|
proc_layout_label :: rtti_proc_label,
|
|
proc_layout_trav :: proc_layout_stack_traversal,
|
|
proc_layout_more :: maybe_proc_id_and_more
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Module layouts and their components.
|
|
%
|
|
|
|
% This type is for strings which may contain embedded null characters.
|
|
% When a string_with_0s is written, a null character will be written
|
|
% in between each string in the list.
|
|
%
|
|
:- type string_with_0s
|
|
---> string_with_0s(list(string)).
|
|
|
|
:- type event_set_layout_data
|
|
---> event_set_layout_data(
|
|
event_set_data,
|
|
|
|
% Maps each event number to an rval that gives the vector
|
|
% of typeinfos for the arguments of that event.
|
|
map(int, rval)
|
|
).
|
|
|
|
:- type file_layout_data
|
|
---> file_layout_data(
|
|
file_name :: string,
|
|
line_no_label_list :: assoc_list(int, layout_slot_name)
|
|
).
|
|
|
|
:- type module_layout_data
|
|
---> module_layout_common_data(
|
|
% defines MR_ModuleCommonLayout
|
|
module_common_name :: module_name,
|
|
string_table_size :: int,
|
|
string_table :: string_with_0s
|
|
)
|
|
; module_layout_data(
|
|
% defines MR_ModuleLayout
|
|
module_name :: module_name,
|
|
module_common :: layout_name,
|
|
proc_layout_names :: list(layout_name),
|
|
file_layouts :: list(file_layout_data),
|
|
trace_level :: trace_level,
|
|
suppressed_events :: int,
|
|
num_label_exec_count :: int,
|
|
maybe_event_specs :: maybe(event_set_layout_data)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Global variables that hold arrays of layout structures.
|
|
%
|
|
|
|
:- type label_vars
|
|
---> label_has_no_var_info
|
|
; label_has_short_var_info
|
|
; label_has_long_var_info.
|
|
|
|
:- type layout_slot_name
|
|
---> layout_slot(layout_array_name, int).
|
|
|
|
:- type layout_array_name
|
|
---> pseudo_type_info_array
|
|
; hlds_var_nums_array
|
|
; short_locns_array
|
|
; long_locns_array
|
|
; user_event_layout_array
|
|
; user_event_var_nums_array
|
|
; label_layout_array(label_vars)
|
|
|
|
; proc_static_call_sites_array
|
|
; proc_static_cp_static_array
|
|
; proc_static_cp_dynamic_array
|
|
; proc_static_array
|
|
; proc_head_var_nums_array
|
|
% A vector of variable numbers, containing the numbers of the
|
|
% procedure's head variables, including the ones generated by
|
|
% the compiler.
|
|
; proc_var_names_array
|
|
% A vector of variable names (represented as offsets into
|
|
% the string table) for a procedure layout structure.
|
|
; proc_body_bytecodes_array
|
|
; proc_table_io_decl_array
|
|
; proc_event_layouts_array
|
|
; proc_exec_trace_array
|
|
; threadscope_string_table_array.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Global variables that hold individual layout structures.
|
|
%
|
|
|
|
:- type proc_layout_kind
|
|
---> proc_layout_traversal
|
|
; proc_layout_proc_id(proc_layout_user_or_uci).
|
|
|
|
:- type proc_layout_user_or_uci
|
|
---> user
|
|
; uci.
|
|
|
|
% Each layout_name identifies a global variable holding one layout
|
|
% structure. We prefer to put layout structures into arrays, because
|
|
% one array holding all N layout structures of a given kind require
|
|
% less space in the symbol table and relocation information sections
|
|
% of object files than N separate global variables, and the reduction
|
|
% in the number of symbols should also improve link times. In some arrays,
|
|
% it is also possible to use an element or sequence of elements two or more
|
|
% times, giving an element of compression.
|
|
%
|
|
% The layout structures we still put into global variables individually are
|
|
%
|
|
% - procedure layouts, which have to have a name derivable from the name of
|
|
% the procedure they represent, since in deep profiling grades call site
|
|
% static structures contain pointers to the proc layout structures of the
|
|
% callee procedures;
|
|
% - layouts for closures, which are relatively few in number,
|
|
% so arrays would do little good; and
|
|
% - module layouts and their components, of which each module will have
|
|
% just one, so arrays would do absolutely *no* good.
|
|
%
|
|
:- type layout_name
|
|
---> proc_layout(rtti_proc_label, proc_layout_kind)
|
|
; closure_proc_id(proc_label, int, proc_label)
|
|
; file_layout(module_name, int)
|
|
; file_layout_line_number_vector(module_name, int)
|
|
; file_layout_label_layout_vector(module_name, int)
|
|
; module_layout_string_table(module_name)
|
|
; module_layout_file_vector(module_name)
|
|
; module_layout_proc_vector(module_name)
|
|
; module_layout_label_exec_count(module_name, int)
|
|
; module_layout_event_set_desc(module_name)
|
|
; module_layout_event_arg_names(module_name, int)
|
|
; module_layout_event_synth_attrs(module_name, int)
|
|
; module_layout_event_synth_attr_args(module_name, int, int)
|
|
; module_layout_event_synth_attr_order(module_name, int, int)
|
|
; module_layout_event_synth_order(module_name, int)
|
|
; module_layout_event_specs(module_name)
|
|
; module_common_layout(module_name)
|
|
; module_layout(module_name).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module layout.
|
|
%-----------------------------------------------------------------------------%
|