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