--- old/src/cpu/aarch64/vm/bytes_aarch64.hpp 2017-04-11 14:39:56.149874392 -0700 +++ new/src/cpu/aarch64/vm/bytes_aarch64.hpp 2017-04-11 14:39:56.001871711 -0700 @@ -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; } --- old/src/cpu/arm/vm/bytes_arm.hpp 2017-04-11 14:39:56.961889099 -0700 +++ new/src/cpu/arm/vm/bytes_arm.hpp 2017-04-11 14:39:56.813886419 -0700 @@ -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]); } --- old/src/cpu/ppc/vm/bytes_ppc.hpp 2017-04-11 14:39:57.713902719 -0700 +++ new/src/cpu/ppc/vm/bytes_ppc.hpp 2017-04-11 14:39:57.589900473 -0700 @@ -37,10 +37,6 @@ #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 @@ #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; } --- old/src/cpu/s390/vm/bytes_s390.hpp 2017-04-11 14:39:58.505917063 -0700 +++ new/src/cpu/s390/vm/bytes_s390.hpp 2017-04-11 14:39:58.377914745 -0700 @@ -42,12 +42,6 @@ // // 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; } --- old/src/cpu/sparc/vm/bytes_sparc.hpp 2017-04-11 14:39:59.313931698 -0700 +++ new/src/cpu/sparc/vm/bytes_sparc.hpp 2017-04-11 14:39:59.149928727 -0700 @@ -34,10 +34,6 @@ // 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; } --- old/src/cpu/x86/vm/bytes_x86.hpp 2017-04-11 14:40:00.073945462 -0700 +++ new/src/cpu/x86/vm/bytes_x86.hpp 2017-04-11 14:39:59.913942565 -0700 @@ -36,36 +36,85 @@ #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; } - - 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; } - + template + static inline T get_native(const void* p) { + assert(p != NULL, "null pointer"); + + T x; + + if (is_ptr_aligned(p, sizeof(T))) { + x = *(T*)p; + } else { + memcpy(&x, p, sizeof(T)); + } + + return x; + } + + template + 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((void*)p); } + static inline u4 get_native_u4(address p) { return get_native((void*)p); } + static inline u8 get_native_u8(address p) { return get_native((void*)p); } + static inline void put_native_u2(address p, u2 x) { put_native((void*)p, x); } + static inline void put_native_u4(address p, u4 x) { put_native((void*)p, x); } + static inline void put_native_u8(address p, u8 x) { put_native((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)); } - - 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)); } - + template + static inline T get_Java(const address p) { + T x = get_native(p); + + if (Endian::is_Java_byte_ordering_different()) { + x = swap(x); + } + + return x; + } + + template + static inline void put_Java(address p, T x) { + if (Endian::is_Java_byte_ordering_different()) { + x = swap(x); + } + + put_native(p, x); + } + + static inline u2 get_Java_u2(address p) { return get_Java(p); } + static inline u4 get_Java_u4(address p) { return get_Java(p); } + static inline u8 get_Java_u8(address p) { return get_Java(p); } + + static inline void put_Java_u2(address p, u2 x) { put_Java(p, x); } + static inline void put_Java_u4(address p, u4 x) { put_Java(p, x); } + static inline void put_Java_u8(address p, u8 x) { put_Java(p, x); } // Efficient swapping of byte ordering + template + 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); --- old/src/cpu/zero/vm/bytes_zero.hpp 2017-04-11 14:40:00.881960097 -0700 +++ new/src/cpu/zero/vm/bytes_zero.hpp 2017-04-11 14:40:00.717957126 -0700 @@ -36,16 +36,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() { -#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){ --- old/src/share/vm/classfile/classFileParser.cpp 2017-04-11 14:40:01.717975238 -0700 +++ new/src/share/vm/classfile/classFileParser.cpp 2017-04-11 14:40:01.553972268 -0700 @@ -1674,19 +1674,13 @@ } -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, +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->get_u1_buffer(); assert(exception_table_start != NULL, "null exception table"); cfs->guarantee_more(8 * exception_table_length, CHECK_NULL); // start_pc, @@ -1804,13 +1798,13 @@ // 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 = @@ -1824,7 +1818,7 @@ "%s has wrong length in class file %s", tbl_name, CHECK_NULL); } - const u2* const localvariable_table_start = cfs->get_u2_buffer(); + const u1* const localvariable_table_start = cfs->get_u1_buffer(); assert(localvariable_table_start != NULL, "null local variable table"); if (!_need_verify) { cfs->skip_u2_fast(size); @@ -1940,10 +1934,10 @@ 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"); @@ -1951,7 +1945,7 @@ *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->get_u1_buffer(); assert(checked_exceptions_start != NULL, "null checked exceptions"); if (!_need_verify) { cfs->skip_u2_fast(size); @@ -2118,10 +2112,10 @@ 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); @@ -2316,10 +2310,10 @@ 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* 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; @@ -2329,9 +2323,9 @@ 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; @@ -2472,17 +2466,17 @@ 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, @@ -2501,18 +2495,18 @@ 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, @@ -2783,10 +2777,10 @@ // 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_maybe(exception_table_start, + m->exception_table_start(), + exception_table_length * sizeof(ExceptionTableElement), + sizeof(u2)); } // Copy method parameters @@ -2802,11 +2796,10 @@ // 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_maybe(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. --- old/src/share/vm/classfile/classFileParser.hpp 2017-04-11 14:40:02.685992770 -0700 +++ new/src/share/vm/classfile/classFileParser.hpp 2017-04-11 14:40:02.529989945 -0700 @@ -238,28 +238,28 @@ 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 u2* parse_checked_exceptions(const ClassFileStream* const cfs, - u2* const checked_exceptions_length, - u4 method_attribute_length, - 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 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, @@ -453,10 +453,10 @@ 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, --- old/src/share/vm/classfile/classFileStream.hpp 2017-04-11 14:40:03.466006897 -0700 +++ new/src/share/vm/classfile/classFileStream.hpp 2017-04-11 14:40:03.314004145 -0700 @@ -128,10 +128,6 @@ 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 { --- old/src/share/vm/interpreter/abstractInterpreter.hpp 2017-04-11 14:40:04.294021894 -0700 +++ new/src/share/vm/interpreter/abstractInterpreter.hpp 2017-04-11 14:40:04.150019286 -0700 @@ -249,7 +249,7 @@ 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 --- old/src/share/vm/interpreter/bytecode.hpp 2017-04-11 14:40:05.122036890 -0700 +++ new/src/share/vm/interpreter/bytecode.hpp 2017-04-11 14:40:04.978034283 -0700 @@ -122,7 +122,7 @@ 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*/)); } }; --- old/src/share/vm/services/heapDumper.cpp 2017-04-11 14:40:05.866050366 -0700 +++ new/src/share/vm/services/heapDumper.cpp 2017-04-11 14:40:05.718047685 -0700 @@ -1134,7 +1134,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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); --- old/src/share/vm/utilities/bytes.hpp 2017-04-11 14:40:06.726065942 -0700 +++ new/src/share/vm/utilities/bytes.hpp 2017-04-11 14:40:06.562062972 -0700 @@ -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 --- old/src/share/vm/utilities/copy.cpp 2017-04-11 14:40:07.582081445 -0700 +++ new/src/share/vm/utilities/copy.cpp 2017-04-11 14:40:07.414078403 -0700 @@ -56,14 +56,17 @@ class CopySwap : AllStatic { public: /** - * Copy and byte swap elements + * Copy and optionally byte swap elements + * + * - 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 + static void conjoint_swap_maybe(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 @@ 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(src, dst, byte_count, elem_size); + do_conjoint_swap(src, dst, byte_count, elem_size); } else { - do_conjoint_swap(src, dst, byte_count, elem_size); + do_conjoint_swap(src, dst, byte_count, elem_size); } } @@ -125,18 +128,19 @@ * @param dst address of destination * @param byte_count number of bytes to copy */ - template - static void do_conjoint_swap(address src, address dst, size_t byte_count) { - address cur_src, cur_dst; + template + 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 @@ 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 @@ /** * Copy and byte swap elements * - * - type of element to copy - * - copy direction + * - type of element to copy + * - copy direction + * - 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 - static void do_conjoint_swap(address src, address dst, size_t byte_count) { + template + 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(src, dst, byte_count); + do_conjoint_swap(src, dst, byte_count); } else { - do_conjoint_swap(src, dst, byte_count); + do_conjoint_swap(src, dst, byte_count); } } else { if (is_ptr_aligned(dst, sizeof(T))) { - do_conjoint_swap(src, dst, byte_count); + do_conjoint_swap(src, dst, byte_count); } else { - do_conjoint_swap(src, dst, byte_count); + do_conjoint_swap(src, dst, byte_count); } } } @@ -201,26 +208,31 @@ /** * Copy and byte swap elements * - * - copy direction + * - copy direction + * - 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 - static void do_conjoint_swap(address src, address dst, size_t byte_count, size_t elem_size) { + template + 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(src, dst, byte_count); break; - case 4: do_conjoint_swap(src, dst, byte_count); break; - case 8: do_conjoint_swap(src, dst, byte_count); break; + case 2: do_conjoint_swap(src, dst, byte_count); break; + case 4: do_conjoint_swap(src, dst, byte_count); break; + case 8: do_conjoint_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_maybe(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_maybe(src, dst, byte_count, elem_size); } // Fill bytes; larger units are filled atomically if everything is aligned. --- old/src/share/vm/utilities/copy.hpp 2017-04-11 14:40:08.418096587 -0700 +++ new/src/share/vm/utilities/copy.hpp 2017-04-11 14:40:08.254093617 -0700 @@ -229,6 +229,16 @@ } /** + * 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 * * @param src address of source @@ -236,7 +246,24 @@ * @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 + static void conjoint_swap_maybe(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 --- old/src/share/vm/utilities/globalDefinitions.hpp 2017-04-11 14:40:09.262111873 -0700 +++ new/src/share/vm/utilities/globalDefinitions.hpp 2017-04-11 14:40:09.094108831 -0700 @@ -487,7 +487,7 @@ 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; }