Guest User

Untitled

a guest
Feb 16th, 2019
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.93 KB | None | 0 0
  1. diff -C 2 -b -w -r ocaml-3.12.1-orig/asmcomp/cmmgen.ml ../ocaml-3.12.1/asmcomp/cmmgen.ml
  2. *** ocaml-3.12.1-orig/asmcomp/cmmgen.ml 2010-11-11 18:08:07.000000000 +0100
  3. --- ../ocaml-3.12.1/asmcomp/cmmgen.ml 2011-10-25 14:12:24.670561997 +0200
  4. ***************
  5. *** 1501,1505 ****
  6. --- 1501,1657 ----
  7. (Array.of_list !inters) actions)
  8.  
  9. + (*
  10. + better_transl_letrec: we are going to combine all allocations
  11. + requiring a recursive binding in one big allocation, hoping that
  12. + all initializations are either recursive allocations (in which case
  13. + they are combined), or not recursive (in which case they can be
  14. + allocated before). If the strategy is not successful, just fallback
  15. + to the former let-rec compilation algorithm.
  16. + *)
  17. +
  18. + and better_transl_letrec bindings cont =
  19. + let block_id = Ident.create "letrec_block" in
  20. +
  21. + let set = ref IdentSet.empty in
  22. + List.iter (fun (id, exp) -> set := IdentSet.add id !set) bindings;
  23. +
  24. + let cont = ref cont in
  25. +
  26. + (* [combine_allocs]: combine all allocations in one, and binds the
  27. + identifiers to offsets in the allocated block. *)
  28. + let combine_allocs allocs =
  29. +
  30. + let rec combine current_size args lets allocs =
  31. + match allocs with
  32. + [] -> (current_size, args, lets)
  33. + | (id, tag, fields) :: allocs ->
  34. + let lets =
  35. + (id, field_address (Cvar block_id) current_size) :: lets
  36. + in
  37. + let wordsize = List.length fields in
  38. + let fields = Cconst_natint(block_header tag wordsize) :: fields in
  39. + let current_size = current_size + 1 + wordsize in
  40. + let args = args @ fields in
  41. + combine current_size args lets allocs
  42. + in
  43. + let (wordsize, args, lets) = combine 0 [] [] allocs in
  44. + (* This optimization is only worth if the block is
  45. + allocated in the minor heap: *)
  46. + if wordsize > Config.max_young_wosize then raise Exit;
  47. + Clet( block_id, Cop( Calloc, args ),
  48. + let rec add_lets lets cont =
  49. + match lets with
  50. + [] -> cont
  51. + | (id, v) :: lets ->
  52. + add_lets lets (Clet( id, v, cont))
  53. + in
  54. + add_lets lets !cont
  55. + )
  56. + in
  57. + let rec for_bindings bindings allocs =
  58. + match bindings with
  59. + [] -> combine_allocs allocs
  60. + | (id, exp) :: bindings ->
  61. + for_binding id exp bindings allocs
  62. +
  63. + and for_binding id exp bindings allocs =
  64. + match exp with
  65. + (*
  66. + | Uclosure(fundecls, clos_vars) ->
  67. + RHS_block (fundecls_size fundecls + List.length clos_vars)
  68. + | Uletrec(bindings, body) ->
  69. + expr_size body
  70. + *)
  71. + | Usequence(exp, exp') ->
  72. + if non_rec_exp exp then
  73. + Csequence ( transl exp, for_binding id exp' bindings allocs)
  74. + else raise Exit
  75. + | Ulet(id2, exp2, body) ->
  76. + if non_rec_exp exp2 then
  77. + Clet (id2, transl exp2,
  78. + for_binding id body bindings allocs)
  79. + else raise Exit
  80. + | Uprim( Pmakearray(Paddrarray | Pintarray), args, _) ->
  81. + for_fields bindings id 0 (List.rev args) [] allocs
  82. + | Uprim(Pmakeblock(tag, mut), args, _) ->
  83. + for_fields bindings id tag (List.rev args) [] allocs
  84. + | _ ->
  85. + if non_rec_exp exp then
  86. + Clet (id, transl exp, for_bindings bindings allocs)
  87. + else raise Exit
  88. +
  89. + (* For each field of a recursive block, either the field value is not
  90. + recursive, in which case it can be computed before, or it is
  91. + recursive, in which case it is first initialized with 1, and we
  92. + modify the continuation to set the field with the correct value after
  93. + the allocation. We could probably handle more cases for the value in
  94. + the field, but it is not clear that is is worth it.
  95. + *)
  96. +
  97. + and for_fields bindings id tag r_args fields allocs =
  98. + match r_args with
  99. + [] -> for_bindings bindings ( (id, tag, fields) :: allocs )
  100. + | arg :: r_args ->
  101. + if non_rec_exp arg then
  102. + for_fields bindings id tag r_args (transl arg :: fields) allocs
  103. + else
  104. + let n = List.length r_args in
  105. + match arg with
  106. + Uvar field_id when IdentSet.mem field_id !set ->
  107. + cont := Csequence ( set_field (Cvar id) n (Cvar field_id) , !cont );
  108. + for_fields bindings id tag r_args ( Cconst_int 1 :: fields) allocs
  109. + | _ ->
  110. + let field_id_name = Printf.sprintf "%s_rec_%d" (Ident.name id) n in
  111. + let field_id = Ident.create field_id_name in
  112. + cont := Csequence( set_field (Cvar id) n (Cvar field_id) , !cont);
  113. + set := IdentSet.add field_id !set;
  114. + for_fields ( (field_id, arg) :: bindings ) id tag r_args
  115. + ( Cconst_int 1 :: fields) allocs
  116. +
  117. + (* [non_rec_exp exp] returns [true] if the current expression does
  118. + not use the recursively defined identifiers, in which case it can
  119. + be executed before allocating the recursive block. *)
  120. + and non_rec_exp exp =
  121. + let rec non_rec_exp exp =
  122. + match exp with
  123. + Uvar id -> if IdentSet.mem id !set then raise Exit
  124. + | Uconst _ -> ()
  125. + | Udirect_apply (_, ulist, _) -> List.iter non_rec_exp ulist
  126. + | Ugeneric_apply (u, ulist, _) -> non_rec_exp u; List.iter non_rec_exp ulist
  127. + | Uclosure (flist, ulist) ->
  128. + List.iter (fun (_, _, _, u) -> non_rec_exp u) flist;
  129. + List.iter non_rec_exp ulist
  130. + | Uoffset (u, _) -> non_rec_exp u
  131. + | Ulet (_, u1, u2) -> non_rec_exp u1; non_rec_exp u2
  132. + | Uletrec (bindings, u) ->
  133. + List.iter (fun (_, u) -> non_rec_exp u) bindings; non_rec_exp u
  134. + | Uprim (_, ulist, _) -> List.iter non_rec_exp ulist
  135. + | Uswitch (u, us) ->
  136. + non_rec_exp u;
  137. + Array.iter non_rec_exp us.us_actions_consts;
  138. + Array.iter non_rec_exp us.us_actions_blocks;
  139. + | Ustaticfail (_, ulist) -> List.iter non_rec_exp ulist
  140. + | Ucatch (_, _, u1, u2) -> non_rec_exp u1; non_rec_exp u2
  141. + | Utrywith (u1, _, u2) -> non_rec_exp u2; non_rec_exp u2
  142. + | Uifthenelse (u1, u2, u3) -> non_rec_exp u1; non_rec_exp u2; non_rec_exp u3
  143. + | Usequence (u1, u2) -> non_rec_exp u1; non_rec_exp u2
  144. + | Uwhile (u1, u2) -> non_rec_exp u1; non_rec_exp u2
  145. + | Ufor (_, u1, u2, _, u3) -> non_rec_exp u1; non_rec_exp u2; non_rec_exp u3
  146. + | Uassign (_, u1) -> non_rec_exp u1
  147. + | Usend (_, u1, u2, ulist, _) ->
  148. + non_rec_exp u1; non_rec_exp u2;
  149. + List.iter non_rec_exp ulist
  150. + in
  151. + try non_rec_exp exp; true with Exit -> false
  152. +
  153. + in
  154. + for_bindings bindings []
  155. +
  156. + (* try to call [better_transl_letrec], and if an Exit exception is
  157. + raised, fallback to default strategy. *)
  158. and transl_letrec bindings cont =
  159. + try
  160. + better_transl_letrec bindings cont
  161. + with Exit ->
  162. let bsz = List.map (fun (id, exp) -> (id, exp, expr_size exp)) bindings in
  163. let rec init_blocks = function
Add Comment
Please, Sign In to add comment