1 (***********************************************************************)
5 (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
7 (* Copyright 1999 Institut National de Recherche en Informatique et *)
8 (* en Automatique. All rights reserved. This file is distributed *)
9 (* under the terms of the Q Public License version 1.0. *)
11 (***********************************************************************)
13 (* $Id: comballoc.ml 7812 2007-01-29 12:11:18Z xleroy $ *)
15 (* Combine heap allocations occurring in the same basic block *)
19 type allocation_state =
20 No_alloc (* no allocation is pending *)
21 | Pending_alloc of Reg.t * int (* an allocation is pending *)
22 (* The arguments of Pending_alloc(reg, ofs) are:
23 reg the register holding the result of the last allocation
24 ofs the alloc position in the allocated block *)
26 let allocated_size = function
28 | Pending_alloc(reg, ofs) -> ofs
30 let rec combine i allocstate =
32 Iend | Ireturn | Iexit _ | Iraise ->
33 (i, allocated_size allocstate)
35 begin match allocstate with
37 let (newnext, newsz) =
38 combine i.next (Pending_alloc(i.res.(0), sz)) in
39 (instr_cons (Iop(Ialloc newsz)) i.arg i.res newnext, 0)
40 | Pending_alloc(reg, ofs) ->
41 if ofs + sz < Config.max_young_wosize then begin
42 let (newnext, newsz) =
43 combine i.next (Pending_alloc(reg, ofs + sz)) in
44 (instr_cons (Iop(Iintop_imm(Iadd, ofs))) [| reg |] i.res newnext,
47 let (newnext, newsz) =
48 combine i.next (Pending_alloc(i.res.(0), sz)) in
49 (instr_cons (Iop(Ialloc newsz)) i.arg i.res newnext, ofs)
52 | Iop(Icall_ind | Icall_imm _ | Iextcall _ |
53 Itailcall_ind | Itailcall_imm _) ->
54 let newnext = combine_restart i.next in
55 (instr_cons_debug i.desc i.arg i.res i.dbg newnext,
56 allocated_size allocstate)
58 let (newnext, sz) = combine i.next allocstate in
59 (instr_cons_debug i.desc i.arg i.res i.dbg newnext, sz)
60 | Iifthenelse(test, ifso, ifnot) ->
61 let newifso = combine_restart ifso in
62 let newifnot = combine_restart ifnot in
63 let newnext = combine_restart i.next in
64 (instr_cons (Iifthenelse(test, newifso, newifnot)) i.arg i.res newnext,
65 allocated_size allocstate)
66 | Iswitch(table, cases) ->
67 let newcases = Array.map combine_restart cases in
68 let newnext = combine_restart i.next in
69 (instr_cons (Iswitch(table, newcases)) i.arg i.res newnext,
70 allocated_size allocstate)
72 let newbody = combine_restart body in
73 (instr_cons (Iloop(newbody)) i.arg i.res i.next,
74 allocated_size allocstate)
75 | Icatch(io, body, handler) ->
76 let (newbody, sz) = combine body allocstate in
77 let newhandler = combine_restart handler in
78 let newnext = combine_restart i.next in
79 (instr_cons (Icatch(io, newbody, newhandler)) i.arg i.res newnext, sz)
80 | Itrywith(body, handler) ->
81 let (newbody, sz) = combine body allocstate in
82 let newhandler = combine_restart handler in
83 let newnext = combine_restart i.next in
84 (instr_cons (Itrywith(newbody, newhandler)) i.arg i.res newnext, sz)
86 and combine_restart i =
87 let (newi, _) = combine i No_alloc in newi
90 {f with fun_body = combine_restart f.fun_body}