aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm
diff options
context:
space:
mode:
authorjiangli <none@none>2012-07-13 20:14:27 -0400
committerjiangli <none@none>2012-07-13 20:14:27 -0400
commit1f0952904d83c0ddc6db527b32f02242cbd33f67 (patch)
tree0ee20bf3b273e443943a12258b29f73beb554592 /src/share/vm
parentee19b080e9911f25d733ed357962bf35ae0156f0 (diff)
parent96b276d261c2b3de763bff86bb5c94826bb033b2 (diff)
Merge
Diffstat (limited to 'src/share/vm')
-rw-r--r--src/share/vm/ci/ciMethod.cpp15
-rw-r--r--src/share/vm/classfile/classFileParser.cpp74
-rw-r--r--src/share/vm/classfile/classFileParser.hpp4
-rw-r--r--src/share/vm/classfile/systemDictionary.cpp1
-rw-r--r--src/share/vm/classfile/verifier.cpp130
-rw-r--r--src/share/vm/interpreter/interpreterRuntime.cpp3
-rw-r--r--src/share/vm/memory/dump.cpp3
-rw-r--r--src/share/vm/memory/oopFactory.cpp7
-rw-r--r--src/share/vm/memory/oopFactory.hpp2
-rw-r--r--src/share/vm/oops/constMethodKlass.cpp37
-rw-r--r--src/share/vm/oops/constMethodKlass.hpp3
-rw-r--r--src/share/vm/oops/constMethodOop.cpp46
-rw-r--r--src/share/vm/oops/constMethodOop.hpp48
-rw-r--r--src/share/vm/oops/generateOopMap.cpp37
-rw-r--r--src/share/vm/oops/methodOop.cpp34
-rw-r--r--src/share/vm/oops/methodOop.hpp70
-rw-r--r--src/share/vm/prims/jvm.cpp13
-rw-r--r--src/share/vm/prims/jvmtiClassFileReconstituter.cpp19
-rw-r--r--src/share/vm/prims/jvmtiRedefineClasses.cpp20
-rw-r--r--src/share/vm/prims/methodHandleWalk.cpp7
-rw-r--r--src/share/vm/runtime/relocator.cpp20
-rw-r--r--src/share/vm/runtime/vmStructs.cpp7
22 files changed, 359 insertions, 241 deletions
diff --git a/src/share/vm/ci/ciMethod.cpp b/src/share/vm/ci/ciMethod.cpp
index 6049d7b93..180f22f21 100644
--- a/src/share/vm/ci/ciMethod.cpp
+++ b/src/share/vm/ci/ciMethod.cpp
@@ -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));
}
}
diff --git a/src/share/vm/classfile/classFileParser.cpp b/src/share/vm/classfile/classFileParser.cpp
index b2cec5375..a7f5ab02f 100644
--- a/src/share/vm/classfile/classFileParser.cpp
+++ b/src/share/vm/classfile/classFileParser.cpp
@@ -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);
diff --git a/src/share/vm/classfile/classFileParser.hpp b/src/share/vm/classfile/classFileParser.hpp
index de781b2fb..008902eac 100644
--- a/src/share/vm/classfile/classFileParser.hpp
+++ b/src/share/vm/classfile/classFileParser.hpp
@@ -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);
diff --git a/src/share/vm/classfile/systemDictionary.cpp b/src/share/vm/classfile/systemDictionary.cpp
index 74901574d..aca21742f 100644
--- a/src/share/vm/classfile/systemDictionary.cpp
+++ b/src/share/vm/classfile/systemDictionary.cpp
@@ -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();
}
diff --git a/src/share/vm/classfile/verifier.cpp b/src/share/vm/classfile/verifier.cpp
index 905456a2b..e5badd62c 100644
--- a/src/share/vm/classfile/verifier.cpp
+++ b/src/share/vm/classfile/verifier.cpp
@@ -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);
+ 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;
}
}
}
diff --git a/src/share/vm/interpreter/interpreterRuntime.cpp b/src/share/vm/interpreter/interpreterRuntime.cpp
index 956dbf869..f5200c381 100644
--- a/src/share/vm/interpreter/interpreterRuntime.cpp
+++ b/src/share/vm/interpreter/interpreterRuntime.cpp
@@ -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);
diff --git a/src/share/vm/memory/dump.cpp b/src/share/vm/memory/dump.cpp
index c99505242..f9dc8b8b9 100644
--- a/src/share/vm/memory/dump.cpp
+++ b/src/share/vm/memory/dump.cpp
@@ -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);
}
diff --git a/src/share/vm/memory/oopFactory.cpp b/src/share/vm/memory/oopFactory.cpp
index 0dd620650..def88ccf1 100644
--- a/src/share/vm/memory/oopFactory.cpp
+++ b/src/share/vm/memory/oopFactory.cpp
@@ -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);
diff --git a/src/share/vm/memory/oopFactory.hpp b/src/share/vm/memory/oopFactory.hpp
index 38de1a4f2..5fd843ee8 100644
--- a/src/share/vm/memory/oopFactory.hpp
+++ b/src/share/vm/memory/oopFactory.hpp
@@ -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);
diff --git a/src/share/vm/oops/constMethodKlass.cpp b/src/share/vm/oops/constMethodKlass.cpp
index b66df9505..e74811f54 100644
--- a/src/share/vm/oops/constMethodKlass.cpp
+++ b/src/share/vm/oops/constMethodKlass.cpp
@@ -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);
}
diff --git a/src/share/vm/oops/constMethodKlass.hpp b/src/share/vm/oops/constMethodKlass.hpp
index 1c3e3c83b..23ba11227 100644
--- a/src/share/vm/oops/constMethodKlass.hpp
+++ b/src/share/vm/oops/constMethodKlass.hpp
@@ -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);
diff --git a/src/share/vm/oops/constMethodOop.cpp b/src/share/vm/oops/constMethodOop.cpp
index cc8dfd501..cb9256da6 100644
--- a/src/share/vm/oops/constMethodOop.cpp
+++ b/src/share/vm/oops/constMethodOop.cpp
@@ -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;
+}
diff --git a/src/share/vm/oops/constMethodOop.hpp b/src/share/vm/oops/constMethodOop.hpp
index 10344ec6d..549192be7 100644
--- a/src/share/vm/oops/constMethodOop.hpp
+++ b/src/share/vm/oops/constMethodOop.hpp
@@ -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; }
diff --git a/src/share/vm/oops/generateOopMap.cpp b/src/share/vm/oops/generateOopMap.cpp
index 58ef93152..3a818aad4 100644
--- a/src/share/vm/oops/generateOopMap.cpp
+++ b/src/share/vm/oops/generateOopMap.cpp
@@ -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));
}
}
}
diff --git a/src/share/vm/oops/methodOop.cpp b/src/share/vm/oops/methodOop.cpp
index 7a0e74e0f..ee5ef09bf 100644
--- a/src/share/vm/oops/methodOop.cpp
+++ b/src/share/vm/oops/methodOop.cpp
@@ -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(),
diff --git a/src/share/vm/oops/methodOop.hpp b/src/share/vm/oops/methodOop.hpp
index 822a47c93..1b8438756 100644
--- a/src/share/vm/oops/methodOop.hpp
+++ b/src/share/vm/oops/methodOop.hpp
@@ -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
diff --git a/src/share/vm/prims/jvm.cpp b/src/share/vm/prims/jvm.cpp
index 1dfec11a8..a211004a3 100644
--- a/src/share/vm/prims/jvm.cpp
+++ b/src/share/vm/prims/jvm.cpp
@@ -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
diff --git a/src/share/vm/prims/jvmtiClassFileReconstituter.cpp b/src/share/vm/prims/jvmtiClassFileReconstituter.cpp
index 60a801213..826556955 100644
--- a/src/share/vm/prims/jvmtiClassFileReconstituter.cpp
+++ b/src/share/vm/prims/jvmtiClassFileReconstituter.cpp
@@ -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) {
diff --git a/src/share/vm/prims/jvmtiRedefineClasses.cpp b/src/share/vm/prims/jvmtiRedefineClasses.cpp
index dbab30e43..2c0550e9e 100644
--- a/src/share/vm/prims/jvmtiRedefineClasses.cpp
+++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp
@@ -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
diff --git a/src/share/vm/prims/methodHandleWalk.cpp b/src/share/vm/prims/methodHandleWalk.cpp
index d4d9a7130..68e83bdc7 100644
--- a/src/share/vm/prims/methodHandleWalk.cpp
+++ b/src/share/vm/prims/methodHandleWalk.cpp
@@ -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);
diff --git a/src/share/vm/runtime/relocator.cpp b/src/share/vm/runtime/relocator.cpp
index a39709077..e385b22fe 100644
--- a/src/share/vm/runtime/relocator.cpp
+++ b/src/share/vm/runtime/relocator.cpp
@@ -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);
}
}
diff --git a/src/share/vm/runtime/vmStructs.cpp b/src/share/vm/runtime/vmStructs.cpp
index fbda7f8ed..60d87ff93 100644
--- a/src/share/vm/runtime/vmStructs.cpp
+++ b/src/share/vm/runtime/vmStructs.cpp
@@ -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 */ \