|
@@ -95,7 +95,6 @@ module ServerCompilationContext = struct
|
|
|
class_paths : (Digest.t,string list) Hashtbl.t;
|
|
|
(* Increased for each compilation *)
|
|
|
mutable compilation_step : int;
|
|
|
- mutable mark_loop : int;
|
|
|
(* A list of delays which are run after compilation *)
|
|
|
mutable delays : (unit -> unit) list;
|
|
|
(* True if it's an actual compilation, false if it's a display operation *)
|
|
@@ -110,7 +109,6 @@ module ServerCompilationContext = struct
|
|
|
class_paths = Hashtbl.create 0;
|
|
|
changed_directories = Hashtbl.create 0;
|
|
|
compilation_step = 0;
|
|
|
- mark_loop = 0;
|
|
|
delays = [];
|
|
|
was_compilation = false;
|
|
|
macro_context_setup = false;
|
|
@@ -339,7 +337,8 @@ let check_module sctx ctx m p =
|
|
|
end
|
|
|
) paths
|
|
|
in
|
|
|
- let start_mark = sctx.mark_loop in
|
|
|
+ let start_mark = sctx.compilation_step in
|
|
|
+ let unknown_state_modules = ref [] in
|
|
|
let rec check m =
|
|
|
let check_module_path () =
|
|
|
let directories = get_changed_directories sctx ctx in
|
|
@@ -414,30 +413,56 @@ let check_module sctx ctx m p =
|
|
|
Some reason
|
|
|
in
|
|
|
(* If the module mark matches our compilation mark, we are done *)
|
|
|
- if m.m_extra.m_checked = start_mark then
|
|
|
- m.m_extra.m_dirty
|
|
|
- else begin
|
|
|
+ if m.m_extra.m_checked = start_mark then begin match m.m_extra.m_cache_state with
|
|
|
+ | MSGood | MSUnknown ->
|
|
|
+ None
|
|
|
+ | MSBad reason ->
|
|
|
+ Some reason
|
|
|
+ end else begin
|
|
|
(* Otherwise, set to current compilation mark for recursion *)
|
|
|
m.m_extra.m_checked <- start_mark;
|
|
|
- let dirty = match m.m_extra.m_dirty with
|
|
|
- | Some _ as dirty ->
|
|
|
+ let dirty = match m.m_extra.m_cache_state with
|
|
|
+ | MSBad reason ->
|
|
|
(* If we are already dirty, stick to it. *)
|
|
|
- dirty
|
|
|
- | None ->
|
|
|
+ Some reason
|
|
|
+ | MSUnknown ->
|
|
|
+ (* This should not happen because any MSUnknown module is supposed to have the current m_checked. *)
|
|
|
+ die "" __LOC__
|
|
|
+ | MSGood ->
|
|
|
(* Otherwise, run the checks *)
|
|
|
+ m.m_extra.m_cache_state <- MSUnknown;
|
|
|
check ()
|
|
|
in
|
|
|
- (* Update the module now. It will use this dirty status for the remainder of this compilation. *)
|
|
|
begin match dirty with
|
|
|
- | Some _ ->
|
|
|
- m.m_extra.m_dirty <- dirty;
|
|
|
+ | Some reason ->
|
|
|
+ (* Update the state if we're dirty. *)
|
|
|
+ m.m_extra.m_cache_state <- MSBad reason;
|
|
|
| None ->
|
|
|
- ()
|
|
|
+ (* We cannot update if we're clean because at this point it might just be an assumption.
|
|
|
+ Instead We add the module to a list which is updated at the end of handling this subgraph. *)
|
|
|
+ unknown_state_modules := m :: !unknown_state_modules;
|
|
|
end;
|
|
|
dirty
|
|
|
end
|
|
|
in
|
|
|
- check m
|
|
|
+ let state = check m in
|
|
|
+ begin match state with
|
|
|
+ | None ->
|
|
|
+ (* If the entire subgraph is clean, we can set all modules to good state *)
|
|
|
+ List.iter (fun m -> m.m_extra.m_cache_state <- MSGood) !unknown_state_modules;
|
|
|
+ | Some _ ->
|
|
|
+ (* Otherwise, unknown state module may or may not be dirty. We didn't check everything eagerly, so we have
|
|
|
+ to make sure that the module is checked again if it appears in a different check. This is achieved by
|
|
|
+ setting m_checked to a lower value and assuming Good state again. *)
|
|
|
+ List.iter (fun m -> match m.m_extra.m_cache_state with
|
|
|
+ | MSUnknown ->
|
|
|
+ m.m_extra.m_checked <- start_mark - 1;
|
|
|
+ m.m_extra.m_cache_state <- MSGood;
|
|
|
+ | MSGood | MSBad _ ->
|
|
|
+ ()
|
|
|
+ ) !unknown_state_modules
|
|
|
+ end;
|
|
|
+ state
|
|
|
|
|
|
(* Adds module [m] and all its dependencies (recursively) from the cache to the current compilation
|
|
|
context. *)
|
|
@@ -481,7 +506,6 @@ let add_modules sctx ctx m p =
|
|
|
let type_module sctx (ctx:Typecore.typer) mpath p =
|
|
|
let t = Timer.timer ["server";"module cache"] in
|
|
|
let com = ctx.Typecore.com in
|
|
|
- sctx.mark_loop <- sctx.mark_loop + 1;
|
|
|
let cc = CommonCache.get_cache com in
|
|
|
try
|
|
|
let m = cc#find_module mpath in
|