agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, 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.

@@ -45,26 +45,24 @@
 
   // anon-enum constants for _flags.
   private static int HAS_LINENUMBER_TABLE;
   private static int HAS_CHECKED_EXCEPTIONS;
   private static int HAS_LOCALVARIABLE_TABLE;
+  private static int HAS_EXCEPTION_TABLE;
 
   private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
     Type type                  = db.lookupType("constMethodOopDesc");
     // Backpointer to non-const methodOop
     method                     = new OopField(type.getOopField("_method"), 0);
-    // The exception handler table. 4-tuples of ints [start_pc, end_pc,
-    // handler_pc, catch_type index] For methods with no exceptions the
-    // table is pointing to Universe::the_empty_int_array
-    exceptionTable             = new OopField(type.getOopField("_exception_table"), 0);
     constMethodSize            = new CIntField(type.getCIntegerField("_constMethod_size"), 0);
     flags                      = new ByteField(type.getJByteField("_flags"), 0);
 
     // enum constants for flags
     HAS_LINENUMBER_TABLE      = db.lookupIntConstant("constMethodOopDesc::_has_linenumber_table").intValue();
     HAS_CHECKED_EXCEPTIONS     = db.lookupIntConstant("constMethodOopDesc::_has_checked_exceptions").intValue();
     HAS_LOCALVARIABLE_TABLE   = db.lookupIntConstant("constMethodOopDesc::_has_localvariable_table").intValue();
+    HAS_EXCEPTION_TABLE       = db.lookupIntConstant("constMethodOopDesc::_has_exception_table").intValue();
 
     // Size of Java bytecodes allocated immediately after constMethodOop.
     codeSize                   = new CIntField(type.getCIntegerField("_code_size"), 0);
     nameIndex                  = new CIntField(type.getCIntegerField("_name_index"), 0);
     signatureIndex             = new CIntField(type.getCIntegerField("_signature_index"), 0);

@@ -76,19 +74,21 @@
     type                       = db.lookupType("CheckedExceptionElement");
     checkedExceptionElementSize = type.getSize();
 
     type                       = db.lookupType("LocalVariableTableElement");
     localVariableTableElementSize = type.getSize();
+
+    type                       = db.lookupType("ExceptionTableElement");
+    exceptionTableElementSize = type.getSize();
   }
 
   ConstMethod(OopHandle handle, ObjectHeap heap) {
     super(handle, heap);
   }
 
   // Fields
   private static OopField  method;
-  private static OopField  exceptionTable;
   private static CIntField constMethodSize;
   private static ByteField flags;
   private static CIntField codeSize;
   private static CIntField nameIndex;
   private static CIntField signatureIndex;

@@ -97,20 +97,17 @@
   // start of bytecode
   private static long bytecodeOffset;
 
   private static long checkedExceptionElementSize;
   private static long localVariableTableElementSize;
+  private static long exceptionTableElementSize;
 
   // Accessors for declared fields
   public Method getMethod() {
     return (Method) method.getValue(this);
   }
 
-  public TypeArray getExceptionTable() {
-    return (TypeArray) exceptionTable.getValue(this);
-  }
-
   public long getConstMethodSize() {
     return constMethodSize.getValue(this);
   }
 
   public byte getFlags() {

@@ -222,11 +219,10 @@
 
   public void iterateFields(OopVisitor visitor, boolean doVMFields) {
     super.iterateFields(visitor, doVMFields);
     if (doVMFields) {
       visitor.doOop(method, true);
-      visitor.doOop(exceptionTable, true);
       visitor.doCInt(constMethodSize, true);
       visitor.doByte(flags, true);
       visitor.doCInt(codeSize, true);
       visitor.doCInt(nameIndex, true);
       visitor.doCInt(signatureIndex, true);

@@ -313,10 +309,27 @@
       offset += localVariableTableElementSize;
     }
     return ret;
   }
 
+  public boolean hasExceptionTable() {
+    return (getFlags() & HAS_EXCEPTION_TABLE) != 0;
+  }
+
+  public ExceptionTableElement[] getExceptionTable() {
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(hasExceptionTable(), "should only be called if table is present");
+    }
+    ExceptionTableElement[] ret = new ExceptionTableElement[getExceptionTableLength()];
+    long offset = offsetOfExceptionTable();
+    for (int i = 0; i < ret.length; i++) {
+      ret[i] = new ExceptionTableElement(getHandle(), offset);
+      offset += exceptionTableElementSize;
+    }
+    return ret;
+  }
+
   public boolean hasCheckedExceptions() {
     return (getFlags() & HAS_CHECKED_EXCEPTIONS) != 0;
   }
 
   public CheckedExceptionElement[] getCheckedExceptions() {

@@ -402,11 +415,14 @@
   // Offset of local variable table length
   private long offsetOfLocalVariableTableLength() {
     if (Assert.ASSERTS_ENABLED) {
       Assert.that(hasLocalVariableTable(), "should only be called if table is present");
     }
-    if (hasCheckedExceptions()) {
+    
+    if (hasExceptionTable()) {
+      return offsetOfExceptionTable() - 2;
+    } else if (hasCheckedExceptions()) {
       return offsetOfCheckedExceptions() - 2;
     } else {
       return offsetOfLastU2Element();
     }
   }

@@ -419,6 +435,35 @@
     }
     offset -= length * localVariableTableElementSize;
     return offset;
   }
 
+  private int getExceptionTableLength() {
+    if (hasExceptionTable()) {
+      return (int) getHandle().getCIntegerAt(offsetOfExceptionTableLength(), 2, true);
+    } else {
+      return 0;
+    }
+  }
+
+  private long offsetOfExceptionTableLength() {
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(hasExceptionTable(), "should only be called if table is present");
+    }
+    if (hasCheckedExceptions()) {
+      return offsetOfCheckedExceptions() - 2;
+    } else {
+      return offsetOfLastU2Element();
+    }
+  }
+
+  private long offsetOfExceptionTable() {
+    long offset = offsetOfExceptionTableLength();
+    long length = getExceptionTableLength();
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(length > 0, "should only be called if table is present");
+    }
+    offset -= length * exceptionTableElementSize;
+    return offset;
+  }
+
 }