Skip to content

Commit 0f36bac

Browse files
committed
change lazy representation not using blocking, fix rescript-lang#4325
1 parent bd5374b commit 0f36bac

File tree

3 files changed

+97
-95
lines changed

3 files changed

+97
-95
lines changed

jscomp/core/lam_convert.ml

+4-2
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,10 @@ let lam_prim ~primitive:( p : Lambda.primitive) ~args loc : Lam.t =
269269
args loc App_infer_full
270270
| Blk_lazy_forward
271271
->
272-
let info : Lam_tag_info.t = Blk_na "" in
273-
prim ~primitive:(Pmakeblock (tag,info,mutable_flag)) ~args loc
272+
Lam.apply
273+
(prim ~primitive:(Pfield (1,Fld_module {name = "from_val"})) loc (*Invariant: hard code {from_fun} position*)
274+
~args: [Lam.global_module (Ident.create_persistent "CamlinternalLazy")] )
275+
args loc App_infer_full
274276
| Blk_na s ->
275277
let info : Lam_tag_info.t = Blk_na s in
276278
prim ~primitive:(Pmakeblock (tag,info,mutable_flag)) ~args loc

jscomp/stdlib-406/camlinternalLazy.ml

+43-60
Original file line numberDiff line numberDiff line change
@@ -13,99 +13,82 @@
1313
(* *)
1414
(**************************************************************************)
1515

16-
(* Internals of forcing lazy values. *)
17-
18-
let lazy_tag = 246
19-
let forward_tag = 250
2016

17+
(* Internals of forcing lazy values. *)
2118
type 'a t = {
22-
mutable tag : int ; (* Invariant: name *)
23-
mutable _0 : 'a
19+
mutable tag : int [@bs.as "tag"] ;
20+
(* Invariant: name *)
21+
mutable value : 'a (* [@bs.as "val"] *)
22+
(* its type is ['a] or [unit -> 'a ] *)
2423
}
2524

26-
external cast_from_lazy : 'a lazy_t -> 'b = "%identity"
27-
external cast_to_lazy : 'b -> 'a lazy_t = "%identity"
2825

29-
(* external new_block : int -> int -> 'a lazy_t = "caml_obj_block" *)
30-
let set_tag : 'a lazy_t -> int -> unit = fun x tag ->
31-
(x |. cast_from_lazy).tag<-tag
32-
let tag : 'a lazy_t -> int = fun x ->
33-
(x |. cast_from_lazy). tag
26+
let%private lazy_tag = 246
27+
let%private forward_tag = 250
28+
external%private magic : 'a -> 'b = "%identity"
3429

35-
let set_field (blk : 'arg lazy_t) (result : 'a) : unit =
36-
(* Obj.set_field (Obj.repr blk) 0 (Obj.repr result) *)
37-
(blk |. cast_from_lazy)._0<-result
38-
let get_field (blk : 'arg lazy_t ) : 'a =
39-
(* Obj.obj (Obj.field (Obj.repr blk) 0) *)
40-
(blk |. cast_from_lazy)._0
30+
let%private lazy_boxed (type a) (l : a ) : bool =
31+
if Js.testAny l then false
32+
else
33+
let t = (magic l : _ t ).tag in
34+
t = forward_tag || t = lazy_tag
4135

42-
let new_block_with_tag tag (value : 'a) : 'arg lazy_t =
43-
({tag ; _0 = value} |. cast_to_lazy)
44-
(* let x = new_block tag 1 in
45-
set_field x value;
46-
x *)
36+
let is_val (type a ) (l : a lazy_t) : bool =
37+
Js.testAny l || ((magic l : _ t ).tag <> lazy_tag)
4738

48-
let from_fun (f : unit -> 'arg ) =
49-
new_block_with_tag lazy_tag f
39+
let from_fun (type arg ) (f : unit -> arg ) : arg lazy_t =
40+
(magic {tag = lazy_tag; value = f} : arg lazy_t)
5041

5142

52-
let from_val (v : 'arg) =
53-
let t = tag (cast_to_lazy v) in
54-
if t = forward_tag || t = lazy_tag then begin
55-
new_block_with_tag forward_tag v
43+
let from_val (type arg ) (v : arg) : arg lazy_t=
44+
if lazy_boxed v then begin
45+
(magic {tag = forward_tag ; value = v} : arg lazy_t )
5646
end else begin
57-
(cast_to_lazy v : 'arg lazy_t)
47+
(magic v : arg lazy_t)
5848
end
5949

50+
exception Undefined
6051

61-
let forward_with_closure (blk : 'arg lazy_t) closure =
52+
let%private forward_with_closure (type a ) (blk : a t) (closure : unit -> a) : a =
6253
let result = closure () in
6354
(* do set_field BEFORE set_tag *)
64-
set_field blk result;
65-
set_tag blk forward_tag;
55+
blk.value <- result;
56+
blk.tag<- forward_tag;
6657
result
6758

6859

69-
exception Undefined
70-
71-
let raise_undefined = (fun () -> raise Undefined)
60+
let%private raise_undefined = (fun () -> raise Undefined)
7261

7362
(* Assume [blk] is a block with tag lazy *)
74-
let force_lazy_block (blk : 'arg lazy_t) =
75-
let closure : unit -> 'arg = get_field blk in
76-
set_field blk raise_undefined;
63+
let%private force_lazy_block (type a ) (blk : a t) : a =
64+
let closure : unit -> a = magic blk.value in
65+
blk.value <- magic raise_undefined;
7766
try
7867
forward_with_closure blk closure
7968
with e ->
80-
set_field blk (fun () -> raise e);
69+
blk.value <- magic (fun () -> raise e);
8170
raise e
8271

8372

8473
(* Assume [blk] is a block with tag lazy *)
85-
let force_val_lazy_block (blk : 'arg lazy_t) =
86-
let closure : unit -> 'arg = get_field blk in
87-
set_field blk raise_undefined;
74+
let%private force_val_lazy_block (type a ) (blk : a t) : a =
75+
let closure : unit -> a = magic blk.value in
76+
blk.value <- magic raise_undefined;
8877
forward_with_closure blk closure
8978

90-
(* [force] is not used, since [Lazy.force] is declared as a primitive
91-
whose code inlines the tag tests of its argument. This function is
92-
here for the sake of completeness, and for debugging purpose. *)
93-
94-
let force (lzv : 'arg lazy_t) : 'arg =
95-
let t = tag lzv in
96-
if t = forward_tag then get_field lzv else
97-
if t <> lazy_tag then cast_from_lazy lzv
98-
else force_lazy_block lzv
9979

10080

101-
let force_val (lzv : 'arg lazy_t) : 'arg =
102-
let t = tag lzv in
103-
if t = forward_tag then get_field lzv else
104-
if t <> lazy_tag then cast_from_lazy lzv
105-
else force_val_lazy_block lzv
106-
81+
let force (type a ) (lzv : a lazy_t) : a =
82+
if lazy_boxed lzv then
83+
if is_val lzv then (magic lzv : _ t).value else
84+
force_lazy_block (magic lzv : _ t)
85+
else magic lzv
10786

10887

10988

89+
let force_val (lzv : 'arg lazy_t) : 'arg =
90+
if lazy_boxed lzv then
91+
if is_val lzv then (magic lzv : _ t).value else
92+
force_val_lazy_block (magic lzv : _ t)
93+
else magic lzv
11094

111-
let is_val (l : 'arg lazy_t) = tag l <> lazy_tag

lib/js/camlinternalLazy.js

+50-33
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,38 @@
33
var Curry = require("./curry.js");
44
var Caml_exceptions = require("./caml_exceptions.js");
55

6+
function is_val(l) {
7+
if (l == null) {
8+
return true;
9+
} else {
10+
return l.tag !== 246;
11+
}
12+
}
13+
14+
function lazy_boxed(l) {
15+
if (l == null) {
16+
return false;
17+
}
18+
var t = l.tag;
19+
if (t === 250) {
20+
return true;
21+
} else {
22+
return t === 246;
23+
}
24+
}
25+
626
function from_fun(f) {
727
return {
828
tag: 246,
9-
_0: f
29+
value: f
1030
};
1131
}
1232

1333
function from_val(v) {
14-
var t = v.tag;
15-
if (t === 250 || t === 246) {
34+
if (lazy_boxed(v)) {
1635
return {
1736
tag: 250,
18-
_0: v
37+
value: v
1938
};
2039
} else {
2140
return v;
@@ -24,7 +43,7 @@ function from_val(v) {
2443

2544
function forward_with_closure(blk, closure) {
2645
var result = Curry._1(closure, undefined);
27-
blk._0 = result;
46+
blk.value = result;
2847
blk.tag = 250;
2948
return result;
3049
}
@@ -36,43 +55,41 @@ function raise_undefined(param) {
3655
}
3756

3857
function force(lzv) {
39-
var t = lzv.tag;
40-
if (t === 250) {
41-
return lzv._0;
42-
} else if (t !== 246) {
43-
return lzv;
44-
} else {
45-
var closure = lzv._0;
46-
lzv._0 = raise_undefined;
47-
try {
48-
return forward_with_closure(lzv, closure);
49-
}
50-
catch (e){
51-
lzv._0 = (function (param) {
52-
throw e;
53-
});
54-
throw e;
58+
if (lazy_boxed(lzv)) {
59+
if (is_val(lzv)) {
60+
return lzv.value;
61+
} else {
62+
var closure = lzv.value;
63+
lzv.value = raise_undefined;
64+
try {
65+
return forward_with_closure(lzv, closure);
66+
}
67+
catch (e){
68+
lzv.value = (function (param) {
69+
throw e;
70+
});
71+
throw e;
72+
}
5573
}
74+
} else {
75+
return lzv;
5676
}
5777
}
5878

5979
function force_val(lzv) {
60-
var t = lzv.tag;
61-
if (t === 250) {
62-
return lzv._0;
63-
} else if (t !== 246) {
64-
return lzv;
80+
if (lazy_boxed(lzv)) {
81+
if (is_val(lzv)) {
82+
return lzv.value;
83+
} else {
84+
var closure = lzv.value;
85+
lzv.value = raise_undefined;
86+
return forward_with_closure(lzv, closure);
87+
}
6588
} else {
66-
var closure = lzv._0;
67-
lzv._0 = raise_undefined;
68-
return forward_with_closure(lzv, closure);
89+
return lzv;
6990
}
7091
}
7192

72-
function is_val(l) {
73-
return l.tag !== 246;
74-
}
75-
7693
exports.Undefined = Undefined;
7794
exports.force = force;
7895
exports.force_val = force_val;

0 commit comments

Comments
 (0)