@@ -57,15 +57,34 @@ and admin_instr' =
57
57
| Label of int32 * instr list * code
58
58
| Frame of int32 * frame * code
59
59
60
- type config =
60
+ type thread =
61
61
{
62
62
frame : frame ;
63
63
code : code ;
64
64
budget : int ; (* to model stack overflow *)
65
65
}
66
66
67
+ type config = thread list
68
+ type thread_id = int
69
+ type status = Running | Result of value list | Trap of exn
70
+
67
71
let frame inst locals = {inst; locals}
68
- let config inst vs es = {frame = frame inst [] ; code = vs, es; budget = 300 }
72
+ let thread inst vs es = {frame = frame inst [] ; code = vs, es; budget = 300 }
73
+ let empty_thread = thread empty_module_inst [] []
74
+ let empty_config = []
75
+ let spawn (c : config ) = List. length c, c @ [empty_thread]
76
+
77
+ let status (c : config ) (n : thread_id ) : status =
78
+ let t = List. nth c n in
79
+ match t.code with
80
+ | vs , [] -> Result (List. rev vs)
81
+ | [] , {it = Trapping msg ; at} :: _ -> Trap (Trap. Error (at, msg))
82
+ | _ -> Running
83
+
84
+ let clear (c : config ) (n : thread_id ) : config =
85
+ let ts1, t, ts2 = Lib.List. extract n c in
86
+ ts1 @ [{t with code = [] , [] }] @ ts2
87
+
69
88
70
89
let plain e = Plain e.it @@ e.at
71
90
@@ -122,11 +141,12 @@ let check_align addr ty sz at =
122
141
* v : value
123
142
* es : instr list
124
143
* vs : value stack
144
+ * t : thread
125
145
* c : config
126
146
*)
127
147
128
- let rec step ( c : config ) : config =
129
- let {frame; code = vs, es; _} = c in
148
+ let rec step_thread ( t : thread ) : thread =
149
+ let {frame; code = vs, es; _} = t in
130
150
let e = List. hd es in
131
151
let vs', es' =
132
152
match e.it, vs with
@@ -355,7 +375,7 @@ let rec step (c : config) : config =
355
375
)
356
376
357
377
| Trapping msg , vs ->
358
- assert false
378
+ [] , [ Trapping msg @@ e.at]
359
379
360
380
| Returning vs' , vs ->
361
381
Crash. error e.at " undefined frame"
@@ -379,8 +399,8 @@ let rec step (c : config) : config =
379
399
vs, [Breaking (Int32. sub k 1l , vs0) @@ at]
380
400
381
401
| Label (n , es0 , code' ), vs ->
382
- let c ' = step {c with code = code'} in
383
- vs, [Label (n, es0, c '.code) @@ e.at]
402
+ let t ' = step_thread {t with code = code'} in
403
+ vs, [Label (n, es0, t '.code) @@ e.at]
384
404
385
405
| Frame (n , frame' , (vs' , [] )), vs ->
386
406
vs' @ vs, []
@@ -392,10 +412,10 @@ let rec step (c : config) : config =
392
412
take n vs0 e.at @ vs, []
393
413
394
414
| Frame (n , frame' , code' ), vs ->
395
- let c ' = step {frame = frame'; code = code'; budget = c .budget - 1 } in
396
- vs, [Frame (n, c '.frame, c '.code) @@ e.at]
415
+ let t ' = step_thread {frame = frame'; code = code'; budget = t .budget - 1 } in
416
+ vs, [Frame (n, t '.frame, t '.code) @@ e.at]
397
417
398
- | Invoke func , vs when c .budget = 0 ->
418
+ | Invoke func , vs when t .budget = 0 ->
399
419
Exhaustion. error e.at " call stack exhausted"
400
420
401
421
| Invoke func , vs ->
@@ -413,37 +433,44 @@ let rec step (c : config) : config =
413
433
try List. rev (f (List. rev args)) @ vs', []
414
434
with Crash (_ , msg ) -> Crash. error e.at msg
415
435
)
416
- in {c with code = vs', es' @ List. tl es}
417
-
436
+ in {t with code = vs', es' @ List. tl es}
418
437
419
- let rec eval (c : config ) : value stack =
420
- match c.code with
421
- | vs , [] ->
422
- vs
423
438
424
- | vs , {it = Trapping msg ; at} :: _ ->
425
- Trap. error at msg
439
+ let rec step (c : config ) (n : thread_id ) : config =
440
+ let ts1, t, ts2 = Lib.List. extract n c in
441
+ if snd t.code = [] then
442
+ step c n
443
+ else
444
+ let t' = try step_thread t with Stack_overflow ->
445
+ Exhaustion. error (List. hd (snd t.code)).at " call stack exhausted"
446
+ in ts1 @ [t'] @ ts2
426
447
427
- | vs , es ->
428
- eval (step c)
448
+ let rec eval (c : config ref ) (n : thread_id ) : value list =
449
+ match status ! c n with
450
+ | Result vs -> vs
451
+ | Trap e -> raise e
452
+ | Running ->
453
+ let c' = step ! c n in
454
+ c := c'; eval c n
429
455
430
456
431
457
(* Functions & Constants *)
432
458
433
- let invoke (func : func_inst ) (vs : value list ) : value list =
459
+ let invoke c n (func : func_inst ) (vs : value list ) : config =
434
460
let at = match func with Func. AstFunc (_ ,_ , f ) -> f.at | _ -> no_region in
435
461
let FuncType (ins, out) = Func. type_of func in
436
462
if List. map Values. type_of vs <> ins then
437
463
Crash. error at " wrong number or types of arguments" ;
438
- let c = config empty_module_inst (List. rev vs) [Invoke func @@ at] in
439
- try List. rev (eval c) with Stack_overflow ->
440
- Exhaustion. error at " call stack exhausted"
464
+ let ts1, t, ts2 = Lib.List. extract n c in
465
+ let vs', es' = t.code in
466
+ let code = List. rev vs @ vs', (Invoke func @@ at) :: es' in
467
+ ts1 @ [{t with code}] @ ts2
441
468
442
469
let eval_const (inst : module_inst ) (const : const ) : value =
443
- let c = config inst [] (List. map plain const.it) in
444
- match eval c with
470
+ let t = thread inst [] (List. map plain const.it) in
471
+ match eval ( ref [t]) 0 with
445
472
| [v] -> v
446
- | vs -> Crash. error const.at " wrong number of results on stack"
473
+ | _ -> Crash. error const.at " wrong number of results on stack"
447
474
448
475
let i32 (v : value ) at =
449
476
match v with
@@ -518,7 +545,7 @@ let add_import (m : module_) (ext : extern) (im : import) (inst : module_inst)
518
545
| ExternMemory mem -> {inst with memories = mem :: inst .memories}
519
546
| ExternGlobal glob -> {inst with globals = glob :: inst .globals}
520
547
521
- let init (m : module_ ) (exts : extern list ) : module_inst =
548
+ let init c n (m : module_ ) (exts : extern list ) : module_inst * config =
522
549
let
523
550
{ imports; tables; memories; globals; funcs; types;
524
551
exports; elems; data; start
@@ -545,5 +572,5 @@ let init (m : module_) (exts : extern list) : module_inst =
545
572
let init_datas = List. map (init_memory inst) data in
546
573
List. iter (fun f -> f () ) init_elems;
547
574
List. iter (fun f -> f () ) init_datas;
548
- Lib.Option. app (fun x -> ignore ( invoke (func inst x) [] )) start;
549
- inst
575
+ let c' = Lib.Option. fold c (fun x -> invoke c n (func inst x) [] ) start in
576
+ inst, c'
0 commit comments