/*
 * 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 VALUE_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();
    VALUE_VALUE            = db.lookupIntConstant("OopMapValue::value_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 VALUE_VALUE        = new OopTypes() { int getValue() { return OopMapValue.VALUE_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 isValue()       { return (getValue() & TYPE_MASK_IN_PLACE) == VALUE_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 == VALUE_VALUE)  return OopTypes.VALUE_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;
  }
}
