Skip to content

Commit a80743b

Browse files
committed
Fix semantics
1 parent 893a9c4 commit a80743b

File tree

12 files changed

+148
-133
lines changed

12 files changed

+148
-133
lines changed

ocaml/runtime/amd64.S

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,8 @@ CFI_STARTPROC
727727
movq C_ARG_2, %rbx /* closure */
728728
movq 0(C_ARG_3), %rax /* argument */
729729
movq 0(%rbx), %r12 /* code pointer */
730+
cmp $1, C_ARG_4
731+
je LBL(caml_start_program_async_exn)
730732
jmp LBL(caml_start_program)
731733
CFI_ENDPROC
732734
ENDFUNCTION(G(caml_callback_asm))
@@ -741,6 +743,8 @@ CFI_STARTPROC
741743
movq 0(C_ARG_3), %rax /* first argument */
742744
movq 8(C_ARG_3), %rbx /* second argument */
743745
LEA_VAR(caml_apply2, %r12) /* code pointer */
746+
cmp $1, C_ARG_4
747+
je LBL(caml_start_program_async_exn)
744748
jmp LBL(caml_start_program)
745749
CFI_ENDPROC
746750
ENDFUNCTION(G(caml_callback2_asm))
@@ -756,24 +760,12 @@ CFI_STARTPROC
756760
movq C_ARG_2, %rsi /* closure */
757761
movq 16(C_ARG_3), %rdi /* third argument */
758762
LEA_VAR(caml_apply3, %r12) /* code pointer */
763+
cmp $1, C_ARG_4
764+
je LBL(caml_start_program_async_exn)
759765
jmp LBL(caml_start_program)
760766
CFI_ENDPROC
761767
ENDFUNCTION(G(caml_callback3_asm))
762768

763-
/* Variant of caml_callback_asm that installs an async exn trap frame. */
764-
FUNCTION(G(caml_callback_asm_async_exn))
765-
CFI_STARTPROC
766-
/* Save callee-save registers */
767-
PUSH_CALLEE_SAVE_REGS
768-
/* Initial loading of arguments */
769-
movq C_ARG_1, %r14 /* Caml_state */
770-
movq C_ARG_2, %rbx /* closure */
771-
movq 0(C_ARG_3), %rax /* argument */
772-
movq 0(%rbx), %r12 /* code pointer */
773-
jmp LBL(caml_start_program_async_exn)
774-
CFI_ENDPROC
775-
ENDFUNCTION(G(caml_callback_asm_async_exn))
776-
777769
FUNCTION(G(caml_ml_array_bound_error))
778770
CFI_STARTPROC
779771
LEA_VAR(caml_array_bound_error, %rax)

ocaml/runtime/callback.c

Lines changed: 104 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -51,26 +51,13 @@ static void init_callback_code(void)
5151
callback_code_inited = 1;
5252
}
5353

54-
static int is_async_exn(value exn)
55-
{
56-
const value *break_exn;
57-
58-
if (caml_global_data == 0) return 0;
59-
60-
if (exn == Field(caml_global_data, STACK_OVERFLOW_EXN)) return 1;
61-
62-
/* "Sys.Break" must match stdlib/sys.mlp. */
63-
break_exn = caml_named_value("Sys.Break");
64-
if (break_exn != NULL && exn == *break_exn) return 1;
65-
66-
return 0;
67-
}
54+
/* Functions that return all exceptions, including asynchronous ones */
6855

6956
static value caml_callbackN_exn0(value closure, int narg, value args[],
70-
int catch_async_exns)
57+
int *returning_async_exn)
7158
{
7259
int i;
73-
value res, exn;
60+
value res;
7461

7562
CAMLassert(narg + 4 <= 256);
7663

@@ -83,90 +70,119 @@ static value caml_callbackN_exn0(value closure, int narg, value args[],
8370
if (!callback_code_inited) init_callback_code();
8471
callback_code[1] = narg + 3;
8572
callback_code[3] = narg;
86-
res = caml_interprete(callback_code, sizeof(callback_code));
73+
res = caml_interprete(callback_code, sizeof(callback_code),
74+
returning_async_exn);
8775
if (Is_exception_result(res)) Caml_state->extern_sp += narg + 4; /* PR#3419 */
8876

89-
if (!Is_exception_result(res)) return res;
90-
91-
exn = Extract_exception(res);
92-
93-
/* When not called from [Sys.with_async_exns], any asynchronous exceptions
94-
must be reraised here, rather than being returned as the result of one
95-
of the [caml_callback*] functions. This will cause them to arrive only
96-
at any [Sys.with_async_exns] and toplevel uncaught exception handler
97-
sites. */
98-
if (!catch_async_exns && is_async_exn(exn)) caml_raise_async(exn);
99-
10077
return res;
10178
}
10279

10380
CAMLexport value caml_callbackN_exn(value closure, int narg, value args[])
10481
{
105-
return caml_callbackN_exn0(closure, narg, args, 0);
82+
return caml_callbackN_exn0(closure, narg, args, NULL);
10683
}
10784

10885
CAMLexport value caml_callback_exn(value closure, value arg1)
10986
{
11087
value arg[1];
11188
arg[0] = arg1;
112-
return caml_callbackN_exn(closure, 1, arg);
89+
return caml_callbackN_exn0(closure, 1, arg, NULL);
11390
}
11491

11592
CAMLexport value caml_callback2_exn(value closure, value arg1, value arg2)
11693
{
11794
value arg[2];
11895
arg[0] = arg1;
11996
arg[1] = arg2;
120-
return caml_callbackN_exn(closure, 2, arg);
97+
return caml_callbackN_exn0(closure, 2, arg, NULL);
12198
}
12299

123100
CAMLexport value caml_callback3_exn(value closure,
124-
value arg1, value arg2, value arg3)
101+
value arg1, value arg2, value arg3)
125102
{
126103
value arg[3];
127104
arg[0] = arg1;
128105
arg[1] = arg2;
129106
arg[2] = arg3;
130-
return caml_callbackN_exn(closure, 3, arg);
107+
return caml_callbackN_exn0(closure, 3, arg, NULL);
108+
}
109+
110+
/* Functions that propagate all exceptions, with any asynchronous exceptions
111+
also being propagated asynchronously. */
112+
113+
CAMLexport value caml_callbackN(value closure, int narg, value args[])
114+
{
115+
value res;
116+
int returning_async_exn;
117+
118+
res = caml_callbackN_exn0(closure, narg, args, &returning_async_exn);
119+
if (Is_exception_result(res)) {
120+
value exn = Extract_exception(res);
121+
if (returning_async_exn) caml_raise_async(exn);
122+
else caml_raise(exn);
123+
}
124+
125+
return res;
131126
}
132127

133-
CAMLexport value caml_callback_async_exn(value closure, value arg1)
128+
CAMLexport value caml_callback(value closure, value arg1)
134129
{
135130
value arg[1];
136131
arg[0] = arg1;
132+
return caml_callbackN(closure, 1, arg);
133+
}
134+
135+
CAMLexport value caml_callback2(value closure, value arg1, value arg2)
136+
{
137+
value arg[2];
138+
arg[0] = arg1;
139+
arg[1] = arg2;
140+
return caml_callbackN(closure, 2, arg);
141+
}
137142

138-
return caml_callbackN_exn0(closure, 1, arg, 1);
143+
CAMLexport value caml_callback3(value closure,
144+
value arg1, value arg2, value arg3)
145+
{
146+
value arg[3];
147+
arg[0] = arg1;
148+
arg[1] = arg2;
149+
arg[2] = arg3;
150+
return caml_callbackN(closure, 3, arg);
139151
}
140152

141153
#else
142154

143155
/* Native-code callbacks. */
144156

145157
typedef value (callback_stub)(caml_domain_state* state, value closure,
146-
value* args);
158+
value* args, int catch_async_exns);
147159

148160
callback_stub caml_callback_asm, caml_callback2_asm, caml_callback3_asm;
149161

150-
CAMLexport value caml_callback_exn(value closure, value arg)
162+
/* First we build functions that allow control as to whether an asynchronous
163+
exception trap frame is installed. */
164+
165+
static value callback(value closure, value arg, int catch_async_exns)
151166
{
152-
return caml_callback_asm(Caml_state, closure, &arg);
167+
return caml_callback_asm(Caml_state, closure, &arg, catch_async_exns);
153168
}
154169

155-
CAMLexport value caml_callback2_exn(value closure, value arg1, value arg2)
170+
static value callback2(value closure, value arg1, value arg2,
171+
int catch_async_exns)
156172
{
157173
value args[] = {arg1, arg2};
158-
return caml_callback2_asm(Caml_state, closure, args);
174+
return caml_callback2_asm(Caml_state, closure, args, catch_async_exns);
159175
}
160176

161-
CAMLexport value caml_callback3_exn(value closure,
162-
value arg1, value arg2, value arg3)
177+
static value callback3(value closure, value arg1, value arg2, value arg3,
178+
int catch_async_exns)
163179
{
164180
value args[] = {arg1, arg2, arg3};
165-
return caml_callback3_asm(Caml_state, closure, args);
181+
return caml_callback3_asm(Caml_state, closure, args, catch_async_exns);
166182
}
167183

168-
169-
CAMLexport value caml_callbackN_exn(value closure, int narg, value args[])
184+
static value callbackN(value closure, int narg, value args[],
185+
int catch_async_exns)
170186
{
171187
CAMLparam1 (closure);
172188
CAMLxparamN (args, narg);
@@ -178,17 +194,17 @@ CAMLexport value caml_callbackN_exn(value closure, int narg, value args[])
178194
/* Pass as many arguments as possible */
179195
switch (narg - i) {
180196
case 1:
181-
res = caml_callback_exn(res, args[i]);
197+
res = callback(res, args[i], catch_async_exns);
182198
if (Is_exception_result(res)) CAMLreturn (res);
183199
i += 1;
184200
break;
185201
case 2:
186-
res = caml_callback2_exn(res, args[i], args[i + 1]);
202+
res = callback2(res, args[i], args[i + 1], catch_async_exns);
187203
if (Is_exception_result(res)) CAMLreturn (res);
188204
i += 2;
189205
break;
190206
default:
191-
res = caml_callback3_exn(res, args[i], args[i + 1], args[i + 2]);
207+
res = callback3(res, args[i], args[i + 1], args[i + 2], catch_async_exns);
192208
if (Is_exception_result(res)) CAMLreturn (res);
193209
i += 3;
194210
break;
@@ -197,39 +213,65 @@ CAMLexport value caml_callbackN_exn(value closure, int narg, value args[])
197213
CAMLreturn (res);
198214
}
199215

200-
extern value (caml_callback_asm_async_exn)
201-
(caml_domain_state* state, value closure, value* args);
216+
/* Functions that return all exceptions, including asynchronous ones */
202217

203-
CAMLexport value caml_callback_async_exn(value closure, value arg)
218+
CAMLexport value caml_callback_exn(value closure, value arg)
204219
{
205-
return caml_callback_asm_async_exn(Caml_state, closure, &arg);
220+
return callback(closure, arg, 1);
206221
}
207222

208-
#endif
223+
CAMLexport value caml_callback2_exn(value closure, value arg1, value arg2)
224+
{
225+
return callback2(closure, arg1, arg2, 1);
226+
}
227+
228+
CAMLexport value caml_callback3_exn(value closure,
229+
value arg1, value arg2, value arg3)
230+
{
231+
return callback3(closure, arg1, arg2, arg3, 1);
232+
}
233+
234+
CAMLexport value caml_callbackN_exn(value closure, int narg, value args[])
235+
{
236+
return callbackN(closure, narg, args, 1);
237+
}
209238

210-
/* Exception-propagating variants of the above */
239+
/* Functions that propagate all exceptions, with any asynchronous exceptions
240+
also being propagated asynchronously. In these cases we do not install
241+
an asynchronous exception trap frame, avoiding any need to perform
242+
comparisons on exception values to determine if they represent asynchronous
243+
exceptions (which would be problematic for [Sys.Break], thus likely
244+
necessitating these being wrapped in another constructor). */
211245

212-
CAMLexport value caml_callback (value closure, value arg)
246+
static value raise_if_exception(value res)
213247
{
214-
return caml_raise_if_exception(caml_callback_exn(closure, arg));
248+
if (Is_exception_result(res)) caml_raise(Extract_exception(res));
249+
return res;
215250
}
216251

217-
CAMLexport value caml_callback2 (value closure, value arg1, value arg2)
252+
CAMLexport value caml_callback(value closure, value arg)
218253
{
219-
return caml_raise_if_exception(caml_callback2_exn(closure, arg1, arg2));
254+
return raise_if_exception(callback(closure, arg, 0));
220255
}
221256

222-
CAMLexport value caml_callback3 (value closure, value arg1, value arg2,
223-
value arg3)
257+
CAMLexport value caml_callback2(value closure, value arg1, value arg2)
224258
{
225-
return caml_raise_if_exception(caml_callback3_exn(closure, arg1, arg2, arg3));
259+
return raise_if_exception(callback2(closure, arg1, arg2, 0));
260+
}
261+
262+
CAMLexport value caml_callback3(value closure,
263+
value arg1, value arg2, value arg3)
264+
{
265+
return raise_if_exception(callback3(closure, arg1, arg2, arg3, 0));
226266
}
227267

228268
CAMLexport value caml_callbackN (value closure, int narg, value args[])
229269
{
230-
return caml_raise_if_exception(caml_callbackN_exn(closure, narg, args));
270+
return raise_if_exception(callbackN(closure, narg, args, 0));
231271
}
232272

273+
#endif
274+
233275
/* Naming of OCaml values */
234276

235277
struct named_value {

ocaml/runtime/caml/callback.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ CAMLextern value caml_callback3_exn (value closure,
3939
value arg1, value arg2, value arg3);
4040
CAMLextern value caml_callbackN_exn (value closure, int narg, value args[]);
4141

42-
CAMLextern value caml_callback_async_exn (value closure, value arg);
43-
4442
CAMLextern const value * caml_named_value (char const * name);
4543
typedef void (*caml_named_action) (const value*, char *);
4644
CAMLextern void caml_iterate_named_values(caml_named_action f);

ocaml/runtime/caml/fail.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,19 @@ struct longjmp_buffer {
6464
#define caml_exn_bucket (Caml_state_field(exn_bucket))
6565

6666
CAMLextern value caml_prepare_for_raise(value v, int *turned_into_async_exn);
67+
68+
/* For internal use of fail_byt.c and fail_nat.c only. */
6769
CAMLextern value caml_check_async_exn0(value res, const char *msg,
6870
value stack_overflow_exn);
6971

72+
/* This function must only be used in a context where it is certain that
73+
occurrences of [Sys.Break] and [Stack_overflow] must be raised as
74+
asynchronous exceptions (for example in a finaliser, signal handler or
75+
memprof callback). */
7076
CAMLextern value caml_check_async_exn(value res, const char *msg);
7177

7278
int caml_is_special_exception(value exn);
7379

74-
CAMLextern value caml_raise_if_exception(value res);
7580
CAMLextern value caml_raise_async_if_exception(value res);
7681

7782
CAMLnoreturn_start

ocaml/runtime/caml/interp.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
#include "mlvalues.h"
2525

2626
/* interpret a bytecode */
27-
value caml_interprete (code_t prog, asize_t prog_size);
27+
value caml_interprete (code_t prog, asize_t prog_size,
28+
int *returning_async_exn);
2829

2930
#endif /* CAML_INTERNALS */
3031

ocaml/runtime/fail.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ CAMLexport value caml_prepare_for_raise(value v, int *turned_into_async_exn)
5454
return v;
5555
}
5656

57+
CAMLexport value caml_raise_async_if_exception(value result)
58+
{
59+
if (Is_exception_result(result)) caml_raise_async(Extract_exception(result));
60+
61+
return result;
62+
}
63+
5764
CAMLexport value caml_check_async_exn0(value res, const char *msg,
5865
value stack_overflow_exn)
5966
{

0 commit comments

Comments
 (0)