From 84adefa331c4159d432d22840663c38f155cd4c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 20 Nov 2009 14:54:40 +0000 Subject: The R13B03 release. --- lib/hipe/util/Makefile | 109 +++++++++++++++++++ lib/hipe/util/hipe_digraph.erl | 238 +++++++++++++++++++++++++++++++++++++++++ lib/hipe/util/hipe_dot.erl | 217 +++++++++++++++++++++++++++++++++++++ lib/hipe/util/hipe_timing.erl | 131 +++++++++++++++++++++++ lib/hipe/util/hipe_vectors.erl | 111 +++++++++++++++++++ lib/hipe/util/hipe_vectors.hrl | 28 +++++ 6 files changed, 834 insertions(+) create mode 100644 lib/hipe/util/Makefile create mode 100644 lib/hipe/util/hipe_digraph.erl create mode 100755 lib/hipe/util/hipe_dot.erl create mode 100644 lib/hipe/util/hipe_timing.erl create mode 100644 lib/hipe/util/hipe_vectors.erl create mode 100644 lib/hipe/util/hipe_vectors.hrl (limited to 'lib/hipe/util') diff --git a/lib/hipe/util/Makefile b/lib/hipe/util/Makefile new file mode 100644 index 0000000000..27cacedf11 --- /dev/null +++ b/lib/hipe/util/Makefile @@ -0,0 +1,109 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +ifndef EBIN +EBIN = ../ebin +endif + +ifndef DOCS +DOCS = ../doc +endif + +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include ../vsn.mk +VSN=$(HIPE_VSN) + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/lib/hipe-$(VSN) + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- +ifdef HIPE_ENABLED +HIPE_MODULES = hipe_vectors +else +HIPE_MODULES = +endif +MODULES = hipe_timing hipe_dot hipe_digraph $(HIPE_MODULES) + +HRL_FILES= +ERL_FILES= $(MODULES:%=%.erl) +TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) +DOC_FILES= $(MODULES:%=$(DOCS)/%.html) + +# APP_FILE= +# APP_SRC= $(APP_FILE).src +# APP_TARGET= $(EBIN)/$(APP_FILE) +# +# APPUP_FILE= +# APPUP_SRC= $(APPUP_FILE).src +# APPUP_TARGET= $(EBIN)/$(APPUP_FILE) + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- + +include ../native.mk + +ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec +warn_untyped_record + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- + +debug opt: $(TARGET_FILES) + +docs: $(DOC_FILES) + +clean: + rm -f $(TARGET_FILES) + rm -f core + +$(DOCS)/%.html:%.erl + erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop + +# ---------------------------------------------------- +# Special Build Targets +# ---------------------------------------------------- + + + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: opt + $(INSTALL_DIR) $(RELSYSDIR)/util + $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/util + $(INSTALL_DIR) $(RELSYSDIR)/ebin + $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin + +release_docs_spec: + + +$(EBIN)/hipe_timing.beam: ../main/hipe.hrl +$(EBIN)/hipe_vectors.beam: hipe_vectors.hrl diff --git a/lib/hipe/util/hipe_digraph.erl b/lib/hipe/util/hipe_digraph.erl new file mode 100644 index 0000000000..a62e913fe5 --- /dev/null +++ b/lib/hipe/util/hipe_digraph.erl @@ -0,0 +1,238 @@ +%% -*- erlang-indent-level: 2 -*- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%%----------------------------------------------------------------------- +%% File : hipe_digraph.erl +%% Author : Tobias Lindahl +%% Purpose : Provides a simple implementation of a directed graph. +%% +%% Created : 9 Feb 2005 by Tobias Lindahl +%%----------------------------------------------------------------------- +-module(hipe_digraph). + +-export([new/0, add_edge/3, add_node/2, add_node_list/2, + from_list/1, to_list/1, get_parents/2, get_children/2]). +-export([reverse_preorder_sccs/1]). + +%%------------------------------------------------------------------------ + +-type ordset(T) :: [T]. % XXX: temporarily + +-record(hipe_digraph, {edges = dict:new() :: dict(), + rev_edges = dict:new() :: dict(), + leaves = ordsets:new() :: ordset(_), % ??? + nodes = sets:new() :: set()}). + +-opaque hdg() :: #hipe_digraph{}. + +%%------------------------------------------------------------------------ + +-spec new() -> hdg(). + +new() -> + #hipe_digraph{edges = dict:new(), rev_edges = dict:new(), + leaves = ordsets:new(), nodes = sets:new()}. + +-spec from_list([_]) -> hdg(). + +from_list(List) -> + Edges = lists:foldl(fun({From, To}, Dict) -> + Fun = fun(Set) -> ordsets:add_element(To, Set) end, + dict:update(From, Fun, [To], Dict) + end, + dict:new(), List), + RevEdges = lists:foldl(fun({From, To}, Dict) -> + Fun = fun(Set) -> + ordsets:add_element(From, Set) + end, + dict:update(To, Fun, [From], Dict) + end, + dict:new(), List), + Keys1 = sets:from_list(dict:fetch_keys(Edges)), + Keys2 = sets:from_list(dict:fetch_keys(RevEdges)), + Nodes = sets:union(Keys1, Keys2), + #hipe_digraph{edges = Edges, rev_edges = RevEdges, + leaves = [], nodes = Nodes}. + +-spec to_list(hdg()) -> [_]. + +to_list(#hipe_digraph{edges = Edges}) -> + List1 = dict:to_list(Edges), + List2 = lists:foldl(fun({From, ToList}, Acc) -> + [[{From, To} || To <- ToList]|Acc] + end, [], List1), + lists:flatten(List2). + +-spec add_node(_, hdg()) -> hdg(). + +add_node(NewNode, DG = #hipe_digraph{nodes=Nodes}) -> + DG#hipe_digraph{nodes = sets:add_element(NewNode, Nodes)}. + +-spec add_node_list([_], hdg()) -> hdg(). + +add_node_list(NewNodes, DG = #hipe_digraph{nodes=Nodes}) -> + Set = sets:from_list(NewNodes), + DG#hipe_digraph{nodes = sets:union(Set, Nodes)}. + +-spec add_edge(_, _, hdg()) -> hdg(). + +add_edge(From, To, #hipe_digraph{edges = Edges, rev_edges = RevEdges, + leaves = Leaves, nodes = Nodes}) -> + Fun1 = fun(Set) -> ordsets:add_element(To, Set) end, + NewEdges = dict:update(From, Fun1, [To], Edges), + Fun2 = fun(Set) -> ordsets:add_element(From, Set) end, + NewRevEdges = dict:update(To, Fun2, [From], RevEdges), + NewLeaves = ordsets:del_element(From, Leaves), + #hipe_digraph{edges = NewEdges, + rev_edges = NewRevEdges, + leaves = NewLeaves, + nodes = sets:add_element(From, sets:add_element(To, Nodes))}. + +%%------------------------------------------------------------------------- + +-spec take_indep_scc(hdg()) -> 'none' | {'ok', [_], hdg()}. + +take_indep_scc(DG = #hipe_digraph{edges = Edges, rev_edges = RevEdges, + leaves = Leaves, nodes = Nodes}) -> + case sets:size(Nodes) =:= 0 of + true -> none; + false -> + {SCC, NewLeaves} = + case Leaves of + [H|T] -> + {[H], T}; + [] -> + case find_all_leaves(Edges) of + [] -> + {[Node|_], _} = dfs(Nodes, RevEdges), + {SCC1, _} = dfs(Node, Edges), + {SCC1, []}; + [H|T] -> + {[H], T} + end + end, + NewEdges = remove_edges(SCC, Edges, RevEdges), + NewRevEdges = remove_edges(SCC, RevEdges, Edges), + NewNodes = sets:subtract(Nodes, sets:from_list(SCC)), + {ok, reverse_preorder(SCC, Edges), + DG#hipe_digraph{edges = NewEdges, rev_edges = NewRevEdges, + leaves = NewLeaves, nodes = NewNodes}} + end. + +find_all_leaves(Edges) -> + List = dict:fold(fun(Key, [Key], Acc) -> [Key|Acc]; + (_, _, Acc) -> Acc + end, [], Edges), + ordsets:from_list(List). + +remove_edges(Nodes0, Edges, RevEdges) -> + Nodes = ordsets:from_list(Nodes0), + Fun = fun(N, Dict) -> dict:erase(N, Dict) end, + Edges1 = lists:foldl(Fun, Edges, Nodes), + remove_edges_in(Nodes, Edges1, RevEdges). + +remove_edges_in([Node|Nodes], Edges, RevEdges) -> + NewEdges = + case dict:find(Node, RevEdges) of + error -> + Edges; + {ok, Set} -> + Fun = fun(Key, Dict) -> + case dict:find(Key, Dict) of + error -> + Dict; + {ok, OldTo} -> + case ordsets:del_element(Node, OldTo) of + [] -> dict:store(Key, [Key], Dict); + NewSet -> dict:store(Key, NewSet, Dict) + end + end + end, + lists:foldl(Fun, Edges, Set) + end, + remove_edges_in(Nodes, NewEdges, RevEdges); +remove_edges_in([], Edges, _RevEdges) -> + Edges. + +reverse_preorder([_] = Nodes, _Edges) -> + Nodes; +reverse_preorder([N|_] = Nodes, Edges) -> + NodeSet = sets:from_list(Nodes), + {PreOrder, _} = dfs(N, Edges), + DFS = [X || X <- PreOrder, sets:is_element(X, NodeSet)], + lists:reverse(DFS). + +%%--------------------------------------------------------------------- + +-spec reverse_preorder_sccs(hdg()) -> [[_]]. + +reverse_preorder_sccs(DG) -> + reverse_preorder_sccs(DG, []). + +reverse_preorder_sccs(DG, Acc) -> + case take_indep_scc(DG) of + none -> lists:reverse(Acc); + {ok, SCC, DG1} -> reverse_preorder_sccs(DG1, [SCC|Acc]) + end. + +%%--------------------------------------------------------------------- + +-spec get_parents(_, hdg()) -> [_]. + +get_parents(Node, #hipe_digraph{rev_edges = RevEdges}) -> + case dict:is_key(Node, RevEdges) of + true -> dict:fetch(Node, RevEdges); + false -> [] + end. + +-spec get_children(_, hdg()) -> [_]. + +get_children(Node, #hipe_digraph{edges = Edges}) -> + case dict:is_key(Node, Edges) of + true -> dict:fetch(Node, Edges); + false -> [] + end. + +%%--------------------------------------------------------------------- +%% dfs/2 returns a preordered depth first search and the nodes visited. + +dfs(Node, Edges) -> + case sets:is_set(Node) of + true -> + dfs(sets:to_list(Node), Edges, sets:new(), []); + false -> + dfs([Node], Edges, sets:new(), []) + end. + +dfs([Node|Left], Edges, Visited, Order) -> + case sets:is_element(Node, Visited) of + true -> + dfs(Left, Edges, Visited, Order); + false -> + NewVisited = sets:add_element(Node, Visited), + case dict:find(Node, Edges) of + error -> + dfs(Left, Edges, NewVisited, [Node|Order]); + {ok, Succ} -> + {NewOrder, NewVisited1} = dfs(Succ, Edges, NewVisited, Order), + dfs(Left, Edges, NewVisited1, [Node|NewOrder]) + end + end; +dfs([], _Edges, Visited, Order) -> + {Order, Visited}. diff --git a/lib/hipe/util/hipe_dot.erl b/lib/hipe/util/hipe_dot.erl new file mode 100755 index 0000000000..d6ef801c88 --- /dev/null +++ b/lib/hipe/util/hipe_dot.erl @@ -0,0 +1,217 @@ +%%% -*- erlang-indent-level: 2 -*- +%%% +%%% %CopyrightBegin% +%%% +%%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%%% +%%% The contents of this file are subject to the Erlang Public License, +%%% Version 1.1, (the "License"); you may not use this file except in +%%% compliance with the License. You should have received a copy of the +%%% Erlang Public License along with this software. If not, it can be +%%% retrieved online at http://www.erlang.org/. +%%% +%%% Software distributed under the License is distributed on an "AS IS" +%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%%% the License for the specific language governing rights and limitations +%%% under the License. +%%% +%%% %CopyrightEnd% +%%% +%%%------------------------------------------------------------------- +%%% File : hipe_dot.erl +%%% Author : Per Gustafsson +%%% Description : +%%% +%%% Created : 25 Nov 2004 by Per Gustafsson +%%%------------------------------------------------------------------- + +-module(hipe_dot). + +-export([translate_digraph/3, translate_digraph/5, + translate_list/3, translate_list/4, translate_list/5]). + +%%-------------------------------------------------------------------- + +-type gnode() :: any(). +-type edge() :: {gnode(), gnode()}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% This module creates .dot representations of graphs from their +%% Erlang representations. There are two different forms of Erlang +%% representations that the module accepts, digraphs and lists of two +%% tuples (where each tuple represents a directed edge). +%% +%% The functions also require a FileName and a name of the graph. The +%% filename is the name of the resulting .dot file the GraphName is +%% pretty much useless. +%% +%% The resulting .dot reprsentation will be stored in the flie FileName. +%% +%% Interfaces: +%% +%% translate_list(Graph::[{Node,Node}], FileName::string(), +%% GraphName::string()) -> ok +%% +%% translate_list(Graph::[{Node,Node}], FileName::string(), +%% GraphName::string(), Options::[option] ) -> ok +%% +%% translate_list(Graph::[{Node,Node}], FileName::string(), +%% GraphName::string(), Fun::fun(term() -> string()), +%% Options::[option]) -> ok +%% +%% The optional Fun argument dictates how the node/names should be output. +%% +%% The option list can be used to pass options to .dot to decide how +%% different nodes and edges should be displayed. +%% +%% translate_digraph has the same interface as translate_list except +%% it takes a digraph rather than a list. +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-spec translate_digraph(digraph(), string(), string()) -> 'ok'. + +translate_digraph(G, FileName, GName) -> + translate_digraph(G, FileName, GName, + fun(X) -> io_lib:format("~p", [X]) end, []). + +-spec translate_digraph(digraph(), string(), string(), + fun((_) -> string()), [_]) -> 'ok'. + +translate_digraph(G, FileName, GName, Fun, Opts) -> + Edges = [digraph:edge(G, X) || X <- digraph:edges(G)], + EdgeList = [{X, Y} || {_, X, Y, _} <- Edges], + translate_list(EdgeList, FileName, GName, Fun, Opts). + +%%-------------------------------------------------------------------- + +-spec translate_list([edge()], string(), string()) -> 'ok'. + +translate_list(List, FileName, GName) -> + translate_list(List, FileName, GName, + fun(X) -> lists:flatten(io_lib:format("~p", [X])) end, []). + +-spec translate_list([edge()], string(), string(), [_]) -> 'ok'. + +translate_list(List, FileName, GName, Opts) -> + translate_list(List, FileName, GName, + fun(X) -> lists:flatten(io_lib:format("~p", [X])) end, Opts). + +-spec translate_list([edge()], string(), string(), + fun((_) -> string()), [_]) -> 'ok'. + +translate_list(List, FileName, GName, Fun, Opts) -> + {NodeList1, NodeList2} = lists:unzip(List), + NodeList = NodeList1 ++ NodeList2, + NodeSet = ordsets:from_list(NodeList), + Start = ["digraph ",GName ," {"], + VertexList = [node_format(Opts, Fun, V) ||V <- NodeSet], + End = ["graph [", GName, "=", GName, "]}"], + EdgeList = [edge_format(Opts, Fun, X, Y) || {X,Y} <- List], + String = [Start, VertexList, EdgeList, End], + %% io:format("~p~n", [lists:flatten([String])]), + ok = file:write_file(FileName, list_to_binary(String)). + +%%-------------------------------------------------------------------- + +node_format(Opt, Fun, V) -> + OptText = nodeoptions(Opt, Fun ,V), + Tmp = io_lib:format("~p", [Fun(V)]), + String = lists:flatten(Tmp), + %% io:format("~p", [String]), + {Width, Heigth} = calc_dim(String), + W = ((Width div 7) + 1) * 0.55, + H = Heigth * 0.4, + SL = io_lib:format("~f", [W]), + SH = io_lib:format("~f", [H]), + [String, " [width=", SL, " heigth=", SH, " ", OptText,"];\n"]. + +edge_format(Opt, Fun, V1, V2) -> + OptText = + case lists:flatten(edgeoptions(Opt, Fun ,V1, V2)) of + [] -> + []; + [_|X] -> + X + end, + String = [io_lib:format("~p", [Fun(V1)]), " -> ", + io_lib:format("~p", [Fun(V2)])], + [String, " [", OptText, "];\n"]. + +calc_dim(String) -> + calc_dim(String, 1, 0, 0). + +calc_dim("\\n" ++ T, H, TmpW, MaxW) -> + calc_dim(T, H+1, 0, erlang:max(TmpW, MaxW)); +calc_dim([_|T], H, TmpW, MaxW) -> + calc_dim(T, H, TmpW+1, MaxW); +calc_dim([], H, TmpW, MaxW) -> + {erlang:max(TmpW, MaxW), H}. + +edgeoptions([{all_edges, {OptName, OptVal}}|T], Fun, V1, V2) -> + case legal_edgeoption(OptName) of + true -> + [io_lib:format(",~p=~p ", [OptName, OptVal])|edgeoptions(T, Fun, V1, V2)] + %% false -> + %% edgeoptions(T, Fun, V1, V2) + end; +edgeoptions([{N1, N2, {OptName, OptVal}}|T], Fun, V1, V2) -> + case %% legal_edgeoption(OptName) andalso + Fun(N1) =:= Fun(V1) andalso Fun(N2) =:= Fun(V2) of + true -> + [io_lib:format(",~p=~p ", [OptName, OptVal])|edgeoptions(T, Fun, V1, V2)]; + false -> + edgeoptions(T, Fun, V1, V2) + end; +edgeoptions([_|T], Fun, V1, V2) -> + edgeoptions(T, Fun, V1, V2); +edgeoptions([], _, _, _) -> + []. + +nodeoptions([{all_nodes, {OptName, OptVal}}|T], Fun, V) -> + case legal_nodeoption(OptName) of + true -> + [io_lib:format(",~p=~p ", [OptName, OptVal])|nodeoptions(T, Fun, V)]; + false -> + nodeoptions(T, Fun, V) + end; +nodeoptions([{Node, {OptName, OptVal}}|T], Fun, V) -> + case Fun(Node) =:= Fun(V) andalso legal_nodeoption(OptName) of + true -> + [io_lib:format("~p=~p ", [OptName, OptVal])|nodeoptions(T, Fun, V)]; + false -> + nodeoptions(T, Fun, V) + end; +nodeoptions([_|T], Fun, V) -> + nodeoptions(T, Fun, V); +nodeoptions([], _Fun, _V) -> + []. + +legal_nodeoption(bottomlabel) -> true; +legal_nodeoption(color) -> true; +legal_nodeoption(comment) -> true; +legal_nodeoption(distortion) -> true; +legal_nodeoption(fillcolor) -> true; +legal_nodeoption(fixedsize) -> true; +legal_nodeoption(fontcolor) -> true; +legal_nodeoption(fontname) -> true; +legal_nodeoption(fontsize) -> true; +legal_nodeoption(group) -> true; +legal_nodeoption(height) -> true; +legal_nodeoption(label) -> true; +legal_nodeoption(layer) -> true; +legal_nodeoption(orientation) -> true; +legal_nodeoption(peripheries) -> true; +legal_nodeoption(regular) -> true; +legal_nodeoption(shape) -> true; +legal_nodeoption(shapefile) -> true; +legal_nodeoption(sides) -> true; +legal_nodeoption(skew) -> true; +legal_nodeoption(style) -> true; +legal_nodeoption(toplabel) -> true; +legal_nodeoption('URL') -> true; +legal_nodeoption(z) -> true; +legal_nodeoption(Option) when is_atom(Option) -> false. + +legal_edgeoption(Option) when is_atom(Option) -> true. diff --git a/lib/hipe/util/hipe_timing.erl b/lib/hipe/util/hipe_timing.erl new file mode 100644 index 0000000000..191db497e2 --- /dev/null +++ b/lib/hipe/util/hipe_timing.erl @@ -0,0 +1,131 @@ +%% -*- erlang-indent-level: 2 -*- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%%==================================================================== +%% Note: Uses the process keys: +%% hipe_time - Indicates what to time. +%% hipe_timers - A stack of timers. +%% {hipe_timer,T} - Delata times for named timers. +%% T - Acc times for all named timers T. +%%==================================================================== + +-module(hipe_timing). +-export([start/2, stop/2, + %% start_timer/0, stop_timer/1, + %% get_hipe_timer_val/1, set_hipe_timer_val/2, + %% start_hipe_timer/1, stop_hipe_timer/1, + start_optional_timer/2, stop_optional_timer/2]). + +-include("../main/hipe.hrl"). + +%%===================================================================== + +-spec start(string(), atom()) -> 'ok'. + +start(Text, Mod) when is_atom(Mod) -> + Timers = + case get(hipe_timers) of + undefined -> []; + Ts -> Ts + end, + Space = [$| || _ <- Timers], + Total = start_timer(), + put(hipe_timers, [Total|Timers]), + ?msg("[@~7w]" ++ Space ++ "> ~s~n", [Total,Text]). + +-spec stop(string(), atom()) -> 'ok'. + +stop(Text, Mod) when is_atom(Mod) -> + {Total,_Last} = erlang:statistics(runtime), + case get(hipe_timers) of + [StartTime|Timers] -> + Space = [$| || _ <- Timers], + put(hipe_timers,Timers), + ?msg("[@~7w]" ++ Space ++ "< ~s: ~w~n", [Total, Text, Total-StartTime]); + _ -> + put(hipe_timers, []), + ?msg("[@~7w]< ~s: ~w~n", [Total, Text, Total]) + end. + +-spec start_optional_timer(string(), atom()) -> 'ok'. + +start_optional_timer(Text, Mod) -> + case get(hipe_time) of + true -> start(Text, Mod); + all -> start(Text, Mod); + Mod -> start(Text, Mod); + List when is_list(List) -> + case lists:member(Mod, List) of + true -> start(Text, Mod); + false -> ok + end; + _ -> ok + end. + +-spec stop_optional_timer(string(), atom()) -> 'ok'. + +stop_optional_timer(Text, Mod) -> + case get(hipe_time) of + true -> stop(Text, Mod); + all -> stop(Text, Mod); + Mod -> stop(Text, Mod); + List when is_list(List) -> + case lists:member(Mod, List) of + true -> stop(Text, Mod); + false -> ok + end; + _ -> ok + end. + +-spec start_timer() -> non_neg_integer(). + +start_timer() -> + {Total, _Last} = erlang:statistics(runtime), + Total. + +%% stop_timer(T) -> +%% {Total, _Last} = erlang:statistics(runtime), +%% Total - T. +%% +%% start_hipe_timer(Timer) -> +%% Time = erlang:statistics(runtime), +%% put({hipe_timer,Timer}, Time). +%% +%% stop_hipe_timer(Timer) -> +%% {T2, _} = erlang:statistics(runtime), +%% T1 = +%% case get({hipe_timer,Timer}) of +%% {T0, _} -> T0; +%% _ -> 0 +%% end, +%% AccT = +%% case get(Timer) of +%% T when is_integer(T) -> T; +%% _ -> 0 +%% end, +%% put(Timer,AccT+T2-T1). +%% +%% get_hipe_timer_val(Timer) -> +%% case get(Timer) of +%% T when is_integer(T) -> T; +%% _ -> 0 +%% end. +%% +%% set_hipe_timer_val(Timer, Val) -> +%% put(Timer, Val). diff --git a/lib/hipe/util/hipe_vectors.erl b/lib/hipe/util/hipe_vectors.erl new file mode 100644 index 0000000000..d153f3a50d --- /dev/null +++ b/lib/hipe/util/hipe_vectors.erl @@ -0,0 +1,111 @@ +%% -*- erlang-indent-level: 2 -*- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% VECTORS IN ERLANG +%% +%% Abstract interface to vectors, indexed from 0 to size-1. + +-module(hipe_vectors). +-export([new/2, + set/3, + get/2, + size/1, + vector_to_list/1, + %% list_to_vector/1, + list/1]). + +-include("hipe_vectors.hrl"). + +%% --------------------------------------------------------------------- + +-ifdef(USE_TUPLES). + +new(N, V) -> + erlang:make_tuple(N, V). + +size(V) -> erlang:tuple_size(V). + +list(Vec) -> + index(tuple_to_list(Vec), 0). + +index([X|Xs],N) -> + [{N,X} | index(Xs,N+1)]; +index([],_) -> + []. + +%% list_to_vector(Xs) -> +%% list_to_tuple(Xs). + +vector_to_list(V) -> + tuple_to_list(V). + +set(Vec, Ix, V) -> + setelement(Ix+1, Vec, V). + +get(Vec, Ix) -> element(Ix+1, Vec). + +-endif. %% ifdef USE_TUPLES + +%% --------------------------------------------------------------------- + +-ifdef(USE_GBTREES). + +-spec new(non_neg_integer(), _) -> hipe_vector(). +new(N, V) when is_integer(N), N >= 0 -> + gb_trees:from_orddict(mklist(N, V)). + +mklist(N, V) -> + mklist(0, N, V). + +mklist(M, N, V) when M < N -> + [{M, V} | mklist(M+1, N, V)]; +mklist(_, _, _) -> + []. + +-spec size(hipe_vector()) -> non_neg_integer(). +size(V) -> gb_trees:size(V). + +-spec list(hipe_vector()) -> [{_, _}]. +list(Vec) -> + gb_trees:to_list(Vec). + +%% -spec list_to_vector([_]) -> hipe_vector(). +%% list_to_vector(Xs) -> +%% gb_trees:from_orddict(index(Xs, 0)). +%% +%% index([X|Xs], N) -> +%% [{N, X} | index(Xs, N+1)]; +%% index([],_) -> +%% []. + +-spec vector_to_list(hipe_vector()) -> [_]. +vector_to_list(V) -> + gb_trees:values(V). + +-spec set(hipe_vector(), non_neg_integer(), _) -> hipe_vector(). +set(Vec, Ix, V) -> + gb_trees:update(Ix, V, Vec). + +-spec get(hipe_vector(), non_neg_integer()) -> any(). +get(Vec, Ix) -> + gb_trees:get(Ix, Vec). + +-endif. %% ifdef USE_GBTREES diff --git a/lib/hipe/util/hipe_vectors.hrl b/lib/hipe/util/hipe_vectors.hrl new file mode 100644 index 0000000000..043faf4c91 --- /dev/null +++ b/lib/hipe/util/hipe_vectors.hrl @@ -0,0 +1,28 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%%-define(USE_TUPLES, true). +-define(USE_GBTREES, true). + +-ifdef(USE_TUPLES). +-type hipe_vector() :: tuple(). +-endif. + +-ifdef(USE_GBTREES). +-type hipe_vector() :: gb_tree(). +-endif. -- cgit v1.2.3