Revert "Remove the need for a NOP operation in automata bytecode."
authorKim Nguyễn <kn@lri.fr>
Mon, 19 Mar 2012 14:24:15 +0000 (15:24 +0100)
committerKim Nguyễn <kn@lri.fr>
Mon, 19 Mar 2012 14:24:15 +0000 (15:24 +0100)
This reverts commit a6c781462ddca7c25fe95789c81c2265f153203c.
The automata is unsound and returns boggus results for child moves
without the nop case.

src/l2JIT.ml
src/l2JIT.mli
src/runtime.ml

index b1fd4da..4abb5e7 100644 (file)
@@ -6,6 +6,7 @@ open Format
 open Ata
 
 type jump =
+  | NOP of unit
   | FIRST_CHILD of StateSet.t
   | NEXT_SIBLING of StateSet.t
   | FIRST_ELEMENT of StateSet.t
@@ -22,21 +23,22 @@ type jump =
   | ELEMENT_SUBTREE of StateSet.t
 
 type dir = DIR_LEFT | DIR_RIGHT
-let _nop = None
-let _first_child s = Some (FIRST_CHILD s)
-let _next_sibling s = Some (NEXT_SIBLING s)
-let _first_element s = Some (FIRST_ELEMENT s)
-let _next_element s = Some (NEXT_ELEMENT s)
-let _tagged_descendant s t = Some (TAGGED_DESCENDANT(s,t))
-let _tagged_following s t = Some (TAGGED_FOLLOWING(s,t))
-let _select_descendant s t = Some (SELECT_DESCENDANT(s,t, Tree.unordered_set_of_set t))
-let _select_following s t = Some (SELECT_FOLLOWING(s,t, Tree.unordered_set_of_set t))
-let _tagged_child s t = Some (TAGGED_CHILD(s,t))
-let _tagged_following_sibling s t = Some (TAGGED_FOLLOWING_SIBLING(s,t))
-let _select_child s t = Some (SELECT_CHILD(s,t, Tree.unordered_set_of_set t))
-let _select_following_sibling s t = Some (SELECT_FOLLOWING_SIBLING(s,t, Tree.unordered_set_of_set t))
-let _tagged_subtree s t = Some (TAGGED_SUBTREE (s, t))
-let _element_subtree s = Some (ELEMENT_SUBTREE s)
+
+let _nop = NOP ()
+let _first_child s = FIRST_CHILD s
+let _next_sibling s = NEXT_SIBLING s
+let _first_element s = FIRST_ELEMENT s
+let _next_element s = NEXT_ELEMENT s
+let _tagged_descendant s t = TAGGED_DESCENDANT(s,t)
+let _tagged_following s t = TAGGED_FOLLOWING(s,t)
+let _select_descendant s t = SELECT_DESCENDANT(s,t, Tree.unordered_set_of_set t)
+let _select_following s t = SELECT_FOLLOWING(s,t, Tree.unordered_set_of_set t)
+let _tagged_child s t = TAGGED_CHILD(s,t)
+let _tagged_following_sibling s t = TAGGED_FOLLOWING_SIBLING(s,t)
+let _select_child s t = SELECT_CHILD(s,t, Tree.unordered_set_of_set t)
+let _select_following_sibling s t = SELECT_FOLLOWING_SIBLING(s,t, Tree.unordered_set_of_set t)
+let _tagged_subtree s t = TAGGED_SUBTREE (s, t)
+let _element_subtree s = ELEMENT_SUBTREE s
 
 
 let jump_stat_table = Hashtbl.create 17
@@ -47,6 +49,7 @@ let jump_stat j =
 
 let print_jump fmt j =
   match j with
+    | NOP _ -> fprintf fmt "nop"
     | FIRST_CHILD _ -> fprintf fmt "first_child"
     | NEXT_SIBLING _ -> fprintf fmt "next_sibling"
     | FIRST_ELEMENT _ -> fprintf fmt "first_element"
@@ -98,17 +101,40 @@ let print_opcode fmt o = match o with
   | LEFT (tl, j) -> fprintf fmt "LEFT(\n[%a], %a)" Translist.print tl print_jump j
   | RIGHT (tl, j) -> fprintf fmt "RIGHT(\n[%a], %a)" Translist.print tl print_jump j
   | BOTH (tl, j1, j2) -> fprintf fmt "BOTH(\n[%a], %a, %a)" Translist.print tl print_jump j1 print_jump j2
-
-let show_stats a =
-  let count = ref 0 in
-  Cache.Lvl2.iteri (fun _ _ _ b -> if not b then incr count) a;
-  eprintf "%!L2JIT: %i used entries\n%!" !count
-
-let create () =
-  let v = Cache.Lvl2.create 4096 dummy in
-  if !Options.verbose then
-    at_exit (fun () -> show_stats v);
-  v
+(*
+let print_cache fmt d =
+  let c = Cache.Lvl2.to_array d in
+  Array.iteri begin fun tag a ->
+    let tagstr = Tag.to_string tag in
+    if a != Cache.Lvl2.dummy_line d && tagstr <> "<INVALID TAG>"
+    then begin
+      fprintf fmt "Entry %s: \n" tagstr;
+      Array.iter (fun o -> if o != dummy then begin
+       print_opcode fmt o;
+       fprintf fmt "\n%!" end) a;
+      fprintf fmt "---------------------------\n%!"
+    end
+  end c
+*)
+let create () = Cache.Lvl2.create 4096 dummy
+(*
+let stats fmt c =
+  let d = Cache.Lvl2.to_array c in
+  let len = Array.fold_left (fun acc a -> Array.length a + acc) 0 d in
+  let lvl1 = Array.fold_left (fun acc a -> if Array.length a == 0 then acc else acc+1) 0 d in
+  let lvl2 = Array.fold_left (fun acc a ->
+                               Array.fold_left (fun acc2 a2 -> if a2 == dummy then acc2 else acc2+1)
+                                 acc a) 0 d
+  in
+  fprintf fmt "L2JIT Statistics:
+\t%i entries
+\t%i used L1 lines
+\t%i used L2 lines
+\ttable size: %ikb\n"
+      len lvl1 lvl2 (Ocaml.size_kb d);
+  fprintf fmt "%s" "L2JIT Content:\n";
+  print_cache fmt c
+*)
 
 let find t tag set = Cache.Lvl2.find t (Uid.to_int set.StateSet.Node.id) tag
 
@@ -129,11 +155,11 @@ let has_text l = Ptset.Int.mem Tag.pcdata l
 let rec translate_jump tree tag (jkind:Ata.jump_kind) dir s =
   let child, desc, sib, fol = Tree.tags tree tag in
      match jkind, dir with
-      | NIL, _ -> None
-      | NODE, DIR_LEFT -> Some (FIRST_CHILD s)
-      | STAR, DIR_LEFT -> Some (FIRST_ELEMENT s)
-      | NODE, DIR_RIGHT -> Some (NEXT_SIBLING s)
-      | STAR, DIR_RIGHT -> Some (NEXT_ELEMENT s)
+      | NIL, _ -> _nop
+      | NODE, DIR_LEFT -> FIRST_CHILD s
+      | STAR, DIR_LEFT -> FIRST_ELEMENT s
+      | NODE, DIR_RIGHT -> NEXT_SIBLING s
+      | STAR, DIR_RIGHT -> NEXT_ELEMENT s
       | JUMP_ONE t, _ ->
          let l_one, l_many, tagged_one, select_one, any, any_notext =
            if dir = DIR_LEFT then
@@ -144,7 +170,7 @@ let rec translate_jump tree tag (jkind:Ata.jump_kind) dir s =
          in
          let labels = Ptset.Int.inter l_one t in
          let c = Ptset.Int.cardinal labels in
-           if c == 0 then None
+           if c == 0 then _nop
            else if Ptset.Int.for_all (fun lab -> not (Ptset.Int.mem lab l_many)) labels then
              translate_jump tree tag (JUMP_MANY(labels)) dir s
            else if c == 1 then tagged_one s (Ptset.Int.choose labels)
@@ -166,35 +192,26 @@ let rec translate_jump tree tag (jkind:Ata.jump_kind) dir s =
            else select_many s labels
 
       | CAPTURE_MANY (t), DIR_LEFT ->
-         if Ptset.Int.is_singleton t then Some (TAGGED_SUBTREE(s, Ptset.Int.choose t))
-         else if t == Tree.element_tags tree then Some (ELEMENT_SUBTREE s)
+         if Ptset.Int.is_singleton t then TAGGED_SUBTREE(s, Ptset.Int.choose t)
+         else if t == Tree.element_tags tree then ELEMENT_SUBTREE s
          else assert false
       | _ -> assert false
 
 let compute_jump auto tree tag states dir =
   if !Options.no_jump then
-    if dir == DIR_LEFT then Some (FIRST_CHILD states)
-    else Some (NEXT_SIBLING states)
+    if dir == DIR_LEFT then FIRST_CHILD states
+    else NEXT_SIBLING states
   else
     let jkind = Ata.top_down_approx auto states tree in
-    translate_jump tree tag jkind dir states
-
-let mk_left tr_list j =
-  match j with
-    Some x -> LEFT(tr_list, x)
-  | _ -> RETURN
-
-let mk_right tr_list j =
-  match j with
-    Some x -> RIGHT(tr_list, x)
-  | _ -> RETURN
-
-let mk_both tr_list j1 j2 =
-  match j1, j2 with
-  | Some x1, Some x2 -> BOTH(tr_list, x1, x2)
-  | None, Some x -> RIGHT(tr_list,x)
-  | Some x, None -> LEFT(tr_list, x)
-  | None, None -> RETURN
+    let jump = translate_jump tree tag jkind dir states in
+      TRACE("level2-jit", 2,
+           __ "Computed jumps for %s %a %s: %a\n%!"
+             (Tag.to_string tag)
+             StateSet.print states
+             (if dir == DIR_LEFT then "left" else "right")
+             print_jump jump
+      );
+    jump
 
 let compile cache2 auto tree tag states =
   let tr_list, states1, states2 =
@@ -211,15 +228,22 @@ let compile cache2 auto tree tag states =
     let empty_s2 = StateSet.is_empty states2 in
       if empty_s1 && empty_s2 then RETURN
       else if empty_s1 then
-       mk_right tr_list
-         (compute_jump auto tree tag states2 DIR_RIGHT)
+       RIGHT (tr_list,
+              compute_jump auto tree tag states2 DIR_RIGHT)
       else if empty_s2 then
-       mk_left tr_list
-         (compute_jump auto tree tag states1 DIR_LEFT)
+       LEFT (tr_list,
+             compute_jump auto tree tag states1 DIR_LEFT)
       else
        let j1 = compute_jump auto tree tag states1 DIR_LEFT in
        let j2 = compute_jump auto tree tag states2 DIR_RIGHT in
-       mk_both tr_list j1 j2
+       BOTH (tr_list, j1, j2);
+  in
+  let op = match op with
+      (*BOTH(_, NOP _, NOP _) |  LEFT(_, NOP _) | RIGHT(_, NOP _) -> RETURN() *)
+    | BOTH(tr, ((NOP _) as l) , NOP _) -> LEFT (tr, l)
+    | BOTH(tr, l, NOP _) -> LEFT (tr, l)
+    | BOTH(tr, NOP _, r) -> RIGHT (tr, r)
+    | _ -> op
   in
     add cache2 tag states op;
     op
index 0da7c46..e6f3aa9 100644 (file)
@@ -1,4 +1,5 @@
 type jump =
+    NOP of unit
   | FIRST_CHILD of StateSet.t
   | NEXT_SIBLING of StateSet.t
   | FIRST_ELEMENT of StateSet.t
index b4de9cf..2d76bc1 100644 (file)
@@ -255,6 +255,7 @@ DEFINE LOOP_TAG (t, states, tag, ctx) = (
 
     and l2jit_dispatch_instr t ctx instr =
       match instr with
+       | L2JIT.NOP () -> nil_res
        | L2JIT.FIRST_CHILD s -> LOOP ((Tree.first_child tree t), s, ctx)
        | L2JIT.NEXT_SIBLING s -> LOOP ((Tree.next_sibling tree t), s, ctx)