/*
 * Copyright (c) 2000, 2001, 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.runtime;

import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.*;

/** */
public class JNIHandleBlock extends VMObject {
  private static Field         handlesField;
  private static CIntegerField topField;
  private static AddressField  nextField;

  private static int           blockSizeInOops;

  static {
    VM.registerVMInitializedObserver(new Observer() {
        public void update(Observable o, Object data) {
          initialize(VM.getVM().getTypeDataBase());
        }
      });
  }

  private static synchronized void initialize(TypeDataBase db) {
    Type type = db.lookupType("JNIHandleBlock");

    handlesField = type.getField("_handles");
    topField = type.getCIntegerField("_top");
    nextField = type.getAddressField("_next");

    blockSizeInOops = db.lookupIntConstant("JNIHandleBlock::block_size_in_oops").intValue();
  }

  public JNIHandleBlock(Address addr) {
    super(addr);
  }

  public JNIHandleBlock next() {
    Address handleAddr = nextField.getValue(addr);
    if (handleAddr == null) {
      return null;
    }

    /* the next handle block is valid only if the current block is full */
    if (top() < blockSizeInOops) {
      return null;
    }
    return new JNIHandleBlock(handleAddr);
  }

  public int top() {
    return (int) topField.getValue(addr);
  }

  public void oopsDo(AddressVisitor visitor) {
    // Visit handles in this block
    for (int i = 0; i < top(); i++) {
      Address cur = getOopHandleAddress(i);
      if (cur != null) {
        visitor.visitAddress(cur);
      }
    }

    // Visit handles in subsequent blocks if necessary
    JNIHandleBlock n = next();
    if (n != null) {
      n.oopsDo(visitor);
    }
  }

  public OopHandle getOopHandle(int x) {
    Address oopAddr = getOopHandleAddress(x);
    if (oopAddr != null) {
      return oopAddr.getOopHandleAt(0);
    }
    return null;
  }

  /** Debugging routine only. Returns non-null JNIHandleBlock
      containing the JNI handle or null if this handle block and its
      successors did not contain it (or if the handle was deleted). */
  public JNIHandleBlock blockContainingHandle(Address jniHandle) {
    JNIHandleBlock cur = this;
    while (cur != null) {
      if (indexOfHandle(jniHandle) >= 0) {
        return cur;
      }
      cur = cur.next();
    }
    return null;
  }

  /** Debugging routine: returns the index (0..top() - 1) of the
      handle in this block, or -1 if the handle was not contained in
      this block. Does not search successor blocks. */
  public int indexOfHandle(Address jniHandle) {
    for (int i = 0; i < top(); i++) {
      Address addr = getOopHandleAddress(i);
      if (addr != null) {
        if (addr.equals(jniHandle)) {
          return i;
        }
      }
    }
    return -1;
  }

  public String toString() {
    Address handleBase = addr.addOffsetTo(handlesField.getOffset());
    Address handleEnd = addr.addOffsetTo(handlesField.getOffset() + top() * VM.getVM().getOopSize());
    return "JNIHandleBlock [" + handleBase + ", " + handleEnd + ")";
  }

  /** Only returns addresses of valid OopHandles */
  private Address getOopHandleAddress(int x) {
    if (Assert.ASSERTS_ENABLED) {
      Assert.that(x < top(), "out of bounds");
    }

    Address oopAddr = addr.addOffsetTo(handlesField.getOffset() + x * VM.getVM().getOopSize());
    OopHandle handle = oopAddr.getOopHandleAt(0);
    if (VM.getVM().getUniverse().isInReserved(handle) && !VM.getVM().getJNIHandles().isDeletedHandle(handle)) {
      /* the oop handle is valid only if it is not freed (i.e. reserved in heap) and is not a deleted oop */
      return oopAddr;
    } else {
      return null;
    }
  }
}
