View Javadoc
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
32    public boolean isValue(int offset) { return !entryAt(offset); }
33    public boolean isOop  (int offset) { return entryAt(offset);  }
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
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  
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  
97    Method method()        { return method; }
98    int bci()              { return bci; }
99    int numberOfEntries()  { return maskSize; }
100   boolean entryAt(int offset) {
101     return mask.at(offset);
102   }
103 
104   void setEmptyMask()    { mask = null; }
105   void allocateBitMask() {
106     if (maskSize > 0) {
107       mask = new BitMap(maskSize);
108     }
109   }
110 
111   // fills the bit mask for native calls
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 
127     VerifyClosure(OopMapCacheEntry entry)          { this.entry = entry; }
128     public void offsetDo(int offset)               { if (!entry.isOop(offset)) failed = true; }
129     boolean failed()                               { return failed; }
130   }
131 
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 }