45 |
45 |
46 // anon-enum constants for _flags. |
46 // anon-enum constants for _flags. |
47 private static int HAS_LINENUMBER_TABLE; |
47 private static int HAS_LINENUMBER_TABLE; |
48 private static int HAS_CHECKED_EXCEPTIONS; |
48 private static int HAS_CHECKED_EXCEPTIONS; |
49 private static int HAS_LOCALVARIABLE_TABLE; |
49 private static int HAS_LOCALVARIABLE_TABLE; |
|
50 private static int HAS_EXCEPTION_TABLE; |
50 |
51 |
51 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { |
52 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { |
52 Type type = db.lookupType("constMethodOopDesc"); |
53 Type type = db.lookupType("constMethodOopDesc"); |
53 constants = new OopField(type.getOopField("_constants"), 0); |
54 constants = new OopField(type.getOopField("_constants"), 0); |
54 // The exception handler table. 4-tuples of ints [start_pc, end_pc, |
|
55 // handler_pc, catch_type index] For methods with no exceptions the |
|
56 // table is pointing to Universe::the_empty_int_array |
|
57 exceptionTable = new OopField(type.getOopField("_exception_table"), 0); |
|
58 constMethodSize = new CIntField(type.getCIntegerField("_constMethod_size"), 0); |
55 constMethodSize = new CIntField(type.getCIntegerField("_constMethod_size"), 0); |
59 flags = new ByteField(type.getJByteField("_flags"), 0); |
56 flags = new ByteField(type.getJByteField("_flags"), 0); |
60 |
57 |
61 // enum constants for flags |
58 // enum constants for flags |
62 HAS_LINENUMBER_TABLE = db.lookupIntConstant("constMethodOopDesc::_has_linenumber_table").intValue(); |
59 HAS_LINENUMBER_TABLE = db.lookupIntConstant("constMethodOopDesc::_has_linenumber_table").intValue(); |
63 HAS_CHECKED_EXCEPTIONS = db.lookupIntConstant("constMethodOopDesc::_has_checked_exceptions").intValue(); |
60 HAS_CHECKED_EXCEPTIONS = db.lookupIntConstant("constMethodOopDesc::_has_checked_exceptions").intValue(); |
64 HAS_LOCALVARIABLE_TABLE = db.lookupIntConstant("constMethodOopDesc::_has_localvariable_table").intValue(); |
61 HAS_LOCALVARIABLE_TABLE = db.lookupIntConstant("constMethodOopDesc::_has_localvariable_table").intValue(); |
|
62 HAS_EXCEPTION_TABLE = db.lookupIntConstant("constMethodOopDesc::_has_exception_table").intValue(); |
65 |
63 |
66 // Size of Java bytecodes allocated immediately after constMethodOop. |
64 // Size of Java bytecodes allocated immediately after constMethodOop. |
67 codeSize = new CIntField(type.getCIntegerField("_code_size"), 0); |
65 codeSize = new CIntField(type.getCIntegerField("_code_size"), 0); |
68 nameIndex = new CIntField(type.getCIntegerField("_name_index"), 0); |
66 nameIndex = new CIntField(type.getCIntegerField("_name_index"), 0); |
69 signatureIndex = new CIntField(type.getCIntegerField("_signature_index"), 0); |
67 signatureIndex = new CIntField(type.getCIntegerField("_signature_index"), 0); |
76 type = db.lookupType("CheckedExceptionElement"); |
74 type = db.lookupType("CheckedExceptionElement"); |
77 checkedExceptionElementSize = type.getSize(); |
75 checkedExceptionElementSize = type.getSize(); |
78 |
76 |
79 type = db.lookupType("LocalVariableTableElement"); |
77 type = db.lookupType("LocalVariableTableElement"); |
80 localVariableTableElementSize = type.getSize(); |
78 localVariableTableElementSize = type.getSize(); |
|
79 |
|
80 type = db.lookupType("ExceptionTableElement"); |
|
81 exceptionTableElementSize = type.getSize(); |
81 } |
82 } |
82 |
83 |
83 ConstMethod(OopHandle handle, ObjectHeap heap) { |
84 ConstMethod(OopHandle handle, ObjectHeap heap) { |
84 super(handle, heap); |
85 super(handle, heap); |
85 } |
86 } |
86 |
87 |
87 // Fields |
88 // Fields |
88 private static OopField constants; |
89 private static OopField constants; |
89 private static OopField exceptionTable; |
|
90 private static CIntField constMethodSize; |
90 private static CIntField constMethodSize; |
91 private static ByteField flags; |
91 private static ByteField flags; |
92 private static CIntField codeSize; |
92 private static CIntField codeSize; |
93 private static CIntField nameIndex; |
93 private static CIntField nameIndex; |
94 private static CIntField signatureIndex; |
94 private static CIntField signatureIndex; |
98 // start of bytecode |
98 // start of bytecode |
99 private static long bytecodeOffset; |
99 private static long bytecodeOffset; |
100 |
100 |
101 private static long checkedExceptionElementSize; |
101 private static long checkedExceptionElementSize; |
102 private static long localVariableTableElementSize; |
102 private static long localVariableTableElementSize; |
|
103 private static long exceptionTableElementSize; |
103 |
104 |
104 public Method getMethod() { |
105 public Method getMethod() { |
105 InstanceKlass ik = (InstanceKlass)getConstants().getPoolHolder(); |
106 InstanceKlass ik = (InstanceKlass)getConstants().getPoolHolder(); |
106 ObjArray methods = ik.getMethods(); |
107 ObjArray methods = ik.getMethods(); |
107 return (Method)methods.getObjAt(getIdNum()); |
108 return (Method)methods.getObjAt(getIdNum()); |
108 } |
109 } |
109 |
110 |
110 // Accessors for declared fields |
111 // Accessors for declared fields |
111 public ConstantPool getConstants() { |
112 public ConstantPool getConstants() { |
112 return (ConstantPool) constants.getValue(this); |
113 return (ConstantPool) constants.getValue(this); |
113 } |
|
114 |
|
115 public TypeArray getExceptionTable() { |
|
116 return (TypeArray) exceptionTable.getValue(this); |
|
117 } |
114 } |
118 |
115 |
119 public long getConstMethodSize() { |
116 public long getConstMethodSize() { |
120 return constMethodSize.getValue(this); |
117 return constMethodSize.getValue(this); |
121 } |
118 } |
233 |
230 |
234 public void iterateFields(OopVisitor visitor, boolean doVMFields) { |
231 public void iterateFields(OopVisitor visitor, boolean doVMFields) { |
235 super.iterateFields(visitor, doVMFields); |
232 super.iterateFields(visitor, doVMFields); |
236 if (doVMFields) { |
233 if (doVMFields) { |
237 visitor.doOop(constants, true); |
234 visitor.doOop(constants, true); |
238 visitor.doOop(exceptionTable, true); |
|
239 visitor.doCInt(constMethodSize, true); |
235 visitor.doCInt(constMethodSize, true); |
240 visitor.doByte(flags, true); |
236 visitor.doByte(flags, true); |
241 visitor.doCInt(codeSize, true); |
237 visitor.doCInt(codeSize, true); |
242 visitor.doCInt(nameIndex, true); |
238 visitor.doCInt(nameIndex, true); |
243 visitor.doCInt(signatureIndex, true); |
239 visitor.doCInt(signatureIndex, true); |
324 offset += localVariableTableElementSize; |
320 offset += localVariableTableElementSize; |
325 } |
321 } |
326 return ret; |
322 return ret; |
327 } |
323 } |
328 |
324 |
|
325 public boolean hasExceptionTable() { |
|
326 return (getFlags() & HAS_EXCEPTION_TABLE) != 0; |
|
327 } |
|
328 |
|
329 public ExceptionTableElement[] getExceptionTable() { |
|
330 if (Assert.ASSERTS_ENABLED) { |
|
331 Assert.that(hasExceptionTable(), "should only be called if table is present"); |
|
332 } |
|
333 ExceptionTableElement[] ret = new ExceptionTableElement[getExceptionTableLength()]; |
|
334 long offset = offsetOfExceptionTable(); |
|
335 for (int i = 0; i < ret.length; i++) { |
|
336 ret[i] = new ExceptionTableElement(getHandle(), offset); |
|
337 offset += exceptionTableElementSize; |
|
338 } |
|
339 return ret; |
|
340 } |
|
341 |
329 public boolean hasCheckedExceptions() { |
342 public boolean hasCheckedExceptions() { |
330 return (getFlags() & HAS_CHECKED_EXCEPTIONS) != 0; |
343 return (getFlags() & HAS_CHECKED_EXCEPTIONS) != 0; |
331 } |
344 } |
332 |
345 |
333 public CheckedExceptionElement[] getCheckedExceptions() { |
346 public CheckedExceptionElement[] getCheckedExceptions() { |
413 // Offset of local variable table length |
426 // Offset of local variable table length |
414 private long offsetOfLocalVariableTableLength() { |
427 private long offsetOfLocalVariableTableLength() { |
415 if (Assert.ASSERTS_ENABLED) { |
428 if (Assert.ASSERTS_ENABLED) { |
416 Assert.that(hasLocalVariableTable(), "should only be called if table is present"); |
429 Assert.that(hasLocalVariableTable(), "should only be called if table is present"); |
417 } |
430 } |
418 if (hasCheckedExceptions()) { |
431 |
|
432 if (hasExceptionTable()) { |
|
433 return offsetOfExceptionTable() - 2; |
|
434 } else if (hasCheckedExceptions()) { |
419 return offsetOfCheckedExceptions() - 2; |
435 return offsetOfCheckedExceptions() - 2; |
420 } else { |
436 } else { |
421 return offsetOfLastU2Element(); |
437 return offsetOfLastU2Element(); |
422 } |
438 } |
423 } |
439 } |
430 } |
446 } |
431 offset -= length * localVariableTableElementSize; |
447 offset -= length * localVariableTableElementSize; |
432 return offset; |
448 return offset; |
433 } |
449 } |
434 |
450 |
|
451 private int getExceptionTableLength() { |
|
452 if (hasExceptionTable()) { |
|
453 return (int) getHandle().getCIntegerAt(offsetOfExceptionTableLength(), 2, true); |
|
454 } else { |
|
455 return 0; |
|
456 } |
|
457 } |
|
458 |
|
459 private long offsetOfExceptionTableLength() { |
|
460 if (Assert.ASSERTS_ENABLED) { |
|
461 Assert.that(hasExceptionTable(), "should only be called if table is present"); |
|
462 } |
|
463 if (hasCheckedExceptions()) { |
|
464 return offsetOfCheckedExceptions() - 2; |
|
465 } else { |
|
466 return offsetOfLastU2Element(); |
|
467 } |
|
468 } |
|
469 |
|
470 private long offsetOfExceptionTable() { |
|
471 long offset = offsetOfExceptionTableLength(); |
|
472 long length = getExceptionTableLength(); |
|
473 if (Assert.ASSERTS_ENABLED) { |
|
474 Assert.that(length > 0, "should only be called if table is present"); |
|
475 } |
|
476 offset -= length * exceptionTableElementSize; |
|
477 return offset; |
|
478 } |
|
479 |
435 } |
480 } |