8180032: Unaligned pointer dereference in ClassFileParser

Reviewed-by: dholmes, hseigel
This commit is contained in:
Mikael Vidstedt 2017-05-26 13:47:33 -07:00
parent 85abe8f6e6
commit f1f868513d
17 changed files with 242 additions and 191 deletions

View File

@ -30,12 +30,6 @@
class Bytes: AllStatic {
public:
// Returns true if the byte ordering used by Java is different from the native byte ordering
// of the underlying machine. For example, this is true for Intel x86, but false for Solaris
// on Sparc.
static inline bool is_Java_byte_ordering_different(){ return true; }
// Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering
// (no special code is needed since x86 CPUs can access unaligned data)
static inline u2 get_native_u2(address p) { return *(u2*)p; }

View File

@ -35,12 +35,6 @@
class Bytes: AllStatic {
public:
// Returns true if the byte ordering used by Java is different from the native byte ordering
// of the underlying machine.
static inline bool is_Java_byte_ordering_different() {
return VM_LITTLE_ENDIAN != 0;
}
static inline u2 get_Java_u2(address p) {
return (u2(p[0]) << 8) | u2(p[1]);
}

View File

@ -37,10 +37,6 @@ class Bytes: AllStatic {
#if defined(VM_LITTLE_ENDIAN)
// Returns true, if the byte ordering used by Java is different from the native byte ordering
// of the underlying machine. For example, true for Intel x86, False, for Solaris on Sparc.
static inline bool is_Java_byte_ordering_different() { return true; }
// Forward declarations of the compiler-dependent implementation
static inline u2 swap_u2(u2 x);
static inline u4 swap_u4(u4 x);
@ -155,10 +151,6 @@ class Bytes: AllStatic {
#else // !defined(VM_LITTLE_ENDIAN)
// Returns true, if the byte ordering used by Java is different from the nativ byte ordering
// of the underlying machine. For example, true for Intel x86, False, for Solaris on Sparc.
static inline bool is_Java_byte_ordering_different() { return false; }
// Thus, a swap between native and Java ordering is always a no-op:
static inline u2 swap_u2(u2 x) { return x; }
static inline u4 swap_u4(u4 x) { return x; }

View File

@ -42,12 +42,6 @@ class Bytes: AllStatic {
//
// In short, it makes no sense on z/Architecture to piecemeal get or put unaligned data.
// Returns true if the byte ordering used by Java is different from
// the native byte ordering of the underlying machine.
// z/Arch is big endian, thus, a swap between native and Java ordering
// is always a no-op.
static inline bool is_Java_byte_ordering_different() { return false; }
// Only swap on little endian machines => suffix `_le'.
static inline u2 swap_u2_le(u2 x) { return x; }
static inline u4 swap_u4_le(u4 x) { return x; }

View File

@ -34,10 +34,6 @@ class Bytes: AllStatic {
// can I count on address always being a pointer to an unsigned char? Yes
// Returns true, if the byte ordering used by Java is different from the nativ byte ordering
// of the underlying machine. For example, true for Intel x86, False, for Solaris on Sparc.
static inline bool is_Java_byte_ordering_different() { return false; }
// Thus, a swap between native and Java ordering is always a no-op:
static inline u2 swap_u2(u2 x) { return x; }
static inline u4 swap_u4(u4 x) { return x; }

View File

@ -36,36 +36,85 @@ class Bytes: AllStatic {
#endif // AMD64
public:
// Returns true if the byte ordering used by Java is different from the native byte ordering
// of the underlying machine. For example, this is true for Intel x86, but false for Solaris
// on Sparc.
static inline bool is_Java_byte_ordering_different(){ return true; }
// Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering
// (no special code is needed since x86 CPUs can access unaligned data)
static inline u2 get_native_u2(address p) { return *(u2*)p; }
static inline u4 get_native_u4(address p) { return *(u4*)p; }
static inline u8 get_native_u8(address p) { return *(u8*)p; }
template <typename T>
static inline T get_native(const void* p) {
assert(p != NULL, "null pointer");
static inline void put_native_u2(address p, u2 x) { *(u2*)p = x; }
static inline void put_native_u4(address p, u4 x) { *(u4*)p = x; }
static inline void put_native_u8(address p, u8 x) { *(u8*)p = x; }
T x;
if (is_ptr_aligned(p, sizeof(T))) {
x = *(T*)p;
} else {
memcpy(&x, p, sizeof(T));
}
return x;
}
template <typename T>
static inline void put_native(void* p, T x) {
assert(p != NULL, "null pointer");
if (is_ptr_aligned(p, sizeof(T))) {
*(T*)p = x;
} else {
memcpy(p, &x, sizeof(T));
}
}
static inline u2 get_native_u2(address p) { return get_native<u2>((void*)p); }
static inline u4 get_native_u4(address p) { return get_native<u4>((void*)p); }
static inline u8 get_native_u8(address p) { return get_native<u8>((void*)p); }
static inline void put_native_u2(address p, u2 x) { put_native<u2>((void*)p, x); }
static inline void put_native_u4(address p, u4 x) { put_native<u4>((void*)p, x); }
static inline void put_native_u8(address p, u8 x) { put_native<u8>((void*)p, x); }
// Efficient reading and writing of unaligned unsigned data in Java
// byte ordering (i.e. big-endian ordering). Byte-order reversal is
// needed since x86 CPUs use little-endian format.
static inline u2 get_Java_u2(address p) { return swap_u2(get_native_u2(p)); }
static inline u4 get_Java_u4(address p) { return swap_u4(get_native_u4(p)); }
static inline u8 get_Java_u8(address p) { return swap_u8(get_native_u8(p)); }
template <typename T>
static inline T get_Java(const address p) {
T x = get_native<T>(p);
static inline void put_Java_u2(address p, u2 x) { put_native_u2(p, swap_u2(x)); }
static inline void put_Java_u4(address p, u4 x) { put_native_u4(p, swap_u4(x)); }
static inline void put_Java_u8(address p, u8 x) { put_native_u8(p, swap_u8(x)); }
if (Endian::is_Java_byte_ordering_different()) {
x = swap<T>(x);
}
return x;
}
template <typename T>
static inline void put_Java(address p, T x) {
if (Endian::is_Java_byte_ordering_different()) {
x = swap<T>(x);
}
put_native<T>(p, x);
}
static inline u2 get_Java_u2(address p) { return get_Java<u2>(p); }
static inline u4 get_Java_u4(address p) { return get_Java<u4>(p); }
static inline u8 get_Java_u8(address p) { return get_Java<u8>(p); }
static inline void put_Java_u2(address p, u2 x) { put_Java<u2>(p, x); }
static inline void put_Java_u4(address p, u4 x) { put_Java<u4>(p, x); }
static inline void put_Java_u8(address p, u8 x) { put_Java<u8>(p, x); }
// Efficient swapping of byte ordering
template <typename T>
static T swap(T x) {
switch (sizeof(T)) {
case sizeof(u1): return x;
case sizeof(u2): return swap_u2(x);
case sizeof(u4): return swap_u4(x);
case sizeof(u8): return swap_u8(x);
default:
guarantee(false, "invalid size: " SIZE_FORMAT "\n", sizeof(T));
return 0;
}
}
static inline u2 swap_u2(u2 x); // compiler-dependent implementation
static inline u4 swap_u4(u4 x); // compiler-dependent implementation
static inline u8 swap_u8(u8 x);

View File

@ -36,16 +36,6 @@ typedef union unaligned {
class Bytes: AllStatic {
public:
// Returns true if the byte ordering used by Java is different
// from the native byte ordering of the underlying machine.
static inline bool is_Java_byte_ordering_different() {
#ifdef VM_LITTLE_ENDIAN
return true;
#else
return false;
#endif
}
// Efficient reading and writing of unaligned unsigned data in
// platform-specific byte ordering.
static inline u2 get_native_u2(address p){

View File

@ -261,7 +261,7 @@ void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const s
case JVM_CONSTANT_Utf8 : {
cfs->guarantee_more(2, CHECK); // utf8_length
u2 utf8_length = cfs->get_u2_fast();
const u1* utf8_buffer = cfs->get_u1_buffer();
const u1* utf8_buffer = cfs->current();
assert(utf8_buffer != NULL, "null utf8 buffer");
// Got utf8 string, guarantee utf8_length+1 bytes, set stream position forward.
cfs->guarantee_more(utf8_length+1, CHECK); // utf8 string, tag/access_flags
@ -1305,7 +1305,7 @@ void ClassFileParser::parse_field_attributes(const ClassFileStream* const cfs,
"Multiple RuntimeVisibleAnnotations attributes for field in class file %s", CHECK);
}
runtime_visible_annotations_length = attribute_length;
runtime_visible_annotations = cfs->get_u1_buffer();
runtime_visible_annotations = cfs->current();
assert(runtime_visible_annotations != NULL, "null visible annotations");
cfs->guarantee_more(runtime_visible_annotations_length, CHECK);
parse_annotations(cp,
@ -1323,7 +1323,7 @@ void ClassFileParser::parse_field_attributes(const ClassFileStream* const cfs,
runtime_invisible_annotations_exists = true;
if (PreserveAllAnnotations) {
runtime_invisible_annotations_length = attribute_length;
runtime_invisible_annotations = cfs->get_u1_buffer();
runtime_invisible_annotations = cfs->current();
assert(runtime_invisible_annotations != NULL, "null invisible annotations");
}
cfs->skip_u1(attribute_length, CHECK);
@ -1333,7 +1333,7 @@ void ClassFileParser::parse_field_attributes(const ClassFileStream* const cfs,
"Multiple RuntimeVisibleTypeAnnotations attributes for field in class file %s", CHECK);
}
runtime_visible_type_annotations_length = attribute_length;
runtime_visible_type_annotations = cfs->get_u1_buffer();
runtime_visible_type_annotations = cfs->current();
assert(runtime_visible_type_annotations != NULL, "null visible type annotations");
cfs->skip_u1(runtime_visible_type_annotations_length, CHECK);
} else if (attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) {
@ -1345,7 +1345,7 @@ void ClassFileParser::parse_field_attributes(const ClassFileStream* const cfs,
}
if (PreserveAllAnnotations) {
runtime_invisible_type_annotations_length = attribute_length;
runtime_invisible_type_annotations = cfs->get_u1_buffer();
runtime_invisible_type_annotations = cfs->current();
assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations");
}
cfs->skip_u1(attribute_length, CHECK);
@ -1699,19 +1699,13 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
}
static void copy_u2_with_conversion(u2* dest, const u2* src, int length) {
while (length-- > 0) {
*dest++ = Bytes::get_Java_u2((u1*) (src++));
}
}
const u2* ClassFileParser::parse_exception_table(const ClassFileStream* const cfs,
u4 code_length,
u4 exception_table_length,
TRAPS) {
const void* ClassFileParser::parse_exception_table(const ClassFileStream* const cfs,
u4 code_length,
u4 exception_table_length,
TRAPS) {
assert(cfs != NULL, "invariant");
const u2* const exception_table_start = cfs->get_u2_buffer();
const void* const exception_table_start = cfs->current();
assert(exception_table_start != NULL, "null exception table");
cfs->guarantee_more(8 * exception_table_length, CHECK_NULL); // start_pc,
@ -1829,13 +1823,13 @@ static void copy_lvt_element(const Classfile_LVT_Element* const src,
// Function is used to parse both attributes:
// LocalVariableTable (LVT) and LocalVariableTypeTable (LVTT)
const u2* ClassFileParser::parse_localvariable_table(const ClassFileStream* cfs,
u4 code_length,
u2 max_locals,
u4 code_attribute_length,
u2* const localvariable_table_length,
bool isLVTT,
TRAPS) {
const void* ClassFileParser::parse_localvariable_table(const ClassFileStream* cfs,
u4 code_length,
u2 max_locals,
u4 code_attribute_length,
u2* const localvariable_table_length,
bool isLVTT,
TRAPS) {
const char* const tbl_name = (isLVTT) ? "LocalVariableTypeTable" : "LocalVariableTable";
*localvariable_table_length = cfs->get_u2(CHECK_NULL);
const unsigned int size =
@ -1849,7 +1843,7 @@ const u2* ClassFileParser::parse_localvariable_table(const ClassFileStream* cfs,
"%s has wrong length in class file %s", tbl_name, CHECK_NULL);
}
const u2* const localvariable_table_start = cfs->get_u2_buffer();
const void* const localvariable_table_start = cfs->current();
assert(localvariable_table_start != NULL, "null local variable table");
if (!_need_verify) {
cfs->skip_u2_fast(size);
@ -1953,7 +1947,7 @@ static const u1* parse_stackmap_table(const ClassFileStream* const cfs,
return NULL;
}
const u1* const stackmap_table_start = cfs->get_u1_buffer();
const u1* const stackmap_table_start = cfs->current();
assert(stackmap_table_start != NULL, "null stackmap table");
// check code_attribute_length first
@ -1965,10 +1959,10 @@ static const u1* parse_stackmap_table(const ClassFileStream* const cfs,
return stackmap_table_start;
}
const u2* ClassFileParser::parse_checked_exceptions(const ClassFileStream* const cfs,
u2* const checked_exceptions_length,
u4 method_attribute_length,
TRAPS) {
const void* ClassFileParser::parse_checked_exceptions(const ClassFileStream* const cfs,
u2* const checked_exceptions_length,
u4 method_attribute_length,
TRAPS) {
assert(cfs != NULL, "invariant");
assert(checked_exceptions_length != NULL, "invariant");
@ -1976,7 +1970,7 @@ const u2* ClassFileParser::parse_checked_exceptions(const ClassFileStream* const
*checked_exceptions_length = cfs->get_u2_fast();
const unsigned int size =
(*checked_exceptions_length) * sizeof(CheckedExceptionElement) / sizeof(u2);
const u2* const checked_exceptions_start = cfs->get_u2_buffer();
const void* const checked_exceptions_start = cfs->current();
assert(checked_exceptions_start != NULL, "null checked exceptions");
if (!_need_verify) {
cfs->skip_u2_fast(size);
@ -2143,10 +2137,10 @@ void ClassFileParser::ClassAnnotationCollector::apply_to(InstanceKlass* ik) {
void ClassFileParser::copy_localvariable_table(const ConstMethod* cm,
int lvt_cnt,
u2* const localvariable_table_length,
const u2**const localvariable_table_start,
const void** const localvariable_table_start,
int lvtt_cnt,
u2* const localvariable_type_table_length,
const u2**const localvariable_type_table_start,
const void** const localvariable_type_table_start,
TRAPS) {
ResourceMark rm(THREAD);
@ -2341,10 +2335,10 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
u4 code_length = 0;
const u1* code_start = 0;
u2 exception_table_length = 0;
const u2* exception_table_start = NULL;
const void* exception_table_start = NULL; // (potentially unaligned) pointer to array of u2 elements
Array<int>* exception_handlers = Universe::the_empty_int_array();
u2 checked_exceptions_length = 0;
const u2* checked_exceptions_start = NULL;
const void* checked_exceptions_start = NULL; // (potentially unaligned) pointer to array of u2 elements
CompressedLineNumberWriteStream* linenumber_table = NULL;
int linenumber_table_length = 0;
int total_lvt_length = 0;
@ -2354,9 +2348,9 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
u2 max_lvt_cnt = INITIAL_MAX_LVT_NUMBER;
u2 max_lvtt_cnt = INITIAL_MAX_LVT_NUMBER;
u2* localvariable_table_length = NULL;
const u2** localvariable_table_start = NULL;
const void** localvariable_table_start = NULL; // (potentially unaligned) pointer to array of LVT attributes
u2* localvariable_type_table_length = NULL;
const u2** localvariable_type_table_start = NULL;
const void** localvariable_type_table_start = NULL; // (potentially unaligned) pointer to LVTT attributes
int method_parameters_length = -1;
const u1* method_parameters_data = NULL;
bool method_parameters_seen = false;
@ -2433,7 +2427,7 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
code_length, CHECK_NULL);
}
// Code pointer
code_start = cfs->get_u1_buffer();
code_start = cfs->current();
assert(code_start != NULL, "null code start");
cfs->guarantee_more(code_length, CHECK_NULL);
cfs->skip_u1_fast(code_length);
@ -2497,17 +2491,17 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2, INITIAL_MAX_LVT_NUMBER);
localvariable_table_start = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, const u2*, INITIAL_MAX_LVT_NUMBER);
THREAD, const void*, INITIAL_MAX_LVT_NUMBER);
localvariable_type_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2, INITIAL_MAX_LVT_NUMBER);
localvariable_type_table_start = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, const u2*, INITIAL_MAX_LVT_NUMBER);
THREAD, const void*, INITIAL_MAX_LVT_NUMBER);
lvt_allocated = true;
}
if (lvt_cnt == max_lvt_cnt) {
max_lvt_cnt <<= 1;
localvariable_table_length = REALLOC_RESOURCE_ARRAY(u2, localvariable_table_length, lvt_cnt, max_lvt_cnt);
localvariable_table_start = REALLOC_RESOURCE_ARRAY(const u2*, localvariable_table_start, lvt_cnt, max_lvt_cnt);
localvariable_table_start = REALLOC_RESOURCE_ARRAY(const void*, localvariable_table_start, lvt_cnt, max_lvt_cnt);
}
localvariable_table_start[lvt_cnt] =
parse_localvariable_table(cfs,
@ -2526,18 +2520,18 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2, INITIAL_MAX_LVT_NUMBER);
localvariable_table_start = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, const u2*, INITIAL_MAX_LVT_NUMBER);
THREAD, const void*, INITIAL_MAX_LVT_NUMBER);
localvariable_type_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2, INITIAL_MAX_LVT_NUMBER);
localvariable_type_table_start = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, const u2*, INITIAL_MAX_LVT_NUMBER);
THREAD, const void*, INITIAL_MAX_LVT_NUMBER);
lvt_allocated = true;
}
// Parse local variable type table
if (lvtt_cnt == max_lvtt_cnt) {
max_lvtt_cnt <<= 1;
localvariable_type_table_length = REALLOC_RESOURCE_ARRAY(u2, localvariable_type_table_length, lvtt_cnt, max_lvtt_cnt);
localvariable_type_table_start = REALLOC_RESOURCE_ARRAY(const u2*, localvariable_type_table_start, lvtt_cnt, max_lvtt_cnt);
localvariable_type_table_start = REALLOC_RESOURCE_ARRAY(const void*, localvariable_type_table_start, lvtt_cnt, max_lvtt_cnt);
}
localvariable_type_table_start[lvtt_cnt] =
parse_localvariable_table(cfs,
@ -2594,7 +2588,7 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
"Invalid MethodParameters method attribute length %u in class file",
method_attribute_length, CHECK_NULL);
}
method_parameters_data = cfs->get_u1_buffer();
method_parameters_data = cfs->current();
cfs->skip_u2_fast(method_parameters_length);
cfs->skip_u2_fast(method_parameters_length);
// ignore this attribute if it cannot be reflected
@ -2634,7 +2628,7 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
CHECK_NULL);
}
runtime_visible_annotations_length = method_attribute_length;
runtime_visible_annotations = cfs->get_u1_buffer();
runtime_visible_annotations = cfs->current();
assert(runtime_visible_annotations != NULL, "null visible annotations");
cfs->guarantee_more(runtime_visible_annotations_length, CHECK_NULL);
parse_annotations(cp,
@ -2653,7 +2647,7 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
runtime_invisible_annotations_exists = true;
if (PreserveAllAnnotations) {
runtime_invisible_annotations_length = method_attribute_length;
runtime_invisible_annotations = cfs->get_u1_buffer();
runtime_invisible_annotations = cfs->current();
assert(runtime_invisible_annotations != NULL, "null invisible annotations");
}
cfs->skip_u1(method_attribute_length, CHECK_NULL);
@ -2664,7 +2658,7 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
CHECK_NULL);
}
runtime_visible_parameter_annotations_length = method_attribute_length;
runtime_visible_parameter_annotations = cfs->get_u1_buffer();
runtime_visible_parameter_annotations = cfs->current();
assert(runtime_visible_parameter_annotations != NULL, "null visible parameter annotations");
cfs->skip_u1(runtime_visible_parameter_annotations_length, CHECK_NULL);
} else if (method_attribute_name == vmSymbols::tag_runtime_invisible_parameter_annotations()) {
@ -2676,7 +2670,7 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
runtime_invisible_parameter_annotations_exists = true;
if (PreserveAllAnnotations) {
runtime_invisible_parameter_annotations_length = method_attribute_length;
runtime_invisible_parameter_annotations = cfs->get_u1_buffer();
runtime_invisible_parameter_annotations = cfs->current();
assert(runtime_invisible_parameter_annotations != NULL,
"null invisible parameter annotations");
}
@ -2688,7 +2682,7 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
CHECK_NULL);
}
annotation_default_length = method_attribute_length;
annotation_default = cfs->get_u1_buffer();
annotation_default = cfs->current();
assert(annotation_default != NULL, "null annotation default");
cfs->skip_u1(annotation_default_length, CHECK_NULL);
} else if (method_attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) {
@ -2698,7 +2692,7 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
CHECK_NULL);
}
runtime_visible_type_annotations_length = method_attribute_length;
runtime_visible_type_annotations = cfs->get_u1_buffer();
runtime_visible_type_annotations = cfs->current();
assert(runtime_visible_type_annotations != NULL, "null visible type annotations");
// No need for the VM to parse Type annotations
cfs->skip_u1(runtime_visible_type_annotations_length, CHECK_NULL);
@ -2712,7 +2706,7 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
}
if (PreserveAllAnnotations) {
runtime_invisible_type_annotations_length = method_attribute_length;
runtime_invisible_type_annotations = cfs->get_u1_buffer();
runtime_invisible_type_annotations = cfs->current();
assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations");
}
cfs->skip_u1(method_attribute_length, CHECK_NULL);
@ -2808,10 +2802,10 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
// 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::conjoint_swap_if_needed<Endian::JAVA>(exception_table_start,
m->exception_table_start(),
exception_table_length * sizeof(ExceptionTableElement),
sizeof(u2));
}
// Copy method parameters
@ -2827,11 +2821,10 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
// Copy checked exceptions
if (checked_exceptions_length > 0) {
const int size =
checked_exceptions_length * sizeof(CheckedExceptionElement) / sizeof(u2);
copy_u2_with_conversion((u2*) m->checked_exceptions_start(),
checked_exceptions_start,
size);
Copy::conjoint_swap_if_needed<Endian::JAVA>(checked_exceptions_start,
m->checked_exceptions_start(),
checked_exceptions_length * sizeof(CheckedExceptionElement),
sizeof(u2));
}
// Copy class file LVT's/LVTT's into the HotSpot internal LVT.
@ -3030,7 +3023,7 @@ void ClassFileParser::parse_classfile_source_debug_extension_attribute(const Cla
TRAPS) {
assert(cfs != NULL, "invariant");
const u1* const sde_buffer = cfs->get_u1_buffer();
const u1* const sde_buffer = cfs->current();
assert(sde_buffer != NULL, "null sde buffer");
// Don't bother storing it if there is no way to retrieve it
@ -3322,7 +3315,7 @@ void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cf
} else {
parsed_innerclasses_attribute = true;
}
inner_classes_attribute_start = cfs->get_u1_buffer();
inner_classes_attribute_start = cfs->current();
inner_classes_attribute_length = attribute_length;
cfs->skip_u1(inner_classes_attribute_length, CHECK);
} else if (tag == vmSymbols::tag_synthetic()) {
@ -3359,7 +3352,7 @@ void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cf
"Multiple RuntimeVisibleAnnotations attributes in class file %s", CHECK);
}
runtime_visible_annotations_length = attribute_length;
runtime_visible_annotations = cfs->get_u1_buffer();
runtime_visible_annotations = cfs->current();
assert(runtime_visible_annotations != NULL, "null visible annotations");
cfs->guarantee_more(runtime_visible_annotations_length, CHECK);
parse_annotations(cp,
@ -3377,7 +3370,7 @@ void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cf
runtime_invisible_annotations_exists = true;
if (PreserveAllAnnotations) {
runtime_invisible_annotations_length = attribute_length;
runtime_invisible_annotations = cfs->get_u1_buffer();
runtime_invisible_annotations = cfs->current();
assert(runtime_invisible_annotations != NULL, "null invisible annotations");
}
cfs->skip_u1(attribute_length, CHECK);
@ -3417,7 +3410,7 @@ void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cf
"Multiple RuntimeVisibleTypeAnnotations attributes in class file %s", CHECK);
}
runtime_visible_type_annotations_length = attribute_length;
runtime_visible_type_annotations = cfs->get_u1_buffer();
runtime_visible_type_annotations = cfs->current();
assert(runtime_visible_type_annotations != NULL, "null visible type annotations");
// No need for the VM to parse Type annotations
cfs->skip_u1(runtime_visible_type_annotations_length, CHECK);
@ -3430,7 +3423,7 @@ void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cf
}
if (PreserveAllAnnotations) {
runtime_invisible_type_annotations_length = attribute_length;
runtime_invisible_type_annotations = cfs->get_u1_buffer();
runtime_invisible_type_annotations = cfs->current();
assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations");
}
cfs->skip_u1(attribute_length, CHECK);

View File

@ -242,28 +242,28 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
bool* const declares_nonstatic_concrete_methods,
TRAPS);
const u2* parse_exception_table(const ClassFileStream* const stream,
u4 code_length,
u4 exception_table_length,
TRAPS);
const void* parse_exception_table(const ClassFileStream* const stream,
u4 code_length,
u4 exception_table_length,
TRAPS);
void parse_linenumber_table(u4 code_attribute_length,
u4 code_length,
CompressedLineNumberWriteStream**const write_stream,
TRAPS);
const u2* parse_localvariable_table(const ClassFileStream* const cfs,
u4 code_length,
u2 max_locals,
u4 code_attribute_length,
u2* const localvariable_table_length,
bool isLVTT,
TRAPS);
const void* parse_localvariable_table(const ClassFileStream* const cfs,
u4 code_length,
u2 max_locals,
u4 code_attribute_length,
u2* const localvariable_table_length,
bool isLVTT,
TRAPS);
const u2* parse_checked_exceptions(const ClassFileStream* const cfs,
u2* const checked_exceptions_length,
u4 method_attribute_length,
TRAPS);
const void* parse_checked_exceptions(const ClassFileStream* const cfs,
u2* const checked_exceptions_length,
u4 method_attribute_length,
TRAPS);
void parse_type_array(u2 array_length,
u4 code_length,
@ -462,10 +462,10 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
void copy_localvariable_table(const ConstMethod* cm,
int lvt_cnt,
u2* const localvariable_table_length,
const u2**const localvariable_table_start,
const void** const localvariable_table_start,
int lvtt_cnt,
u2* const localvariable_type_table_length,
const u2** const localvariable_type_table_start,
const void** const localvariable_type_table_start,
TRAPS);
void copy_method_annotations(ConstMethod* cm,

View File

@ -121,17 +121,6 @@ class ClassFileStream: public ResourceObj {
return res;
}
// Get direct pointer into stream at current position.
// Returns NULL if length elements are not remaining. The caller is
// responsible for calling skip below if buffer contents is used.
const u1* get_u1_buffer() const {
return _current;
}
const u2* get_u2_buffer() const {
return (const u2*) _current;
}
// Skip length u1 or u2 elements from stream
void skip_u1(int length, TRAPS) const;
void skip_u1_fast(int length) const {

View File

@ -249,7 +249,7 @@ class AbstractInterpreter: AllStatic {
return (oop*) slot_addr;
}
static jint* int_addr_in_slot(intptr_t* slot_addr) {
if ((int) sizeof(jint) < wordSize && !Bytes::is_Java_byte_ordering_different())
if ((int) sizeof(jint) < wordSize && !Endian::is_Java_byte_ordering_different())
// big-endian LP64
return (jint*)(slot_addr + 1) - 1;
else

View File

@ -122,7 +122,7 @@ class Bytecode: public StackObj {
static void assert_constant_size(int required_size, int where, Bytecodes::Code bc, bool is_wide = false) NOT_DEBUG_RETURN;
static void assert_native_index(Bytecodes::Code bc, bool is_wide = false) NOT_DEBUG_RETURN;
static bool can_use_native_byte_order(Bytecodes::Code bc, bool is_wide = false) {
return (!Bytes::is_Java_byte_ordering_different() || Bytecodes::native_byte_order(bc /*, is_wide*/));
return (!Endian::is_Java_byte_ordering_different() || Bytecodes::native_byte_order(bc /*, is_wide*/));
}
};

View File

@ -1134,7 +1134,7 @@ void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) {
switch (type) {
case T_INT : {
if (Bytes::is_Java_byte_ordering_different()) {
if (Endian::is_Java_byte_ordering_different()) {
WRITE_ARRAY(array, int, u4, length);
} else {
writer->write_raw((void*)(array->int_at_addr(0)), length_in_bytes);
@ -1146,7 +1146,7 @@ void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) {
break;
}
case T_CHAR : {
if (Bytes::is_Java_byte_ordering_different()) {
if (Endian::is_Java_byte_ordering_different()) {
WRITE_ARRAY(array, char, u2, length);
} else {
writer->write_raw((void*)(array->char_at_addr(0)), length_in_bytes);
@ -1154,7 +1154,7 @@ void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) {
break;
}
case T_SHORT : {
if (Bytes::is_Java_byte_ordering_different()) {
if (Endian::is_Java_byte_ordering_different()) {
WRITE_ARRAY(array, short, u2, length);
} else {
writer->write_raw((void*)(array->short_at_addr(0)), length_in_bytes);
@ -1162,7 +1162,7 @@ void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) {
break;
}
case T_BOOLEAN : {
if (Bytes::is_Java_byte_ordering_different()) {
if (Endian::is_Java_byte_ordering_different()) {
WRITE_ARRAY(array, bool, u1, length);
} else {
writer->write_raw((void*)(array->bool_at_addr(0)), length_in_bytes);
@ -1170,7 +1170,7 @@ void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) {
break;
}
case T_LONG : {
if (Bytes::is_Java_byte_ordering_different()) {
if (Endian::is_Java_byte_ordering_different()) {
WRITE_ARRAY(array, long, u8, length);
} else {
writer->write_raw((void*)(array->long_at_addr(0)), length_in_bytes);

View File

@ -27,6 +27,27 @@
#include "utilities/macros.hpp"
class Endian : AllStatic {
public:
enum Order {
LITTLE,
BIG,
JAVA = BIG,
NATIVE =
#ifdef VM_LITTLE_ENDIAN
LITTLE
#else
BIG
#endif
};
// Returns true, if the byte ordering used by Java is different from
// the native byte ordering of the underlying machine.
static inline bool is_Java_byte_ordering_different() {
return NATIVE != JAVA;
}
};
#include CPU_HEADER(bytes)
#endif // SHARE_VM_UTILITIES_BYTES_HPP

View File

@ -56,14 +56,17 @@ void Copy::conjoint_memory_atomic(void* from, void* to, size_t size) {
class CopySwap : AllStatic {
public:
/**
* Copy and byte swap elements
* Copy and optionally byte swap elements
*
* <swap> - true if elements should be byte swapped
*
* @param src address of source
* @param dst address of destination
* @param byte_count number of bytes to copy
* @param elem_size size of the elements to copy-swap
*/
static void conjoint_swap(address src, address dst, size_t byte_count, size_t elem_size) {
template<bool swap>
static void conjoint_swap_if_needed(const void* src, void* dst, size_t byte_count, size_t elem_size) {
assert(src != NULL, "address must not be NULL");
assert(dst != NULL, "address must not be NULL");
assert(elem_size == 2 || elem_size == 4 || elem_size == 8,
@ -71,12 +74,12 @@ public:
assert(is_size_aligned(byte_count, elem_size),
"byte_count " SIZE_FORMAT " must be multiple of element size " SIZE_FORMAT, byte_count, elem_size);
address src_end = src + byte_count;
address src_end = (address)src + byte_count;
if (dst <= src || dst >= src_end) {
do_conjoint_swap<RIGHT>(src, dst, byte_count, elem_size);
do_conjoint_swap<RIGHT,swap>(src, dst, byte_count, elem_size);
} else {
do_conjoint_swap<LEFT>(src, dst, byte_count, elem_size);
do_conjoint_swap<LEFT,swap>(src, dst, byte_count, elem_size);
}
}
@ -125,18 +128,19 @@ private:
* @param dst address of destination
* @param byte_count number of bytes to copy
*/
template <typename T, CopyDirection D, bool is_src_aligned, bool is_dst_aligned>
static void do_conjoint_swap(address src, address dst, size_t byte_count) {
address cur_src, cur_dst;
template <typename T, CopyDirection D, bool swap, bool is_src_aligned, bool is_dst_aligned>
static void do_conjoint_swap(const void* src, void* dst, size_t byte_count) {
const char* cur_src;
char* cur_dst;
switch (D) {
case RIGHT:
cur_src = src;
cur_dst = dst;
cur_src = (const char*)src;
cur_dst = (char*)dst;
break;
case LEFT:
cur_src = src + byte_count - sizeof(T);
cur_dst = dst + byte_count - sizeof(T);
cur_src = (const char*)src + byte_count - sizeof(T);
cur_dst = (char*)dst + byte_count - sizeof(T);
break;
}
@ -149,7 +153,9 @@ private:
memcpy(&tmp, cur_src, sizeof(T));
}
tmp = byte_swap(tmp);
if (swap) {
tmp = byte_swap(tmp);
}
if (is_dst_aligned) {
*(T*)cur_dst = tmp;
@ -173,26 +179,27 @@ private:
/**
* Copy and byte swap elements
*
* <T> - type of element to copy
* <D> - copy direction
* <T> - type of element to copy
* <D> - copy direction
* <swap> - true if elements should be byte swapped
*
* @param src address of source
* @param dst address of destination
* @param byte_count number of bytes to copy
*/
template <typename T, CopyDirection direction>
static void do_conjoint_swap(address src, address dst, size_t byte_count) {
template <typename T, CopyDirection direction, bool swap>
static void do_conjoint_swap(const void* src, void* dst, size_t byte_count) {
if (is_ptr_aligned(src, sizeof(T))) {
if (is_ptr_aligned(dst, sizeof(T))) {
do_conjoint_swap<T,direction,true,true>(src, dst, byte_count);
do_conjoint_swap<T,direction,swap,true,true>(src, dst, byte_count);
} else {
do_conjoint_swap<T,direction,true,false>(src, dst, byte_count);
do_conjoint_swap<T,direction,swap,true,false>(src, dst, byte_count);
}
} else {
if (is_ptr_aligned(dst, sizeof(T))) {
do_conjoint_swap<T,direction,false,true>(src, dst, byte_count);
do_conjoint_swap<T,direction,swap,false,true>(src, dst, byte_count);
} else {
do_conjoint_swap<T,direction,false,false>(src, dst, byte_count);
do_conjoint_swap<T,direction,swap,false,false>(src, dst, byte_count);
}
}
}
@ -201,26 +208,31 @@ private:
/**
* Copy and byte swap elements
*
* <D> - copy direction
* <D> - copy direction
* <swap> - true if elements should be byte swapped
*
* @param src address of source
* @param dst address of destination
* @param byte_count number of bytes to copy
* @param elem_size size of the elements to copy-swap
*/
template <CopyDirection D>
static void do_conjoint_swap(address src, address dst, size_t byte_count, size_t elem_size) {
template <CopyDirection D, bool swap>
static void do_conjoint_swap(const void* src, void* dst, size_t byte_count, size_t elem_size) {
switch (elem_size) {
case 2: do_conjoint_swap<uint16_t,D>(src, dst, byte_count); break;
case 4: do_conjoint_swap<uint32_t,D>(src, dst, byte_count); break;
case 8: do_conjoint_swap<uint64_t,D>(src, dst, byte_count); break;
case 2: do_conjoint_swap<uint16_t,D,swap>(src, dst, byte_count); break;
case 4: do_conjoint_swap<uint32_t,D,swap>(src, dst, byte_count); break;
case 8: do_conjoint_swap<uint64_t,D,swap>(src, dst, byte_count); break;
default: guarantee(false, "do_conjoint_swap: Invalid elem_size " SIZE_FORMAT "\n", elem_size);
}
}
};
void Copy::conjoint_swap(address src, address dst, size_t byte_count, size_t elem_size) {
CopySwap::conjoint_swap(src, dst, byte_count, elem_size);
void Copy::conjoint_copy(const void* src, void* dst, size_t byte_count, size_t elem_size) {
CopySwap::conjoint_swap_if_needed<false>(src, dst, byte_count, elem_size);
}
void Copy::conjoint_swap(const void* src, void* dst, size_t byte_count, size_t elem_size) {
CopySwap::conjoint_swap_if_needed<true>(src, dst, byte_count, elem_size);
}
// Fill bytes; larger units are filled atomically if everything is aligned.

View File

@ -228,6 +228,16 @@ class Copy : AllStatic {
}
}
/**
* Copy elements
*
* @param src address of source
* @param dst address of destination
* @param byte_count number of bytes to copy
* @param elem_size size of the elements to copy-swap
*/
static void conjoint_copy(const void* src, void* dst, size_t byte_count, size_t elem_size);
/**
* Copy and *unconditionally* byte swap elements
*
@ -236,7 +246,24 @@ class Copy : AllStatic {
* @param byte_count number of bytes to copy
* @param elem_size size of the elements to copy-swap
*/
static void conjoint_swap(address src, address dst, size_t byte_count, size_t elem_size);
static void conjoint_swap(const void* src, void* dst, size_t byte_count, size_t elem_size);
/**
* Copy and byte swap elements from the specified endian to the native (cpu) endian if needed (if they differ)
*
* @param src address of source
* @param dst address of destination
* @param byte_count number of bytes to copy
* @param elem_size size of the elements to copy-swap
*/
template <Endian::Order endian>
static void conjoint_swap_if_needed(const void* src, void* dst, size_t byte_count, size_t elem_size) {
if (Endian::NATIVE != endian) {
conjoint_swap(src, dst, byte_count, elem_size);
} else {
conjoint_copy(src, dst, byte_count, elem_size);
}
}
// Fill methods

View File

@ -487,7 +487,7 @@ inline bool is_size_aligned(size_t size, size_t alignment) {
return align_size_up_(size, alignment) == size;
}
inline bool is_ptr_aligned(void* ptr, size_t alignment) {
inline bool is_ptr_aligned(const void* ptr, size_t alignment) {
return align_size_up_((intptr_t)ptr, (intptr_t)alignment) == (intptr_t)ptr;
}