mirror of
https://github.com/openjdk/jdk.git
synced 2026-06-05 10:12:35 +00:00
8180032: Unaligned pointer dereference in ClassFileParser
Reviewed-by: dholmes, hseigel
This commit is contained in:
parent
85abe8f6e6
commit
f1f868513d
@ -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; }
|
||||
|
||||
@ -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]);
|
||||
}
|
||||
|
||||
@ -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; }
|
||||
|
||||
@ -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; }
|
||||
|
||||
@ -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; }
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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){
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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*/));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user