1/*
2 * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25#include "precompiled.hpp"
26#include "runtime/sharedRuntime.hpp"
27#include "utilities/align.hpp"
28#include "utilities/copy.hpp"
29
30
31// Copy bytes; larger units are filled atomically if everything is aligned.
32void Copy::conjoint_memory_atomic(void* from, void* to, size_t size) {
33  address src = (address) from;
34  address dst = (address) to;
35  uintptr_t bits = (uintptr_t) src | (uintptr_t) dst | (uintptr_t) size;
36
37  // (Note:  We could improve performance by ignoring the low bits of size,
38  // and putting a short cleanup loop after each bulk copy loop.
39  // There are plenty of other ways to make this faster also,
40  // and it's a slippery slope.  For now, let's keep this code simple
41  // since the simplicity helps clarify the atomicity semantics of
42  // this operation.  There are also CPU-specific assembly versions
43  // which may or may not want to include such optimizations.)
44
45  if (bits % sizeof(jlong) == 0) {
46    Copy::conjoint_jlongs_atomic((jlong*) src, (jlong*) dst, size / sizeof(jlong));
47  } else if (bits % sizeof(jint) == 0) {
48    Copy::conjoint_jints_atomic((jint*) src, (jint*) dst, size / sizeof(jint));
49  } else if (bits % sizeof(jshort) == 0) {
50    Copy::conjoint_jshorts_atomic((jshort*) src, (jshort*) dst, size / sizeof(jshort));
51  } else {
52    // Not aligned, so no need to be atomic.
53    Copy::conjoint_jbytes((void*) src, (void*) dst, size);
54  }
55}
56
57class CopySwap : AllStatic {
58public:
59  /**
60   * Copy and optionally byte swap elements
61   *
62   * <swap> - true if elements should be byte swapped
63   *
64   * @param src address of source
65   * @param dst address of destination
66   * @param byte_count number of bytes to copy
67   * @param elem_size size of the elements to copy-swap
68   */
69  template<bool swap>
70  static void conjoint_swap_if_needed(const void* src, void* dst, size_t byte_count, size_t elem_size) {
71    assert(src != NULL, "address must not be NULL");
72    assert(dst != NULL, "address must not be NULL");
73    assert(elem_size == 2 || elem_size == 4 || elem_size == 8,
74           "incorrect element size: " SIZE_FORMAT, elem_size);
75    assert(is_aligned(byte_count, elem_size),
76           "byte_count " SIZE_FORMAT " must be multiple of element size " SIZE_FORMAT, byte_count, elem_size);
77
78    address src_end = (address)src + byte_count;
79
80    if (dst <= src || dst >= src_end) {
81      do_conjoint_swap<RIGHT,swap>(src, dst, byte_count, elem_size);
82    } else {
83      do_conjoint_swap<LEFT,swap>(src, dst, byte_count, elem_size);
84    }
85  }
86
87private:
88  /**
89   * Byte swap a 16-bit value
90   */
91  static uint16_t byte_swap(uint16_t x) {
92    return (x << 8) | (x >> 8);
93  }
94
95  /**
96   * Byte swap a 32-bit value
97   */
98  static uint32_t byte_swap(uint32_t x) {
99    uint16_t lo = (uint16_t)x;
100    uint16_t hi = (uint16_t)(x >> 16);
101
102    return ((uint32_t)byte_swap(lo) << 16) | (uint32_t)byte_swap(hi);
103  }
104
105  /**
106   * Byte swap a 64-bit value
107   */
108  static uint64_t byte_swap(uint64_t x) {
109    uint32_t lo = (uint32_t)x;
110    uint32_t hi = (uint32_t)(x >> 32);
111
112    return ((uint64_t)byte_swap(lo) << 32) | (uint64_t)byte_swap(hi);
113  }
114
115  enum CopyDirection {
116    RIGHT, // lower -> higher address
117    LEFT   // higher -> lower address
118  };
119
120  /**
121   * Copy and byte swap elements
122   *
123   * <T> - type of element to copy
124   * <D> - copy direction
125   * <is_src_aligned> - true if src argument is aligned to element size
126   * <is_dst_aligned> - true if dst argument is aligned to element size
127   *
128   * @param src address of source
129   * @param dst address of destination
130   * @param byte_count number of bytes to copy
131   */
132  template <typename T, CopyDirection D, bool swap, bool is_src_aligned, bool is_dst_aligned>
133  static void do_conjoint_swap(const void* src, void* dst, size_t byte_count) {
134    const char* cur_src;
135    char* cur_dst;
136
137    switch (D) {
138    case RIGHT:
139      cur_src = (const char*)src;
140      cur_dst = (char*)dst;
141      break;
142    case LEFT:
143      cur_src = (const char*)src + byte_count - sizeof(T);
144      cur_dst = (char*)dst + byte_count - sizeof(T);
145      break;
146    }
147
148    for (size_t i = 0; i < byte_count / sizeof(T); i++) {
149      T tmp;
150
151      if (is_src_aligned) {
152        tmp = *(T*)cur_src;
153      } else {
154        memcpy(&tmp, cur_src, sizeof(T));
155      }
156
157      if (swap) {
158        tmp = byte_swap(tmp);
159      }
160
161      if (is_dst_aligned) {
162        *(T*)cur_dst = tmp;
163      } else {
164        memcpy(cur_dst, &tmp, sizeof(T));
165      }
166
167      switch (D) {
168      case RIGHT:
169        cur_src += sizeof(T);
170        cur_dst += sizeof(T);
171        break;
172      case LEFT:
173        cur_src -= sizeof(T);
174        cur_dst -= sizeof(T);
175        break;
176      }
177    }
178  }
179
180  /**
181   * Copy and byte swap elements
182   *
183   * <T>    - type of element to copy
184   * <D>    - copy direction
185   * <swap> - true if elements should be byte swapped
186   *
187   * @param src address of source
188   * @param dst address of destination
189   * @param byte_count number of bytes to copy
190   */
191  template <typename T, CopyDirection direction, bool swap>
192  static void do_conjoint_swap(const void* src, void* dst, size_t byte_count) {
193    if (is_aligned(src, sizeof(T))) {
194      if (is_aligned(dst, sizeof(T))) {
195        do_conjoint_swap<T,direction,swap,true,true>(src, dst, byte_count);
196      } else {
197        do_conjoint_swap<T,direction,swap,true,false>(src, dst, byte_count);
198      }
199    } else {
200      if (is_aligned(dst, sizeof(T))) {
201        do_conjoint_swap<T,direction,swap,false,true>(src, dst, byte_count);
202      } else {
203        do_conjoint_swap<T,direction,swap,false,false>(src, dst, byte_count);
204      }
205    }
206  }
207
208
209  /**
210   * Copy and byte swap elements
211   *
212   * <D>    - copy direction
213   * <swap> - true if elements should be byte swapped
214   *
215   * @param src address of source
216   * @param dst address of destination
217   * @param byte_count number of bytes to copy
218   * @param elem_size size of the elements to copy-swap
219   */
220  template <CopyDirection D, bool swap>
221  static void do_conjoint_swap(const void* src, void* dst, size_t byte_count, size_t elem_size) {
222    switch (elem_size) {
223    case 2: do_conjoint_swap<uint16_t,D,swap>(src, dst, byte_count); break;
224    case 4: do_conjoint_swap<uint32_t,D,swap>(src, dst, byte_count); break;
225    case 8: do_conjoint_swap<uint64_t,D,swap>(src, dst, byte_count); break;
226    default: guarantee(false, "do_conjoint_swap: Invalid elem_size " SIZE_FORMAT "\n", elem_size);
227    }
228  }
229};
230
231void Copy::conjoint_copy(const void* src, void* dst, size_t byte_count, size_t elem_size) {
232  CopySwap::conjoint_swap_if_needed<false>(src, dst, byte_count, elem_size);
233}
234
235void Copy::conjoint_swap(const void* src, void* dst, size_t byte_count, size_t elem_size) {
236  CopySwap::conjoint_swap_if_needed<true>(src, dst, byte_count, elem_size);
237}
238
239// Fill bytes; larger units are filled atomically if everything is aligned.
240void Copy::fill_to_memory_atomic(void* to, size_t size, jubyte value) {
241  address dst = (address) to;
242  uintptr_t bits = (uintptr_t) to | (uintptr_t) size;
243  if (bits % sizeof(jlong) == 0) {
244    jlong fill = (julong)( (jubyte)value ); // zero-extend
245    if (fill != 0) {
246      fill += fill << 8;
247      fill += fill << 16;
248      fill += fill << 32;
249    }
250    //Copy::fill_to_jlongs_atomic((jlong*) dst, size / sizeof(jlong));
251    for (uintptr_t off = 0; off < size; off += sizeof(jlong)) {
252      *(jlong*)(dst + off) = fill;
253    }
254  } else if (bits % sizeof(jint) == 0) {
255    jint fill = (juint)( (jubyte)value ); // zero-extend
256    if (fill != 0) {
257      fill += fill << 8;
258      fill += fill << 16;
259    }
260    //Copy::fill_to_jints_atomic((jint*) dst, size / sizeof(jint));
261    for (uintptr_t off = 0; off < size; off += sizeof(jint)) {
262      *(jint*)(dst + off) = fill;
263    }
264  } else if (bits % sizeof(jshort) == 0) {
265    jshort fill = (jushort)( (jubyte)value ); // zero-extend
266    fill += fill << 8;
267    //Copy::fill_to_jshorts_atomic((jshort*) dst, size / sizeof(jshort));
268    for (uintptr_t off = 0; off < size; off += sizeof(jshort)) {
269      *(jshort*)(dst + off) = fill;
270    }
271  } else {
272    // Not aligned, so no need to be atomic.
273    Copy::fill_to_bytes(dst, size, value);
274  }
275}
276