@@ -42,6 +42,7 @@ let source_map_enabled : Source_map.Encoding_spec.t option -> bool = function
4242 | Some _ -> true
4343
4444let output_gen
45+ ~write_shape
4546 ~standalone
4647 ~custom_header
4748 ~build_info
@@ -53,7 +54,15 @@ let output_gen
5354 Driver. configure fmt;
5455 if standalone then header ~custom_header fmt;
5556 if Config.Flag. header () then jsoo_header fmt build_info;
56- let sm = f ~standalone ~source_map (k, fmt) in
57+ let sm, shapes = f ~standalone ~shapes: write_shape ~source_map (k, fmt) in
58+ (if write_shape
59+ then
60+ match output_file with
61+ | `Stdout -> ()
62+ | `Name name ->
63+ Shape.Store. save'
64+ (Filename. remove_extension name ^ Shape.Store. ext)
65+ (StringMap. bindings shapes));
5766 match source_map, sm with
5867 | None , _ | _ , None -> ()
5968 | Some { output_file = output ; source_map; keep_empty } , Some sm ->
@@ -71,7 +80,6 @@ let output_gen
7180 Pretty_print. newline fmt;
7281 Pretty_print. string fmt (Printf. sprintf " //# sourceMappingURL=%s\n " urlData)
7382 in
74-
7583 match output_file with
7684 | `Stdout -> f stdout `Stdout
7785 | `Name name -> Filename. gen_file name (fun chan -> f chan `File )
@@ -132,6 +140,11 @@ let sourcemap_of_infos ~base l =
132140
133141let sourcemap_of_info ~base info = sourcemap_of_infos ~base [ info ]
134142
143+ let map_fst f (x , y ) = f x, y
144+
145+ let merge_shape a b =
146+ StringMap. union (fun _name s1 s2 -> if Shape. equal s1 s2 then Some s1 else None ) a b
147+
135148let run
136149 { Cmd_arg. common
137150 ; profile
@@ -156,6 +169,8 @@ let run
156169 ; keep_unit_names
157170 ; include_runtime
158171 ; effects
172+ ; shape_files
173+ ; write_shape
159174 } =
160175 let source_map_base =
161176 Option. map ~f: (fun spec -> spec.Source_map.Encoding_spec. source_map) source_map
@@ -172,6 +187,7 @@ let run
172187 | `Name _ , _ -> () );
173188 List. iter params ~f: (fun (s , v ) -> Config.Param. set s v);
174189 List. iter static_env ~f: (fun (s , v ) -> Eval. set_static_env s v);
190+ List. iter shape_files ~f: (fun fn -> Shape.Store. load' fn);
175191 let t = Timer. make () in
176192 let include_dirs =
177193 List. filter_map (include_dirs @ [ " +stdlib/" ]) ~f: (fun d -> Findlib. find [] d)
@@ -251,6 +267,7 @@ let run
251267 (one : Parse_bytecode.one )
252268 ~check_sourcemap
253269 ~standalone
270+ ~shapes
254271 ~(source_map : Source_map.Encoding_spec.t option )
255272 ~link
256273 output_file =
@@ -269,6 +286,7 @@ let run
269286 let code = Code. prepend one.code instr in
270287 Driver. f
271288 ~standalone
289+ ~shapes
272290 ?profile
273291 ~link
274292 ~wrap_with_fun
@@ -292,6 +310,7 @@ let run
292310 let res =
293311 Driver. f
294312 ~standalone
313+ ~shapes
295314 ?profile
296315 ~link
297316 ~wrap_with_fun
@@ -313,14 +332,22 @@ let run
313332 let output_partial
314333 (cmo : Cmo_format.compilation_unit )
315334 ~standalone
335+ ~shapes
316336 ~source_map
317337 code
318338 ((_ , fmt ) as output_file ) =
319339 assert (not standalone);
320340 let uinfo = Unit_info. of_cmo cmo in
321341 Pretty_print. string fmt " \n " ;
322342 Pretty_print. string fmt (Unit_info. to_string uinfo);
323- output code ~check_sourcemap: true ~source_map ~standalone ~link: `No output_file
343+ output
344+ code
345+ ~check_sourcemap: true
346+ ~source_map
347+ ~standalone
348+ ~shapes
349+ ~link: `No
350+ output_file
324351 in
325352 let output_partial_runtime ~standalone ~source_map ((_ , fmt ) as output_file ) =
326353 assert (not standalone);
@@ -371,22 +398,24 @@ let run
371398 { code; cmis = StringSet. empty; debug = Parse_bytecode.Debug. default_summary }
372399 in
373400 output_gen
401+ ~write_shape
374402 ~standalone: true
375403 ~custom_header
376404 ~build_info: (Build_info. create `Runtime )
377405 ~source_map
378406 (fst output_file)
379- (fun ~standalone ~source_map ((_ , fmt ) as output_file ) ->
407+ (fun ~standalone ~shapes ~ source_map ((_ , fmt ) as output_file ) ->
380408 Pretty_print. string fmt " \n " ;
381409 Pretty_print. string fmt (Unit_info. to_string uinfo);
382410 output
383411 code
384412 ~check_sourcemap: false
385413 ~source_map
386414 ~standalone
415+ ~shapes
387416 ~link: `All
388417 output_file
389- |> sourcemap_of_info ~base: source_map_base)
418+ |> map_fst ( sourcemap_of_info ~base: source_map_base) )
390419 | (`Stdin | `File _ ) as bytecode ->
391420 let kind, ic, close_ic, include_dirs =
392421 match bytecode with
@@ -419,20 +448,22 @@ let run
419448 in
420449 if times () then Format. eprintf " parsing: %a@." Timer. print t1;
421450 output_gen
451+ ~write_shape
422452 ~standalone: true
423453 ~custom_header
424454 ~build_info: (Build_info. create `Exe )
425455 ~source_map
426456 (fst output_file)
427- (fun ~standalone ~source_map output_file ->
457+ (fun ~standalone ~shapes ~ source_map output_file ->
428458 output
429459 code
430460 ~check_sourcemap: true
431461 ~standalone
462+ ~shapes
432463 ~source_map
433464 ~link: (if linkall then `All else `Needed )
434465 output_file
435- |> sourcemap_of_info ~base: source_map_base)
466+ |> map_fst ( sourcemap_of_info ~base: source_map_base) )
436467 | `Cmo cmo ->
437468 let output_file =
438469 match output_file, keep_unit_names with
@@ -457,20 +488,26 @@ let run
457488 in
458489 if times () then Format. eprintf " parsing: %a@." Timer. print t1;
459490 output_gen
491+ ~write_shape
460492 ~standalone: false
461493 ~custom_header
462494 ~build_info: (Build_info. create `Cmo )
463495 ~source_map
464496 output_file
465- (fun ~standalone ~source_map output ->
497+ (fun ~standalone ~shapes ~ source_map output ->
466498 match include_runtime with
467499 | true ->
468- let sm1 = output_partial_runtime ~standalone ~source_map output in
469- let sm2 = output_partial cmo code ~standalone ~source_map output in
470- sourcemap_of_infos ~base: source_map_base [ sm1; sm2 ]
500+ let sm1, sh1 =
501+ output_partial_runtime ~standalone ~shapes ~source_map output
502+ in
503+ let sm2, sh2 =
504+ output_partial cmo code ~standalone ~shapes ~source_map output
505+ in
506+ ( sourcemap_of_infos ~base: source_map_base [ sm1; sm2 ]
507+ , merge_shape sh1 sh2 )
471508 | false ->
472- output_partial cmo code ~standalone ~source_map output
473- |> sourcemap_of_info ~base: source_map_base)
509+ output_partial cmo code ~standalone ~shapes ~ source_map output
510+ |> map_fst ( sourcemap_of_info ~base: source_map_base) )
474511 | `Cma cma when keep_unit_names ->
475512 (if include_runtime
476513 then
@@ -486,14 +523,15 @@ let run
486523 failwith " use [-o dirname/] or remove [--keep-unit-names]"
487524 in
488525 output_gen
526+ ~write_shape
489527 ~standalone: false
490528 ~custom_header
491529 ~build_info: (Build_info. create `Runtime )
492530 ~source_map
493531 (`Name output_file)
494- (fun ~standalone ~source_map output ->
495- output_partial_runtime ~standalone ~source_map output
496- |> sourcemap_of_info ~base: source_map_base));
532+ (fun ~standalone ~shapes ~ source_map output ->
533+ output_partial_runtime ~standalone ~shapes ~ source_map output
534+ |> map_fst ( sourcemap_of_info ~base: source_map_base) ));
497535 List. iter cma.lib_units ~f: (fun cmo ->
498536 let output_file =
499537 match output_file with
@@ -522,23 +560,26 @@ let run
522560 t1
523561 (Ocaml_compiler.Cmo_format. name cmo);
524562 output_gen
563+ ~write_shape
525564 ~standalone: false
526565 ~custom_header
527566 ~build_info: (Build_info. create `Cma )
528567 ~source_map
529568 (`Name output_file)
530- (fun ~standalone ~source_map output ->
531- output_partial ~standalone ~source_map cmo code output
532- |> sourcemap_of_info ~base: source_map_base))
569+ (fun ~standalone ~shapes ~ source_map output ->
570+ output_partial ~standalone ~shapes ~ source_map cmo code output
571+ |> map_fst ( sourcemap_of_info ~base: source_map_base) ))
533572 | `Cma cma ->
534- let f ~standalone ~source_map output =
535- let source_map_runtime =
573+ let f ~standalone ~shapes ~source_map output =
574+ (* Always compute shapes because it can be used by other units of the cma *)
575+ let shapes = shapes || true in
576+ let runtime =
536577 if not include_runtime
537578 then None
538- else Some (output_partial_runtime ~standalone ~source_map output)
579+ else Some (output_partial_runtime ~standalone ~shapes ~ source_map output)
539580 in
540581
541- let source_map_units =
582+ let units =
542583 List. map cma.lib_units ~f: (fun cmo ->
543584 let t1 = Timer. make () in
544585 let code =
@@ -556,16 +597,22 @@ let run
556597 Timer. print
557598 t1
558599 (Ocaml_compiler.Cmo_format. name cmo);
559- output_partial ~standalone ~source_map cmo code output)
600+ output_partial ~standalone ~shapes ~source_map cmo code output)
601+ in
602+ let sm_and_shapes =
603+ match runtime with
604+ | None -> units
605+ | Some x -> x :: units
560606 in
561- let sm =
562- match source_map_runtime with
563- | None -> source_map_units
564- | Some x -> x :: source_map_units
607+ let shapes =
608+ List. fold_left sm_and_shapes ~init: StringMap. empty ~f: (fun acc (_ , s ) ->
609+ merge_shape s acc)
565610 in
566- sourcemap_of_infos ~base: source_map_base sm
611+ ( sourcemap_of_infos ~base: source_map_base (List. map sm_and_shapes ~f: fst)
612+ , shapes )
567613 in
568614 output_gen
615+ ~write_shape
569616 ~standalone: false
570617 ~custom_header
571618 ~build_info: (Build_info. create `Cma )
0 commit comments