8 * This code is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * version 2 for more details (a copy is included in the LICENSE file that
12 * accompanied this code).
13 *
14 * You should have received a copy of the GNU General Public License version
15 * 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 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 *
22 */
23
24 #include "precompiled.hpp"
25 #include "asm/assembler.hpp"
26 #include "assembler_arm.inline.hpp"
27 #include "gc/shared/barrierSet.hpp"
28 #include "gc/shared/barrierSetCodeGen.hpp"
29 #include "interpreter/interpreter.hpp"
30 #include "nativeInst_arm.hpp"
31 #include "oops/instanceOop.hpp"
32 #include "oops/method.hpp"
33 #include "oops/objArrayKlass.hpp"
34 #include "oops/oop.inline.hpp"
35 #include "prims/methodHandles.hpp"
36 #include "runtime/frame.inline.hpp"
37 #include "runtime/handles.inline.hpp"
38 #include "runtime/sharedRuntime.hpp"
39 #include "runtime/stubCodeGenerator.hpp"
40 #include "runtime/stubRoutines.hpp"
41 #include "utilities/align.hpp"
42 #ifdef COMPILER2
43 #include "opto/runtime.hpp"
44 #endif
45
46 // Declaration and definition of StubGenerator (no .hpp file).
47 // For a more detailed description of the stub routine structure
|
8 * This code is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * version 2 for more details (a copy is included in the LICENSE file that
12 * accompanied this code).
13 *
14 * You should have received a copy of the GNU General Public License version
15 * 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 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 *
22 */
23
24 #include "precompiled.hpp"
25 #include "asm/assembler.hpp"
26 #include "assembler_arm.inline.hpp"
27 #include "gc/shared/barrierSet.hpp"
28 #include "gc/shared/barrierSetAssembler.hpp"
29 #include "interpreter/interpreter.hpp"
30 #include "nativeInst_arm.hpp"
31 #include "oops/instanceOop.hpp"
32 #include "oops/method.hpp"
33 #include "oops/objArrayKlass.hpp"
34 #include "oops/oop.inline.hpp"
35 #include "prims/methodHandles.hpp"
36 #include "runtime/frame.inline.hpp"
37 #include "runtime/handles.inline.hpp"
38 #include "runtime/sharedRuntime.hpp"
39 #include "runtime/stubCodeGenerator.hpp"
40 #include "runtime/stubRoutines.hpp"
41 #include "utilities/align.hpp"
42 #ifdef COMPILER2
43 #include "opto/runtime.hpp"
44 #endif
45
46 // Declaration and definition of StubGenerator (no .hpp file).
47 // For a more detailed description of the stub routine structure
|
2858 // Generates pattern of code to be placed after raw data copying in generate_oop_copy
2859 // Includes return from arraycopy stub.
2860 //
2861 // Arguments:
2862 // to: destination pointer after copying.
2863 // if 'forward' then 'to' == upper bound, else 'to' == beginning of the modified region
2864 // count: total number of copied elements, 32-bit int
2865 //
2866 // Blows all volatile (R0-R3 on 32-bit ARM, R0-R18 on AArch64, Rtemp, LR) and 'to', 'count', 'tmp' registers.
2867 void oop_arraycopy_stub_epilogue_helper(Register to, Register count, Register tmp, bool status, bool forward, DecoratorSet decorato
2868 assert_different_registers(to, count, tmp);
2869
2870 if (forward) {
2871 // 'to' is upper bound of the modified region
2872 // restore initial dst:
2873 __ sub_ptr_scaled_int32(to, to, count, LogBytesPerHeapOop);
2874 }
2875
2876 // 'to' is the beginning of the region
2877
2878 BarrierSet *bs = BarrierSet::barrier_set();
2879 BarrierSetCodeGen *code_gen = bs->code_gen();
2880 code_gen->arraycopy_epilogue(this, decorators, true, to, count, tmp);
2881
2882 if (status) {
2883 __ mov(R0, 0); // OK
2884 }
2885
2886 #ifdef AARCH64
2887 __ raw_pop(LR, ZR);
2888 __ ret();
2889 #else
2890 __ pop(PC);
2891 #endif // AARCH64
2892 }
2893
2894
2895 // Generate stub for assign-compatible oop copy. If "aligned" is true, the
2896 // "from" and "to" addresses are assumed to be heapword aligned.
2897 //
2898 // If "disjoint" is true, arrays are assumed to be disjoint, otherwise they may overlap and
2899 // "nooverlap_target" must be specified as the address to jump if they don't.
|
2858 // Generates pattern of code to be placed after raw data copying in generate_oop_copy
2859 // Includes return from arraycopy stub.
2860 //
2861 // Arguments:
2862 // to: destination pointer after copying.
2863 // if 'forward' then 'to' == upper bound, else 'to' == beginning of the modified region
2864 // count: total number of copied elements, 32-bit int
2865 //
2866 // Blows all volatile (R0-R3 on 32-bit ARM, R0-R18 on AArch64, Rtemp, LR) and 'to', 'count', 'tmp' registers.
2867 void oop_arraycopy_stub_epilogue_helper(Register to, Register count, Register tmp, bool status, bool forward, DecoratorSet decorato
2868 assert_different_registers(to, count, tmp);
2869
2870 if (forward) {
2871 // 'to' is upper bound of the modified region
2872 // restore initial dst:
2873 __ sub_ptr_scaled_int32(to, to, count, LogBytesPerHeapOop);
2874 }
2875
2876 // 'to' is the beginning of the region
2877
2878 BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
2879 bs->arraycopy_epilogue(this, decorators, true, to, count, tmp);
2880
2881 if (status) {
2882 __ mov(R0, 0); // OK
2883 }
2884
2885 #ifdef AARCH64
2886 __ raw_pop(LR, ZR);
2887 __ ret();
2888 #else
2889 __ pop(PC);
2890 #endif // AARCH64
2891 }
2892
2893
2894 // Generate stub for assign-compatible oop copy. If "aligned" is true, the
2895 // "from" and "to" addresses are assumed to be heapword aligned.
2896 //
2897 // If "disjoint" is true, arrays are assumed to be disjoint, otherwise they may overlap and
2898 // "nooverlap_target" must be specified as the address to jump if they don't.
|
2936 const int log_bytes_per_count = LogBytesPerHeapOop;
2937
2938 const Register saved_count = LR;
2939 const int callee_saved_regs = 3; // R0-R2
2940
2941 // LR is used later to save barrier args
2942 #ifdef AARCH64
2943 __ raw_push(LR, ZR);
2944 #else
2945 __ push(LR);
2946 #endif // AARCH64
2947
2948 DecoratorSet decorators = 0;
2949 if (disjoint) {
2950 decorators |= ARRAYCOPY_DISJOINT;
2951 }
2952 if (aligned) {
2953 decorators |= ARRAYCOPY_ALIGNED;
2954 }
2955
2956 BarrierSet *bs = BarrierSet::barrier_set();
2957 BarrierSetCodeGen *code_gen = bs->code_gen();
2958 code_gen->arraycopy_prologue(this, decorators, true, to, count, callee_saved_regs);
2959
2960 // save arguments for barrier generation (after the pre barrier)
2961 __ mov(saved_count, count);
2962
2963 if (!forward) {
2964 __ add_ptr_scaled_int32(to, to, count, log_bytes_per_count);
2965 __ add_ptr_scaled_int32(from, from, count, log_bytes_per_count);
2966 }
2967
2968 // for short arrays, just do single element copy
2969 Label L_small_array;
2970 const int small_copy_limit = (8*wordSize + 7)/bytes_per_count; // XXX optim: tune the limit higher ?
2971 __ cmp_32(count, small_copy_limit);
2972 __ b(L_small_array, le);
2973
2974 bool from_is_aligned = (bytes_per_count >= 8);
2975 if (aligned && forward && (HeapWordSize % 8 == 0)) {
2976 // if 'from' is heapword aligned and HeapWordSize is divisible by 8,
2977 // then from is aligned by 8
|
2935 const int log_bytes_per_count = LogBytesPerHeapOop;
2936
2937 const Register saved_count = LR;
2938 const int callee_saved_regs = 3; // R0-R2
2939
2940 // LR is used later to save barrier args
2941 #ifdef AARCH64
2942 __ raw_push(LR, ZR);
2943 #else
2944 __ push(LR);
2945 #endif // AARCH64
2946
2947 DecoratorSet decorators = 0;
2948 if (disjoint) {
2949 decorators |= ARRAYCOPY_DISJOINT;
2950 }
2951 if (aligned) {
2952 decorators |= ARRAYCOPY_ALIGNED;
2953 }
2954
2955 BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
2956 bs->arraycopy_prologue(this, decorators, true, to, count, callee_saved_regs);
2957
2958 // save arguments for barrier generation (after the pre barrier)
2959 __ mov(saved_count, count);
2960
2961 if (!forward) {
2962 __ add_ptr_scaled_int32(to, to, count, log_bytes_per_count);
2963 __ add_ptr_scaled_int32(from, from, count, log_bytes_per_count);
2964 }
2965
2966 // for short arrays, just do single element copy
2967 Label L_small_array;
2968 const int small_copy_limit = (8*wordSize + 7)/bytes_per_count; // XXX optim: tune the limit higher ?
2969 __ cmp_32(count, small_copy_limit);
2970 __ b(L_small_array, le);
2971
2972 bool from_is_aligned = (bytes_per_count >= 8);
2973 if (aligned && forward && (HeapWordSize % 8 == 0)) {
2974 // if 'from' is heapword aligned and HeapWordSize is divisible by 8,
2975 // then from is aligned by 8
|
3203
3204 const int callee_saved_regs = AARCH64_ONLY(5) NOT_AARCH64(4); // LR saved differently
3205
3206 Label load_element, store_element, do_epilogue, fail;
3207
3208 BLOCK_COMMENT("Entry:");
3209
3210 __ zap_high_non_significant_bits(R2);
3211
3212 #ifdef AARCH64
3213 __ raw_push(LR, ZR);
3214 __ raw_push(R19, R20);
3215 #else
3216 int pushed = 0;
3217 __ push(LR);
3218 pushed+=1;
3219 #endif // AARCH64
3220
3221 DecoratorSet decorators = ARRAYCOPY_CHECKCAST;
3222
3223 BarrierSet *bs = BarrierSet::barrier_set();
3224 BarrierSetCodeGen *code_gen = bs->code_gen();
3225 code_gen->arraycopy_prologue(this, decorators, true, to, count, callee_saved_regs);
3226
3227 #ifndef AARCH64
3228 const RegisterSet caller_saved_regs = RegisterSet(R4,R6) | RegisterSet(R8,R9) | altFP_7_11;
3229 __ push(caller_saved_regs);
3230 assert(caller_saved_regs.size() == 6, "check the count");
3231 pushed+=6;
3232
3233 __ ldr(R4_ckval,Address(SP, wordSize*pushed)); // read the argument that was on the stack
3234 #endif // !AARCH64
3235
3236 // Save arguments for barrier generation (after the pre barrier):
3237 // - must be a caller saved register and not LR
3238 // - ARM32: avoid R10 in case RThread is needed
3239 const Register saved_count = AARCH64_ONLY(R19) NOT_AARCH64(altFP_7_11);
3240 #ifdef AARCH64
3241 __ mov_w(saved_count, count);
3242 __ cbnz_w(count, load_element); // and test count
3243 #else
3244 __ movs(saved_count, count); // and test count
|
3201
3202 const int callee_saved_regs = AARCH64_ONLY(5) NOT_AARCH64(4); // LR saved differently
3203
3204 Label load_element, store_element, do_epilogue, fail;
3205
3206 BLOCK_COMMENT("Entry:");
3207
3208 __ zap_high_non_significant_bits(R2);
3209
3210 #ifdef AARCH64
3211 __ raw_push(LR, ZR);
3212 __ raw_push(R19, R20);
3213 #else
3214 int pushed = 0;
3215 __ push(LR);
3216 pushed+=1;
3217 #endif // AARCH64
3218
3219 DecoratorSet decorators = ARRAYCOPY_CHECKCAST;
3220
3221 BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
3222 bs->arraycopy_prologue(this, decorators, true, to, count, callee_saved_regs);
3223
3224 #ifndef AARCH64
3225 const RegisterSet caller_saved_regs = RegisterSet(R4,R6) | RegisterSet(R8,R9) | altFP_7_11;
3226 __ push(caller_saved_regs);
3227 assert(caller_saved_regs.size() == 6, "check the count");
3228 pushed+=6;
3229
3230 __ ldr(R4_ckval,Address(SP, wordSize*pushed)); // read the argument that was on the stack
3231 #endif // !AARCH64
3232
3233 // Save arguments for barrier generation (after the pre barrier):
3234 // - must be a caller saved register and not LR
3235 // - ARM32: avoid R10 in case RThread is needed
3236 const Register saved_count = AARCH64_ONLY(R19) NOT_AARCH64(altFP_7_11);
3237 #ifdef AARCH64
3238 __ mov_w(saved_count, count);
3239 __ cbnz_w(count, load_element); // and test count
3240 #else
3241 __ movs(saved_count, count); // and test count
|
3283 // ======== end loop ========
3284
3285 // It was a real error; we must depend on the caller to finish the job.
3286 // Register count has number of *remaining* oops, saved_count number of *total* oops.
3287 // Emit GC store barriers for the oops we have copied
3288 // and report their number to the caller (0 or (-1^n))
3289 __ BIND(fail);
3290
3291 // Note: fail marked by the fact that count differs from saved_count
3292
3293 __ BIND(do_epilogue);
3294
3295 Register copied = AARCH64_ONLY(R20) NOT_AARCH64(R4); // saved
3296 Label L_not_copied;
3297
3298 __ subs_32(copied, saved_count, count); // copied count (in saved reg)
3299 __ b(L_not_copied, eq); // nothing was copied, skip post barrier
3300 __ sub(to, to, AsmOperand(copied, lsl, LogBytesPerHeapOop)); // initial to value
3301 __ mov(R12, copied); // count arg scratched by post barrier
3302
3303 code_gen->arraycopy_epilogue(this, decorators, true, to, R12, R3);
3304
3305 assert_different_registers(R3,R12,LR,copied,saved_count);
3306 inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr, R3, R12);
3307
3308 __ BIND(L_not_copied);
3309 __ cmp_32(copied, saved_count); // values preserved in saved registers
3310
3311 #ifdef AARCH64
3312 __ csinv(R0, ZR, copied, eq); // 0 if all copied else NOT(copied)
3313 __ raw_pop(R19, R20);
3314 __ raw_pop(LR, ZR);
3315 __ ret();
3316 #else
3317 __ mov(R0, 0, eq); // 0 if all copied
3318 __ mvn(R0, copied, ne); // else NOT(copied)
3319 __ pop(caller_saved_regs);
3320 __ pop(PC);
3321 #endif // AARCH64
3322
|
3280 // ======== end loop ========
3281
3282 // It was a real error; we must depend on the caller to finish the job.
3283 // Register count has number of *remaining* oops, saved_count number of *total* oops.
3284 // Emit GC store barriers for the oops we have copied
3285 // and report their number to the caller (0 or (-1^n))
3286 __ BIND(fail);
3287
3288 // Note: fail marked by the fact that count differs from saved_count
3289
3290 __ BIND(do_epilogue);
3291
3292 Register copied = AARCH64_ONLY(R20) NOT_AARCH64(R4); // saved
3293 Label L_not_copied;
3294
3295 __ subs_32(copied, saved_count, count); // copied count (in saved reg)
3296 __ b(L_not_copied, eq); // nothing was copied, skip post barrier
3297 __ sub(to, to, AsmOperand(copied, lsl, LogBytesPerHeapOop)); // initial to value
3298 __ mov(R12, copied); // count arg scratched by post barrier
3299
3300 bs->arraycopy_epilogue(this, decorators, true, to, R12, R3);
3301
3302 assert_different_registers(R3,R12,LR,copied,saved_count);
3303 inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr, R3, R12);
3304
3305 __ BIND(L_not_copied);
3306 __ cmp_32(copied, saved_count); // values preserved in saved registers
3307
3308 #ifdef AARCH64
3309 __ csinv(R0, ZR, copied, eq); // 0 if all copied else NOT(copied)
3310 __ raw_pop(R19, R20);
3311 __ raw_pop(LR, ZR);
3312 __ ret();
3313 #else
3314 __ mov(R0, 0, eq); // 0 if all copied
3315 __ mvn(R0, copied, ne); // else NOT(copied)
3316 __ pop(caller_saved_regs);
3317 __ pop(PC);
3318 #endif // AARCH64
3319
|