Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/utilities/copy.cpp
32285 views
/*1* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "runtime/sharedRuntime.hpp"26#include "utilities/copy.hpp"272829// Copy bytes; larger units are filled atomically if everything is aligned.30void Copy::conjoint_memory_atomic(void* from, void* to, size_t size) {31address src = (address) from;32address dst = (address) to;33uintptr_t bits = (uintptr_t) src | (uintptr_t) dst | (uintptr_t) size;3435// (Note: We could improve performance by ignoring the low bits of size,36// and putting a short cleanup loop after each bulk copy loop.37// There are plenty of other ways to make this faster also,38// and it's a slippery slope. For now, let's keep this code simple39// since the simplicity helps clarify the atomicity semantics of40// this operation. There are also CPU-specific assembly versions41// which may or may not want to include such optimizations.)4243if (bits % sizeof(jlong) == 0) {44Copy::conjoint_jlongs_atomic((jlong*) src, (jlong*) dst, size / sizeof(jlong));45} else if (bits % sizeof(jint) == 0) {46Copy::conjoint_jints_atomic((jint*) src, (jint*) dst, size / sizeof(jint));47} else if (bits % sizeof(jshort) == 0) {48Copy::conjoint_jshorts_atomic((jshort*) src, (jshort*) dst, size / sizeof(jshort));49} else {50// Not aligned, so no need to be atomic.51Copy::conjoint_jbytes((void*) src, (void*) dst, size);52}53}5455class CopySwap : AllStatic {56public:57/**58* Copy and byte swap elements59*60* @param src address of source61* @param dst address of destination62* @param byte_count number of bytes to copy63* @param elem_size size of the elements to copy-swap64*/65static void conjoint_swap(address src, address dst, size_t byte_count, size_t elem_size) {66assert(src != NULL, "address must not be NULL");67assert(dst != NULL, "address must not be NULL");68assert(elem_size == 2 || elem_size == 4 || elem_size == 8,69err_msg("incorrect element size: " SIZE_FORMAT, elem_size));70assert(is_size_aligned(byte_count, elem_size),71err_msg("byte_count " SIZE_FORMAT " must be multiple of element size " SIZE_FORMAT, byte_count, elem_size));7273address src_end = src + byte_count;7475if (dst <= src || dst >= src_end) {76do_conjoint_swap<RIGHT>(src, dst, byte_count, elem_size);77} else {78do_conjoint_swap<LEFT>(src, dst, byte_count, elem_size);79}80}8182private:83/**84* Byte swap a 16-bit value85*/86static uint16_t byte_swap(uint16_t x) {87return (x << 8) | (x >> 8);88}8990/**91* Byte swap a 32-bit value92*/93static uint32_t byte_swap(uint32_t x) {94uint16_t lo = (uint16_t)x;95uint16_t hi = (uint16_t)(x >> 16);9697return ((uint32_t)byte_swap(lo) << 16) | (uint32_t)byte_swap(hi);98}99100/**101* Byte swap a 64-bit value102*/103static uint64_t byte_swap(uint64_t x) {104uint32_t lo = (uint32_t)x;105uint32_t hi = (uint32_t)(x >> 32);106107return ((uint64_t)byte_swap(lo) << 32) | (uint64_t)byte_swap(hi);108}109110enum CopyDirection {111RIGHT, // lower -> higher address112LEFT // higher -> lower address113};114115/**116* Copy and byte swap elements117*118* <T> - type of element to copy119* <D> - copy direction120* <is_src_aligned> - true if src argument is aligned to element size121* <is_dst_aligned> - true if dst argument is aligned to element size122*123* @param src address of source124* @param dst address of destination125* @param byte_count number of bytes to copy126*/127template <typename T, CopyDirection D, bool is_src_aligned, bool is_dst_aligned>128static void do_conjoint_swap(address src, address dst, size_t byte_count) {129address cur_src, cur_dst;130131switch (D) {132case RIGHT:133cur_src = src;134cur_dst = dst;135break;136case LEFT:137cur_src = src + byte_count - sizeof(T);138cur_dst = dst + byte_count - sizeof(T);139break;140}141142for (size_t i = 0; i < byte_count / sizeof(T); i++) {143T tmp;144145if (is_src_aligned) {146tmp = *(T*)cur_src;147} else {148memcpy(&tmp, cur_src, sizeof(T));149}150151tmp = byte_swap(tmp);152153if (is_dst_aligned) {154*(T*)cur_dst = tmp;155} else {156memcpy(cur_dst, &tmp, sizeof(T));157}158159switch (D) {160case RIGHT:161cur_src += sizeof(T);162cur_dst += sizeof(T);163break;164case LEFT:165cur_src -= sizeof(T);166cur_dst -= sizeof(T);167break;168}169}170}171172/**173* Copy and byte swap elements174*175* <T> - type of element to copy176* <D> - copy direction177*178* @param src address of source179* @param dst address of destination180* @param byte_count number of bytes to copy181*/182template <typename T, CopyDirection direction>183static void do_conjoint_swap(address src, address dst, size_t byte_count) {184if (is_ptr_aligned(src, sizeof(T))) {185if (is_ptr_aligned(dst, sizeof(T))) {186do_conjoint_swap<T,direction,true,true>(src, dst, byte_count);187} else {188do_conjoint_swap<T,direction,true,false>(src, dst, byte_count);189}190} else {191if (is_ptr_aligned(dst, sizeof(T))) {192do_conjoint_swap<T,direction,false,true>(src, dst, byte_count);193} else {194do_conjoint_swap<T,direction,false,false>(src, dst, byte_count);195}196}197}198199200/**201* Copy and byte swap elements202*203* <D> - copy direction204*205* @param src address of source206* @param dst address of destination207* @param byte_count number of bytes to copy208* @param elem_size size of the elements to copy-swap209*/210template <CopyDirection D>211static void do_conjoint_swap(address src, address dst, size_t byte_count, size_t elem_size) {212switch (elem_size) {213case 2: do_conjoint_swap<uint16_t,D>(src, dst, byte_count); break;214case 4: do_conjoint_swap<uint32_t,D>(src, dst, byte_count); break;215case 8: do_conjoint_swap<uint64_t,D>(src, dst, byte_count); break;216default: guarantee(false, err_msg("do_conjoint_swap: Invalid elem_size %zd\n", elem_size));217}218}219};220221void Copy::conjoint_swap(address src, address dst, size_t byte_count, size_t elem_size) {222CopySwap::conjoint_swap(src, dst, byte_count, elem_size);223}224225// Fill bytes; larger units are filled atomically if everything is aligned.226void Copy::fill_to_memory_atomic(void* to, size_t size, jubyte value) {227address dst = (address) to;228uintptr_t bits = (uintptr_t) to | (uintptr_t) size;229if (bits % sizeof(jlong) == 0) {230jlong fill = (julong)( (jubyte)value ); // zero-extend231if (fill != 0) {232fill += fill << 8;233fill += fill << 16;234fill += fill << 32;235}236//Copy::fill_to_jlongs_atomic((jlong*) dst, size / sizeof(jlong));237for (uintptr_t off = 0; off < size; off += sizeof(jlong)) {238*(jlong*)(dst + off) = fill;239}240} else if (bits % sizeof(jint) == 0) {241jint fill = (juint)( (jubyte)value ); // zero-extend242if (fill != 0) {243fill += fill << 8;244fill += fill << 16;245}246//Copy::fill_to_jints_atomic((jint*) dst, size / sizeof(jint));247for (uintptr_t off = 0; off < size; off += sizeof(jint)) {248*(jint*)(dst + off) = fill;249}250} else if (bits % sizeof(jshort) == 0) {251jshort fill = (jushort)( (jubyte)value ); // zero-extend252fill += fill << 8;253//Copy::fill_to_jshorts_atomic((jshort*) dst, size / sizeof(jshort));254for (uintptr_t off = 0; off < size; off += sizeof(jshort)) {255*(jshort*)(dst + off) = fill;256}257} else {258// Not aligned, so no need to be atomic.259Copy::fill_to_bytes(dst, size, value);260}261}262263264