Skip to content

Commit d8be62b

Browse files
authored
Merge pull request rescript-lang#969 from chenglou/ref-equal
Add quick path to caml_obj.caml_equal
2 parents be3fc3a + 201d3d2 commit d8be62b

File tree

2 files changed

+87
-85
lines changed

2 files changed

+87
-85
lines changed

jscomp/runtime/caml_obj.ml

+82-83
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
(* Copyright (C) 2015-2016 Bloomberg Finance L.P.
2-
*
2+
*
33
* This program is free software: you can redistribute it and/or modify
44
* it under the terms of the GNU Lesser General Public License as published by
55
* the Free Software Foundation, either version 3 of the License, or
@@ -17,7 +17,7 @@
1717
* but WITHOUT ANY WARRANTY; without even the implied warranty of
1818
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1919
* GNU Lesser General Public License for more details.
20-
*
20+
*
2121
* You should have received a copy of the GNU Lesser General Public License
2222
* along with this program; if not, write to the Free Software
2323
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)
@@ -36,114 +36,114 @@
3636
let obj = Obj.new_block Obj.object_tag table.size
3737
]}
3838
39-
Here we only need generate expression like this
39+
Here we only need generate expression like this
4040
{[
41-
{ tag : tag ; length : size }
41+
{ tag : tag ; length : size }
4242
]}
43-
we don't need fill fields, since it is not required by GC
43+
we don't need fill fields, since it is not required by GC
4444
4545
*)
4646

47-
(**
48-
Since now we change it back to use
49-
Array representation
50-
this function is higly dependent
47+
(**
48+
Since now we change it back to use
49+
Array representation
50+
this function is higly dependent
5151
on how objects are encoded in buckle.
5252
5353
There are potentially some issues with wrong implementation of
54-
`caml_obj_dup`, for example, people call `Obj.dup` for a record,
55-
and new record, since currently, `new record` will generate a
56-
`slice` function (which assume the record is an array), and the
54+
`caml_obj_dup`, for example, people call `Obj.dup` for a record,
55+
and new record, since currently, `new record` will generate a
56+
`slice` function (which assume the record is an array), and the
5757
output is no longer an array. (it might be something like { 0 : x , 1 : y} )
5858
5959
{[
6060
let u : record = Obj.dup x in
6161
let h = {u with x = 3}
62-
]}
62+
]}
6363
6464
==>
6565
6666
{[
6767
var u = caml_obj_dup (x)
6868
var new_record = u.slice ()
69-
69+
7070
]}
7171
*)
7272

73-
let caml_obj_dup (x : Obj.t) =
73+
let caml_obj_dup (x : Obj.t) =
7474
let len = Bs_obj.length x in
7575
let v = Caml_array.new_uninitialized len in
76-
for i = 0 to len - 1 do
76+
for i = 0 to len - 1 do
7777
Array.unsafe_set v i (Obj.field x i)
7878
done;
7979
Obj.set_tag (Obj.repr v) (Bs_obj.tag x );
80-
Obj.repr v
80+
Obj.repr v
8181

8282

8383

84-
let caml_obj_truncate (x : Obj.t) (new_size : int) =
84+
let caml_obj_truncate (x : Obj.t) (new_size : int) =
8585
let len = Bs_obj.length x in
86-
if new_size <= 0 || new_size > len then
86+
if new_size <= 0 || new_size > len then
8787
raise (Invalid_argument "Obj.truncate")
88-
else
88+
else
8989
if len <> new_size then
90-
begin
90+
begin
9191
for i = new_size to len - 1 do
9292
Obj.set_field x i (Obj.magic 0)
9393
done;
94-
Bs_obj.set_length x new_size
94+
Bs_obj.set_length x new_size
9595
end
9696

97-
9897

99-
let caml_lazy_make_forward x = lazy x
98+
99+
let caml_lazy_make_forward x = lazy x
100100

101101
(** TODO: the dummy one should be [{}] *)
102-
let caml_update_dummy x y =
102+
let caml_update_dummy x y =
103103
let len = Bs_obj.length y in
104-
for i = 0 to len - 1 do
104+
for i = 0 to len - 1 do
105105
Obj.set_field x i (Obj.field y i)
106106
done ;
107107
Obj.set_tag x (Obj.tag y);
108108
Bs_obj.set_length x (Bs_obj.length y)
109109

110-
let caml_int_compare (x : int) (y: int) : int =
110+
let caml_int_compare (x : int) (y: int) : int =
111111
if x < y then -1 else if x = y then 0 else 1
112112

113-
let caml_string_compare (x : string) (y: string) : int =
113+
let caml_string_compare (x : string) (y: string) : int =
114114
if x < y then -1 else if x = y then 0 else 1
115115

116-
let unsafe_js_compare x y =
117-
if x == y then 0 else
118-
if Js.to_bool @@ Js.unsafe_lt x y then -1
116+
let unsafe_js_compare x y =
117+
if x == y then 0 else
118+
if Js.to_bool @@ Js.unsafe_lt x y then -1
119119
else 1
120-
(** TODO: investigate total
121-
[compare x y] returns [0] if [x] is equal to [y],
122-
a negative integer if [x] is less than [y],
123-
and a positive integer if [x] is greater than [y].
124-
The ordering implemented by compare is compatible with the comparison
125-
predicates [=], [<] and [>] defined above, with one difference on the treatment of the float value
126-
[nan].
127-
128-
Namely, the comparison predicates treat nan as different from any other float value,
129-
including itself; while compare treats [nan] as equal to itself and less than any other float value.
120+
(** TODO: investigate total
121+
[compare x y] returns [0] if [x] is equal to [y],
122+
a negative integer if [x] is less than [y],
123+
and a positive integer if [x] is greater than [y].
124+
The ordering implemented by compare is compatible with the comparison
125+
predicates [=], [<] and [>] defined above, with one difference on the treatment of the float value
126+
[nan].
127+
128+
Namely, the comparison predicates treat nan as different from any other float value,
129+
including itself; while compare treats [nan] as equal to itself and less than any other float value.
130130
This treatment of [nan] ensures that compare defines a total ordering relation.
131-
compare applied to functional values may raise Invalid_argument. compare applied to cyclic structures
131+
compare applied to functional values may raise Invalid_argument. compare applied to cyclic structures
132132
may not terminate.
133133
134134
The compare function can be used as the comparison function required by the [Set.Make] and [Map.Make] functors,
135135
as well as the [List.sort] and [Array.sort] functions.
136136
*)
137-
let rec caml_compare (a : Obj.t) (b : Obj.t) : int =
137+
let rec caml_compare (a : Obj.t) (b : Obj.t) : int =
138138
if Js.typeof a = "string" then
139139
caml_string_compare (Obj.magic a) (Obj.magic b )
140140
else if Js.typeof a = "number" then
141141
caml_int_compare (Obj.magic a) (Obj.magic b )
142-
else if Js.typeof a = "boolean"
142+
else if Js.typeof a = "boolean"
143143
|| Js.typeof a = "null"
144144
|| Js.typeof a = "undefined"
145-
then
146-
unsafe_js_compare a b
145+
then
146+
unsafe_js_compare a b
147147
else
148148
(* if js_is_instance_array a then *)
149149
(* 0 *)
@@ -155,92 +155,91 @@ let rec caml_compare (a : Obj.t) (b : Obj.t) : int =
155155
*)
156156
if tag_a = 250 then
157157
caml_compare (Obj.field a 0) b
158-
else if tag_b = 250 then
158+
else if tag_b = 250 then
159159
caml_compare a (Obj.field b 0)
160160
else if tag_a = 248 (* object/exception *) then
161-
caml_int_compare (Obj.magic @@ Obj.field a 1) (Obj.magic @@ Obj.field b 1 )
162-
else if tag_a = 251 (* abstract_tag *) then
161+
caml_int_compare (Obj.magic @@ Obj.field a 1) (Obj.magic @@ Obj.field b 1 )
162+
else if tag_a = 251 (* abstract_tag *) then
163163
raise (Invalid_argument "equal: abstract value")
164164
else if tag_a <> tag_b then
165165
if tag_a < tag_b then (-1) else 1
166166
else
167-
let len_a = Bs_obj.length a in
168-
let len_b = Bs_obj.length b in
169-
if len_a = len_b then
170-
aux_same_length a b 0 len_a
171-
else if len_a < len_b then
172-
aux_length_a_short a b 0 len_a
173-
else
167+
let len_a = Bs_obj.length a in
168+
let len_b = Bs_obj.length b in
169+
if len_a = len_b then
170+
aux_same_length a b 0 len_a
171+
else if len_a < len_b then
172+
aux_length_a_short a b 0 len_a
173+
else
174174
aux_length_b_short a b 0 len_b
175-
and aux_same_length (a : Obj.t) (b : Obj.t) i same_length =
175+
and aux_same_length (a : Obj.t) (b : Obj.t) i same_length =
176176
if i = same_length then
177177
0
178-
else
178+
else
179179
let res = caml_compare (Obj.field a i) (Obj.field b i) in
180180
if res <> 0 then res
181181
else aux_same_length a b (i + 1) same_length
182-
and aux_length_a_short (a : Obj.t) (b : Obj.t) i short_length =
183-
if i = short_length then -1
184-
else
182+
and aux_length_a_short (a : Obj.t) (b : Obj.t) i short_length =
183+
if i = short_length then -1
184+
else
185185
let res = caml_compare (Obj.field a i) (Obj.field b i) in
186186
if res <> 0 then res
187187
else aux_length_a_short a b (i+1) short_length
188-
and aux_length_b_short (a : Obj.t) (b : Obj.t) i short_length =
188+
and aux_length_b_short (a : Obj.t) (b : Obj.t) i short_length =
189189
if i = short_length then 1
190190
else
191191
let res = caml_compare (Obj.field a i) (Obj.field b i) in
192192
if res <> 0 then res
193-
else aux_length_b_short a b (i+1) short_length
193+
else aux_length_b_short a b (i+1) short_length
194194

195195
type eq = Obj.t -> Obj.t -> bool
196196

197-
let rec caml_equal (a : Obj.t) (b : Obj.t) : bool =
198-
if Js.typeof a = "string"
197+
let rec caml_equal (a : Obj.t) (b : Obj.t) : bool =
198+
(* first, check using reference equality *)
199+
if a == b then true
200+
else if Js.typeof a = "string"
199201
|| Js.typeof a = "number"
200202
|| Js.typeof a = "boolean"
201203
|| Js.typeof a = "undefined"
202204
|| Js.typeof a = "null"
203-
then a == b else
205+
then false
206+
else
204207
let tag_a = Bs_obj.tag a in
205208
let tag_b = Bs_obj.tag b in
206209
(* double_array_tag: 254
207210
forward_tag:250
208211
*)
209212
if tag_a = 250 then
210213
caml_equal (Obj.field a 0) b
211-
else if tag_b = 250 then
214+
else if tag_b = 250 then
212215
caml_equal a (Obj.field b 0)
213216
else if tag_a = 248 (* object/exception *) then
214-
(Obj.magic @@ Obj.field a 1) == (Obj.magic @@ Obj.field b 1 )
215-
else if tag_a = 251 (* abstract_tag *) then
217+
(Obj.magic @@ Obj.field a 1) == (Obj.magic @@ Obj.field b 1 )
218+
else if tag_a = 251 (* abstract_tag *) then
216219
raise (Invalid_argument "equal: abstract value")
217220
else if tag_a <> tag_b then
218-
false
221+
false
219222
else
220-
let len_a = Bs_obj.length a in
221-
let len_b = Bs_obj.length b in
222-
if len_a = len_b then
223-
aux_equal_length a b 0 len_a
223+
let len_a = Bs_obj.length a in
224+
let len_b = Bs_obj.length b in
225+
if len_a = len_b then
226+
aux_equal_length a b 0 len_a
224227
else false
225-
and aux_equal_length (a : Obj.t) (b : Obj.t) i same_length =
228+
and aux_equal_length (a : Obj.t) (b : Obj.t) i same_length =
226229
if i = same_length then
227230
true
228-
else
229-
caml_equal (Obj.field a i) (Obj.field b i)
231+
else
232+
caml_equal (Obj.field a i) (Obj.field b i)
230233
&& aux_equal_length a b (i + 1) same_length
231234

232235
let caml_notequal a b = not (caml_equal a b)
233236

234237
let caml_int32_compare = caml_int_compare
235238
let caml_nativeint_compare = caml_int_compare
236-
let caml_greaterequal a b = caml_compare a b >= 0
239+
let caml_greaterequal a b = caml_compare a b >= 0
237240

238-
let caml_greaterthan a b = caml_compare a b > 0
241+
let caml_greaterthan a b = caml_compare a b > 0
239242

240243
let caml_lessequal a b = caml_compare a b <= 0
241244

242245
let caml_lessthan a b = caml_compare a b < 0
243-
244-
245-
246-

lib/js/caml_obj.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,11 @@ function caml_equal(_a, _b) {
203203
while(true) {
204204
var b = _b;
205205
var a = _a;
206-
if (typeof a === "string" || typeof a === "number" || typeof a === "boolean" || typeof a === "undefined" || typeof a === "null") {
207-
return +(a === b);
206+
if (a === b) {
207+
return /* true */1;
208+
}
209+
else if (typeof a === "string" || typeof a === "number" || typeof a === "boolean" || typeof a === "undefined" || typeof a === "null") {
210+
return /* false */0;
208211
}
209212
else {
210213
var tag_a = a.tag | 0;

0 commit comments

Comments
 (0)