summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Leroy <xavier.leroy@inria.fr>2014-06-05 13:59:33 +0000
committerXavier Leroy <xavier.leroy@inria.fr>2014-06-05 13:59:33 +0000
commit18d23e3a3def856ad1c5696ea2ebe079306cb9d3 (patch)
tree7241a24675859c949de7f71cf22391d043cd3d44
parentd1b1fbee667b5ce1c3b466d438418d4e9ff45e81 (diff)
Reflecting commit 14963 on version/4.02:
PR#2719: wrong scheduling of bound checks within a try...with Invalid_argument -> _ ... git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@14964 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
-rw-r--r--Changes2
-rw-r--r--asmcomp/schedgen.ml35
-rw-r--r--testsuite/makefiles/Makefile.common2
-rw-r--r--testsuite/tests/basic-more/pr2719.ml17
-rw-r--r--testsuite/tests/basic-more/pr2719.reference4
5 files changed, 47 insertions, 13 deletions
diff --git a/Changes b/Changes
index 019e74b30..4b123fb29 100644
--- a/Changes
+++ b/Changes
@@ -152,6 +152,8 @@ OCamldoc:
(Maxence Guesdon, report by Anil Madhavapeddy)
Bug fixes:
+- PR#2719: wrong scheduling of bound checks within a
+ try...with Invalid_argument -> _ ... (Xavier Leroy)
- PR#4719: Sys.executable_name wrong if executable name contains dots (Windows)
(Alain Frisch, report by Bart Jacobs)
- PR#4855: 'camlp4 -I +dir' accepted, dir is relative to 'camlp4 -where'
diff --git a/asmcomp/schedgen.ml b/asmcomp/schedgen.ml
index 89fee29b6..f7af44367 100644
--- a/asmcomp/schedgen.ml
+++ b/asmcomp/schedgen.ml
@@ -138,6 +138,8 @@ let some_load = (Iload(Cmm.Word, Arch.identity_addressing))
class virtual scheduler_generic = object (self)
+val mutable trywith_nesting = 0
+
(* Determine whether an operation ends a basic block or not.
Can be overridden for some processors to signal specific instructions
that terminate a basic block. *)
@@ -154,9 +156,16 @@ method oper_in_basic_block = function
(* Determine whether an instruction ends a basic block or not *)
-method private instr_in_basic_block instr =
+(* PR#2719: it is generally incorrect to schedule checkbound instructions
+ within a try ... with Invalid_argument _ -> ...
+ Hence, a checkbound instruction within a try...with block ends the
+ current basic block. *)
+
+method private instr_in_basic_block instr try_nesting =
match instr.desc with
- Lop op -> self#oper_in_basic_block op
+ Lop op ->
+ self#oper_in_basic_block op &&
+ not (try_nesting > 0 && self#is_checkbound op)
| Lreloadretaddr -> true
| _ -> false
@@ -345,19 +354,21 @@ method private reschedule ready_queue date cont =
method schedule_fundecl f =
- let rec schedule i =
+ let rec schedule i try_nesting =
match i.desc with
- Lend -> i
+ | Lend -> i
+ | Lpushtrap -> { i with next = schedule i.next (try_nesting + 1) }
+ | Lpoptrap -> { i with next = schedule i.next (try_nesting - 1) }
| _ ->
- if self#instr_in_basic_block i then begin
+ if self#instr_in_basic_block i try_nesting then begin
clear_code_dag();
- schedule_block [] i
+ schedule_block [] i try_nesting
end else
- { i with next = schedule i.next }
+ { i with next = schedule i.next try_nesting }
- and schedule_block ready_queue i =
- if self#instr_in_basic_block i then
- schedule_block (self#add_instruction ready_queue i) i.next
+ and schedule_block ready_queue i try_nesting =
+ if self#instr_in_basic_block i try_nesting then
+ schedule_block (self#add_instruction ready_queue i) i.next try_nesting
else begin
let critical_outputs =
match i.desc with
@@ -366,11 +377,11 @@ method schedule_fundecl f =
| Lreturn -> [||]
| _ -> i.arg in
List.iter (fun x -> ignore (longest_path critical_outputs x)) ready_queue;
- self#reschedule ready_queue 0 (schedule i)
+ self#reschedule ready_queue 0 (schedule i try_nesting)
end in
if f.fun_fast then begin
- let new_body = schedule f.fun_body in
+ let new_body = schedule f.fun_body 0 in
clear_code_dag();
{ fun_name = f.fun_name;
fun_body = new_body;
diff --git a/testsuite/makefiles/Makefile.common b/testsuite/makefiles/Makefile.common
index ae6aceaa2..5fdf5a184 100644
--- a/testsuite/makefiles/Makefile.common
+++ b/testsuite/makefiles/Makefile.common
@@ -110,7 +110,7 @@ defaultclean:
.cmxa.so:
@$(OCAMLOPT) -o $@ -shared -linkall $(ADD_COMPFLAGS) $<
-.mly.ml:
+%.ml %.mli: %.mly
@$(OCAMLYACC) -q $< 2> /dev/null
.mll.ml:
diff --git a/testsuite/tests/basic-more/pr2719.ml b/testsuite/tests/basic-more/pr2719.ml
new file mode 100644
index 000000000..f0a9d6a4f
--- /dev/null
+++ b/testsuite/tests/basic-more/pr2719.ml
@@ -0,0 +1,17 @@
+open Printf
+
+let bug () =
+ let mat = [| [|false|] |]
+ and test = ref false in
+ printf "Value of test at the beginning : %b\n" !test; flush stdout;
+ (try let _ = mat.(0).(-1) in
+ (test := true;
+ printf "Am I going through this block of instructions ?\n";
+ flush stdout)
+ with Invalid_argument _ -> printf "Value of test now : %b\n" !test
+ );
+ (try if mat.(0).(-1) then ()
+ with Invalid_argument _ -> ()
+ )
+
+let () = bug ()
diff --git a/testsuite/tests/basic-more/pr2719.reference b/testsuite/tests/basic-more/pr2719.reference
new file mode 100644
index 000000000..073d0916d
--- /dev/null
+++ b/testsuite/tests/basic-more/pr2719.reference
@@ -0,0 +1,4 @@
+Value of test at the beginning : false
+Value of test now : false
+
+All tests succeeded.