/* * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ package sun.jvm.hotspot.compiler; import java.util.*; import sun.jvm.hotspot.code.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.utilities.*; public class OopMapValue { private short value; private short contentReg; /** Read from target VM; located in compiler/oopMap.hpp */ // How bits are organized static int TYPE_BITS; static int REGISTER_BITS; static int TYPE_SHIFT; static int REGISTER_SHIFT; static int TYPE_MASK; static int TYPE_MASK_IN_PLACE; static int REGISTER_MASK; static int REGISTER_MASK_IN_PLACE; // Types of OopValues static int UNUSED_VALUE; static int OOP_VALUE; static int NARROWOOP_VALUE; static int CALLEE_SAVED_VALUE; static int DERIVED_OOP_VALUE; static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { initialize(VM.getVM().getTypeDataBase()); } }); } private static void initialize(TypeDataBase db) { TYPE_BITS = db.lookupIntConstant("OopMapValue::type_bits").intValue(); REGISTER_BITS = db.lookupIntConstant("OopMapValue::register_bits").intValue(); TYPE_SHIFT = db.lookupIntConstant("OopMapValue::type_shift").intValue(); REGISTER_SHIFT = db.lookupIntConstant("OopMapValue::register_shift").intValue(); TYPE_MASK = db.lookupIntConstant("OopMapValue::type_mask").intValue(); TYPE_MASK_IN_PLACE = db.lookupIntConstant("OopMapValue::type_mask_in_place").intValue(); REGISTER_MASK = db.lookupIntConstant("OopMapValue::register_mask").intValue(); REGISTER_MASK_IN_PLACE = db.lookupIntConstant("OopMapValue::register_mask_in_place").intValue(); UNUSED_VALUE = db.lookupIntConstant("OopMapValue::unused_value").intValue(); OOP_VALUE = db.lookupIntConstant("OopMapValue::oop_value").intValue(); NARROWOOP_VALUE = db.lookupIntConstant("OopMapValue::narrowoop_value").intValue(); CALLEE_SAVED_VALUE = db.lookupIntConstant("OopMapValue::callee_saved_value").intValue(); DERIVED_OOP_VALUE = db.lookupIntConstant("OopMapValue::derived_oop_value").intValue(); } public static abstract class OopTypes { public static final OopTypes UNUSED_VALUE = new OopTypes() { int getValue() { return OopMapValue.UNUSED_VALUE; }}; public static final OopTypes OOP_VALUE = new OopTypes() { int getValue() { return OopMapValue.OOP_VALUE; }}; public static final OopTypes NARROWOOP_VALUE = new OopTypes() { int getValue() { return OopMapValue.NARROWOOP_VALUE; }}; public static final OopTypes CALLEE_SAVED_VALUE = new OopTypes() { int getValue() { return OopMapValue.CALLEE_SAVED_VALUE; }}; public static final OopTypes DERIVED_OOP_VALUE = new OopTypes() { int getValue() { return OopMapValue.DERIVED_OOP_VALUE; }}; abstract int getValue(); protected OopTypes() {} } public OopMapValue() { setValue((short) 0); setContentReg(new VMReg(0)); } public OopMapValue(VMReg reg, OopTypes t) { setReg(reg); setType(t); } public OopMapValue(VMReg reg, OopTypes t, VMReg reg2) { setReg(reg); setType(t); setContentReg(reg2); } public OopMapValue(CompressedReadStream stream) { readFrom(stream); } public void readFrom(CompressedReadStream stream) { setValue((short) stream.readInt()); if (isCalleeSaved() || isDerivedOop()) { setContentReg(new VMReg(stream.readInt())); } } // Querying public boolean isOop() { return (getValue() & TYPE_MASK_IN_PLACE) == OOP_VALUE; } public boolean isNarrowOop() { return (getValue() & TYPE_MASK_IN_PLACE) == NARROWOOP_VALUE; } public boolean isCalleeSaved() { return (getValue() & TYPE_MASK_IN_PLACE) == CALLEE_SAVED_VALUE; } public boolean isDerivedOop() { return (getValue() & TYPE_MASK_IN_PLACE) == DERIVED_OOP_VALUE; } public VMReg getReg() { return new VMReg((getValue() & REGISTER_MASK_IN_PLACE) >> REGISTER_SHIFT); } public void setReg(VMReg r) { setValue((short) (r.getValue() << REGISTER_SHIFT | (getValue() & TYPE_MASK_IN_PLACE))); } public OopTypes getType() { int which = (getValue() & TYPE_MASK_IN_PLACE); if (which == UNUSED_VALUE) return OopTypes.UNUSED_VALUE; else if (which == OOP_VALUE) return OopTypes.OOP_VALUE; else if (which == NARROWOOP_VALUE) return OopTypes.NARROWOOP_VALUE; else if (which == CALLEE_SAVED_VALUE) return OopTypes.CALLEE_SAVED_VALUE; else if (which == DERIVED_OOP_VALUE) return OopTypes.DERIVED_OOP_VALUE; else throw new InternalError("unknown which " + which + " (TYPE_MASK_IN_PLACE = " + TYPE_MASK_IN_PLACE + ")"); } public void setType(OopTypes t) { setValue((short) ((getValue() & REGISTER_MASK_IN_PLACE) | t.getValue())); } public VMReg getContentReg() { return new VMReg(contentReg); } public void setContentReg(VMReg r) { contentReg = (short) r.getValue(); } /** Physical location queries */ public boolean isRegisterLoc() { return (getReg().lessThan(VM.getVM().getVMRegImplInfo().getStack0())); } public boolean isStackLoc() { return (getReg().greaterThanOrEqual(VM.getVM().getVMRegImplInfo().getStack0())); } /** Returns offset from sp. */ public int getStackOffset() { if (Assert.ASSERTS_ENABLED) { Assert.that(isStackLoc(), "must be stack location"); } return getReg().minus(VM.getVM().getVMRegImplInfo().getStack0()); } //-------------------------------------------------------------------------------- // Internals only below this point // private void setValue(short value) { this.value = value; } private int getValue() { return value; } }