Summary: Spacetime profiling showed that this was allocating a lot more than it needs to. Switching to a `Hashtbl` makes the memory overhead go away, and halves the memory consumption of the whole frontend on some pathological files. This also brings the file "clang_ast_main.ml" into the infer repo, renamed to "ClangPointers.ml" (and given an mli). It's useful to have something like "clang_ast_main.ml" checked into the facebook-clang-plugins repo to illustrate how to use the OCaml AST visitor generated by atdgen, but it can be simplified to be more pedagogical instead of being the visitor used in infer. Reviewed By: jberdine Differential Revision: D4884383 fbshipit-source-id: 88f324amaster
parent
aa50d90a7d
commit
1727bd4125
@ -0,0 +1,112 @@
|
||||
(*
|
||||
* Copyright (c) 2015 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*)
|
||||
|
||||
open! IStd
|
||||
|
||||
type t = Clang_ast_t.pointer
|
||||
|
||||
module Map = Map.Make(Int)
|
||||
|
||||
let ivar_to_property_table = Int.Table.create ~size:256 ()
|
||||
let pointer_decl_table = Int.Table.create ~size:256 ()
|
||||
let pointer_stmt_table = Int.Table.create ~size:256 ()
|
||||
let pointer_type_table = Int.Table.create ~size:256 ()
|
||||
|
||||
let empty_v = Clang_ast_visit.empty_visitor
|
||||
(* This function is not thread-safe *)
|
||||
let visit_ast
|
||||
?(visit_decl=empty_v) ?(visit_stmt=empty_v) ?(visit_type=empty_v) ?(visit_src_loc=empty_v)
|
||||
top_decl =
|
||||
Clang_ast_visit.decl_visitor := visit_decl;
|
||||
Clang_ast_visit.stmt_visitor := visit_stmt;
|
||||
Clang_ast_visit.type_visitor := visit_type;
|
||||
Clang_ast_visit.source_location_visitor := visit_src_loc;
|
||||
match Clang_ast_v.validate_decl [] top_decl (* visit *) with
|
||||
| None ->
|
||||
()
|
||||
| Some error ->
|
||||
failwithf "ERROR: visiting the clang AST failed with error %s"
|
||||
(Ag_util.Validation.string_of_error error)
|
||||
|
||||
let get_ptr_from_node node =
|
||||
match node with
|
||||
| `DeclNode decl ->
|
||||
let decl_info = Clang_ast_proj.get_decl_tuple decl in
|
||||
decl_info.Clang_ast_t.di_pointer
|
||||
| `StmtNode stmt ->
|
||||
let stmt_info,_ = Clang_ast_proj.get_stmt_tuple stmt in
|
||||
stmt_info.Clang_ast_t.si_pointer
|
||||
| `TypeNode c_type ->
|
||||
let type_info = Clang_ast_proj.get_type_tuple c_type in
|
||||
type_info.Clang_ast_t.ti_pointer
|
||||
|
||||
let get_val_from_node node =
|
||||
match node with
|
||||
| `DeclNode decl -> decl
|
||||
| `StmtNode stmt -> stmt
|
||||
| `TypeNode c_type -> c_type
|
||||
|
||||
let add_node_to_cache node cache =
|
||||
let key = get_ptr_from_node node in
|
||||
let data = get_val_from_node node in
|
||||
Int.Table.set cache ~key ~data
|
||||
|
||||
let process_decl _ decl =
|
||||
add_node_to_cache (`DeclNode decl) pointer_decl_table;
|
||||
match decl with
|
||||
| Clang_ast_t.ObjCPropertyDecl (_, _, {opdi_ivar_decl=Some decl_ref}) ->
|
||||
let ivar_pointer = decl_ref.Clang_ast_t.dr_decl_pointer in
|
||||
Int.Table.set ivar_to_property_table ~key:ivar_pointer ~data:decl
|
||||
| _ -> ()
|
||||
|
||||
let add_stmt_to_cache _ stmt =
|
||||
add_node_to_cache (`StmtNode stmt) pointer_stmt_table
|
||||
|
||||
let add_type_to_cache _ c_type =
|
||||
add_node_to_cache (`TypeNode c_type) pointer_type_table
|
||||
|
||||
let previous_sloc = { Clang_ast_t.sl_file = None; sl_line = None; sl_column = None }
|
||||
|
||||
let get_sloc current previous =
|
||||
match current with
|
||||
| None -> previous
|
||||
| Some _ -> current
|
||||
|
||||
let mutate_sloc sloc file line column =
|
||||
let open Clang_ast_t in
|
||||
sloc.sl_file <- file;
|
||||
sloc.sl_line <- line;
|
||||
sloc.sl_column <- column
|
||||
|
||||
let reset_sloc sloc = mutate_sloc sloc None None None
|
||||
|
||||
let complete_source_location _ source_loc =
|
||||
let open Clang_ast_t in
|
||||
let file = get_sloc source_loc.sl_file previous_sloc.sl_file in
|
||||
let line = get_sloc source_loc.sl_line previous_sloc.sl_line in
|
||||
let column = get_sloc source_loc.sl_column previous_sloc.sl_column in
|
||||
mutate_sloc source_loc file line column;
|
||||
mutate_sloc previous_sloc file line column
|
||||
|
||||
let reset_cache () =
|
||||
Int.Table.clear pointer_decl_table;
|
||||
Int.Table.clear pointer_stmt_table;
|
||||
Int.Table.clear pointer_type_table;
|
||||
Int.Table.clear ivar_to_property_table;
|
||||
reset_sloc previous_sloc
|
||||
|
||||
(* This function is not thread-safe *)
|
||||
let populate_all_tables top_decl =
|
||||
reset_cache ();
|
||||
(* populate caches *)
|
||||
visit_ast
|
||||
~visit_decl:process_decl
|
||||
~visit_stmt:add_stmt_to_cache
|
||||
~visit_type:add_type_to_cache
|
||||
~visit_src_loc:complete_source_location top_decl
|
@ -0,0 +1,30 @@
|
||||
(*
|
||||
* Copyright (c) 2017 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*)
|
||||
open! IStd
|
||||
|
||||
(** pointers produced by the AST exporter to represent sharing in the AST *)
|
||||
type t = Clang_ast_t.pointer
|
||||
|
||||
module Map : module type of Map.Make(Int)
|
||||
|
||||
(** maps ivar decl pointer to its decl record *)
|
||||
val ivar_to_property_table : Clang_ast_t.decl Int.Table.t
|
||||
|
||||
(** maps decl pointer to its decl record *)
|
||||
val pointer_decl_table : Clang_ast_t.decl Int.Table.t
|
||||
|
||||
(** maps stmt pointer to its stmt record *)
|
||||
val pointer_stmt_table : Clang_ast_t.stmt Int.Table.t
|
||||
|
||||
(** map pointer to its type *)
|
||||
val pointer_type_table : Clang_ast_t.c_type Int.Table.t
|
||||
|
||||
(** discover what pointers should point to in the tables above; should be run once for the current
|
||||
toplevel decl *)
|
||||
val populate_all_tables : Clang_ast_t.decl -> unit
|
Loading…
Reference in new issue