51 // Not aligned, so no need to be atomic. |
51 // Not aligned, so no need to be atomic. |
52 Copy::conjoint_jbytes((void*) src, (void*) dst, size); |
52 Copy::conjoint_jbytes((void*) src, (void*) dst, size); |
53 } |
53 } |
54 } |
54 } |
55 |
55 |
|
56 class CopySwap : AllStatic { |
|
57 public: |
|
58 /** |
|
59 * Copy and byte swap elements |
|
60 * |
|
61 * @param src address of source |
|
62 * @param dst address of destination |
|
63 * @param byte_count number of bytes to copy |
|
64 * @param elem_size size of the elements to copy-swap |
|
65 */ |
|
66 static void conjoint_swap(address src, address dst, size_t byte_count, size_t elem_size) { |
|
67 assert(src != NULL, "address must not be NULL"); |
|
68 assert(dst != NULL, "address must not be NULL"); |
|
69 assert(elem_size == 2 || elem_size == 4 || elem_size == 8, |
|
70 "incorrect element size: " SIZE_FORMAT, elem_size); |
|
71 assert(is_size_aligned(byte_count, elem_size), |
|
72 "byte_count " SIZE_FORMAT " must be multiple of element size " SIZE_FORMAT, byte_count, elem_size); |
|
73 |
|
74 address src_end = src + byte_count; |
|
75 |
|
76 if (dst <= src || dst >= src_end) { |
|
77 do_conjoint_swap<RIGHT>(src, dst, byte_count, elem_size); |
|
78 } else { |
|
79 do_conjoint_swap<LEFT>(src, dst, byte_count, elem_size); |
|
80 } |
|
81 } |
|
82 |
|
83 private: |
|
84 /** |
|
85 * Byte swap a 16-bit value |
|
86 */ |
|
87 static uint16_t byte_swap(uint16_t x) { |
|
88 return (x << 8) | (x >> 8); |
|
89 } |
|
90 |
|
91 /** |
|
92 * Byte swap a 32-bit value |
|
93 */ |
|
94 static uint32_t byte_swap(uint32_t x) { |
|
95 uint16_t lo = (uint16_t)x; |
|
96 uint16_t hi = (uint16_t)(x >> 16); |
|
97 |
|
98 return ((uint32_t)byte_swap(lo) << 16) | (uint32_t)byte_swap(hi); |
|
99 } |
|
100 |
|
101 /** |
|
102 * Byte swap a 64-bit value |
|
103 */ |
|
104 static uint64_t byte_swap(uint64_t x) { |
|
105 uint32_t lo = (uint32_t)x; |
|
106 uint32_t hi = (uint32_t)(x >> 32); |
|
107 |
|
108 return ((uint64_t)byte_swap(lo) << 32) | (uint64_t)byte_swap(hi); |
|
109 } |
|
110 |
|
111 enum CopyDirection { |
|
112 RIGHT, // lower -> higher address |
|
113 LEFT // higher -> lower address |
|
114 }; |
|
115 |
|
116 /** |
|
117 * Copy and byte swap elements |
|
118 * |
|
119 * <T> - type of element to copy |
|
120 * <D> - copy direction |
|
121 * <is_src_aligned> - true if src argument is aligned to element size |
|
122 * <is_dst_aligned> - true if dst argument is aligned to element size |
|
123 * |
|
124 * @param src address of source |
|
125 * @param dst address of destination |
|
126 * @param byte_count number of bytes to copy |
|
127 */ |
|
128 template <typename T, CopyDirection D, bool is_src_aligned, bool is_dst_aligned> |
|
129 static void do_conjoint_swap(address src, address dst, size_t byte_count) { |
|
130 address cur_src, cur_dst; |
|
131 |
|
132 switch (D) { |
|
133 case RIGHT: |
|
134 cur_src = src; |
|
135 cur_dst = dst; |
|
136 break; |
|
137 case LEFT: |
|
138 cur_src = src + byte_count - sizeof(T); |
|
139 cur_dst = dst + byte_count - sizeof(T); |
|
140 break; |
|
141 } |
|
142 |
|
143 for (size_t i = 0; i < byte_count / sizeof(T); i++) { |
|
144 T tmp; |
|
145 |
|
146 if (is_src_aligned) { |
|
147 tmp = *(T*)cur_src; |
|
148 } else { |
|
149 memcpy(&tmp, cur_src, sizeof(T)); |
|
150 } |
|
151 |
|
152 tmp = byte_swap(tmp); |
|
153 |
|
154 if (is_dst_aligned) { |
|
155 *(T*)cur_dst = tmp; |
|
156 } else { |
|
157 memcpy(cur_dst, &tmp, sizeof(T)); |
|
158 } |
|
159 |
|
160 switch (D) { |
|
161 case RIGHT: |
|
162 cur_src += sizeof(T); |
|
163 cur_dst += sizeof(T); |
|
164 break; |
|
165 case LEFT: |
|
166 cur_src -= sizeof(T); |
|
167 cur_dst -= sizeof(T); |
|
168 break; |
|
169 } |
|
170 } |
|
171 } |
|
172 |
|
173 /** |
|
174 * Copy and byte swap elements |
|
175 * |
|
176 * <T> - type of element to copy |
|
177 * <D> - copy direction |
|
178 * |
|
179 * @param src address of source |
|
180 * @param dst address of destination |
|
181 * @param byte_count number of bytes to copy |
|
182 */ |
|
183 template <typename T, CopyDirection direction> |
|
184 static void do_conjoint_swap(address src, address dst, size_t byte_count) { |
|
185 if (is_ptr_aligned(src, sizeof(T))) { |
|
186 if (is_ptr_aligned(dst, sizeof(T))) { |
|
187 do_conjoint_swap<T,direction,true,true>(src, dst, byte_count); |
|
188 } else { |
|
189 do_conjoint_swap<T,direction,true,false>(src, dst, byte_count); |
|
190 } |
|
191 } else { |
|
192 if (is_ptr_aligned(dst, sizeof(T))) { |
|
193 do_conjoint_swap<T,direction,false,true>(src, dst, byte_count); |
|
194 } else { |
|
195 do_conjoint_swap<T,direction,false,false>(src, dst, byte_count); |
|
196 } |
|
197 } |
|
198 } |
|
199 |
|
200 |
|
201 /** |
|
202 * Copy and byte swap elements |
|
203 * |
|
204 * <D> - copy direction |
|
205 * |
|
206 * @param src address of source |
|
207 * @param dst address of destination |
|
208 * @param byte_count number of bytes to copy |
|
209 * @param elem_size size of the elements to copy-swap |
|
210 */ |
|
211 template <CopyDirection D> |
|
212 static void do_conjoint_swap(address src, address dst, size_t byte_count, size_t elem_size) { |
|
213 switch (elem_size) { |
|
214 case 2: do_conjoint_swap<uint16_t,D>(src, dst, byte_count); break; |
|
215 case 4: do_conjoint_swap<uint32_t,D>(src, dst, byte_count); break; |
|
216 case 8: do_conjoint_swap<uint64_t,D>(src, dst, byte_count); break; |
|
217 default: guarantee(false, "do_conjoint_swap: Invalid elem_size %zd\n", elem_size); |
|
218 } |
|
219 } |
|
220 }; |
|
221 |
|
222 void Copy::conjoint_swap(address src, address dst, size_t byte_count, size_t elem_size) { |
|
223 CopySwap::conjoint_swap(src, dst, byte_count, elem_size); |
|
224 } |
56 |
225 |
57 // Fill bytes; larger units are filled atomically if everything is aligned. |
226 // Fill bytes; larger units are filled atomically if everything is aligned. |
58 void Copy::fill_to_memory_atomic(void* to, size_t size, jubyte value) { |
227 void Copy::fill_to_memory_atomic(void* to, size_t size, jubyte value) { |
59 address dst = (address) to; |
228 address dst = (address) to; |
60 uintptr_t bits = (uintptr_t) to | (uintptr_t) size; |
229 uintptr_t bits = (uintptr_t) to | (uintptr_t) size; |