提交 85d771bd 编写于 作者: J jiangli

Merge

......@@ -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;
}
}
/*
* 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);
}
}
/*
* 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();
}
......
/*
* 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());
}
}
......
/*
* 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 */
......
/*
* 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();
}
......
/*
* 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);
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 (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);
}
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;
}
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;
}
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;
}
}
}
......
/*
* 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);
}
/*
* 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; }
......
/*
* 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");
for (int j = 0; j < ext_length; j += entry_size) {
int cur_index = ex_table->int_at(j + klass_index_offset);
ExceptionTable ex_table(method());
int ext_length = ex_table.length();
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
......
/*
* 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);
......
/*
* 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 */ \
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册