89 lines
3.8 KiB
OCaml
89 lines
3.8 KiB
OCaml
(***********************************************************************)
|
|
(* *)
|
|
(* OCaml *)
|
|
(* *)
|
|
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
|
|
(* *)
|
|
(* Copyright 1999 Institut National de Recherche en Informatique et *)
|
|
(* en Automatique. All rights reserved. This file is distributed *)
|
|
(* under the terms of the Q Public License version 1.0. *)
|
|
(* *)
|
|
(***********************************************************************)
|
|
|
|
(* Combine heap allocations occurring in the same basic block *)
|
|
|
|
open Mach
|
|
|
|
type allocation_state =
|
|
No_alloc (* no allocation is pending *)
|
|
| Pending_alloc of Reg.t * int (* an allocation is pending *)
|
|
(* The arguments of Pending_alloc(reg, ofs) are:
|
|
reg the register holding the result of the last allocation
|
|
ofs the alloc position in the allocated block *)
|
|
|
|
let allocated_size = function
|
|
No_alloc -> 0
|
|
| Pending_alloc(reg, ofs) -> ofs
|
|
|
|
let rec combine i allocstate =
|
|
match i.desc with
|
|
Iend | Ireturn | Iexit _ | Iraise _ ->
|
|
(i, allocated_size allocstate)
|
|
| Iop(Ialloc sz) ->
|
|
begin match allocstate with
|
|
No_alloc ->
|
|
let (newnext, newsz) =
|
|
combine i.next (Pending_alloc(i.res.(0), sz)) in
|
|
(instr_cons (Iop(Ialloc newsz)) i.arg i.res newnext, 0)
|
|
| Pending_alloc(reg, ofs) ->
|
|
if ofs + sz < Config.max_young_wosize * Arch.size_addr then begin
|
|
let (newnext, newsz) =
|
|
combine i.next (Pending_alloc(reg, ofs + sz)) in
|
|
(instr_cons (Iop(Iintop_imm(Iadd, ofs))) [| reg |] i.res newnext,
|
|
newsz)
|
|
end else begin
|
|
let (newnext, newsz) =
|
|
combine i.next (Pending_alloc(i.res.(0), sz)) in
|
|
(instr_cons (Iop(Ialloc newsz)) i.arg i.res newnext, ofs)
|
|
end
|
|
end
|
|
| Iop(Icall_ind | Icall_imm _ | Iextcall _ |
|
|
Itailcall_ind | Itailcall_imm _) ->
|
|
let newnext = combine_restart i.next in
|
|
(instr_cons_debug i.desc i.arg i.res i.dbg newnext,
|
|
allocated_size allocstate)
|
|
| Iop op ->
|
|
let (newnext, sz) = combine i.next allocstate in
|
|
(instr_cons_debug i.desc i.arg i.res i.dbg newnext, sz)
|
|
| Iifthenelse(test, ifso, ifnot) ->
|
|
let newifso = combine_restart ifso in
|
|
let newifnot = combine_restart ifnot in
|
|
let newnext = combine_restart i.next in
|
|
(instr_cons (Iifthenelse(test, newifso, newifnot)) i.arg i.res newnext,
|
|
allocated_size allocstate)
|
|
| Iswitch(table, cases) ->
|
|
let newcases = Array.map combine_restart cases in
|
|
let newnext = combine_restart i.next in
|
|
(instr_cons (Iswitch(table, newcases)) i.arg i.res newnext,
|
|
allocated_size allocstate)
|
|
| Iloop(body) ->
|
|
let newbody = combine_restart body in
|
|
(instr_cons (Iloop(newbody)) i.arg i.res i.next,
|
|
allocated_size allocstate)
|
|
| Icatch(io, body, handler) ->
|
|
let (newbody, sz) = combine body allocstate in
|
|
let newhandler = combine_restart handler in
|
|
let newnext = combine_restart i.next in
|
|
(instr_cons (Icatch(io, newbody, newhandler)) i.arg i.res newnext, sz)
|
|
| Itrywith(body, handler) ->
|
|
let (newbody, sz) = combine body allocstate in
|
|
let newhandler = combine_restart handler in
|
|
let newnext = combine_restart i.next in
|
|
(instr_cons (Itrywith(newbody, newhandler)) i.arg i.res newnext, sz)
|
|
|
|
and combine_restart i =
|
|
let (newi, _) = combine i No_alloc in newi
|
|
|
|
let fundecl f =
|
|
{f with fun_body = combine_restart f.fun_body}
|