1 cananian 1.1.2.1 // DefaultAllocationStrategy.java, created Fri Feb 12  3:01:41 1999 by duncan
  2 cananian 1.1.2.1 // Copyright (C) 1998 Duncan Bryce <duncan@lcs.mit.edu>
  3 cananian 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 cananian 1.1.2.1 package harpoon.Interpret.Tree;
  5 cananian 1.1.2.1 
  6 cananian 1.1.2.1 import harpoon.ClassFile.HCodeElement;
  7 cananian 1.1.2.1 import harpoon.IR.Tree.BINOP;
  8 cananian 1.1.2.1 import harpoon.IR.Tree.Bop;
  9 cananian 1.1.2.1 import harpoon.IR.Tree.CJUMP;
 10 cananian 1.1.2.1 import harpoon.IR.Tree.CONST;
 11 cananian 1.1.2.1 import harpoon.IR.Tree.ESEQ;
 12 cananian 1.1.2.1 import harpoon.IR.Tree.Exp;
 13 cananian 1.1.2.1 import harpoon.IR.Tree.JUMP;
 14 cananian 1.1.2.1 import harpoon.IR.Tree.LABEL;
 15 cananian 1.1.2.1 import harpoon.IR.Tree.MOVE;
 16 cananian 1.1.2.1 import harpoon.IR.Tree.NAME;
 17 cananian 1.1.2.1 import harpoon.IR.Tree.NATIVECALL;
 18 cananian 1.1.2.1 import harpoon.IR.Tree.Stm;
 19 cananian 1.1.2.1 import harpoon.IR.Tree.TEMP;
 20 cananian 1.1.2.1 import harpoon.IR.Tree.TreeFactory;
 21 cananian 1.1.2.1 import harpoon.IR.Tree.Type;
 22 cananian 1.1.2.1 import harpoon.Temp.Label;
 23 cananian 1.1.2.1 import harpoon.Temp.Temp;
 24 cananian 1.1.2.1 
 25 cananian 1.1.2.1 import java.util.Arrays;
 26 cananian 1.1.2.1 import java.util.List;
 27 cananian 1.1.2.1 
 28 cananian 1.1.2.1 /**
 29 cananian 1.1.2.1  * A simple-minded version of Appel's fast-allocation strategy
 30 cananian 1.1.2.1  *
 31 cananian 1.1.2.1  * @author   Duncan Bryce <duncan@lcs.mit.edu>
 32 cananian 1.2      * @version  $Id: DefaultAllocationStrategy.java,v 1.2 2002/02/25 21:05:50 cananian Exp $
 33 cananian 1.1.2.1  */
 34 cananian 1.1.2.2 class DefaultAllocationStrategy implements AllocationStrategy {
 35 cananian 1.1.2.1 
 36 cananian 1.1.2.1     private AllocationInfo info;
 37 cananian 1.1.2.1 
 38 cananian 1.1.2.1     public DefaultAllocationStrategy(AllocationInfo info) {
 39 cananian 1.1.2.1         this.info = info;
 40 cananian 1.1.2.1     }
 41 cananian 1.1.2.1 
 42 cananian 1.1.2.1     /** 
 43 cananian 1.1.2.1    *  Returns a <code>Stm</code> object which allocates a block of memory 
 44 cananian 1.1.2.1    *  of the specified size.   
 45 cananian 1.1.2.1    */
 46 cananian 1.1.2.1     public Exp memAlloc(Exp size)
 47 cananian 1.1.2.1     {
 48 cananian 1.1.2.1         LABEL        l0, l1, l2, l3, l4;
 49 cananian 1.1.2.1         NAME         gc, exit_oom;
 50 cananian 1.1.2.1         TEMP         triedGC; // INT type
 51 cananian 1.1.2.1         TEMP         memLimit, newMemPtr, nextPtr, resultPtr, tmp;
 52 cananian 1.1.2.1         HCodeElement src = size;
 53 cananian 1.1.2.1         TreeFactory  tf  = size.getFactory();
 54 cananian 1.1.2.1         Stm[]        stms;
 55 cananian 1.1.2.1 
 56 cananian 1.1.2.1         triedGC   = new TEMP(tf,src,Type.INT,     new Temp(tf.tempFactory()));
 57 cananian 1.1.2.1         nextPtr   = new TEMP(tf,src,Type.POINTER, info.getNextPtr());
 58 cananian 1.1.2.1         memLimit  = new TEMP(tf,src,Type.POINTER, info.getMemLimit());
 59 cananian 1.1.2.1         newMemPtr = new TEMP(tf,src,Type.POINTER, new Temp(tf.tempFactory()));
 60 cananian 1.1.2.1         resultPtr = new TEMP(tf,src,Type.POINTER, new Temp(tf.tempFactory()));
 61 cananian 1.1.2.1         tmp       = new TEMP(tf,src,Type.POINTER, new Temp(tf.tempFactory()));
 62 cananian 1.1.2.1 
 63 cananian 1.1.2.1         l0        = new LABEL(tf, src, new Label(), false);
 64 cananian 1.1.2.1         l1        = new LABEL(tf, src, new Label(), false);
 65 cananian 1.1.2.1         l2        = new LABEL(tf, src, new Label(), false);
 66 cananian 1.1.2.1         l3        = new LABEL(tf, src, new Label(), false);
 67 cananian 1.1.2.1         l4        = new LABEL(tf, src, new Label(), false);
 68 cananian 1.1.2.1         gc        = new NAME(tf, src, info.GC());
 69 cananian 1.1.2.1         exit_oom  = new NAME(tf, src, info.exitOutOfMemory());
 70 cananian 1.1.2.1       
 71 cananian 1.1.2.1         stms = new Stm[] { 
 72 cananian 1.1.2.1             // triedGC <-- 0; 
 73 cananian 1.1.2.1             new MOVE(tf, src, triedGC, new CONST(tf, src, (int)0)),
 74 cananian 1.1.2.1 
 75 cananian 1.1.2.1             // newMemPtr <-- info.next_ptr() + size
 76 cananian 1.1.2.1             new MOVE
 77 cananian 1.1.2.1             (tf, src, newMemPtr, 
 78 cananian 1.1.2.1              new BINOP
 79 cananian 1.1.2.1              (tf, src, Type.POINTER, Bop.ADD,
 80 cananian 1.1.2.1               nextPtr, 
 81 cananian 1.1.2.1               size)),
 82 cananian 1.1.2.1         
 83 cananian 1.1.2.1             // LABEL 0 
 84 cananian 1.1.2.1             l0,
 85 cananian 1.1.2.1 
 86 cananian 1.1.2.1             // Is (limit > next + N) ?
 87 cananian 1.1.2.1             new CJUMP
 88 cananian 1.1.2.1             (tf, src, 
 89 cananian 1.1.2.1              new BINOP
 90 cananian 1.1.2.1              (tf, src, Type.POINTER, Bop.CMPGT,
 91 cananian 1.1.2.1               memLimit, 
 92 cananian 1.1.2.1               newMemPtr),
 93 cananian 1.1.2.1              l1.label,  // There's enough space
 94 cananian 1.1.2.1              l2.label), // Not enough space!
 95 cananian 1.1.2.1       
 96 cananian 1.1.2.1         
 97 cananian 1.1.2.1             // LABEL 2
 98 cananian 1.1.2.1             l2,
 99 cananian 1.1.2.1 
100 cananian 1.1.2.1             // (limit > next + N) == FALSE.
101 cananian 1.1.2.1             // If (triedGC!=0), then perform garbage collection and try again.
102 cananian 1.1.2.1             // Otherwise, we're out of memory.
103 cananian 1.1.2.1             new CJUMP
104 cananian 1.1.2.1             (tf, src, triedGC, 
105 cananian 1.1.2.1              l3.label,   // If tried GC already, out of mem
106 cananian 1.1.2.1              l4.label),  // If mem alloc fails, call GC
107 cananian 1.1.2.1             
108 cananian 1.1.2.1             // LABEL 3
109 cananian 1.1.2.1             l3,
110 cananian 1.1.2.1         
111 cananian 1.1.2.1             // Throw OutOfMemoryError
112 cananian 1.1.2.1             new NATIVECALL(tf, src, tmp, exit_oom, null),
113 cananian 1.1.2.1         
114 cananian 1.1.2.1             // LABEL 4
115 cananian 1.1.2.1             l4,
116 cananian 1.1.2.1         
117 cananian 1.1.2.1             // triedGC <-- 1
118 cananian 1.1.2.1             new MOVE(tf, src, triedGC, new CONST(tf, src, 1)),
119 cananian 1.1.2.1             
120 cananian 1.1.2.1             // call the garbage collector
121 cananian 1.1.2.1             new NATIVECALL(tf, src, tmp, gc, null),
122 cananian 1.1.2.1         
123 cananian 1.1.2.1             // try to allocate memory again
124 cananian 1.1.2.1             new JUMP(tf, src, l0.label),
125 cananian 1.1.2.1 
126 cananian 1.1.2.1             // LABEL 1
127 cananian 1.1.2.1             l1,
128 cananian 1.1.2.1 
129 cananian 1.1.2.1             // There is enough memory to allocate.  
130 cananian 1.1.2.1             // Increment the "next" ptr, and MOVE the result to a useful
131 cananian 1.1.2.1             // place
132 cananian 1.1.2.1             //
133 cananian 1.1.2.1             new MOVE(tf, src, resultPtr, nextPtr),
134 cananian 1.1.2.1             new MOVE(tf, src, nextPtr, newMemPtr)
135 cananian 1.1.2.1         };
136 cananian 1.1.2.1         
137 cananian 1.1.2.1         // Combine the Stm objects into one ESEQ object, and return it.
138 cananian 1.1.2.1         //
139 cananian 1.1.2.1         return new ESEQ(tf, src, Stm.toStm(Arrays.asList(stms)), resultPtr);
140 cananian 1.1.2.1     }
141 cananian 1.1.2.1     
142 cananian 1.2     }