summaryrefslogtreecommitdiff
path: root/tools/ocamlprof.ml
diff options
context:
space:
mode:
Diffstat (limited to 'tools/ocamlprof.ml')
-rw-r--r--tools/ocamlprof.ml482
1 files changed, 0 insertions, 482 deletions
diff --git a/tools/ocamlprof.ml b/tools/ocamlprof.ml
deleted file mode 100644
index f1b637baf2..0000000000
--- a/tools/ocamlprof.ml
+++ /dev/null
@@ -1,482 +0,0 @@
-(***********************************************************************)
-(* *)
-(* Objective Caml *)
-(* *)
-(* Damien Doligez and Francois Rouaix, INRIA Rocquencourt *)
-(* Ported to Caml Special Light by John Malecki *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. All rights reserved. This file is distributed *)
-(* under the terms of the Q Public License version 1.0. *)
-(* *)
-(***********************************************************************)
-
-(* $Id$ *)
-
-open Printf
-
-open Clflags
-open Config
-open Location
-open Misc
-open Parsetree
-
-(* User programs must not use identifiers that start with this prefix. *)
-let idprefix = "__ocaml_prof";;
-
-
-(* Errors specific to the profiler *)
-exception Profiler of string
-
-(* Modes *)
-let instr_fun = ref false
-and instr_match = ref false
-and instr_if = ref false
-and instr_loops = ref false
-and instr_try = ref false
-
-let cur_point = ref 0
-and inchan = ref stdin
-and outchan = ref stdout
-
-(* To copy source fragments *)
-let copy_buffer = String.create 256
-
-let copy_chars_unix nchars =
- let n = ref nchars in
- while !n > 0 do
- let m = input !inchan copy_buffer 0 (min !n 256) in
- if m = 0 then raise End_of_file;
- output !outchan copy_buffer 0 m;
- n := !n - m
- done
-
-let copy_chars_win32 nchars =
- for i = 1 to nchars do
- let c = input_char !inchan in
- if c <> '\r' then output_char !outchan c
- done
-
-let copy_chars =
- match Sys.os_type with
- "Win32" | "Cygwin" -> copy_chars_win32
- | _ -> copy_chars_unix
-
-let copy next =
- assert (next >= !cur_point);
- seek_in !inchan !cur_point;
- copy_chars (next - !cur_point);
- cur_point := next;
-;;
-
-let prof_counter = ref 0;;
-
-let instr_mode = ref false
-
-type insert = Open | Close;;
-let to_insert = ref ([] : (insert * int) list);;
-
-let insert_action st en =
- to_insert := (Open, st) :: (Close, en) :: !to_insert
-;;
-
-(* Producing instrumented code *)
-let add_incr_counter modul (kind,pos) =
- copy pos;
- match kind with
- | Close -> fprintf !outchan ")";
- | Open ->
- fprintf !outchan
- "(%s_cnt_%s_.(%d) <- Pervasives.succ %s_cnt_%s_.(%d); "
- idprefix modul !prof_counter idprefix modul !prof_counter;
- incr prof_counter;
-;;
-
-let counters = ref (Array.create 0 0)
-
-(* User defined marker *)
-let special_id = ref ""
-
-(* Producing results of profile run *)
-let add_val_counter (kind,pos) =
- if kind = Open then begin
- copy pos;
- fprintf !outchan "(* %s%d *) " !special_id !counters.(!prof_counter);
- incr prof_counter;
- end
-;;
-
-(* ************* rewrite ************* *)
-
-let insert_profile rw_exp ex =
- let st = ex.pexp_loc.loc_start.Lexing.pos_cnum
- and en = ex.pexp_loc.loc_end.Lexing.pos_cnum
- and gh = ex.pexp_loc.loc_ghost
- in
- if gh || st = en then
- rw_exp true ex
- else begin
- insert_action st en;
- rw_exp false ex;
- end
-;;
-
-
-let pos_len = ref 0
-
-let init_rewrite modes mod_name =
- cur_point := 0;
- if !instr_mode then begin
- fprintf !outchan "let %s_cnt_%s_ = Array.create 0000000" idprefix mod_name;
- pos_len := pos_out !outchan;
- fprintf !outchan
- " 0;; Profiling.counters := \
- (\"%s\", (\"%s\", %s_cnt_%s_)) :: !Profiling.counters;; "
- mod_name modes idprefix mod_name
- end
-
-let final_rewrite add_function =
- to_insert := Sort.list (fun x y -> snd x < snd y) !to_insert;
- prof_counter := 0;
- List.iter add_function !to_insert;
- copy (in_channel_length !inchan);
- if !instr_mode then begin
- let len = string_of_int !prof_counter in
- if String.length len > 7 then raise (Profiler "too many counters");
- seek_out !outchan (!pos_len - String.length len);
- output_string !outchan len
- end;
- (* Cannot close because outchan is stdout and Format doesn't like
- a closed stdout.
- close_out !outchan;
- *)
-;;
-
-let rec rewrite_patexp_list iflag l =
- rewrite_exp_list iflag (List.map snd l)
-
-and rewrite_patlexp_list iflag l =
- rewrite_exp_list iflag (List.map snd l)
-
-and rewrite_labelexp_list iflag l =
- rewrite_exp_list iflag (List.map snd l)
-
-and rewrite_exp_list iflag l =
- List.iter (rewrite_exp iflag) l
-
-and rewrite_exp iflag sexp =
- if iflag then insert_profile rw_exp sexp
- else rw_exp false sexp
-
-and rw_exp iflag sexp =
- match sexp.pexp_desc with
- Pexp_ident lid -> ()
- | Pexp_constant cst -> ()
-
- | Pexp_let(_, spat_sexp_list, sbody) ->
- rewrite_patexp_list iflag spat_sexp_list;
- rewrite_exp iflag sbody
-
- | Pexp_function (_, _, caselist) ->
- if !instr_fun && not sexp.pexp_loc.loc_ghost then
- rewrite_function iflag caselist
- else
- rewrite_patlexp_list iflag caselist
-
- | Pexp_match(sarg, caselist) ->
- rewrite_exp iflag sarg;
- if !instr_match && not sexp.pexp_loc.loc_ghost then
- rewrite_funmatching caselist
- else
- rewrite_patlexp_list iflag caselist
-
- | Pexp_try(sbody, caselist) ->
- rewrite_exp iflag sbody;
- if !instr_try && not sexp.pexp_loc.loc_ghost then
- rewrite_trymatching caselist
- else
- rewrite_patexp_list iflag caselist
-
- | Pexp_apply(sfunct, sargs) ->
- rewrite_exp iflag sfunct;
- rewrite_exp_list iflag (List.map snd sargs)
-
- | Pexp_tuple sexpl ->
- rewrite_exp_list iflag sexpl
-
- | Pexp_construct(_, None, _) -> ()
- | Pexp_construct(_, Some sarg, _) ->
- rewrite_exp iflag sarg
-
- | Pexp_variant(_, None) -> ()
- | Pexp_variant(_, Some sarg) ->
- rewrite_exp iflag sarg
-
- | Pexp_record(lid_sexp_list, None) ->
- rewrite_labelexp_list iflag lid_sexp_list
- | Pexp_record(lid_sexp_list, Some sexp) ->
- rewrite_exp iflag sexp;
- rewrite_labelexp_list iflag lid_sexp_list
-
- | Pexp_field(sarg, _) ->
- rewrite_exp iflag sarg
-
- | Pexp_setfield(srecord, _, snewval) ->
- rewrite_exp iflag srecord;
- rewrite_exp iflag snewval
-
- | Pexp_array(sargl) ->
- rewrite_exp_list iflag sargl
-
- | Pexp_ifthenelse(scond, sifso, None) ->
- rewrite_exp iflag scond;
- rewrite_ifbody iflag sexp.pexp_loc.loc_ghost sifso
- | Pexp_ifthenelse(scond, sifso, Some sifnot) ->
- rewrite_exp iflag scond;
- rewrite_ifbody iflag sexp.pexp_loc.loc_ghost sifso;
- rewrite_ifbody iflag sexp.pexp_loc.loc_ghost sifnot
-
- | Pexp_sequence(sexp1, sexp2) ->
- rewrite_exp iflag sexp1;
- rewrite_exp iflag sexp2
-
- | Pexp_while(scond, sbody) ->
- rewrite_exp iflag scond;
- if !instr_loops && not sexp.pexp_loc.loc_ghost
- then insert_profile rw_exp sbody
- else rewrite_exp iflag sbody
-
- | Pexp_for(_, slow, shigh, _, sbody) ->
- rewrite_exp iflag slow;
- rewrite_exp iflag shigh;
- if !instr_loops && not sexp.pexp_loc.loc_ghost
- then insert_profile rw_exp sbody
- else rewrite_exp iflag sbody
-
- | Pexp_constraint(sarg, _, _) ->
- rewrite_exp iflag sarg
-
- | Pexp_when(scond, sbody) ->
- rewrite_exp iflag scond;
- rewrite_exp iflag sbody
-
- | Pexp_send (sobj, _) ->
- rewrite_exp iflag sobj
-
- | Pexp_new _ -> ()
-
- | Pexp_setinstvar (_, sarg) ->
- rewrite_exp iflag sarg
-
- | Pexp_override l ->
- List.iter (fun (_, sexp) -> rewrite_exp iflag sexp) l
-
- | Pexp_letmodule (_, smod, sexp) ->
- rewrite_mod iflag smod;
- rewrite_exp iflag sexp
-
- | Pexp_assert (cond) -> rewrite_exp iflag cond
- | Pexp_assertfalse -> ()
-
- | Pexp_lazy (expr) -> rewrite_exp iflag expr
-
- | Pexp_poly (sexp, _) -> rewrite_exp iflag sexp
-
- | Pexp_object (_, fieldl) ->
- List.iter (rewrite_class_field iflag) fieldl
-
-and rewrite_ifbody iflag ghost sifbody =
- if !instr_if && not ghost then
- insert_profile rw_exp sifbody
- else
- rewrite_exp iflag sifbody
-
-(* called only when !instr_fun *)
-and rewrite_annotate_exp_list l =
- List.iter
- (function
- | {pexp_desc = Pexp_when(scond, sbody)}
- -> insert_profile rw_exp scond;
- insert_profile rw_exp sbody;
- | {pexp_desc = Pexp_constraint(sbody, _, _)} (* let f x : t = e *)
- -> insert_profile rw_exp sbody
- | sexp -> insert_profile rw_exp sexp)
- l
-
-and rewrite_function iflag = function
- | [spat, ({pexp_desc = Pexp_function _} as sexp)] -> rewrite_exp iflag sexp
- | l -> rewrite_funmatching l
-
-and rewrite_funmatching l =
- rewrite_annotate_exp_list (List.map snd l)
-
-and rewrite_trymatching l =
- rewrite_annotate_exp_list (List.map snd l)
-
-(* Rewrite a class definition *)
-
-and rewrite_class_field iflag =
- function
- Pcf_inher (cexpr, _) -> rewrite_class_expr iflag cexpr
- | Pcf_val (_, _, sexp, _) -> rewrite_exp iflag sexp
- | Pcf_meth (_, _, ({pexp_desc = Pexp_function _} as sexp), _) ->
- rewrite_exp iflag sexp
- | Pcf_meth (_, _, sexp, loc) ->
- if !instr_fun && not loc.loc_ghost then insert_profile rw_exp sexp
- else rewrite_exp iflag sexp
- | Pcf_let(_, spat_sexp_list, _) ->
- rewrite_patexp_list iflag spat_sexp_list
- | Pcf_init sexp ->
- rewrite_exp iflag sexp
- | Pcf_virt _ | Pcf_cstr _ -> ()
-
-and rewrite_class_expr iflag cexpr =
- match cexpr.pcl_desc with
- Pcl_constr _ -> ()
- | Pcl_structure (_, fields) ->
- List.iter (rewrite_class_field iflag) fields
- | Pcl_fun (_, _, _, cexpr) ->
- rewrite_class_expr iflag cexpr
- | Pcl_apply (cexpr, exprs) ->
- rewrite_class_expr iflag cexpr;
- List.iter (rewrite_exp iflag) (List.map snd exprs)
- | Pcl_let (_, spat_sexp_list, cexpr) ->
- rewrite_patexp_list iflag spat_sexp_list;
- rewrite_class_expr iflag cexpr
- | Pcl_constraint (cexpr, _) ->
- rewrite_class_expr iflag cexpr
-
-and rewrite_class_declaration iflag cl =
- rewrite_class_expr iflag cl.pci_expr
-
-(* Rewrite a module expression or structure expression *)
-
-and rewrite_mod iflag smod =
- match smod.pmod_desc with
- Pmod_ident lid -> ()
- | Pmod_structure sstr -> List.iter (rewrite_str_item iflag) sstr
- | Pmod_functor(param, smty, sbody) -> rewrite_mod iflag sbody
- | Pmod_apply(smod1, smod2) -> rewrite_mod iflag smod1; rewrite_mod iflag smod2
- | Pmod_constraint(smod, smty) -> rewrite_mod iflag smod
-
-and rewrite_str_item iflag item =
- match item.pstr_desc with
- Pstr_eval exp -> rewrite_exp iflag exp
- | Pstr_value(_, exps)
- -> List.iter (function (_,exp) -> rewrite_exp iflag exp) exps
- | Pstr_module(name, smod) -> rewrite_mod iflag smod
- | Pstr_class classes -> List.iter (rewrite_class_declaration iflag) classes
- | _ -> ()
-
-(* Rewrite a .ml file *)
-let rewrite_file srcfile add_function =
- inchan := open_in_bin srcfile;
- let lb = Lexing.from_channel !inchan in
- Location.input_name := srcfile;
- Location.init lb srcfile;
- List.iter (rewrite_str_item false) (Parse.implementation lb);
- final_rewrite add_function;
- close_in !inchan
-
-(* Copy a non-.ml file without change *)
-let null_rewrite srcfile =
- inchan := open_in_bin srcfile;
- copy (in_channel_length !inchan);
- close_in !inchan
-;;
-
-(* Setting flags from saved config *)
-let set_flags s =
- for i = 0 to String.length s - 1 do
- match String.get s i with
- 'f' -> instr_fun := true
- | 'm' -> instr_match := true
- | 'i' -> instr_if := true
- | 'l' -> instr_loops := true
- | 't' -> instr_try := true
- | 'a' -> instr_fun := true; instr_match := true;
- instr_if := true; instr_loops := true;
- instr_try := true
- | _ -> ()
- done
-
-(* Command-line options *)
-
-let modes = ref "fm"
-let dumpfile = ref "ocamlprof.dump"
-
-(* Process a file *)
-
-let process_intf_file filename = null_rewrite filename;;
-
-let process_impl_file filename =
- let modname = Filename.basename(Filename.chop_extension filename) in
- if !instr_mode then begin
- (* Instrumentation mode *)
- set_flags !modes;
- init_rewrite !modes modname;
- rewrite_file filename (add_incr_counter modname);
- end else begin
- (* Results mode *)
- let ic = open_in_bin !dumpfile in
- let allcounters =
- (input_value ic : (string * (string * int array)) list) in
- close_in ic;
- let (modes, cv) =
- try
- List.assoc modname allcounters
- with Not_found ->
- raise(Profiler("Module " ^ modname ^ " not used in this profile."))
- in
- counters := cv;
- set_flags modes;
- init_rewrite modes modname;
- rewrite_file filename add_val_counter;
- end
-;;
-
-let process_anon_file filename =
- if Filename.check_suffix filename ".ml" then
- process_impl_file filename
- else
- process_intf_file filename
-;;
-
-(* Main function *)
-
-open Format
-
-let usage = "Usage: ocamlprof <options> <files>\noptions are:"
-
-let main () =
- try
- Arg.parse [
- "-f", Arg.String (fun s -> dumpfile := s),
- "<file> Use <file> as dump file (default ocamlprof.dump)";
- "-F", Arg.String (fun s -> special_id := s),
- "<s> Insert string <s> with the counts";
- "-impl", Arg.String process_impl_file,
- "<file> Process <file> as a .ml file";
- "-instrument", Arg.Set instr_mode, " (undocumented)";
- "-intf", Arg.String process_intf_file,
- "<file> Process <file> as a .mli file";
- "-m", Arg.String (fun s -> modes := s), "<flags> (undocumented)"
- ] process_anon_file usage;
- exit 0
- with x ->
- let report_error ppf = function
- | Lexer.Error(err, range) ->
- fprintf ppf "@[%a%a@]@."
- Location.print range Lexer.report_error err
- | Syntaxerr.Error err ->
- fprintf ppf "@[%a@]@."
- Syntaxerr.report_error err
- | Profiler msg ->
- fprintf ppf "@[%s@]@." msg
- | Sys_error msg ->
- fprintf ppf "@[I/O error:@ %s@]@." msg
- | x -> raise x in
- report_error Format.err_formatter x;
- exit 2
-
-let _ = main ()