Skip to content

Commit 07912b0

Browse files
authored
Merge pull request #4457 from BuckleScript/tweak
Fix #4456, specialize String.make
2 parents 2554e2a + 4da352c commit 07912b0

38 files changed

+1280
-1349
lines changed

jscomp/core/lam_analysis.ml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ let rec no_side_effects (lam : Lam.t) : bool =
5656
(* non-observable side effect *)
5757
| "caml_sys_get_config"
5858
| "caml_sys_get_argv" (* should be fine *)
59-
60-
| "caml_create_string" (* TODO: add more *)
59+
| "caml_string_repeat"
6160
| "caml_make_vect"
6261
| "caml_create_bytes"
6362
| "caml_obj_dup"

jscomp/core/lam_dispatch_primitive.ml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,20 @@ let translate loc (prim_name : string)
380380
E.string_comp Ge e0 e1
381381
| _ -> assert false
382382
end
383+
| "caml_string_repeat"
384+
->
385+
begin match args with
386+
| [ n ; {expression_desc = Number (Int {i})} ] ->
387+
let str = (String.make 1 (Char.chr (Int32.to_int i))) in
388+
begin match n.expression_desc with
389+
| Number (Int {i = 1l}) -> E.str str
390+
| _ ->
391+
E.call (E.dot (E.str str) "repeat") [n]
392+
~info:Js_call_info.builtin_runtime_call
393+
end
394+
| _ ->
395+
E.runtime_call Js_runtime_modules.string "make" args
396+
end
383397
| "caml_string_greaterthan"
384398
->
385399
begin match args with
@@ -475,7 +489,7 @@ let translate loc (prim_name : string)
475489
| _ -> assert false
476490
end
477491
| "caml_create_bytes"
478-
| "caml_create_string" ->
492+
->
479493
(* Bytes.create *)
480494
(* Note that for invalid range, JS raise an Exception RangeError,
481495
here in OCaml it's [Invalid_argument], we have to preserve this semantics.

jscomp/main/builtin_cmi_datasets.ml

Lines changed: 5 additions & 5 deletions
Large diffs are not rendered by default.

jscomp/main/builtin_cmj_datasets.ml

Lines changed: 3 additions & 3 deletions
Large diffs are not rendered by default.

jscomp/runtime/caml_lexer.ml

Lines changed: 48 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -103,36 +103,23 @@ function caml_lex_array(s) {
103103
* @returns {any}
104104
*)
105105
let caml_lex_engine_aux : lex_tables -> int -> lexbuf -> exn -> int = [%raw{|function (tbl, start_state, lexbuf, exn){
106-
// Lexing.lexbuf
107-
var lex_buffer = 'lex_buffer';
108-
var lex_buffer_len = 'lex_buffer_len';
109-
var lex_start_pos = 'lex_start_pos';
110-
var lex_curr_pos = 'lex_curr_pos';
111-
var lex_last_pos = 'lex_last_pos';
112-
var lex_last_action = 'lex_last_action';
113-
var lex_eof_reached = 'lex_eof_reached';
114-
// Lexing.lex_tables
115-
var lex_base = 'lex_base';
116-
var lex_backtrk = 'lex_backtrk';
117-
var lex_default = 'lex_default';
118-
var lex_trans = 'lex_trans';
119-
var lex_check = 'lex_check';
106+
120107
if (!tbl.processed) {
121-
tbl.lex_base = caml_lex_array(tbl[lex_base]);
122-
tbl.lex_backtrk = caml_lex_array(tbl[lex_backtrk]);
123-
tbl.lex_check = caml_lex_array(tbl[lex_check]);
124-
tbl.lex_trans = caml_lex_array(tbl[lex_trans]);
125-
tbl.lex_default = caml_lex_array(tbl[lex_default]);
108+
tbl.lex_base = caml_lex_array(tbl.lex_base);
109+
tbl.lex_backtrk = caml_lex_array(tbl.lex_backtrk);
110+
tbl.lex_check = caml_lex_array(tbl.lex_check);
111+
tbl.lex_trans = caml_lex_array(tbl.lex_trans);
112+
tbl.lex_default = caml_lex_array(tbl.lex_default);
126113
tbl.processed = true;
127114
}
128115
var c;
129116
var state = start_state;
130-
//var buffer = bytes_of_string(lexbuf[lex_buffer]);
131-
var buffer = lexbuf[lex_buffer];
117+
//var buffer = bytes_of_string(lexbuf.lex_buffer);
118+
var buffer = lexbuf.lex_buffer;
132119
if (state >= 0) {
133120
/* First entry */
134-
lexbuf[lex_last_pos] = lexbuf[lex_start_pos] = lexbuf[lex_curr_pos];
135-
lexbuf[lex_last_action] = -1;
121+
lexbuf.lex_last_pos = lexbuf.lex_start_pos = lexbuf.lex_curr_pos;
122+
lexbuf.lex_last_action = -1;
136123
}
137124
else {
138125
/* Reentry after refill */
@@ -146,20 +133,20 @@ let caml_lex_engine_aux : lex_tables -> int -> lexbuf -> exn -> int = [%raw{|fun
146133
/* See if it's a backtrack point */
147134
var backtrk = tbl.lex_backtrk[state];
148135
if (backtrk >= 0) {
149-
lexbuf[lex_last_pos] = lexbuf[lex_curr_pos];
150-
lexbuf[lex_last_action] = backtrk;
136+
lexbuf.lex_last_pos = lexbuf.lex_curr_pos;
137+
lexbuf.lex_last_action = backtrk;
151138
}
152139
/* See if we need a refill */
153-
if (lexbuf[lex_curr_pos] >= lexbuf[lex_buffer_len]) {
154-
if (lexbuf[lex_eof_reached] === 0)
140+
if (lexbuf.lex_curr_pos >= lexbuf.lex_buffer_len) {
141+
if (lexbuf.lex_eof_reached === 0)
155142
return -state - 1;
156143
else
157144
c = 256;
158145
}
159146
else {
160147
/* Read next input char */
161-
c = buffer[lexbuf[lex_curr_pos]];
162-
lexbuf[lex_curr_pos]++;
148+
c = buffer[lexbuf.lex_curr_pos];
149+
lexbuf.lex_curr_pos++;
163150
}
164151
/* Determine next state */
165152
if (tbl.lex_check[base + c] === state) {
@@ -170,18 +157,18 @@ let caml_lex_engine_aux : lex_tables -> int -> lexbuf -> exn -> int = [%raw{|fun
170157
}
171158
/* If no transition on this char, return to last backtrack point */
172159
if (state < 0) {
173-
lexbuf[lex_curr_pos] = lexbuf[lex_last_pos];
174-
if (lexbuf[lex_last_action] == -1)
160+
lexbuf.lex_curr_pos = lexbuf.lex_last_pos;
161+
if (lexbuf.lex_last_action == -1)
175162
throw exn
176163
else
177-
return lexbuf[lex_last_action];
164+
return lexbuf.lex_last_action;
178165
}
179166
else {
180167
/* Erase the EOF condition only if the EOF pseudo-character was
181168
consumed by the automaton (i.e. there was no backtrack above)
182169
*/
183170
if (c == 256)
184-
lexbuf[lex_eof_reached] = 0;
171+
lexbuf.lex_eof_reached = 0;
185172
}
186173
}
187174
}
@@ -252,47 +239,27 @@ function caml_lex_run_tag(s, i, mem) {
252239

253240

254241
let caml_new_lex_engine_aux : lex_tables -> int -> lexbuf -> exn -> int= [%raw{|function (tbl, start_state, lexbuf, exn) {
255-
// Lexing.lexbuf
256-
var lex_buffer = 'lex_buffer';
257-
var lex_buffer_len = 'lex_buffer_len';
258-
var lex_start_pos = 'lex_start_pos';
259-
var lex_curr_pos = 'lex_curr_pos';
260-
var lex_last_pos = 'lex_last_pos';
261-
var lex_last_action = 'lex_last_action';
262-
var lex_eof_reached = 'lex_eof_reached';
263-
var lex_mem = 'lex_mem';
264-
// Lexing.lex_tables
265-
var lex_base = 'lex_base';
266-
var lex_backtrk = 'lex_backtrk';
267-
var lex_default = 'lex_default';
268-
var lex_trans = 'lex_trans';
269-
var lex_check = 'lex_check';
270-
var lex_base_code = 'lex_base_code';
271-
var lex_backtrk_code = 'lex_backtrk_code';
272-
var lex_default_code = 'lex_default_code';
273-
var lex_trans_code = 'lex_trans_code';
274-
var lex_check_code = 'lex_check_code';
275-
var lex_code = 'lex_code';
242+
276243
if (!tbl.processed) {
277-
tbl.lex_base = caml_lex_array(tbl[lex_base]);
278-
tbl.lex_backtrk = caml_lex_array(tbl[lex_backtrk]);
279-
tbl.lex_check = caml_lex_array(tbl[lex_check]);
280-
tbl.lex_trans = caml_lex_array(tbl[lex_trans]);
281-
tbl.lex_default = caml_lex_array(tbl[lex_default]);
282-
tbl.lex_base_code = caml_lex_array(tbl[lex_base_code]);
283-
tbl.lex_backtrk_code = caml_lex_array(tbl[lex_backtrk_code]);
284-
tbl.lex_check_code = caml_lex_array(tbl[lex_check_code]);
285-
tbl.lex_trans_code = caml_lex_array(tbl[lex_trans_code]);
286-
tbl.lex_default_code = caml_lex_array(tbl[lex_default_code]);
244+
tbl.lex_base = caml_lex_array(tbl.lex_base);
245+
tbl.lex_backtrk = caml_lex_array(tbl.lex_backtrk);
246+
tbl.lex_check = caml_lex_array(tbl.lex_check);
247+
tbl.lex_trans = caml_lex_array(tbl.lex_trans);
248+
tbl.lex_default = caml_lex_array(tbl.lex_default);
249+
tbl.lex_base_code = caml_lex_array(tbl.lex_base_code);
250+
tbl.lex_backtrk_code = caml_lex_array(tbl.lex_backtrk_code);
251+
tbl.lex_check_code = caml_lex_array(tbl.lex_check_code);
252+
tbl.lex_trans_code = caml_lex_array(tbl.lex_trans_code);
253+
tbl.lex_default_code = caml_lex_array(tbl.lex_default_code);
287254
tbl.processed = true;
288255
}
289256
var c, state = start_state;
290-
//var buffer = caml_bytes_of_string(lexbuf[lex_buffer]);
291-
var buffer = lexbuf[lex_buffer];
257+
//var buffer = caml_bytes_of_string(lexbuf.lex_buffer);
258+
var buffer = lexbuf.lex_buffer;
292259
if (state >= 0) {
293260
/* First entry */
294-
lexbuf[lex_last_pos] = lexbuf[lex_start_pos] = lexbuf[lex_curr_pos];
295-
lexbuf[lex_last_action] = -1;
261+
lexbuf.lex_last_pos = lexbuf.lex_start_pos = lexbuf.lex_curr_pos;
262+
lexbuf.lex_last_action = -1;
296263
}
297264
else {
298265
/* Reentry after refill */
@@ -303,28 +270,28 @@ let caml_new_lex_engine_aux : lex_tables -> int -> lexbuf -> exn -> int= [%raw{|
303270
var base = tbl.lex_base[state];
304271
if (base < 0) {
305272
var pc_off = tbl.lex_base_code[state];
306-
caml_lex_run_tag(tbl.lex_code, pc_off, lexbuf[lex_mem]);
273+
caml_lex_run_tag(tbl.lex_code, pc_off, lexbuf.lex_mem);
307274
return -base - 1;
308275
}
309276
/* See if it's a backtrack point */
310277
var backtrk = tbl.lex_backtrk[state];
311278
if (backtrk >= 0) {
312279
var pc_off = tbl.lex_backtrk_code[state];
313-
caml_lex_run_tag(tbl.lex_code, pc_off, lexbuf[lex_mem]);
314-
lexbuf[lex_last_pos] = lexbuf[lex_curr_pos];
315-
lexbuf[lex_last_action] = backtrk;
280+
caml_lex_run_tag(tbl.lex_code, pc_off, lexbuf.lex_mem);
281+
lexbuf.lex_last_pos = lexbuf.lex_curr_pos;
282+
lexbuf.lex_last_action = backtrk;
316283
}
317284
/* See if we need a refill */
318-
if (lexbuf[lex_curr_pos] >= lexbuf[lex_buffer_len]) {
319-
if (lexbuf[lex_eof_reached] == 0)
285+
if (lexbuf.lex_curr_pos >= lexbuf.lex_buffer_len) {
286+
if (lexbuf.lex_eof_reached == 0)
320287
return -state - 1;
321288
else
322289
c = 256;
323290
}
324291
else {
325292
/* Read next input char */
326-
c = buffer[lexbuf[lex_curr_pos]];
327-
lexbuf[lex_curr_pos]++;
293+
c = buffer[lexbuf.lex_curr_pos];
294+
lexbuf.lex_curr_pos++;
328295
}
329296
/* Determine next state */
330297
var pstate = state;
@@ -334,11 +301,11 @@ let caml_new_lex_engine_aux : lex_tables -> int -> lexbuf -> exn -> int= [%raw{|
334301
state = tbl.lex_default[state];
335302
/* If no transition on this char, return to last backtrack point */
336303
if (state < 0) {
337-
lexbuf[lex_curr_pos] = lexbuf[lex_last_pos];
338-
if (lexbuf[lex_last_action] == -1)
304+
lexbuf.lex_curr_pos = lexbuf.lex_last_pos;
305+
if (lexbuf.lex_last_action == -1)
339306
throw exn;
340307
else
341-
return lexbuf[lex_last_action];
308+
return lexbuf.lex_last_action;
342309
}
343310
else {
344311
/* If some transition, get and perform memory moves */
@@ -348,12 +315,12 @@ let caml_new_lex_engine_aux : lex_tables -> int -> lexbuf -> exn -> int= [%raw{|
348315
else
349316
pc_off = tbl.lex_default_code[pstate];
350317
if (pc_off > 0)
351-
caml_lex_run_mem(tbl.lex_code, pc_off, lexbuf[lex_mem], lexbuf[lex_curr_pos]);
318+
caml_lex_run_mem(tbl.lex_code, pc_off, lexbuf.lex_mem, lexbuf.lex_curr_pos);
352319
/* Erase the EOF condition only if the EOF pseudo-character was
353320
consumed by the automaton (i.e. there was no backtrack above)
354321
*/
355322
if (c == 256)
356-
lexbuf[lex_eof_reached] = 0;
323+
lexbuf.lex_eof_reached = 0;
357324
}
358325
}
359326
}

jscomp/runtime/caml_string.ml

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,8 @@ let get s i=
3636
raise (Invalid_argument "index out of bounds")
3737
else Caml_string_extern.unsafe_get s i
3838

39-
(* let caml_string_get16 s i =
40-
Caml_char.code (Caml_string_extern.unsafe_get s i) + Caml_char.code (Caml_string_extern.unsafe_get s (i+1)) lsl 8
41-
42-
let caml_string_get32 s i =
43-
Caml_char.code (Caml_string_extern.unsafe_get s i) +
44-
Caml_char.code (Caml_string_extern.unsafe_get s (i+1)) lsl 8 +
45-
Caml_char.code (Caml_string_extern.unsafe_get s (i+2)) lsl 16 +
46-
Caml_char.code (Caml_string_extern.unsafe_get s (i+3)) lsl 24 *)
47-
48-
49-
(* let get s i =
50-
if i < 0 || i >= Caml_string_extern.length s then
51-
raise (Invalid_argument "index out of bounds")
52-
else Caml_string_extern.unsafe_get s i
53-
*)
39+
let make n (ch : char) : string =
40+
(Caml_string_extern.of_char ch)
41+
|. Caml_string_extern.repeat n
42+
43+

jscomp/runtime/caml_string.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,5 @@
2424

2525

2626
val get : string -> int -> char
27+
28+
val make : int -> char -> string

jscomp/stdlib-406/string.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
external length : string -> int = "%string_length"
2525
external get : string -> int -> char = "%string_safe_get"
2626
external set : bytes -> int -> char -> unit = "%bytes_safe_set"
27-
external create : int -> bytes = "caml_create_string"
27+
external create : int -> bytes = "caml_create_bytes"
2828
external unsafe_get : string -> int -> char = "%string_unsafe_get"
2929
external unsafe_set : bytes -> int -> char -> unit = "%bytes_unsafe_set"
3030
external unsafe_blit : string -> int -> bytes -> int -> int -> unit
@@ -36,9 +36,9 @@ module B = Bytes
3636

3737
let bts = B.unsafe_to_string
3838
let bos = B.unsafe_of_string
39-
(*-FIXME: replaced by Belt.String.repeat *)
40-
let make n c =
41-
B.make n c |> bts
39+
40+
external make : int -> char -> string = "caml_string_repeat"
41+
4242
let init n f =
4343
B.init n f |> bts
4444
let copy s =

jscomp/stdlib-406/string.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ external set : bytes -> int -> char -> unit = "%bytes_safe_set"
6868
6969
@deprecated This is a deprecated alias of {!Bytes.set}.[ ] *)
7070

71-
external create : int -> bytes = "caml_create_string"
71+
external create : int -> bytes = "caml_create_bytes"
7272
[@@ocaml.deprecated "Use Bytes.create instead."]
7373
(** [String.create n] returns a fresh byte sequence of length [n].
7474
The sequence is uninitialized and contains arbitrary bytes.

jscomp/stdlib-406/stringLabels.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ external set : bytes -> int -> char -> unit = "%bytes_safe_set"
3434
3535
@deprecated This is a deprecated alias of {!BytesLabels.set}. *)
3636

37-
external create : int -> bytes = "caml_create_string"
37+
external create : int -> bytes = "caml_create_bytes"
3838
[@@ocaml.deprecated "Use BytesLabels.create instead."]
3939
(** [String.create n] returns a fresh byte sequence of length [n].
4040
The sequence is uninitialized and contains arbitrary bytes.

0 commit comments

Comments
 (0)