Merge
This commit is contained in:
commit
8f066485db
@ -47,14 +47,11 @@ public class ConstMethod extends Oop {
|
||||
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");
|
||||
constants = new OopField(type.getOopField("_constants"), 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);
|
||||
|
||||
@ -62,6 +59,7 @@ public class ConstMethod extends Oop {
|
||||
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);
|
||||
@ -78,6 +76,9 @@ public class ConstMethod extends Oop {
|
||||
|
||||
type = db.lookupType("LocalVariableTableElement");
|
||||
localVariableTableElementSize = type.getSize();
|
||||
|
||||
type = db.lookupType("ExceptionTableElement");
|
||||
exceptionTableElementSize = type.getSize();
|
||||
}
|
||||
|
||||
ConstMethod(OopHandle handle, ObjectHeap heap) {
|
||||
@ -86,7 +87,6 @@ public class ConstMethod extends Oop {
|
||||
|
||||
// Fields
|
||||
private static OopField constants;
|
||||
private static OopField exceptionTable;
|
||||
private static CIntField constMethodSize;
|
||||
private static ByteField flags;
|
||||
private static CIntField codeSize;
|
||||
@ -100,6 +100,7 @@ public class ConstMethod extends Oop {
|
||||
|
||||
private static long checkedExceptionElementSize;
|
||||
private static long localVariableTableElementSize;
|
||||
private static long exceptionTableElementSize;
|
||||
|
||||
public Method getMethod() {
|
||||
InstanceKlass ik = (InstanceKlass)getConstants().getPoolHolder();
|
||||
@ -112,10 +113,6 @@ public class ConstMethod extends Oop {
|
||||
return (ConstantPool) constants.getValue(this);
|
||||
}
|
||||
|
||||
public TypeArray getExceptionTable() {
|
||||
return (TypeArray) exceptionTable.getValue(this);
|
||||
}
|
||||
|
||||
public long getConstMethodSize() {
|
||||
return constMethodSize.getValue(this);
|
||||
}
|
||||
@ -235,7 +232,6 @@ public class ConstMethod extends Oop {
|
||||
super.iterateFields(visitor, doVMFields);
|
||||
if (doVMFields) {
|
||||
visitor.doOop(constants, true);
|
||||
visitor.doOop(exceptionTable, true);
|
||||
visitor.doCInt(constMethodSize, true);
|
||||
visitor.doByte(flags, true);
|
||||
visitor.doCInt(codeSize, true);
|
||||
@ -326,6 +322,23 @@ public class ConstMethod extends Oop {
|
||||
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;
|
||||
}
|
||||
@ -415,7 +428,10 @@ public class ConstMethod extends Oop {
|
||||
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();
|
||||
@ -432,4 +448,33 @@ public class ConstMethod extends Oop {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*
|
||||
* 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.oops;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.interpreter.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
public class ExceptionTableElement {
|
||||
static {
|
||||
VM.registerVMInitializedObserver(new Observer() {
|
||||
public void update(Observable o, Object data) {
|
||||
initialize(VM.getVM().getTypeDataBase());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
|
||||
Type type = db.lookupType("ExceptionTableElement");
|
||||
offsetOfStartPC = type.getCIntegerField("start_pc").getOffset();
|
||||
offsetOfEndPC = type.getCIntegerField("end_pc").getOffset();
|
||||
offsetOfHandlerPC = type.getCIntegerField("handler_pc").getOffset();
|
||||
offsetOfCatchTypeIndex = type.getCIntegerField("catch_type_index").getOffset();
|
||||
}
|
||||
|
||||
private static long offsetOfStartPC;
|
||||
private static long offsetOfEndPC;
|
||||
private static long offsetOfHandlerPC;
|
||||
private static long offsetOfCatchTypeIndex;
|
||||
|
||||
private OopHandle handle;
|
||||
private long offset;
|
||||
|
||||
public ExceptionTableElement(OopHandle handle, long offset) {
|
||||
this.handle = handle;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
public int getStartPC() {
|
||||
return (int) handle.getCIntegerAt(offset + offsetOfStartPC, 2, true);
|
||||
}
|
||||
|
||||
public int getEndPC() {
|
||||
return (int) handle.getCIntegerAt(offset + offsetOfEndPC, 2, true);
|
||||
}
|
||||
|
||||
public int getHandlerPC() {
|
||||
return (int) handle.getCIntegerAt(offset + offsetOfHandlerPC, 2, true);
|
||||
}
|
||||
|
||||
public int getCatchTypeIndex() {
|
||||
return (int) handle.getCIntegerAt(offset + offsetOfCatchTypeIndex, 2, true);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 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
|
||||
@ -651,10 +651,11 @@ public class GenerateOopMap {
|
||||
boolean fellThrough = false; // False to get first BB marked.
|
||||
|
||||
// First mark all exception handlers as start of a basic-block
|
||||
TypeArray excps = method().getExceptionTable();
|
||||
for(int i = 0; i < excps.getLength(); i += 4) {
|
||||
int handler_pc_idx = i+2;
|
||||
markBB(excps.getIntAt(handler_pc_idx), null);
|
||||
if (method().hasExceptionTable()) {
|
||||
ExceptionTableElement[] excps = method().getExceptionTable();
|
||||
for(int i = 0; i < excps.length; i++) {
|
||||
markBB(excps[i].getHandlerPC(), null);
|
||||
}
|
||||
}
|
||||
|
||||
// Then iterate through the code
|
||||
@ -891,14 +892,15 @@ public class GenerateOopMap {
|
||||
|
||||
// Mark entry basic block as alive and all exception handlers
|
||||
_basic_blocks[0].markAsAlive();
|
||||
TypeArray excps = method().getExceptionTable();
|
||||
for(int i = 0; i < excps.getLength(); i += 4) {
|
||||
int handler_pc_idx = i+2;
|
||||
BasicBlock bb = getBasicBlockAt(excps.getIntAt(handler_pc_idx));
|
||||
// If block is not already alive (due to multiple exception handlers to same bb), then
|
||||
// make it alive
|
||||
if (bb.isDead())
|
||||
bb.markAsAlive();
|
||||
if (method().hasExceptionTable()) {
|
||||
ExceptionTableElement[] excps = method().getExceptionTable();
|
||||
for(int i = 0; i < excps.length; i ++) {
|
||||
BasicBlock bb = getBasicBlockAt(excps[i].getHandlerPC());
|
||||
// If block is not already alive (due to multiple exception handlers to same bb), then
|
||||
// make it alive
|
||||
if (bb.isDead())
|
||||
bb.markAsAlive();
|
||||
}
|
||||
}
|
||||
|
||||
BytecodeStream bcs = new BytecodeStream(_method);
|
||||
@ -1468,12 +1470,12 @@ public class GenerateOopMap {
|
||||
|
||||
if (_has_exceptions) {
|
||||
int bci = itr.bci();
|
||||
TypeArray exct = method().getExceptionTable();
|
||||
for(int i = 0; i< exct.getLength(); i+=4) {
|
||||
int start_pc = exct.getIntAt(i);
|
||||
int end_pc = exct.getIntAt(i+1);
|
||||
int handler_pc = exct.getIntAt(i+2);
|
||||
int catch_type = exct.getIntAt(i+3);
|
||||
ExceptionTableElement[] exct = method().getExceptionTable();
|
||||
for(int i = 0; i< exct.length; i++) {
|
||||
int start_pc = exct[i].getStartPC();
|
||||
int end_pc = exct[i].getEndPC();
|
||||
int handler_pc = exct[i].getHandlerPC();
|
||||
int catch_type = exct[i].getCatchTypeIndex();
|
||||
|
||||
if (start_pc <= bci && bci < end_pc) {
|
||||
BasicBlock excBB = getBasicBlockAt(handler_pc);
|
||||
@ -2151,7 +2153,7 @@ public class GenerateOopMap {
|
||||
_conflict = false;
|
||||
_max_locals = (int) method().getMaxLocals();
|
||||
_max_stack = (int) method().getMaxStack();
|
||||
_has_exceptions = (method().getExceptionTable().getLength() > 0);
|
||||
_has_exceptions = (method().hasExceptionTable());
|
||||
_nof_refval_conflicts = 0;
|
||||
_init_vars = new ArrayList(5); // There are seldom more than 5 init_vars
|
||||
_report_result = false;
|
||||
|
@ -127,7 +127,6 @@ public class Method extends Oop {
|
||||
return getConstMethod().getConstants();
|
||||
}
|
||||
public MethodData getMethodData() { return (MethodData) methodData.getValue(this); }
|
||||
public TypeArray getExceptionTable() { return getConstMethod().getExceptionTable(); }
|
||||
/** WARNING: this is in words, not useful in this system; use getObjectSize() instead */
|
||||
public long getMethodSize() { return methodSize.getValue(this); }
|
||||
public long getMaxStack() { return maxStack.getValue(this); }
|
||||
@ -328,6 +327,14 @@ public class Method extends Oop {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasExceptionTable() {
|
||||
return getConstMethod().hasExceptionTable();
|
||||
}
|
||||
|
||||
public ExceptionTableElement[] getExceptionTable() {
|
||||
return getConstMethod().getExceptionTable();
|
||||
}
|
||||
|
||||
public boolean hasCheckedExceptions() {
|
||||
return getConstMethod().hasCheckedExceptions();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 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
|
||||
@ -504,11 +504,14 @@ public class ClassWriter implements /* imports */ ClassConstants
|
||||
2 /* exp. table len. */ +
|
||||
2 /* code attr. count */;
|
||||
|
||||
TypeArray exceptionTable = m.getExceptionTable();
|
||||
final int exceptionTableLen = (int) exceptionTable.getLength();
|
||||
if (exceptionTableLen != 0) {
|
||||
boolean hasExceptionTable = m.hasExceptionTable();
|
||||
ExceptionTableElement[] exceptionTable = null;
|
||||
int exceptionTableLen = 0;
|
||||
if (hasExceptionTable) {
|
||||
exceptionTable = m.getExceptionTable();
|
||||
exceptionTableLen = exceptionTable.length;
|
||||
if (DEBUG) debugMessage("\tmethod has exception table");
|
||||
codeSize += (exceptionTableLen / 4) /* exception table is 4-tuple array */
|
||||
codeSize += exceptionTableLen /* exception table is 4-tuple array */
|
||||
* (2 /* start_pc */ +
|
||||
2 /* end_pc */ +
|
||||
2 /* handler_pc */ +
|
||||
@ -586,15 +589,15 @@ public class ClassWriter implements /* imports */ ClassConstants
|
||||
dos.write(code);
|
||||
|
||||
// write exception table size
|
||||
dos.writeShort((short) (exceptionTableLen / 4));
|
||||
if (DEBUG) debugMessage("\texception table length = " + (exceptionTableLen / 4));
|
||||
dos.writeShort((short) exceptionTableLen);
|
||||
if (DEBUG) debugMessage("\texception table length = " + exceptionTableLen);
|
||||
|
||||
if (exceptionTableLen != 0) {
|
||||
for (int e = 0; e < exceptionTableLen; e += 4) {
|
||||
dos.writeShort((short) exceptionTable.getIntAt(e));
|
||||
dos.writeShort((short) exceptionTable.getIntAt(e + 1));
|
||||
dos.writeShort((short) exceptionTable.getIntAt(e + 2));
|
||||
dos.writeShort((short) exceptionTable.getIntAt(e + 3));
|
||||
for (int e = 0; e < exceptionTableLen; e++) {
|
||||
dos.writeShort((short) exceptionTable[e].getStartPC());
|
||||
dos.writeShort((short) exceptionTable[e].getEndPC());
|
||||
dos.writeShort((short) exceptionTable[e].getHandlerPC());
|
||||
dos.writeShort((short) exceptionTable[e].getCatchTypeIndex());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 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
|
||||
@ -783,37 +783,39 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
||||
});
|
||||
|
||||
// display exception table for this method
|
||||
TypeArray exceptionTable = method.getExceptionTable();
|
||||
// exception table is 4 tuple array of shorts
|
||||
int numEntries = (int)exceptionTable.getLength() / 4;
|
||||
if (numEntries != 0) {
|
||||
buf.h4("Exception Table");
|
||||
buf.beginTable(1);
|
||||
buf.beginTag("tr");
|
||||
buf.headerCell("start bci");
|
||||
buf.headerCell("end bci");
|
||||
buf.headerCell("handler bci");
|
||||
buf.headerCell("catch type");
|
||||
buf.endTag("tr");
|
||||
|
||||
for (int e = 0; e < numEntries; e += 4) {
|
||||
boolean hasException = method.hasExceptionTable();
|
||||
if (hasException) {
|
||||
ExceptionTableElement[] exceptionTable = method.getExceptionTable();
|
||||
int numEntries = exceptionTable.length;
|
||||
if (numEntries != 0) {
|
||||
buf.h4("Exception Table");
|
||||
buf.beginTable(1);
|
||||
buf.beginTag("tr");
|
||||
buf.cell(Integer.toString(exceptionTable.getIntAt(e)));
|
||||
buf.cell(Integer.toString(exceptionTable.getIntAt(e + 1)));
|
||||
buf.cell(Integer.toString(exceptionTable.getIntAt(e + 2)));
|
||||
short cpIndex = (short) exceptionTable.getIntAt(e + 3);
|
||||
ConstantPool.CPSlot obj = cpIndex == 0? null : cpool.getSlotAt(cpIndex);
|
||||
if (obj == null) {
|
||||
buf.cell("Any");
|
||||
} else if (obj.isMetaData()) {
|
||||
buf.cell(obj.getSymbol().asString().replace('/', '.'));
|
||||
} else {
|
||||
buf.cell(genKlassLink((InstanceKlass)obj.getOop()));
|
||||
}
|
||||
buf.headerCell("start bci");
|
||||
buf.headerCell("end bci");
|
||||
buf.headerCell("handler bci");
|
||||
buf.headerCell("catch type");
|
||||
buf.endTag("tr");
|
||||
}
|
||||
|
||||
buf.endTable();
|
||||
for (int e = 0; e < numEntries; e ++) {
|
||||
buf.beginTag("tr");
|
||||
buf.cell(Integer.toString(exceptionTable[e].getStartPC()));
|
||||
buf.cell(Integer.toString(exceptionTable[e].getEndPC()));
|
||||
buf.cell(Integer.toString(exceptionTable[e].getHandlerPC()));
|
||||
short cpIndex = (short) exceptionTable[e].getCatchTypeIndex();
|
||||
ConstantPool.CPSlot obj = cpIndex == 0? null : cpool.getSlotAt(cpIndex);
|
||||
if (obj == null) {
|
||||
buf.cell("Any");
|
||||
} else if (obj.isMetaData()) {
|
||||
buf.cell(obj.getSymbol().asString().replace('/', '.'));
|
||||
} else {
|
||||
buf.cell(genKlassLink((InstanceKlass)obj.getOop()));
|
||||
}
|
||||
buf.endTag("tr");
|
||||
}
|
||||
|
||||
buf.endTable();
|
||||
}
|
||||
}
|
||||
|
||||
// display constant pool hyperlink
|
||||
|
@ -516,7 +516,7 @@ name_for_methodOop(jvm_agent_t* J, uint64_t methodOopPtr, char * result, size_t
|
||||
|
||||
err = read_pointer(J, methodOopPtr + OFFSET_methodOopDesc_constMethod, &constMethod);
|
||||
CHECK_FAIL(err);
|
||||
err = read_pointer(J->P, constMethod + OFFSET_constMethodOopDesc_constants, &constantPool);
|
||||
err = read_pointer(J, constMethod + OFFSET_constMethodOopDesc_constants, &constantPool);
|
||||
CHECK_FAIL(err);
|
||||
|
||||
/* To get name string */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 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
|
||||
@ -79,7 +79,7 @@ ciMethod::ciMethod(methodHandle h_m) : ciObject(h_m) {
|
||||
_max_locals = h_m()->max_locals();
|
||||
_code_size = h_m()->code_size();
|
||||
_intrinsic_id = h_m()->intrinsic_id();
|
||||
_handler_count = h_m()->exception_table()->length() / 4;
|
||||
_handler_count = h_m()->exception_table_length();
|
||||
_uses_monitors = h_m()->access_flags().has_monitor_bytecodes();
|
||||
_balanced_monitors = !_uses_monitors || h_m()->access_flags().is_monitor_matching();
|
||||
_is_c1_compilable = !h_m()->is_not_c1_compilable();
|
||||
@ -198,7 +198,7 @@ void ciMethod::load_code() {
|
||||
}
|
||||
|
||||
// And load the exception table.
|
||||
typeArrayOop exc_table = me->exception_table();
|
||||
ExceptionTable exc_table(me);
|
||||
|
||||
// Allocate one extra spot in our list of exceptions. This
|
||||
// last entry will be used to represent the possibility that
|
||||
@ -209,13 +209,12 @@ void ciMethod::load_code() {
|
||||
* (_handler_count + 1));
|
||||
if (_handler_count > 0) {
|
||||
for (int i=0; i<_handler_count; i++) {
|
||||
int base = i*4;
|
||||
_exception_handlers[i] = new (arena) ciExceptionHandler(
|
||||
holder(),
|
||||
/* start */ exc_table->int_at(base),
|
||||
/* limit */ exc_table->int_at(base+1),
|
||||
/* goto pc */ exc_table->int_at(base+2),
|
||||
/* cp index */ exc_table->int_at(base+3));
|
||||
/* start */ exc_table.start_pc(i),
|
||||
/* limit */ exc_table.end_pc(i),
|
||||
/* goto pc */ exc_table.handler_pc(i),
|
||||
/* cp index */ exc_table.catch_type_index(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1284,42 +1284,38 @@ static void copy_u2_with_conversion(u2* dest, u2* src, int length) {
|
||||
}
|
||||
|
||||
|
||||
typeArrayHandle ClassFileParser::parse_exception_table(u4 code_length,
|
||||
u4 exception_table_length,
|
||||
constantPoolHandle cp,
|
||||
TRAPS) {
|
||||
u2* ClassFileParser::parse_exception_table(u4 code_length,
|
||||
u4 exception_table_length,
|
||||
constantPoolHandle cp,
|
||||
TRAPS) {
|
||||
ClassFileStream* cfs = stream();
|
||||
typeArrayHandle nullHandle;
|
||||
|
||||
// 4-tuples of ints [start_pc, end_pc, handler_pc, catch_type index]
|
||||
typeArrayOop eh = oopFactory::new_permanent_intArray(exception_table_length*4, CHECK_(nullHandle));
|
||||
typeArrayHandle exception_handlers = typeArrayHandle(THREAD, eh);
|
||||
|
||||
int index = 0;
|
||||
cfs->guarantee_more(8 * exception_table_length, CHECK_(nullHandle)); // start_pc, end_pc, handler_pc, catch_type_index
|
||||
for (unsigned int i = 0; i < exception_table_length; i++) {
|
||||
u2 start_pc = cfs->get_u2_fast();
|
||||
u2 end_pc = cfs->get_u2_fast();
|
||||
u2 handler_pc = cfs->get_u2_fast();
|
||||
u2 catch_type_index = cfs->get_u2_fast();
|
||||
// Will check legal target after parsing code array in verifier.
|
||||
if (_need_verify) {
|
||||
u2* exception_table_start = cfs->get_u2_buffer();
|
||||
assert(exception_table_start != NULL, "null exception table");
|
||||
cfs->guarantee_more(8 * exception_table_length, CHECK_NULL); // start_pc, end_pc, handler_pc, catch_type_index
|
||||
// Will check legal target after parsing code array in verifier.
|
||||
if (_need_verify) {
|
||||
for (unsigned int i = 0; i < exception_table_length; i++) {
|
||||
u2 start_pc = cfs->get_u2_fast();
|
||||
u2 end_pc = cfs->get_u2_fast();
|
||||
u2 handler_pc = cfs->get_u2_fast();
|
||||
u2 catch_type_index = cfs->get_u2_fast();
|
||||
guarantee_property((start_pc < end_pc) && (end_pc <= code_length),
|
||||
"Illegal exception table range in class file %s", CHECK_(nullHandle));
|
||||
"Illegal exception table range in class file %s",
|
||||
CHECK_NULL);
|
||||
guarantee_property(handler_pc < code_length,
|
||||
"Illegal exception table handler in class file %s", CHECK_(nullHandle));
|
||||
"Illegal exception table handler in class file %s",
|
||||
CHECK_NULL);
|
||||
if (catch_type_index != 0) {
|
||||
guarantee_property(valid_cp_range(catch_type_index, cp->length()) &&
|
||||
is_klass_reference(cp, catch_type_index),
|
||||
"Catch type in exception table has bad constant type in class file %s", CHECK_(nullHandle));
|
||||
"Catch type in exception table has bad constant type in class file %s", CHECK_NULL);
|
||||
}
|
||||
}
|
||||
exception_handlers->int_at_put(index++, start_pc);
|
||||
exception_handlers->int_at_put(index++, end_pc);
|
||||
exception_handlers->int_at_put(index++, handler_pc);
|
||||
exception_handlers->int_at_put(index++, catch_type_index);
|
||||
} else {
|
||||
cfs->skip_u2_fast(exception_table_length * 4);
|
||||
}
|
||||
return exception_handlers;
|
||||
return exception_table_start;
|
||||
}
|
||||
|
||||
void ClassFileParser::parse_linenumber_table(
|
||||
@ -1712,6 +1708,7 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
|
||||
u4 code_length = 0;
|
||||
u1* code_start = 0;
|
||||
u2 exception_table_length = 0;
|
||||
u2* exception_table_start = NULL;
|
||||
typeArrayHandle exception_handlers(THREAD, Universe::the_empty_int_array());
|
||||
u2 checked_exceptions_length = 0;
|
||||
u2* checked_exceptions_start = NULL;
|
||||
@ -1798,7 +1795,7 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
|
||||
cfs->guarantee_more(2, CHECK_(nullHandle)); // exception_table_length
|
||||
exception_table_length = cfs->get_u2_fast();
|
||||
if (exception_table_length > 0) {
|
||||
exception_handlers =
|
||||
exception_table_start =
|
||||
parse_exception_table(code_length, exception_table_length, cp, CHECK_(nullHandle));
|
||||
}
|
||||
|
||||
@ -2002,9 +1999,13 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
|
||||
}
|
||||
|
||||
// All sizing information for a methodOop is finally available, now create it
|
||||
methodOop m_oop = oopFactory::new_method(code_length, access_flags, linenumber_table_length,
|
||||
total_lvt_length, checked_exceptions_length,
|
||||
oopDesc::IsSafeConc, CHECK_(nullHandle));
|
||||
methodOop m_oop = oopFactory::new_method(code_length, access_flags,
|
||||
linenumber_table_length,
|
||||
total_lvt_length,
|
||||
exception_table_length,
|
||||
checked_exceptions_length,
|
||||
oopDesc::IsSafeConc,
|
||||
CHECK_(nullHandle));
|
||||
methodHandle m (THREAD, m_oop);
|
||||
|
||||
ClassLoadingService::add_class_method_size(m_oop->size()*HeapWordSize);
|
||||
@ -2035,16 +2036,15 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
|
||||
// Fill in code attribute information
|
||||
m->set_max_stack(max_stack);
|
||||
m->set_max_locals(max_locals);
|
||||
m->constMethod()->set_stackmap_data(stackmap_data());
|
||||
|
||||
/**
|
||||
* The exception_table field is the flag used to indicate
|
||||
* The stackmap_data field is the flag used to indicate
|
||||
* that the methodOop and it's associated constMethodOop are partially
|
||||
* initialized and thus are exempt from pre/post GC verification. Once
|
||||
* the field is set, the oops are considered fully initialized so make
|
||||
* sure that the oops can pass verification when this field is set.
|
||||
*/
|
||||
m->set_exception_table(exception_handlers());
|
||||
m->constMethod()->set_stackmap_data(stackmap_data());
|
||||
|
||||
// Copy byte codes
|
||||
m->set_code(code_start);
|
||||
@ -2055,6 +2055,14 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
|
||||
linenumber_table->buffer(), linenumber_table_length);
|
||||
}
|
||||
|
||||
// Copy exception table
|
||||
if (exception_table_length > 0) {
|
||||
int size =
|
||||
exception_table_length * sizeof(ExceptionTableElement) / sizeof(u2);
|
||||
copy_u2_with_conversion((u2*) m->exception_table_start(),
|
||||
exception_table_start, size);
|
||||
}
|
||||
|
||||
// Copy checked exceptions
|
||||
if (checked_exceptions_length > 0) {
|
||||
int size = checked_exceptions_length * sizeof(CheckedExceptionElement) / sizeof(u2);
|
||||
|
@ -113,8 +113,8 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||
objArrayHandle methods_parameter_annotations,
|
||||
objArrayHandle methods_default_annotations,
|
||||
TRAPS);
|
||||
typeArrayHandle parse_exception_table(u4 code_length, u4 exception_table_length,
|
||||
constantPoolHandle cp, TRAPS);
|
||||
u2* parse_exception_table(u4 code_length, u4 exception_table_length,
|
||||
constantPoolHandle cp, TRAPS);
|
||||
void parse_linenumber_table(
|
||||
u4 code_attribute_length, u4 code_length,
|
||||
CompressedLineNumberWriteStream** write_stream, TRAPS);
|
||||
|
@ -2771,7 +2771,6 @@ class ClassStatistics: AllStatic {
|
||||
nmethods++;
|
||||
method_size += m->size();
|
||||
// class loader uses same objArray for empty vectors, so don't count these
|
||||
if (m->exception_table()->length() != 0) method_size += m->exception_table()->size();
|
||||
if (m->has_stackmap_table()) {
|
||||
method_size += m->stackmap_data()->size();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 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
|
||||
@ -1368,47 +1368,48 @@ char* ClassVerifier::generate_code_data(methodHandle m, u4 code_length, TRAPS) {
|
||||
}
|
||||
|
||||
void ClassVerifier::verify_exception_handler_table(u4 code_length, char* code_data, int& min, int& max, TRAPS) {
|
||||
typeArrayHandle exhandlers (THREAD, _method->exception_table());
|
||||
ExceptionTable exhandlers(_method());
|
||||
int exlength = exhandlers.length();
|
||||
constantPoolHandle cp (THREAD, _method->constants());
|
||||
|
||||
if (exhandlers() != NULL) {
|
||||
for(int i = 0; i < exhandlers->length();) {
|
||||
u2 start_pc = exhandlers->int_at(i++);
|
||||
u2 end_pc = exhandlers->int_at(i++);
|
||||
u2 handler_pc = exhandlers->int_at(i++);
|
||||
if (start_pc >= code_length || code_data[start_pc] == 0) {
|
||||
class_format_error("Illegal exception table start_pc %d", start_pc);
|
||||
return;
|
||||
}
|
||||
if (end_pc != code_length) { // special case: end_pc == code_length
|
||||
if (end_pc > code_length || code_data[end_pc] == 0) {
|
||||
class_format_error("Illegal exception table end_pc %d", end_pc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (handler_pc >= code_length || code_data[handler_pc] == 0) {
|
||||
class_format_error("Illegal exception table handler_pc %d", handler_pc);
|
||||
return;
|
||||
}
|
||||
int catch_type_index = exhandlers->int_at(i++);
|
||||
if (catch_type_index != 0) {
|
||||
VerificationType catch_type = cp_index_to_type(
|
||||
catch_type_index, cp, CHECK_VERIFY(this));
|
||||
VerificationType throwable =
|
||||
VerificationType::reference_type(vmSymbols::java_lang_Throwable());
|
||||
bool is_subclass = throwable.is_assignable_from(
|
||||
catch_type, this, CHECK_VERIFY(this));
|
||||
if (!is_subclass) {
|
||||
// 4286534: should throw VerifyError according to recent spec change
|
||||
verify_error(
|
||||
"Catch type is not a subclass of Throwable in handler %d",
|
||||
handler_pc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (start_pc < min) min = start_pc;
|
||||
if (end_pc > max) max = end_pc;
|
||||
for(int i = 0; i < exlength; i++) {
|
||||
//reacquire the table in case a GC happened
|
||||
ExceptionTable exhandlers(_method());
|
||||
u2 start_pc = exhandlers.start_pc(i);
|
||||
u2 end_pc = exhandlers.end_pc(i);
|
||||
u2 handler_pc = exhandlers.handler_pc(i);
|
||||
if (start_pc >= code_length || code_data[start_pc] == 0) {
|
||||
class_format_error("Illegal exception table start_pc %d", start_pc);
|
||||
return;
|
||||
}
|
||||
if (end_pc != code_length) { // special case: end_pc == code_length
|
||||
if (end_pc > code_length || code_data[end_pc] == 0) {
|
||||
class_format_error("Illegal exception table end_pc %d", end_pc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (handler_pc >= code_length || code_data[handler_pc] == 0) {
|
||||
class_format_error("Illegal exception table handler_pc %d", handler_pc);
|
||||
return;
|
||||
}
|
||||
int catch_type_index = exhandlers.catch_type_index(i);
|
||||
if (catch_type_index != 0) {
|
||||
VerificationType catch_type = cp_index_to_type(
|
||||
catch_type_index, cp, CHECK_VERIFY(this));
|
||||
VerificationType throwable =
|
||||
VerificationType::reference_type(vmSymbols::java_lang_Throwable());
|
||||
bool is_subclass = throwable.is_assignable_from(
|
||||
catch_type, this, CHECK_VERIFY(this));
|
||||
if (!is_subclass) {
|
||||
// 4286534: should throw VerifyError according to recent spec change
|
||||
verify_error(
|
||||
"Catch type is not a subclass of Throwable in handler %d",
|
||||
handler_pc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (start_pc < min) min = start_pc;
|
||||
if (end_pc > max) max = end_pc;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1474,35 +1475,36 @@ u2 ClassVerifier::verify_stackmap_table(u2 stackmap_index, u2 bci,
|
||||
void ClassVerifier::verify_exception_handler_targets(u2 bci, bool this_uninit, StackMapFrame* current_frame,
|
||||
StackMapTable* stackmap_table, TRAPS) {
|
||||
constantPoolHandle cp (THREAD, _method->constants());
|
||||
typeArrayHandle exhandlers (THREAD, _method->exception_table());
|
||||
if (exhandlers() != NULL) {
|
||||
for(int i = 0; i < exhandlers->length();) {
|
||||
u2 start_pc = exhandlers->int_at(i++);
|
||||
u2 end_pc = exhandlers->int_at(i++);
|
||||
u2 handler_pc = exhandlers->int_at(i++);
|
||||
int catch_type_index = exhandlers->int_at(i++);
|
||||
if(bci >= start_pc && bci < end_pc) {
|
||||
u1 flags = current_frame->flags();
|
||||
if (this_uninit) { flags |= FLAG_THIS_UNINIT; }
|
||||
StackMapFrame* new_frame = current_frame->frame_in_exception_handler(flags);
|
||||
if (catch_type_index != 0) {
|
||||
// We know that this index refers to a subclass of Throwable
|
||||
VerificationType catch_type = cp_index_to_type(
|
||||
catch_type_index, cp, CHECK_VERIFY(this));
|
||||
new_frame->push_stack(catch_type, CHECK_VERIFY(this));
|
||||
} else {
|
||||
VerificationType throwable =
|
||||
VerificationType::reference_type(vmSymbols::java_lang_Throwable());
|
||||
new_frame->push_stack(throwable, CHECK_VERIFY(this));
|
||||
}
|
||||
bool match = stackmap_table->match_stackmap(
|
||||
new_frame, handler_pc, true, false, CHECK_VERIFY(this));
|
||||
if (!match) {
|
||||
verify_error(bci,
|
||||
"Stack map does not match the one at exception handler %d",
|
||||
handler_pc);
|
||||
return;
|
||||
}
|
||||
ExceptionTable exhandlers(_method());
|
||||
int exlength = exhandlers.length();
|
||||
for(int i = 0; i < exlength; i++) {
|
||||
//reacquire the table in case a GC happened
|
||||
ExceptionTable exhandlers(_method());
|
||||
u2 start_pc = exhandlers.start_pc(i);
|
||||
u2 end_pc = exhandlers.end_pc(i);
|
||||
u2 handler_pc = exhandlers.handler_pc(i);
|
||||
int catch_type_index = exhandlers.catch_type_index(i);
|
||||
if(bci >= start_pc && bci < end_pc) {
|
||||
u1 flags = current_frame->flags();
|
||||
if (this_uninit) { flags |= FLAG_THIS_UNINIT; }
|
||||
StackMapFrame* new_frame = current_frame->frame_in_exception_handler(flags);
|
||||
if (catch_type_index != 0) {
|
||||
// We know that this index refers to a subclass of Throwable
|
||||
VerificationType catch_type = cp_index_to_type(
|
||||
catch_type_index, cp, CHECK_VERIFY(this));
|
||||
new_frame->push_stack(catch_type, CHECK_VERIFY(this));
|
||||
} else {
|
||||
VerificationType throwable =
|
||||
VerificationType::reference_type(vmSymbols::java_lang_Throwable());
|
||||
new_frame->push_stack(throwable, CHECK_VERIFY(this));
|
||||
}
|
||||
bool match = stackmap_table->match_stackmap(
|
||||
new_frame, handler_pc, true, false, CHECK_VERIFY(this));
|
||||
if (!match) {
|
||||
verify_error(bci,
|
||||
"Stack map does not match the one at exception handler %d",
|
||||
handler_pc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
@ -375,7 +375,6 @@ IRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea
|
||||
Handle h_exception(thread, exception);
|
||||
methodHandle h_method (thread, method(thread));
|
||||
constantPoolHandle h_constants(thread, h_method->constants());
|
||||
typeArrayHandle h_extable (thread, h_method->exception_table());
|
||||
bool should_repeat;
|
||||
int handler_bci;
|
||||
int current_bci = bci(thread);
|
||||
|
@ -231,8 +231,6 @@ public:
|
||||
if (obj->is_constMethod()) {
|
||||
mark_object(obj);
|
||||
mark_object(constMethodOop(obj)->stackmap_data());
|
||||
// Exception tables are needed by ci code during compilation.
|
||||
mark_object(constMethodOop(obj)->exception_table());
|
||||
}
|
||||
|
||||
// Mark objects referenced by klass objects which are read-only.
|
||||
@ -513,7 +511,6 @@ public:
|
||||
for(i = 0; i < methods->length(); i++) {
|
||||
methodOop m = methodOop(methods->obj_at(i));
|
||||
mark_and_move_for_policy(OP_favor_startup, m->constMethod(), _move_ro);
|
||||
mark_and_move_for_policy(OP_favor_runtime, m->constMethod()->exception_table(), _move_ro);
|
||||
mark_and_move_for_policy(OP_favor_runtime, m->constMethod()->stackmap_data(), _move_ro);
|
||||
}
|
||||
|
||||
|
@ -140,14 +140,15 @@ klassOop oopFactory::new_instanceKlass(Symbol* name, int vtable_len, int itable_
|
||||
constMethodOop oopFactory::new_constMethod(int byte_code_size,
|
||||
int compressed_line_number_size,
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
bool is_conc_safe,
|
||||
TRAPS) {
|
||||
klassOop cmkObj = Universe::constMethodKlassObj();
|
||||
constMethodKlass* cmk = constMethodKlass::cast(cmkObj);
|
||||
return cmk->allocate(byte_code_size, compressed_line_number_size,
|
||||
localvariable_table_length, checked_exceptions_length,
|
||||
is_conc_safe,
|
||||
localvariable_table_length, exception_table_length,
|
||||
checked_exceptions_length, is_conc_safe,
|
||||
CHECK_NULL);
|
||||
}
|
||||
|
||||
@ -155,6 +156,7 @@ constMethodOop oopFactory::new_constMethod(int byte_code_size,
|
||||
methodOop oopFactory::new_method(int byte_code_size, AccessFlags access_flags,
|
||||
int compressed_line_number_size,
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
bool is_conc_safe,
|
||||
TRAPS) {
|
||||
@ -164,6 +166,7 @@ methodOop oopFactory::new_method(int byte_code_size, AccessFlags access_flags,
|
||||
constMethodOop cm = new_constMethod(byte_code_size,
|
||||
compressed_line_number_size,
|
||||
localvariable_table_length,
|
||||
exception_table_length,
|
||||
checked_exceptions_length,
|
||||
is_conc_safe, CHECK_NULL);
|
||||
constMethodHandle rw(THREAD, cm);
|
||||
|
@ -86,6 +86,7 @@ private:
|
||||
static constMethodOop new_constMethod(int byte_code_size,
|
||||
int compressed_line_number_size,
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
bool is_conc_safe,
|
||||
TRAPS);
|
||||
@ -97,6 +98,7 @@ public:
|
||||
AccessFlags access_flags,
|
||||
int compressed_line_number_size,
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
bool is_conc_safe,
|
||||
TRAPS);
|
||||
|
@ -65,6 +65,7 @@ bool constMethodKlass::oop_is_conc_safe(oop obj) const {
|
||||
constMethodOop constMethodKlass::allocate(int byte_code_size,
|
||||
int compressed_line_number_size,
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
bool is_conc_safe,
|
||||
TRAPS) {
|
||||
@ -72,6 +73,7 @@ constMethodOop constMethodKlass::allocate(int byte_code_size,
|
||||
int size = constMethodOopDesc::object_size(byte_code_size,
|
||||
compressed_line_number_size,
|
||||
localvariable_table_length,
|
||||
exception_table_length,
|
||||
checked_exceptions_length);
|
||||
KlassHandle h_k(THREAD, as_klassOop());
|
||||
constMethodOop cm = (constMethodOop)
|
||||
@ -82,12 +84,12 @@ constMethodOop constMethodKlass::allocate(int byte_code_size,
|
||||
cm->init_fingerprint();
|
||||
cm->set_constants(NULL);
|
||||
cm->set_stackmap_data(NULL);
|
||||
cm->set_exception_table(NULL);
|
||||
cm->set_code_size(byte_code_size);
|
||||
cm->set_constMethod_size(size);
|
||||
cm->set_inlined_tables_length(checked_exceptions_length,
|
||||
compressed_line_number_size,
|
||||
localvariable_table_length);
|
||||
localvariable_table_length,
|
||||
exception_table_length);
|
||||
assert(cm->size() == size, "wrong size for object");
|
||||
cm->set_is_conc_safe(is_conc_safe);
|
||||
cm->set_partially_loaded();
|
||||
@ -100,7 +102,6 @@ void constMethodKlass::oop_follow_contents(oop obj) {
|
||||
constMethodOop cm = constMethodOop(obj);
|
||||
MarkSweep::mark_and_push(cm->adr_constants());
|
||||
MarkSweep::mark_and_push(cm->adr_stackmap_data());
|
||||
MarkSweep::mark_and_push(cm->adr_exception_table());
|
||||
// Performance tweak: We skip iterating over the klass pointer since we
|
||||
// know that Universe::constMethodKlassObj never moves.
|
||||
}
|
||||
@ -112,7 +113,6 @@ void constMethodKlass::oop_follow_contents(ParCompactionManager* cm,
|
||||
constMethodOop cm_oop = constMethodOop(obj);
|
||||
PSParallelCompact::mark_and_push(cm, cm_oop->adr_constants());
|
||||
PSParallelCompact::mark_and_push(cm, cm_oop->adr_stackmap_data());
|
||||
PSParallelCompact::mark_and_push(cm, cm_oop->adr_exception_table());
|
||||
// Performance tweak: We skip iterating over the klass pointer since we
|
||||
// know that Universe::constMethodKlassObj never moves.
|
||||
}
|
||||
@ -123,7 +123,6 @@ int constMethodKlass::oop_oop_iterate(oop obj, OopClosure* blk) {
|
||||
constMethodOop cm = constMethodOop(obj);
|
||||
blk->do_oop(cm->adr_constants());
|
||||
blk->do_oop(cm->adr_stackmap_data());
|
||||
blk->do_oop(cm->adr_exception_table());
|
||||
// Get size before changing pointers.
|
||||
// Don't call size() or oop_size() since that is a virtual call.
|
||||
int size = cm->object_size();
|
||||
@ -139,8 +138,6 @@ int constMethodKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr)
|
||||
if (mr.contains(adr)) blk->do_oop(adr);
|
||||
adr = cm->adr_stackmap_data();
|
||||
if (mr.contains(adr)) blk->do_oop(adr);
|
||||
adr = cm->adr_exception_table();
|
||||
if (mr.contains(adr)) blk->do_oop(adr);
|
||||
// Get size before changing pointers.
|
||||
// Don't call size() or oop_size() since that is a virtual call.
|
||||
int size = cm->object_size();
|
||||
@ -155,7 +152,6 @@ int constMethodKlass::oop_adjust_pointers(oop obj) {
|
||||
constMethodOop cm = constMethodOop(obj);
|
||||
MarkSweep::adjust_pointer(cm->adr_constants());
|
||||
MarkSweep::adjust_pointer(cm->adr_stackmap_data());
|
||||
MarkSweep::adjust_pointer(cm->adr_exception_table());
|
||||
// Get size before changing pointers.
|
||||
// Don't call size() or oop_size() since that is a virtual call.
|
||||
int size = cm->object_size();
|
||||
@ -190,7 +186,6 @@ void constMethodKlass::oop_print_on(oop obj, outputStream* st) {
|
||||
constMethodOop m = constMethodOop(obj);
|
||||
st->print(" - constants: " INTPTR_FORMAT " ", (address)m->constants());
|
||||
m->constants()->print_value_on(st); st->cr();
|
||||
st->print(" - exceptions: " INTPTR_FORMAT "\n", (address)m->exception_table());
|
||||
if (m->has_stackmap_table()) {
|
||||
st->print(" - stackmap data: ");
|
||||
m->stackmap_data()->print_value_on(st);
|
||||
@ -228,8 +223,6 @@ void constMethodKlass::oop_verify_on(oop obj, outputStream* st) {
|
||||
typeArrayOop stackmap_data = m->stackmap_data();
|
||||
guarantee(stackmap_data == NULL ||
|
||||
stackmap_data->is_perm(), "should be in permspace");
|
||||
guarantee(m->exception_table()->is_perm(), "should be in permspace");
|
||||
guarantee(m->exception_table()->is_typeArray(), "should be type array");
|
||||
|
||||
address m_end = (address)((oop*) m + m->size());
|
||||
address compressed_table_start = m->code_end();
|
||||
@ -244,11 +237,15 @@ void constMethodKlass::oop_verify_on(oop obj, outputStream* st) {
|
||||
compressed_table_end += stream.position();
|
||||
}
|
||||
guarantee(compressed_table_end <= m_end, "invalid method layout");
|
||||
// Verify checked exceptions and local variable tables
|
||||
// Verify checked exceptions, exception table and local variable tables
|
||||
if (m->has_checked_exceptions()) {
|
||||
u2* addr = m->checked_exceptions_length_addr();
|
||||
guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
|
||||
}
|
||||
if (m->has_exception_handler()) {
|
||||
u2* addr = m->exception_table_length_addr();
|
||||
guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
|
||||
}
|
||||
if (m->has_localvariable_table()) {
|
||||
u2* addr = m->localvariable_table_length_addr();
|
||||
guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
|
||||
@ -257,12 +254,12 @@ void constMethodKlass::oop_verify_on(oop obj, outputStream* st) {
|
||||
u2* uncompressed_table_start;
|
||||
if (m->has_localvariable_table()) {
|
||||
uncompressed_table_start = (u2*) m->localvariable_table_start();
|
||||
} else {
|
||||
if (m->has_checked_exceptions()) {
|
||||
} else if (m->has_exception_handler()) {
|
||||
uncompressed_table_start = (u2*) m->exception_table_start();
|
||||
} else if (m->has_checked_exceptions()) {
|
||||
uncompressed_table_start = (u2*) m->checked_exceptions_start();
|
||||
} else {
|
||||
} else {
|
||||
uncompressed_table_start = (u2*) m_end;
|
||||
}
|
||||
}
|
||||
int gap = (intptr_t) uncompressed_table_start - (intptr_t) compressed_table_end;
|
||||
int max_gap = align_object_size(1)*BytesPerWord;
|
||||
@ -273,8 +270,8 @@ void constMethodKlass::oop_verify_on(oop obj, outputStream* st) {
|
||||
bool constMethodKlass::oop_partially_loaded(oop obj) const {
|
||||
assert(obj->is_constMethod(), "object must be klass");
|
||||
constMethodOop m = constMethodOop(obj);
|
||||
// check whether exception_table points to self (flag for partially loaded)
|
||||
return m->exception_table() == (typeArrayOop)obj;
|
||||
// check whether stackmap_data points to self (flag for partially loaded)
|
||||
return m->stackmap_data() == (typeArrayOop)obj;
|
||||
}
|
||||
|
||||
|
||||
@ -282,6 +279,6 @@ bool constMethodKlass::oop_partially_loaded(oop obj) const {
|
||||
void constMethodKlass::oop_set_partially_loaded(oop obj) {
|
||||
assert(obj->is_constMethod(), "object must be klass");
|
||||
constMethodOop m = constMethodOop(obj);
|
||||
// Temporarily set exception_table to point to self
|
||||
m->set_exception_table((typeArrayOop)obj);
|
||||
// Temporarily set stackmap_data to point to self
|
||||
m->set_stackmap_data((typeArrayOop)obj);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2010, 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
|
||||
@ -46,6 +46,7 @@ public:
|
||||
DEFINE_ALLOCATE_PERMANENT(constMethodKlass);
|
||||
constMethodOop allocate(int byte_code_size, int compressed_line_number_size,
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
bool is_conc_safe,
|
||||
TRAPS);
|
||||
|
@ -35,6 +35,7 @@ const u2 constMethodOopDesc::UNSET_IDNUM = 0xFFFF;
|
||||
int constMethodOopDesc::object_size(int code_size,
|
||||
int compressed_line_number_size,
|
||||
int local_variable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length) {
|
||||
int extra_bytes = code_size;
|
||||
if (compressed_line_number_size > 0) {
|
||||
@ -49,6 +50,10 @@ int constMethodOopDesc::object_size(int code_size,
|
||||
extra_bytes +=
|
||||
local_variable_table_length * sizeof(LocalVariableTableElement);
|
||||
}
|
||||
if (exception_table_length > 0) {
|
||||
extra_bytes += sizeof(u2);
|
||||
extra_bytes += exception_table_length * sizeof(ExceptionTableElement);
|
||||
}
|
||||
int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord;
|
||||
return align_object_size(header_size() + extra_words);
|
||||
}
|
||||
@ -73,23 +78,40 @@ u2* constMethodOopDesc::checked_exceptions_length_addr() const {
|
||||
return last_u2_element();
|
||||
}
|
||||
|
||||
u2* constMethodOopDesc::localvariable_table_length_addr() const {
|
||||
assert(has_localvariable_table(), "called only if table is present");
|
||||
u2* constMethodOopDesc::exception_table_length_addr() const {
|
||||
assert(has_exception_handler(), "called only if table is present");
|
||||
if (has_checked_exceptions()) {
|
||||
// If checked_exception present, locate immediately before them.
|
||||
return (u2*) checked_exceptions_start() - 1;
|
||||
} else {
|
||||
// Else, the linenumber table is at the end of the constMethod.
|
||||
// Else, the exception table is at the end of the constMethod.
|
||||
return last_u2_element();
|
||||
}
|
||||
}
|
||||
|
||||
u2* constMethodOopDesc::localvariable_table_length_addr() const {
|
||||
assert(has_localvariable_table(), "called only if table is present");
|
||||
if (has_exception_handler()) {
|
||||
// If exception_table present, locate immediately before them.
|
||||
return (u2*) exception_table_start() - 1;
|
||||
} else {
|
||||
if (has_checked_exceptions()) {
|
||||
// If checked_exception present, locate immediately before them.
|
||||
return (u2*) checked_exceptions_start() - 1;
|
||||
} else {
|
||||
// Else, the linenumber table is at the end of the constMethod.
|
||||
return last_u2_element();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Update the flags to indicate the presence of these optional fields.
|
||||
void constMethodOopDesc::set_inlined_tables_length(
|
||||
int checked_exceptions_len,
|
||||
int compressed_line_number_size,
|
||||
int localvariable_table_len) {
|
||||
int localvariable_table_len,
|
||||
int exception_table_len) {
|
||||
// Must be done in the order below, otherwise length_addr accessors
|
||||
// will not work. Only set bit in header if length is positive.
|
||||
assert(_flags == 0, "Error");
|
||||
@ -100,6 +122,10 @@ void constMethodOopDesc::set_inlined_tables_length(
|
||||
_flags |= _has_checked_exceptions;
|
||||
*(checked_exceptions_length_addr()) = checked_exceptions_len;
|
||||
}
|
||||
if (exception_table_len > 0) {
|
||||
_flags |= _has_exception_table;
|
||||
*(exception_table_length_addr()) = exception_table_len;
|
||||
}
|
||||
if (localvariable_table_len > 0) {
|
||||
_flags |= _has_localvariable_table;
|
||||
*(localvariable_table_length_addr()) = localvariable_table_len;
|
||||
@ -133,3 +159,15 @@ LocalVariableTableElement* constMethodOopDesc::localvariable_table_start() const
|
||||
addr -= length * sizeof(LocalVariableTableElement) / sizeof(u2);
|
||||
return (LocalVariableTableElement*) addr;
|
||||
}
|
||||
|
||||
int constMethodOopDesc::exception_table_length() const {
|
||||
return has_exception_handler() ? *(exception_table_length_addr()) : 0;
|
||||
}
|
||||
|
||||
ExceptionTableElement* constMethodOopDesc::exception_table_start() const {
|
||||
u2* addr = exception_table_length_addr();
|
||||
u2 length = *addr;
|
||||
assert(length > 0, "should only be called if table is present");
|
||||
addr -= length * sizeof(ExceptionTableElement) / sizeof(u2);
|
||||
return (ExceptionTableElement*)addr;
|
||||
}
|
||||
|
@ -43,7 +43,6 @@
|
||||
// | fingerprint 2 |
|
||||
// | constants (oop) |
|
||||
// | stackmap_data (oop) |
|
||||
// | exception_table (oop) |
|
||||
// | constMethod_size |
|
||||
// | interp_kind | flags | code_size |
|
||||
// | name index | signature index |
|
||||
@ -64,7 +63,13 @@
|
||||
// | (length is u2, elements are 6-tuples of u2) |
|
||||
// | (see class LocalVariableTableElement) |
|
||||
// | (access flags bit tells whether table is present) |
|
||||
// | (indexed from end of contMethodOop) |
|
||||
// | (indexed from end of constMethodOop) |
|
||||
// |------------------------------------------------------|
|
||||
// | exception table + length (length last) |
|
||||
// | (length is u2, elements are 4-tuples of u2) |
|
||||
// | (see class ExceptionTableElement) |
|
||||
// | (access flags bit tells whether table is present) |
|
||||
// | (indexed from end of constMethodOop) |
|
||||
// |------------------------------------------------------|
|
||||
// | checked exceptions elements + length (length last) |
|
||||
// | (length is u2, elements are u2) |
|
||||
@ -93,6 +98,15 @@ class LocalVariableTableElement VALUE_OBJ_CLASS_SPEC {
|
||||
};
|
||||
|
||||
|
||||
// Utitily class describing elements in exception table
|
||||
class ExceptionTableElement VALUE_OBJ_CLASS_SPEC {
|
||||
public:
|
||||
u2 start_pc;
|
||||
u2 end_pc;
|
||||
u2 handler_pc;
|
||||
u2 catch_type_index;
|
||||
};
|
||||
|
||||
class constMethodOopDesc : public oopDesc {
|
||||
friend class constMethodKlass;
|
||||
friend class VMStructs;
|
||||
@ -100,7 +114,8 @@ private:
|
||||
enum {
|
||||
_has_linenumber_table = 1,
|
||||
_has_checked_exceptions = 2,
|
||||
_has_localvariable_table = 4
|
||||
_has_localvariable_table = 4,
|
||||
_has_exception_table = 8
|
||||
};
|
||||
|
||||
// Bit vector of signature
|
||||
@ -114,7 +129,7 @@ private:
|
||||
|
||||
public:
|
||||
oop* oop_block_beg() const { return adr_constants(); }
|
||||
oop* oop_block_end() const { return adr_exception_table() + 1; }
|
||||
oop* oop_block_end() const { return adr_stackmap_data() + 1; }
|
||||
|
||||
private:
|
||||
//
|
||||
@ -126,11 +141,6 @@ private:
|
||||
// Raw stackmap data for the method
|
||||
typeArrayOop _stackmap_data;
|
||||
|
||||
// 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
|
||||
typeArrayOop _exception_table;
|
||||
|
||||
//
|
||||
// End of the oop block.
|
||||
//
|
||||
@ -152,7 +162,8 @@ public:
|
||||
// Inlined tables
|
||||
void set_inlined_tables_length(int checked_exceptions_len,
|
||||
int compressed_line_number_size,
|
||||
int localvariable_table_len);
|
||||
int localvariable_table_len,
|
||||
int exception_table_len);
|
||||
|
||||
bool has_linenumber_table() const
|
||||
{ return (_flags & _has_linenumber_table) != 0; }
|
||||
@ -163,6 +174,9 @@ public:
|
||||
bool has_localvariable_table() const
|
||||
{ return (_flags & _has_localvariable_table) != 0; }
|
||||
|
||||
bool has_exception_handler() const
|
||||
{ return (_flags & _has_exception_table) != 0; }
|
||||
|
||||
void set_interpreter_kind(int kind) { _interpreter_kind = kind; }
|
||||
int interpreter_kind(void) const { return _interpreter_kind; }
|
||||
|
||||
@ -181,11 +195,6 @@ public:
|
||||
}
|
||||
bool has_stackmap_table() const { return _stackmap_data != NULL; }
|
||||
|
||||
// exception handler table
|
||||
typeArrayOop exception_table() const { return _exception_table; }
|
||||
void set_exception_table(typeArrayOop e) { oop_store_without_check((oop*) &_exception_table, (oop) e); }
|
||||
bool has_exception_handler() const { return exception_table() != NULL && exception_table()->length() > 0; }
|
||||
|
||||
void init_fingerprint() {
|
||||
const uint64_t initval = CONST64(0x8000000000000000);
|
||||
_fingerprint = initval;
|
||||
@ -235,6 +244,7 @@ public:
|
||||
// Object size needed
|
||||
static int object_size(int code_size, int compressed_line_number_size,
|
||||
int local_variable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length);
|
||||
|
||||
int object_size() const { return _constMethod_size; }
|
||||
@ -256,6 +266,7 @@ public:
|
||||
u_char* compressed_linenumber_table() const; // not preserved by gc
|
||||
u2* checked_exceptions_length_addr() const;
|
||||
u2* localvariable_table_length_addr() const;
|
||||
u2* exception_table_length_addr() const;
|
||||
|
||||
// checked exceptions
|
||||
int checked_exceptions_length() const;
|
||||
@ -265,6 +276,10 @@ public:
|
||||
int localvariable_table_length() const;
|
||||
LocalVariableTableElement* localvariable_table_start() const;
|
||||
|
||||
// exception table
|
||||
int exception_table_length() const;
|
||||
ExceptionTableElement* exception_table_start() const;
|
||||
|
||||
// byte codes
|
||||
void set_code(address code) {
|
||||
if (code_size() > 0) {
|
||||
@ -282,13 +297,10 @@ public:
|
||||
// interpreter support
|
||||
static ByteSize constants_offset()
|
||||
{ return byte_offset_of(constMethodOopDesc, _constants); }
|
||||
static ByteSize exception_table_offset()
|
||||
{ return byte_offset_of(constMethodOopDesc, _exception_table); }
|
||||
|
||||
// Garbage collection support
|
||||
oop* adr_constants() const { return (oop*)&_constants; }
|
||||
oop* adr_stackmap_data() const { return (oop*)&_stackmap_data; }
|
||||
oop* adr_exception_table() const { return (oop*)&_exception_table; }
|
||||
bool is_conc_safe() { return _is_conc_safe; }
|
||||
void set_is_conc_safe(bool v) { _is_conc_safe = v; }
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
@ -400,10 +400,9 @@ void GenerateOopMap::mark_bbheaders_and_count_gc_points() {
|
||||
bool fellThrough = false; // False to get first BB marked.
|
||||
|
||||
// First mark all exception handlers as start of a basic-block
|
||||
typeArrayOop excps = method()->exception_table();
|
||||
for(int i = 0; i < excps->length(); i += 4) {
|
||||
int handler_pc_idx = i+2;
|
||||
bb_mark_fct(this, excps->int_at(handler_pc_idx), NULL);
|
||||
ExceptionTable excps(method());
|
||||
for(int i = 0; i < excps.length(); i ++) {
|
||||
bb_mark_fct(this, excps.handler_pc(i), NULL);
|
||||
}
|
||||
|
||||
// Then iterate through the code
|
||||
@ -450,10 +449,9 @@ void GenerateOopMap::mark_reachable_code() {
|
||||
|
||||
// Mark entry basic block as alive and all exception handlers
|
||||
_basic_blocks[0].mark_as_alive();
|
||||
typeArrayOop excps = method()->exception_table();
|
||||
for(int i = 0; i < excps->length(); i += 4) {
|
||||
int handler_pc_idx = i+2;
|
||||
BasicBlock *bb = get_basic_block_at(excps->int_at(handler_pc_idx));
|
||||
ExceptionTable excps(method());
|
||||
for(int i = 0; i < excps.length(); i++) {
|
||||
BasicBlock *bb = get_basic_block_at(excps.handler_pc(i));
|
||||
// If block is not already alive (due to multiple exception handlers to same bb), then
|
||||
// make it alive
|
||||
if (bb->is_dead()) bb->mark_as_alive();
|
||||
@ -1181,12 +1179,12 @@ void GenerateOopMap::do_exception_edge(BytecodeStream* itr) {
|
||||
|
||||
if (_has_exceptions) {
|
||||
int bci = itr->bci();
|
||||
typeArrayOop exct = method()->exception_table();
|
||||
for(int i = 0; i< exct->length(); i+=4) {
|
||||
int start_pc = exct->int_at(i);
|
||||
int end_pc = exct->int_at(i+1);
|
||||
int handler_pc = exct->int_at(i+2);
|
||||
int catch_type = exct->int_at(i+3);
|
||||
ExceptionTable exct(method());
|
||||
for(int i = 0; i< exct.length(); i++) {
|
||||
int start_pc = exct.start_pc(i);
|
||||
int end_pc = exct.end_pc(i);
|
||||
int handler_pc = exct.handler_pc(i);
|
||||
int catch_type = exct.catch_type_index(i);
|
||||
|
||||
if (start_pc <= bci && bci < end_pc) {
|
||||
BasicBlock *excBB = get_basic_block_at(handler_pc);
|
||||
@ -2055,7 +2053,7 @@ void GenerateOopMap::compute_map(TRAPS) {
|
||||
_conflict = false;
|
||||
_max_locals = method()->max_locals();
|
||||
_max_stack = method()->max_stack();
|
||||
_has_exceptions = (method()->exception_table()->length() > 0);
|
||||
_has_exceptions = (method()->has_exception_handler());
|
||||
_nof_refval_conflicts = 0;
|
||||
_init_vars = new GrowableArray<intptr_t>(5); // There are seldom more than 5 init_vars
|
||||
_report_result = false;
|
||||
@ -2070,9 +2068,10 @@ void GenerateOopMap::compute_map(TRAPS) {
|
||||
if (Verbose) {
|
||||
_method->print_codes();
|
||||
tty->print_cr("Exception table:");
|
||||
typeArrayOop excps = method()->exception_table();
|
||||
for(int i = 0; i < excps->length(); i += 4) {
|
||||
tty->print_cr("[%d - %d] -> %d", excps->int_at(i + 0), excps->int_at(i + 1), excps->int_at(i + 2));
|
||||
ExceptionTable excps(method());
|
||||
for(int i = 0; i < excps.length(); i ++) {
|
||||
tty->print_cr("[%d - %d] -> %d",
|
||||
excps.start_pc(i), excps.end_pc(i), excps.handler_pc(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -111,25 +111,21 @@ char* methodOopDesc::name_and_sig_as_C_string(Klass* klass, Symbol* method_name,
|
||||
|
||||
int methodOopDesc::fast_exception_handler_bci_for(KlassHandle ex_klass, int throw_bci, TRAPS) {
|
||||
// exception table holds quadruple entries of the form (beg_bci, end_bci, handler_bci, klass_index)
|
||||
const int beg_bci_offset = 0;
|
||||
const int end_bci_offset = 1;
|
||||
const int handler_bci_offset = 2;
|
||||
const int klass_index_offset = 3;
|
||||
const int entry_size = 4;
|
||||
// access exception table
|
||||
typeArrayHandle table (THREAD, constMethod()->exception_table());
|
||||
int length = table->length();
|
||||
assert(length % entry_size == 0, "exception table format has changed");
|
||||
ExceptionTable table(this);
|
||||
int length = table.length();
|
||||
// iterate through all entries sequentially
|
||||
constantPoolHandle pool(THREAD, constants());
|
||||
for (int i = 0; i < length; i += entry_size) {
|
||||
int beg_bci = table->int_at(i + beg_bci_offset);
|
||||
int end_bci = table->int_at(i + end_bci_offset);
|
||||
for (int i = 0; i < length; i ++) {
|
||||
//reacquire the table in case a GC happened
|
||||
ExceptionTable table(this);
|
||||
int beg_bci = table.start_pc(i);
|
||||
int end_bci = table.end_pc(i);
|
||||
assert(beg_bci <= end_bci, "inconsistent exception table");
|
||||
if (beg_bci <= throw_bci && throw_bci < end_bci) {
|
||||
// exception handler bci range covers throw_bci => investigate further
|
||||
int handler_bci = table->int_at(i + handler_bci_offset);
|
||||
int klass_index = table->int_at(i + klass_index_offset);
|
||||
int handler_bci = table.handler_pc(i);
|
||||
int klass_index = table.catch_type_index(i);
|
||||
if (klass_index == 0) {
|
||||
return handler_bci;
|
||||
} else if (ex_klass.is_null()) {
|
||||
@ -980,7 +976,7 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
|
||||
{
|
||||
int flags_bits = (JVM_MH_INVOKE_BITS | JVM_ACC_PUBLIC | JVM_ACC_FINAL);
|
||||
methodOop m_oop = oopFactory::new_method(0, accessFlags_from(flags_bits),
|
||||
0, 0, 0, IsSafeConc, CHECK_(empty));
|
||||
0, 0, 0, 0, IsSafeConc, CHECK_(empty));
|
||||
m = methodHandle(THREAD, m_oop);
|
||||
}
|
||||
m->set_constants(cp());
|
||||
@ -994,7 +990,6 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
|
||||
m->set_result_index(rtf.type());
|
||||
#endif
|
||||
m->compute_size_of_parameters(THREAD);
|
||||
m->set_exception_table(Universe::the_empty_int_array());
|
||||
m->init_intrinsic_id();
|
||||
assert(m->intrinsic_id() == vmIntrinsics::_invokeExact ||
|
||||
m->intrinsic_id() == vmIntrinsics::_invokeGeneric, "must be an invoker");
|
||||
@ -1038,6 +1033,7 @@ methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_cod
|
||||
AccessFlags flags = m->access_flags();
|
||||
int checked_exceptions_len = m->checked_exceptions_length();
|
||||
int localvariable_len = m->localvariable_table_length();
|
||||
int exception_table_len = m->exception_table_length();
|
||||
// Allocate newm_oop with the is_conc_safe parameter set
|
||||
// to IsUnsafeConc to indicate that newm_oop is not yet
|
||||
// safe for concurrent processing by a GC.
|
||||
@ -1045,6 +1041,7 @@ methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_cod
|
||||
flags,
|
||||
new_compressed_linenumber_size,
|
||||
localvariable_len,
|
||||
exception_table_len,
|
||||
checked_exceptions_len,
|
||||
IsUnsafeConc,
|
||||
CHECK_(methodHandle()));
|
||||
@ -1085,6 +1082,7 @@ methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_cod
|
||||
newm->set_method_size(new_method_size);
|
||||
assert(newm->code_size() == new_code_length, "check");
|
||||
assert(newm->checked_exceptions_length() == checked_exceptions_len, "check");
|
||||
assert(newm->exception_table_length() == exception_table_len, "check");
|
||||
assert(newm->localvariable_table_length() == localvariable_len, "check");
|
||||
// Copy new byte codes
|
||||
memcpy(newm->code_base(), new_code, new_code_length);
|
||||
@ -1100,6 +1098,12 @@ methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_cod
|
||||
m->checked_exceptions_start(),
|
||||
checked_exceptions_len * sizeof(CheckedExceptionElement));
|
||||
}
|
||||
// Copy exception table
|
||||
if (exception_table_len > 0) {
|
||||
memcpy(newm->exception_table_start(),
|
||||
m->exception_table_start(),
|
||||
exception_table_len * sizeof(ExceptionTableElement));
|
||||
}
|
||||
// Copy local variable number table
|
||||
if (localvariable_len > 0) {
|
||||
memcpy(newm->localvariable_table_start(),
|
||||
|
@ -282,12 +282,12 @@ class methodOopDesc : public oopDesc {
|
||||
}
|
||||
|
||||
// exception handler table
|
||||
typeArrayOop exception_table() const
|
||||
{ return constMethod()->exception_table(); }
|
||||
void set_exception_table(typeArrayOop e)
|
||||
{ constMethod()->set_exception_table(e); }
|
||||
bool has_exception_handler() const
|
||||
{ return constMethod()->has_exception_handler(); }
|
||||
int exception_table_length() const
|
||||
{ return constMethod()->exception_table_length(); }
|
||||
ExceptionTableElement* exception_table_start() const
|
||||
{ return constMethod()->exception_table_start(); }
|
||||
|
||||
// Finds the first entry point bci of an exception handler for an
|
||||
// exception of klass ex_klass thrown at throw_bci. A value of NULL
|
||||
@ -835,4 +835,66 @@ class BreakpointInfo : public CHeapObj<mtClass> {
|
||||
void clear(methodOop method);
|
||||
};
|
||||
|
||||
// Utility class for access exception handlers
|
||||
class ExceptionTable : public StackObj {
|
||||
private:
|
||||
ExceptionTableElement* _table;
|
||||
u2 _length;
|
||||
|
||||
public:
|
||||
ExceptionTable(methodOop m) {
|
||||
if (m->has_exception_handler()) {
|
||||
_table = m->exception_table_start();
|
||||
_length = m->exception_table_length();
|
||||
} else {
|
||||
_table = NULL;
|
||||
_length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int length() const {
|
||||
return _length;
|
||||
}
|
||||
|
||||
u2 start_pc(int idx) const {
|
||||
assert(idx < _length, "out of bounds");
|
||||
return _table[idx].start_pc;
|
||||
}
|
||||
|
||||
void set_start_pc(int idx, u2 value) {
|
||||
assert(idx < _length, "out of bounds");
|
||||
_table[idx].start_pc = value;
|
||||
}
|
||||
|
||||
u2 end_pc(int idx) const {
|
||||
assert(idx < _length, "out of bounds");
|
||||
return _table[idx].end_pc;
|
||||
}
|
||||
|
||||
void set_end_pc(int idx, u2 value) {
|
||||
assert(idx < _length, "out of bounds");
|
||||
_table[idx].end_pc = value;
|
||||
}
|
||||
|
||||
u2 handler_pc(int idx) const {
|
||||
assert(idx < _length, "out of bounds");
|
||||
return _table[idx].handler_pc;
|
||||
}
|
||||
|
||||
void set_handler_pc(int idx, u2 value) {
|
||||
assert(idx < _length, "out of bounds");
|
||||
_table[idx].handler_pc = value;
|
||||
}
|
||||
|
||||
u2 catch_type_index(int idx) const {
|
||||
assert(idx < _length, "out of bounds");
|
||||
return _table[idx].catch_type_index;
|
||||
}
|
||||
|
||||
void set_catch_type_index(int idx, u2 value) {
|
||||
assert(idx < _length, "out of bounds");
|
||||
_table[idx].catch_type_index = value;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_OOPS_METHODOOP_HPP
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "oops/fieldStreams.hpp"
|
||||
#include "oops/instanceKlass.hpp"
|
||||
#include "oops/objArrayKlass.hpp"
|
||||
#include "oops/methodOop.hpp"
|
||||
#include "prims/jvm.h"
|
||||
#include "prims/jvm_misc.hpp"
|
||||
#include "prims/jvmtiExport.hpp"
|
||||
@ -2183,11 +2184,11 @@ JVM_QUICK_ENTRY(void, JVM_GetMethodIxExceptionTableEntry(JNIEnv *env, jclass cls
|
||||
klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
|
||||
k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
|
||||
oop method = instanceKlass::cast(k)->methods()->obj_at(method_index);
|
||||
typeArrayOop extable = methodOop(method)->exception_table();
|
||||
entry->start_pc = extable->int_at(entry_index * 4);
|
||||
entry->end_pc = extable->int_at(entry_index * 4 + 1);
|
||||
entry->handler_pc = extable->int_at(entry_index * 4 + 2);
|
||||
entry->catchType = extable->int_at(entry_index * 4 + 3);
|
||||
ExceptionTable extable((methodOop(method)));
|
||||
entry->start_pc = extable.start_pc(entry_index);
|
||||
entry->end_pc = extable.end_pc(entry_index);
|
||||
entry->handler_pc = extable.handler_pc(entry_index);
|
||||
entry->catchType = extable.catch_type_index(entry_index);
|
||||
JVM_END
|
||||
|
||||
|
||||
@ -2196,7 +2197,7 @@ JVM_QUICK_ENTRY(jint, JVM_GetMethodIxExceptionTableLength(JNIEnv *env, jclass cl
|
||||
klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
|
||||
k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
|
||||
oop method = instanceKlass::cast(k)->methods()->obj_at(method_index);
|
||||
return methodOop(method)->exception_table()->length() / 4;
|
||||
return methodOop(method)->exception_table_length();
|
||||
JVM_END
|
||||
|
||||
|
||||
|
@ -191,15 +191,14 @@ void JvmtiClassFileReconstituter::write_code_attribute(methodHandle method) {
|
||||
}
|
||||
}
|
||||
|
||||
typeArrayHandle exception_table(thread(), const_method->exception_table());
|
||||
int exception_table_length = exception_table->length();
|
||||
int exception_table_entries = exception_table_length / 4;
|
||||
ExceptionTable exception_table(method());
|
||||
int exception_table_length = exception_table.length();
|
||||
int code_size = const_method->code_size();
|
||||
int size =
|
||||
2+2+4 + // max_stack, max_locals, code_length
|
||||
code_size + // code
|
||||
2 + // exception_table_length
|
||||
(2+2+2+2) * exception_table_entries + // exception_table
|
||||
(2+2+2+2) * exception_table_length + // exception_table
|
||||
2 + // attributes_count
|
||||
attr_size; // attributes
|
||||
|
||||
@ -209,12 +208,12 @@ void JvmtiClassFileReconstituter::write_code_attribute(methodHandle method) {
|
||||
write_u2(method->max_locals());
|
||||
write_u4(code_size);
|
||||
copy_bytecodes(method, (unsigned char*)writeable_address(code_size));
|
||||
write_u2(exception_table_entries);
|
||||
for (int index = 0; index < exception_table_length; ) {
|
||||
write_u2(exception_table->int_at(index++));
|
||||
write_u2(exception_table->int_at(index++));
|
||||
write_u2(exception_table->int_at(index++));
|
||||
write_u2(exception_table->int_at(index++));
|
||||
write_u2(exception_table_length);
|
||||
for (int index = 0; index < exception_table_length; index++) {
|
||||
write_u2(exception_table.start_pc(index));
|
||||
write_u2(exception_table.end_pc(index));
|
||||
write_u2(exception_table.handler_pc(index));
|
||||
write_u2(exception_table.catch_type_index(index));
|
||||
}
|
||||
write_u2(attr_count);
|
||||
if (line_num_cnt != 0) {
|
||||
|
@ -2478,23 +2478,17 @@ void VM_RedefineClasses::set_new_constant_pool(
|
||||
// to use new constant pool indices as needed. The exception table
|
||||
// holds quadruple entries of the form:
|
||||
// (beg_bci, end_bci, handler_bci, klass_index)
|
||||
const int beg_bci_offset = 0;
|
||||
const int end_bci_offset = 1;
|
||||
const int handler_bci_offset = 2;
|
||||
const int klass_index_offset = 3;
|
||||
const int entry_size = 4;
|
||||
|
||||
typeArrayHandle ex_table (THREAD, method->exception_table());
|
||||
int ext_length = ex_table->length();
|
||||
assert(ext_length % entry_size == 0, "exception table format has changed");
|
||||
ExceptionTable ex_table(method());
|
||||
int ext_length = ex_table.length();
|
||||
|
||||
for (int j = 0; j < ext_length; j += entry_size) {
|
||||
int cur_index = ex_table->int_at(j + klass_index_offset);
|
||||
for (int j = 0; j < ext_length; j ++) {
|
||||
int cur_index = ex_table.catch_type_index(j);
|
||||
int new_index = find_new_index(cur_index);
|
||||
if (new_index != 0) {
|
||||
RC_TRACE_WITH_THREAD(0x00080000, THREAD,
|
||||
("ext-klass_index change: %d to %d", cur_index, new_index));
|
||||
ex_table->int_at_put(j + klass_index_offset, new_index);
|
||||
ex_table.set_catch_type_index(j, new_index);
|
||||
}
|
||||
} // end for each exception table entry
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 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
|
||||
@ -1796,7 +1796,7 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) {
|
||||
{
|
||||
methodOop m_oop = oopFactory::new_method(bytecode_length(),
|
||||
accessFlags_from(flags_bits),
|
||||
0, 0, 0, oopDesc::IsSafeConc, CHECK_(empty));
|
||||
0, 0, 0, 0, oopDesc::IsSafeConc, CHECK_(empty));
|
||||
m = methodHandle(THREAD, m_oop);
|
||||
}
|
||||
|
||||
@ -1812,9 +1812,6 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) {
|
||||
m->set_max_locals(max_locals());
|
||||
m->set_size_of_parameters(_num_params);
|
||||
|
||||
typeArrayHandle exception_handlers(THREAD, Universe::the_empty_int_array());
|
||||
m->set_exception_table(exception_handlers());
|
||||
|
||||
// Rewrite the method and set up the constant pool cache.
|
||||
objArrayOop m_array = oopFactory::new_system_objArray(1, CHECK_(empty));
|
||||
objArrayHandle methods(THREAD, m_array);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
@ -392,16 +392,16 @@ void Relocator::change_jumps(int break_bci, int delta) {
|
||||
// The width of instruction at "pc" is changing by "delta". Adjust the
|
||||
// exception table, if any, of "rc->mb".
|
||||
void Relocator::adjust_exception_table(int bci, int delta) {
|
||||
typeArrayOop table = method()->exception_table();
|
||||
for (int index = 0; index < table->length(); index +=4) {
|
||||
if (table->int_at(index) > bci) {
|
||||
table->int_at_put(index+0, table->int_at(index+0) + delta);
|
||||
table->int_at_put(index+1, table->int_at(index+1) + delta);
|
||||
} else if (bci < table->int_at(index+1)) {
|
||||
table->int_at_put(index+1, table->int_at(index+1) + delta);
|
||||
ExceptionTable table(_method());
|
||||
for (int index = 0; index < table.length(); index ++) {
|
||||
if (table.start_pc(index) > bci) {
|
||||
table.set_start_pc(index, table.start_pc(index) + delta);
|
||||
table.set_end_pc(index, table.end_pc(index) + delta);
|
||||
} else if (bci < table.end_pc(index)) {
|
||||
table.set_end_pc(index, table.end_pc(index) + delta);
|
||||
}
|
||||
if (table->int_at(index+2) > bci)
|
||||
table->int_at_put(index+2, table->int_at(index+2) + delta);
|
||||
if (table.handler_pc(index) > bci)
|
||||
table.set_handler_pc(index, table.handler_pc(index) + delta);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -388,7 +388,6 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
|
||||
volatile_nonstatic_field(constMethodOopDesc, _fingerprint, uint64_t) \
|
||||
nonstatic_field(constMethodOopDesc, _constants, constantPoolOop) \
|
||||
nonstatic_field(constMethodOopDesc, _stackmap_data, typeArrayOop) \
|
||||
nonstatic_field(constMethodOopDesc, _exception_table, typeArrayOop) \
|
||||
nonstatic_field(constMethodOopDesc, _constMethod_size, int) \
|
||||
nonstatic_field(constMethodOopDesc, _interpreter_kind, jbyte) \
|
||||
nonstatic_field(constMethodOopDesc, _flags, jbyte) \
|
||||
@ -425,6 +424,10 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
|
||||
nonstatic_field(LocalVariableTableElement, descriptor_cp_index, u2) \
|
||||
nonstatic_field(LocalVariableTableElement, signature_cp_index, u2) \
|
||||
nonstatic_field(LocalVariableTableElement, slot, u2) \
|
||||
nonstatic_field(ExceptionTableElement, start_pc, u2) \
|
||||
nonstatic_field(ExceptionTableElement, end_pc, u2) \
|
||||
nonstatic_field(ExceptionTableElement, handler_pc, u2) \
|
||||
nonstatic_field(ExceptionTableElement, catch_type_index, u2) \
|
||||
nonstatic_field(BreakpointInfo, _orig_bytecode, Bytecodes::Code) \
|
||||
nonstatic_field(BreakpointInfo, _bci, int) \
|
||||
nonstatic_field(BreakpointInfo, _name_index, u2) \
|
||||
@ -1460,6 +1463,7 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
|
||||
\
|
||||
declare_toplevel_type(CheckedExceptionElement) \
|
||||
declare_toplevel_type(LocalVariableTableElement) \
|
||||
declare_toplevel_type(ExceptionTableElement) \
|
||||
\
|
||||
/******************************************/ \
|
||||
/* Generation and space hierarchies */ \
|
||||
@ -2301,6 +2305,7 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
|
||||
declare_constant(constMethodOopDesc::_has_linenumber_table) \
|
||||
declare_constant(constMethodOopDesc::_has_checked_exceptions) \
|
||||
declare_constant(constMethodOopDesc::_has_localvariable_table) \
|
||||
declare_constant(constMethodOopDesc::_has_exception_table) \
|
||||
\
|
||||
/*************************************/ \
|
||||
/* instanceKlass enum */ \
|
||||
|
Loading…
x
Reference in New Issue
Block a user