1 /*
2  * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 package sun.jvm.hotspot.interpreter;
26 
27 import sun.jvm.hotspot.oops.*;
28 import sun.jvm.hotspot.utilities.*;
29 
30 public class OopMapCacheEntry {
31   // Iteration
isValue(int offset)32   public boolean isValue(int offset) { return !entryAt(offset); }
isOop(int offset)33   public boolean isOop  (int offset) { return entryAt(offset);  }
iterateOop(OffsetClosure oopClosure)34   public void    iterateOop(OffsetClosure oopClosure) {
35     int n = numberOfEntries();
36     for (int i = 0; i < n; i++) {
37       if (entryAt(i)) {
38         oopClosure.offsetDo(i);
39       }
40     }
41   }
42 
43   // Initialization
fill(Method method, int bci)44   public void fill(Method method, int bci) {
45     this.method = method;
46     this.bci = bci;
47     if (method.isNative()) {
48       // Native method activations have oops only among the parameters and one
49       // extra oop following the parameters (the mirror for static native methods).
50       fillForNative();
51     } else {
52       OopMapForCacheEntry gen = new OopMapForCacheEntry(method, bci, this);
53       gen.computeMap();
54     }
55   }
56 
setMask(CellTypeStateList vars, CellTypeStateList stack, int stackTop)57   public void setMask(CellTypeStateList vars,
58                       CellTypeStateList stack,
59                       int stackTop) {
60     // compute bit mask size
61     int maxLocals = (int) method.getMaxLocals();
62     int nEntries  = maxLocals + stackTop;
63     maskSize      = nEntries;
64     allocateBitMask();
65 
66     CellTypeStateList curList = vars;
67     int listIdx = 0;
68 
69     for (int entryIdx = 0; entryIdx < nEntries; entryIdx++, listIdx++) {
70       // switch to stack when done with locals
71       if (entryIdx == maxLocals) {
72         curList = stack;
73         listIdx = 0;
74       }
75 
76       CellTypeState cell = curList.get(listIdx);
77       // set oop bit
78       if ( cell.isReference()) {
79         mask.atPut(entryIdx, true);
80       }
81     }
82 
83     // verify bit mask
84     if (Assert.ASSERTS_ENABLED) {
85       Assert.that(verifyMask(vars, stack, maxLocals, stackTop), "mask could not be verified");
86     }
87   }
88 
89   //----------------------------------------------------------------------
90   // Internals only below this point
91   //
92   private Method method;    // the method for which the mask is valid
93   private int    bci;       // the bci    for which the mask is valid
94   private int    maskSize;  // the required mask size in bits
95   private BitMap mask;      // may be null if mask is empty
96 
method()97   Method method()        { return method; }
bci()98   int bci()              { return bci; }
numberOfEntries()99   int numberOfEntries()  { return maskSize; }
entryAt(int offset)100   boolean entryAt(int offset) {
101     return mask.at(offset);
102   }
103 
setEmptyMask()104   void setEmptyMask()    { mask = null; }
allocateBitMask()105   void allocateBitMask() {
106     if (maskSize > 0) {
107       mask = new BitMap(maskSize);
108     }
109   }
110 
111   // fills the bit mask for native calls
fillForNative()112   void fillForNative() {
113     if (Assert.ASSERTS_ENABLED) {
114       Assert.that(method.isNative(), "method must be native method");
115     }
116     maskSize = (int) method.getSizeOfParameters();
117     allocateBitMask();
118     // fill mask for parameters
119     MaskFillerForNative mf = new MaskFillerForNative(method, mask, maskSize);
120     mf.generate();
121   }
122 
123   static class VerifyClosure implements OffsetClosure {
124     private OopMapCacheEntry entry;
125     private boolean          failed;
126 
VerifyClosure(OopMapCacheEntry entry)127     VerifyClosure(OopMapCacheEntry entry)          { this.entry = entry; }
offsetDo(int offset)128     public void offsetDo(int offset)               { if (!entry.isOop(offset)) failed = true; }
failed()129     boolean failed()                               { return failed; }
130   }
131 
verifyMask(CellTypeStateList vars, CellTypeStateList stack, int maxLocals, int stackTop)132   boolean verifyMask(CellTypeStateList vars, CellTypeStateList stack, int maxLocals, int stackTop) {
133     // Check mask includes map
134     VerifyClosure blk = new VerifyClosure(this);
135     iterateOop(blk);
136     if (blk.failed()) return false;
137 
138     // Check if map is generated correctly
139     for(int i = 0; i < maxLocals; i++) {
140       boolean v1 = isOop(i);
141       boolean v2 = vars.get(i).isReference();
142       if (Assert.ASSERTS_ENABLED) {
143         Assert.that(v1 == v2, "locals oop mask generation error");
144       }
145     }
146 
147     for(int j = 0; j < stackTop; j++) {
148       boolean v1 = isOop(maxLocals + j);
149       boolean v2 = stack.get(j).isReference();
150       if (Assert.ASSERTS_ENABLED) {
151         Assert.that(v1 == v2, "stack oop mask generation error");
152       }
153     }
154     return true;
155   }
156 }
157