mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
7020521: arraycopy stubs place prebarriers incorrectly
Rearranged the pre-barrier placement in arraycopy stubs so that they are properly called in case of chained calls. Also refactored the code a little bit so that it looks uniform across the platforms and is more readable. Reviewed-by: never, kvn
This commit is contained in:
parent
4b3ada699d
commit
1c5e7bf24a
3 changed files with 292 additions and 254 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -968,19 +968,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
static address disjoint_byte_copy_entry;
|
|
||||||
static address disjoint_short_copy_entry;
|
|
||||||
static address disjoint_int_copy_entry;
|
|
||||||
static address disjoint_long_copy_entry;
|
|
||||||
static address disjoint_oop_copy_entry;
|
|
||||||
|
|
||||||
static address byte_copy_entry;
|
|
||||||
static address short_copy_entry;
|
|
||||||
static address int_copy_entry;
|
|
||||||
static address long_copy_entry;
|
|
||||||
static address oop_copy_entry;
|
|
||||||
|
|
||||||
static address checkcast_copy_entry;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Verify that a register contains clean 32-bits positive value
|
// Verify that a register contains clean 32-bits positive value
|
||||||
|
@ -1283,7 +1270,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// to: O1
|
// to: O1
|
||||||
// count: O2 treated as signed
|
// count: O2 treated as signed
|
||||||
//
|
//
|
||||||
address generate_disjoint_byte_copy(bool aligned, const char * name) {
|
address generate_disjoint_byte_copy(bool aligned, address *entry, const char *name) {
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", name);
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
@ -1299,9 +1286,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
|
|
||||||
assert_clean_int(count, O3); // Make sure 'count' is clean int.
|
assert_clean_int(count, O3); // Make sure 'count' is clean int.
|
||||||
|
|
||||||
if (!aligned) disjoint_byte_copy_entry = __ pc();
|
if (entry != NULL) {
|
||||||
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
*entry = __ pc();
|
||||||
if (!aligned) BLOCK_COMMENT("Entry:");
|
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
}
|
||||||
|
|
||||||
// for short arrays, just do single element copy
|
// for short arrays, just do single element copy
|
||||||
__ cmp(count, 23); // 16 + 7
|
__ cmp(count, 23); // 16 + 7
|
||||||
|
@ -1391,15 +1380,13 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// to: O1
|
// to: O1
|
||||||
// count: O2 treated as signed
|
// count: O2 treated as signed
|
||||||
//
|
//
|
||||||
address generate_conjoint_byte_copy(bool aligned, const char * name) {
|
address generate_conjoint_byte_copy(bool aligned, address nooverlap_target,
|
||||||
|
address *entry, const char *name) {
|
||||||
// Do reverse copy.
|
// Do reverse copy.
|
||||||
|
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", name);
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
address nooverlap_target = aligned ?
|
|
||||||
StubRoutines::arrayof_jbyte_disjoint_arraycopy() :
|
|
||||||
disjoint_byte_copy_entry;
|
|
||||||
|
|
||||||
Label L_skip_alignment, L_align, L_aligned_copy;
|
Label L_skip_alignment, L_align, L_aligned_copy;
|
||||||
Label L_copy_byte, L_copy_byte_loop, L_exit;
|
Label L_copy_byte, L_copy_byte_loop, L_exit;
|
||||||
|
@ -1412,9 +1399,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
|
|
||||||
assert_clean_int(count, O3); // Make sure 'count' is clean int.
|
assert_clean_int(count, O3); // Make sure 'count' is clean int.
|
||||||
|
|
||||||
if (!aligned) byte_copy_entry = __ pc();
|
if (entry != NULL) {
|
||||||
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
*entry = __ pc();
|
||||||
if (!aligned) BLOCK_COMMENT("Entry:");
|
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
}
|
||||||
|
|
||||||
array_overlap_test(nooverlap_target, 0);
|
array_overlap_test(nooverlap_target, 0);
|
||||||
|
|
||||||
|
@ -1504,7 +1493,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// to: O1
|
// to: O1
|
||||||
// count: O2 treated as signed
|
// count: O2 treated as signed
|
||||||
//
|
//
|
||||||
address generate_disjoint_short_copy(bool aligned, const char * name) {
|
address generate_disjoint_short_copy(bool aligned, address *entry, const char * name) {
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", name);
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
@ -1520,9 +1509,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
|
|
||||||
assert_clean_int(count, O3); // Make sure 'count' is clean int.
|
assert_clean_int(count, O3); // Make sure 'count' is clean int.
|
||||||
|
|
||||||
if (!aligned) disjoint_short_copy_entry = __ pc();
|
if (entry != NULL) {
|
||||||
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
*entry = __ pc();
|
||||||
if (!aligned) BLOCK_COMMENT("Entry:");
|
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
}
|
||||||
|
|
||||||
// for short arrays, just do single element copy
|
// for short arrays, just do single element copy
|
||||||
__ cmp(count, 11); // 8 + 3 (22 bytes)
|
__ cmp(count, 11); // 8 + 3 (22 bytes)
|
||||||
|
@ -1842,15 +1833,13 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// to: O1
|
// to: O1
|
||||||
// count: O2 treated as signed
|
// count: O2 treated as signed
|
||||||
//
|
//
|
||||||
address generate_conjoint_short_copy(bool aligned, const char * name) {
|
address generate_conjoint_short_copy(bool aligned, address nooverlap_target,
|
||||||
|
address *entry, const char *name) {
|
||||||
// Do reverse copy.
|
// Do reverse copy.
|
||||||
|
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", name);
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
address nooverlap_target = aligned ?
|
|
||||||
StubRoutines::arrayof_jshort_disjoint_arraycopy() :
|
|
||||||
disjoint_short_copy_entry;
|
|
||||||
|
|
||||||
Label L_skip_alignment, L_skip_alignment2, L_aligned_copy;
|
Label L_skip_alignment, L_skip_alignment2, L_aligned_copy;
|
||||||
Label L_copy_2_bytes, L_copy_2_bytes_loop, L_exit;
|
Label L_copy_2_bytes, L_copy_2_bytes_loop, L_exit;
|
||||||
|
@ -1865,9 +1854,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
|
|
||||||
assert_clean_int(count, O3); // Make sure 'count' is clean int.
|
assert_clean_int(count, O3); // Make sure 'count' is clean int.
|
||||||
|
|
||||||
if (!aligned) short_copy_entry = __ pc();
|
if (entry != NULL) {
|
||||||
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
*entry = __ pc();
|
||||||
if (!aligned) BLOCK_COMMENT("Entry:");
|
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
}
|
||||||
|
|
||||||
array_overlap_test(nooverlap_target, 1);
|
array_overlap_test(nooverlap_target, 1);
|
||||||
|
|
||||||
|
@ -2072,7 +2063,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// to: O1
|
// to: O1
|
||||||
// count: O2 treated as signed
|
// count: O2 treated as signed
|
||||||
//
|
//
|
||||||
address generate_disjoint_int_copy(bool aligned, const char * name) {
|
address generate_disjoint_int_copy(bool aligned, address *entry, const char *name) {
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", name);
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
@ -2080,9 +2071,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
const Register count = O2;
|
const Register count = O2;
|
||||||
assert_clean_int(count, O3); // Make sure 'count' is clean int.
|
assert_clean_int(count, O3); // Make sure 'count' is clean int.
|
||||||
|
|
||||||
if (!aligned) disjoint_int_copy_entry = __ pc();
|
if (entry != NULL) {
|
||||||
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
*entry = __ pc();
|
||||||
if (!aligned) BLOCK_COMMENT("Entry:");
|
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
}
|
||||||
|
|
||||||
generate_disjoint_int_copy_core(aligned);
|
generate_disjoint_int_copy_core(aligned);
|
||||||
|
|
||||||
|
@ -2204,20 +2197,19 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// to: O1
|
// to: O1
|
||||||
// count: O2 treated as signed
|
// count: O2 treated as signed
|
||||||
//
|
//
|
||||||
address generate_conjoint_int_copy(bool aligned, const char * name) {
|
address generate_conjoint_int_copy(bool aligned, address nooverlap_target,
|
||||||
|
address *entry, const char *name) {
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", name);
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
|
||||||
address nooverlap_target = aligned ?
|
|
||||||
StubRoutines::arrayof_jint_disjoint_arraycopy() :
|
|
||||||
disjoint_int_copy_entry;
|
|
||||||
|
|
||||||
assert_clean_int(O2, O3); // Make sure 'count' is clean int.
|
assert_clean_int(O2, O3); // Make sure 'count' is clean int.
|
||||||
|
|
||||||
if (!aligned) int_copy_entry = __ pc();
|
if (entry != NULL) {
|
||||||
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
*entry = __ pc();
|
||||||
if (!aligned) BLOCK_COMMENT("Entry:");
|
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
}
|
||||||
|
|
||||||
array_overlap_test(nooverlap_target, 2);
|
array_overlap_test(nooverlap_target, 2);
|
||||||
|
|
||||||
|
@ -2336,16 +2328,18 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// to: O1
|
// to: O1
|
||||||
// count: O2 treated as signed
|
// count: O2 treated as signed
|
||||||
//
|
//
|
||||||
address generate_disjoint_long_copy(bool aligned, const char * name) {
|
address generate_disjoint_long_copy(bool aligned, address *entry, const char *name) {
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", name);
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
|
||||||
assert_clean_int(O2, O3); // Make sure 'count' is clean int.
|
assert_clean_int(O2, O3); // Make sure 'count' is clean int.
|
||||||
|
|
||||||
if (!aligned) disjoint_long_copy_entry = __ pc();
|
if (entry != NULL) {
|
||||||
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
*entry = __ pc();
|
||||||
if (!aligned) BLOCK_COMMENT("Entry:");
|
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
}
|
||||||
|
|
||||||
generate_disjoint_long_copy_core(aligned);
|
generate_disjoint_long_copy_core(aligned);
|
||||||
|
|
||||||
|
@ -2406,19 +2400,21 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// to: O1
|
// to: O1
|
||||||
// count: O2 treated as signed
|
// count: O2 treated as signed
|
||||||
//
|
//
|
||||||
address generate_conjoint_long_copy(bool aligned, const char * name) {
|
address generate_conjoint_long_copy(bool aligned, address nooverlap_target,
|
||||||
|
address *entry, const char *name) {
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", name);
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
|
||||||
assert(!aligned, "usage");
|
assert(!aligned, "usage");
|
||||||
address nooverlap_target = disjoint_long_copy_entry;
|
|
||||||
|
|
||||||
assert_clean_int(O2, O3); // Make sure 'count' is clean int.
|
assert_clean_int(O2, O3); // Make sure 'count' is clean int.
|
||||||
|
|
||||||
if (!aligned) long_copy_entry = __ pc();
|
if (entry != NULL) {
|
||||||
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
*entry = __ pc();
|
||||||
if (!aligned) BLOCK_COMMENT("Entry:");
|
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
}
|
||||||
|
|
||||||
array_overlap_test(nooverlap_target, 3);
|
array_overlap_test(nooverlap_target, 3);
|
||||||
|
|
||||||
|
@ -2439,7 +2435,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// to: O1
|
// to: O1
|
||||||
// count: O2 treated as signed
|
// count: O2 treated as signed
|
||||||
//
|
//
|
||||||
address generate_disjoint_oop_copy(bool aligned, const char * name) {
|
address generate_disjoint_oop_copy(bool aligned, address *entry, const char *name) {
|
||||||
|
|
||||||
const Register from = O0; // source array address
|
const Register from = O0; // source array address
|
||||||
const Register to = O1; // destination array address
|
const Register to = O1; // destination array address
|
||||||
|
@ -2451,9 +2447,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
|
|
||||||
assert_clean_int(count, O3); // Make sure 'count' is clean int.
|
assert_clean_int(count, O3); // Make sure 'count' is clean int.
|
||||||
|
|
||||||
if (!aligned) disjoint_oop_copy_entry = __ pc();
|
if (entry != NULL) {
|
||||||
// caller can pass a 64-bit byte count here
|
*entry = __ pc();
|
||||||
if (!aligned) BLOCK_COMMENT("Entry:");
|
// caller can pass a 64-bit byte count here
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
}
|
||||||
|
|
||||||
// save arguments for barrier generation
|
// save arguments for barrier generation
|
||||||
__ mov(to, G1);
|
__ mov(to, G1);
|
||||||
|
@ -2487,7 +2485,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// to: O1
|
// to: O1
|
||||||
// count: O2 treated as signed
|
// count: O2 treated as signed
|
||||||
//
|
//
|
||||||
address generate_conjoint_oop_copy(bool aligned, const char * name) {
|
address generate_conjoint_oop_copy(bool aligned, address nooverlap_target,
|
||||||
|
address *entry, const char *name) {
|
||||||
|
|
||||||
const Register from = O0; // source array address
|
const Register from = O0; // source array address
|
||||||
const Register to = O1; // destination array address
|
const Register to = O1; // destination array address
|
||||||
|
@ -2499,22 +2498,19 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
|
|
||||||
assert_clean_int(count, O3); // Make sure 'count' is clean int.
|
assert_clean_int(count, O3); // Make sure 'count' is clean int.
|
||||||
|
|
||||||
if (!aligned) oop_copy_entry = __ pc();
|
if (entry != NULL) {
|
||||||
// caller can pass a 64-bit byte count here
|
*entry = __ pc();
|
||||||
if (!aligned) BLOCK_COMMENT("Entry:");
|
// caller can pass a 64-bit byte count here
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
}
|
||||||
|
|
||||||
|
array_overlap_test(nooverlap_target, LogBytesPerHeapOop);
|
||||||
|
|
||||||
// save arguments for barrier generation
|
// save arguments for barrier generation
|
||||||
__ mov(to, G1);
|
__ mov(to, G1);
|
||||||
__ mov(count, G5);
|
__ mov(count, G5);
|
||||||
|
|
||||||
gen_write_ref_array_pre_barrier(G1, G5);
|
gen_write_ref_array_pre_barrier(G1, G5);
|
||||||
|
|
||||||
address nooverlap_target = aligned ?
|
|
||||||
StubRoutines::arrayof_oop_disjoint_arraycopy() :
|
|
||||||
disjoint_oop_copy_entry;
|
|
||||||
|
|
||||||
array_overlap_test(nooverlap_target, LogBytesPerHeapOop);
|
|
||||||
|
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
if (UseCompressedOops) {
|
if (UseCompressedOops) {
|
||||||
generate_conjoint_int_copy_core(aligned);
|
generate_conjoint_int_copy_core(aligned);
|
||||||
|
@ -2582,7 +2578,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// ckval: O4 (super_klass)
|
// ckval: O4 (super_klass)
|
||||||
// ret: O0 zero for success; (-1^K) where K is partial transfer count
|
// ret: O0 zero for success; (-1^K) where K is partial transfer count
|
||||||
//
|
//
|
||||||
address generate_checkcast_copy(const char* name) {
|
address generate_checkcast_copy(const char *name, address *entry) {
|
||||||
|
|
||||||
const Register O0_from = O0; // source array address
|
const Register O0_from = O0; // source array address
|
||||||
const Register O1_to = O1; // destination array address
|
const Register O1_to = O1; // destination array address
|
||||||
|
@ -2600,8 +2596,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
StubCodeMark mark(this, "StubRoutines", name);
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
|
||||||
gen_write_ref_array_pre_barrier(O1, O2);
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
// We sometimes save a frame (see generate_type_check below).
|
// We sometimes save a frame (see generate_type_check below).
|
||||||
// If this will cause trouble, let's fail now instead of later.
|
// If this will cause trouble, let's fail now instead of later.
|
||||||
|
@ -2625,9 +2619,13 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
}
|
}
|
||||||
#endif //ASSERT
|
#endif //ASSERT
|
||||||
|
|
||||||
checkcast_copy_entry = __ pc();
|
if (entry != NULL) {
|
||||||
// caller can pass a 64-bit byte count here (from generic stub)
|
*entry = __ pc();
|
||||||
BLOCK_COMMENT("Entry:");
|
// caller can pass a 64-bit byte count here (from generic stub)
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_write_ref_array_pre_barrier(O1_to, O2_count);
|
||||||
|
|
||||||
Label load_element, store_element, do_card_marks, fail, done;
|
Label load_element, store_element, do_card_marks, fail, done;
|
||||||
__ addcc(O2_count, 0, G1_remain); // initialize loop index, and test it
|
__ addcc(O2_count, 0, G1_remain); // initialize loop index, and test it
|
||||||
|
@ -2700,7 +2698,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// Examines the alignment of the operands and dispatches
|
// Examines the alignment of the operands and dispatches
|
||||||
// to a long, int, short, or byte copy loop.
|
// to a long, int, short, or byte copy loop.
|
||||||
//
|
//
|
||||||
address generate_unsafe_copy(const char* name) {
|
address generate_unsafe_copy(const char* name,
|
||||||
|
address byte_copy_entry,
|
||||||
|
address short_copy_entry,
|
||||||
|
address int_copy_entry,
|
||||||
|
address long_copy_entry) {
|
||||||
|
|
||||||
const Register O0_from = O0; // source array address
|
const Register O0_from = O0; // source array address
|
||||||
const Register O1_to = O1; // destination array address
|
const Register O1_to = O1; // destination array address
|
||||||
|
@ -2796,8 +2798,13 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// O0 == 0 - success
|
// O0 == 0 - success
|
||||||
// O0 == -1 - need to call System.arraycopy
|
// O0 == -1 - need to call System.arraycopy
|
||||||
//
|
//
|
||||||
address generate_generic_copy(const char *name) {
|
address generate_generic_copy(const char *name,
|
||||||
|
address entry_jbyte_arraycopy,
|
||||||
|
address entry_jshort_arraycopy,
|
||||||
|
address entry_jint_arraycopy,
|
||||||
|
address entry_oop_arraycopy,
|
||||||
|
address entry_jlong_arraycopy,
|
||||||
|
address entry_checkcast_arraycopy) {
|
||||||
Label L_failed, L_objArray;
|
Label L_failed, L_objArray;
|
||||||
|
|
||||||
// Input registers
|
// Input registers
|
||||||
|
@ -2970,15 +2977,15 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
|
|
||||||
BLOCK_COMMENT("choose copy loop based on element size");
|
BLOCK_COMMENT("choose copy loop based on element size");
|
||||||
__ cmp(G3_elsize, 0);
|
__ cmp(G3_elsize, 0);
|
||||||
__ br(Assembler::equal,true,Assembler::pt,StubRoutines::_jbyte_arraycopy);
|
__ br(Assembler::equal, true, Assembler::pt, entry_jbyte_arraycopy);
|
||||||
__ delayed()->signx(length, count); // length
|
__ delayed()->signx(length, count); // length
|
||||||
|
|
||||||
__ cmp(G3_elsize, LogBytesPerShort);
|
__ cmp(G3_elsize, LogBytesPerShort);
|
||||||
__ br(Assembler::equal,true,Assembler::pt,StubRoutines::_jshort_arraycopy);
|
__ br(Assembler::equal, true, Assembler::pt, entry_jshort_arraycopy);
|
||||||
__ delayed()->signx(length, count); // length
|
__ delayed()->signx(length, count); // length
|
||||||
|
|
||||||
__ cmp(G3_elsize, LogBytesPerInt);
|
__ cmp(G3_elsize, LogBytesPerInt);
|
||||||
__ br(Assembler::equal,true,Assembler::pt,StubRoutines::_jint_arraycopy);
|
__ br(Assembler::equal, true, Assembler::pt, entry_jint_arraycopy);
|
||||||
__ delayed()->signx(length, count); // length
|
__ delayed()->signx(length, count); // length
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
{ Label L;
|
{ Label L;
|
||||||
|
@ -2989,7 +2996,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ bind(L);
|
__ bind(L);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
__ br(Assembler::always,false,Assembler::pt,StubRoutines::_jlong_arraycopy);
|
__ br(Assembler::always, false, Assembler::pt, entry_jlong_arraycopy);
|
||||||
__ delayed()->signx(length, count); // length
|
__ delayed()->signx(length, count); // length
|
||||||
|
|
||||||
// objArrayKlass
|
// objArrayKlass
|
||||||
|
@ -3013,7 +3020,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ add(src, src_pos, from); // src_addr
|
__ add(src, src_pos, from); // src_addr
|
||||||
__ add(dst, dst_pos, to); // dst_addr
|
__ add(dst, dst_pos, to); // dst_addr
|
||||||
__ BIND(L_plain_copy);
|
__ BIND(L_plain_copy);
|
||||||
__ br(Assembler::always, false, Assembler::pt,StubRoutines::_oop_arraycopy);
|
__ br(Assembler::always, false, Assembler::pt, entry_oop_arraycopy);
|
||||||
__ delayed()->signx(length, count); // length
|
__ delayed()->signx(length, count); // length
|
||||||
|
|
||||||
__ BIND(L_checkcast_copy);
|
__ BIND(L_checkcast_copy);
|
||||||
|
@ -3057,7 +3064,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ ld_ptr(G4_dst_klass, ek_offset, O4); // dest elem klass
|
__ ld_ptr(G4_dst_klass, ek_offset, O4); // dest elem klass
|
||||||
// lduw(O4, sco_offset, O3); // sco of elem klass
|
// lduw(O4, sco_offset, O3); // sco of elem klass
|
||||||
|
|
||||||
__ br(Assembler::always, false, Assembler::pt, checkcast_copy_entry);
|
__ br(Assembler::always, false, Assembler::pt, entry_checkcast_arraycopy);
|
||||||
__ delayed()->lduw(O4, sco_offset, O3);
|
__ delayed()->lduw(O4, sco_offset, O3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3068,39 +3075,76 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_arraycopy_stubs() {
|
void generate_arraycopy_stubs() {
|
||||||
|
address entry;
|
||||||
|
address entry_jbyte_arraycopy;
|
||||||
|
address entry_jshort_arraycopy;
|
||||||
|
address entry_jint_arraycopy;
|
||||||
|
address entry_oop_arraycopy;
|
||||||
|
address entry_jlong_arraycopy;
|
||||||
|
address entry_checkcast_arraycopy;
|
||||||
|
|
||||||
// Note: the disjoint stubs must be generated first, some of
|
StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(false, &entry,
|
||||||
// the conjoint stubs use them.
|
"jbyte_disjoint_arraycopy");
|
||||||
StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(false, "jbyte_disjoint_arraycopy");
|
StubRoutines::_jbyte_arraycopy = generate_conjoint_byte_copy(false, entry, &entry_jbyte_arraycopy,
|
||||||
StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, "jshort_disjoint_arraycopy");
|
"jbyte_arraycopy");
|
||||||
StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_copy(false, "jint_disjoint_arraycopy");
|
StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, &entry,
|
||||||
StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_copy(false, "jlong_disjoint_arraycopy");
|
"jshort_disjoint_arraycopy");
|
||||||
StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_oop_copy(false, "oop_disjoint_arraycopy");
|
StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(false, entry, &entry_jshort_arraycopy,
|
||||||
StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(true, "arrayof_jbyte_disjoint_arraycopy");
|
"jshort_arraycopy");
|
||||||
StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_short_copy(true, "arrayof_jshort_disjoint_arraycopy");
|
StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_copy(false, &entry,
|
||||||
StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_int_copy(true, "arrayof_jint_disjoint_arraycopy");
|
"jint_disjoint_arraycopy");
|
||||||
StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_long_copy(true, "arrayof_jlong_disjoint_arraycopy");
|
StubRoutines::_jint_arraycopy = generate_conjoint_int_copy(false, entry, &entry_jint_arraycopy,
|
||||||
StubRoutines::_arrayof_oop_disjoint_arraycopy = generate_disjoint_oop_copy(true, "arrayof_oop_disjoint_arraycopy");
|
"jint_arraycopy");
|
||||||
|
StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_copy(false, &entry,
|
||||||
|
"jlong_disjoint_arraycopy");
|
||||||
|
StubRoutines::_jlong_arraycopy = generate_conjoint_long_copy(false, entry, &entry_jlong_arraycopy,
|
||||||
|
"jlong_arraycopy");
|
||||||
|
StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_oop_copy(false, &entry,
|
||||||
|
"oop_disjoint_arraycopy");
|
||||||
|
StubRoutines::_oop_arraycopy = generate_conjoint_oop_copy(false, entry, &entry_oop_arraycopy,
|
||||||
|
"oop_arraycopy");
|
||||||
|
|
||||||
StubRoutines::_jbyte_arraycopy = generate_conjoint_byte_copy(false, "jbyte_arraycopy");
|
|
||||||
StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(false, "jshort_arraycopy");
|
StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(true, &entry,
|
||||||
StubRoutines::_jint_arraycopy = generate_conjoint_int_copy(false, "jint_arraycopy");
|
"arrayof_jbyte_disjoint_arraycopy");
|
||||||
StubRoutines::_jlong_arraycopy = generate_conjoint_long_copy(false, "jlong_arraycopy");
|
StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_byte_copy(true, entry, NULL,
|
||||||
StubRoutines::_oop_arraycopy = generate_conjoint_oop_copy(false, "oop_arraycopy");
|
"arrayof_jbyte_arraycopy");
|
||||||
StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_byte_copy(true, "arrayof_jbyte_arraycopy");
|
|
||||||
StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_short_copy(true, "arrayof_jshort_arraycopy");
|
StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_short_copy(true, &entry,
|
||||||
|
"arrayof_jshort_disjoint_arraycopy");
|
||||||
|
StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_short_copy(true, entry, NULL,
|
||||||
|
"arrayof_jshort_arraycopy");
|
||||||
|
|
||||||
|
StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_int_copy(true, &entry,
|
||||||
|
"arrayof_jint_disjoint_arraycopy");
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
// since sizeof(jint) < sizeof(HeapWord), there's a different flavor:
|
// since sizeof(jint) < sizeof(HeapWord), there's a different flavor:
|
||||||
StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_int_copy(true, "arrayof_jint_arraycopy");
|
StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_int_copy(true, entry, NULL, "arrayof_jint_arraycopy");
|
||||||
#else
|
#else
|
||||||
StubRoutines::_arrayof_jint_arraycopy = StubRoutines::_jint_arraycopy;
|
StubRoutines::_arrayof_jint_arraycopy = StubRoutines::_jint_arraycopy;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_long_copy(true, NULL,
|
||||||
|
"arrayof_jlong_disjoint_arraycopy");
|
||||||
|
StubRoutines::_arrayof_oop_disjoint_arraycopy = generate_disjoint_oop_copy(true, NULL,
|
||||||
|
"arrayof_oop_disjoint_arraycopy");
|
||||||
|
|
||||||
StubRoutines::_arrayof_jlong_arraycopy = StubRoutines::_jlong_arraycopy;
|
StubRoutines::_arrayof_jlong_arraycopy = StubRoutines::_jlong_arraycopy;
|
||||||
StubRoutines::_arrayof_oop_arraycopy = StubRoutines::_oop_arraycopy;
|
StubRoutines::_arrayof_oop_arraycopy = StubRoutines::_oop_arraycopy;
|
||||||
|
|
||||||
StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy");
|
StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy);
|
||||||
StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy");
|
StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy",
|
||||||
StubRoutines::_generic_arraycopy = generate_generic_copy("generic_arraycopy");
|
entry_jbyte_arraycopy,
|
||||||
|
entry_jshort_arraycopy,
|
||||||
|
entry_jint_arraycopy,
|
||||||
|
entry_jlong_arraycopy);
|
||||||
|
StubRoutines::_generic_arraycopy = generate_generic_copy("generic_arraycopy",
|
||||||
|
entry_jbyte_arraycopy,
|
||||||
|
entry_jshort_arraycopy,
|
||||||
|
entry_jint_arraycopy,
|
||||||
|
entry_oop_arraycopy,
|
||||||
|
entry_jlong_arraycopy,
|
||||||
|
entry_checkcast_arraycopy);
|
||||||
|
|
||||||
StubRoutines::_jbyte_fill = generate_fill(T_BYTE, false, "jbyte_fill");
|
StubRoutines::_jbyte_fill = generate_fill(T_BYTE, false, "jbyte_fill");
|
||||||
StubRoutines::_jshort_fill = generate_fill(T_SHORT, false, "jshort_fill");
|
StubRoutines::_jshort_fill = generate_fill(T_SHORT, false, "jshort_fill");
|
||||||
|
@ -3224,21 +3268,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
|
|
||||||
}; // end class declaration
|
}; // end class declaration
|
||||||
|
|
||||||
|
|
||||||
address StubGenerator::disjoint_byte_copy_entry = NULL;
|
|
||||||
address StubGenerator::disjoint_short_copy_entry = NULL;
|
|
||||||
address StubGenerator::disjoint_int_copy_entry = NULL;
|
|
||||||
address StubGenerator::disjoint_long_copy_entry = NULL;
|
|
||||||
address StubGenerator::disjoint_oop_copy_entry = NULL;
|
|
||||||
|
|
||||||
address StubGenerator::byte_copy_entry = NULL;
|
|
||||||
address StubGenerator::short_copy_entry = NULL;
|
|
||||||
address StubGenerator::int_copy_entry = NULL;
|
|
||||||
address StubGenerator::long_copy_entry = NULL;
|
|
||||||
address StubGenerator::oop_copy_entry = NULL;
|
|
||||||
|
|
||||||
address StubGenerator::checkcast_copy_entry = NULL;
|
|
||||||
|
|
||||||
void StubGenerator_generate(CodeBuffer* code, bool all) {
|
void StubGenerator_generate(CodeBuffer* code, bool all) {
|
||||||
StubGenerator g(code, all);
|
StubGenerator g(code, all);
|
||||||
}
|
}
|
||||||
|
|
|
@ -945,6 +945,12 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ movptr(from , Address(rsp, 12+ 4));
|
__ movptr(from , Address(rsp, 12+ 4));
|
||||||
__ movptr(to , Address(rsp, 12+ 8));
|
__ movptr(to , Address(rsp, 12+ 8));
|
||||||
__ movl(count, Address(rsp, 12+ 12));
|
__ movl(count, Address(rsp, 12+ 12));
|
||||||
|
|
||||||
|
if (entry != NULL) {
|
||||||
|
*entry = __ pc(); // Entry point from conjoint arraycopy stub.
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
}
|
||||||
|
|
||||||
if (t == T_OBJECT) {
|
if (t == T_OBJECT) {
|
||||||
__ testl(count, count);
|
__ testl(count, count);
|
||||||
__ jcc(Assembler::zero, L_0_count);
|
__ jcc(Assembler::zero, L_0_count);
|
||||||
|
@ -952,9 +958,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ mov(saved_to, to); // save 'to'
|
__ mov(saved_to, to); // save 'to'
|
||||||
}
|
}
|
||||||
|
|
||||||
*entry = __ pc(); // Entry point from conjoint arraycopy stub.
|
|
||||||
BLOCK_COMMENT("Entry:");
|
|
||||||
|
|
||||||
__ subptr(to, from); // to --> to_from
|
__ subptr(to, from); // to --> to_from
|
||||||
__ cmpl(count, 2<<shift); // Short arrays (< 8 bytes) copy by element
|
__ cmpl(count, 2<<shift); // Short arrays (< 8 bytes) copy by element
|
||||||
__ jcc(Assembler::below, L_copy_4_bytes); // use unsigned cmp
|
__ jcc(Assembler::below, L_copy_4_bytes); // use unsigned cmp
|
||||||
|
@ -1108,23 +1111,17 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ movptr(src , Address(rsp, 12+ 4)); // from
|
__ movptr(src , Address(rsp, 12+ 4)); // from
|
||||||
__ movptr(dst , Address(rsp, 12+ 8)); // to
|
__ movptr(dst , Address(rsp, 12+ 8)); // to
|
||||||
__ movl2ptr(count, Address(rsp, 12+12)); // count
|
__ movl2ptr(count, Address(rsp, 12+12)); // count
|
||||||
if (t == T_OBJECT) {
|
|
||||||
gen_write_ref_array_pre_barrier(dst, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry != NULL) {
|
if (entry != NULL) {
|
||||||
*entry = __ pc(); // Entry point from generic arraycopy stub.
|
*entry = __ pc(); // Entry point from generic arraycopy stub.
|
||||||
BLOCK_COMMENT("Entry:");
|
BLOCK_COMMENT("Entry:");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t == T_OBJECT) {
|
// nooverlap_target expects arguments in rsi and rdi.
|
||||||
__ testl(count, count);
|
|
||||||
__ jcc(Assembler::zero, L_0_count);
|
|
||||||
}
|
|
||||||
__ mov(from, src);
|
__ mov(from, src);
|
||||||
__ mov(to , dst);
|
__ mov(to , dst);
|
||||||
|
|
||||||
// arrays overlap test
|
// arrays overlap test: dispatch to disjoint stub if necessary.
|
||||||
RuntimeAddress nooverlap(nooverlap_target);
|
RuntimeAddress nooverlap(nooverlap_target);
|
||||||
__ cmpptr(dst, src);
|
__ cmpptr(dst, src);
|
||||||
__ lea(end, Address(src, count, sf, 0)); // src + count * elem_size
|
__ lea(end, Address(src, count, sf, 0)); // src + count * elem_size
|
||||||
|
@ -1132,6 +1129,12 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ cmpptr(dst, end);
|
__ cmpptr(dst, end);
|
||||||
__ jump_cc(Assembler::aboveEqual, nooverlap);
|
__ jump_cc(Assembler::aboveEqual, nooverlap);
|
||||||
|
|
||||||
|
if (t == T_OBJECT) {
|
||||||
|
__ testl(count, count);
|
||||||
|
__ jcc(Assembler::zero, L_0_count);
|
||||||
|
gen_write_ref_array_pre_barrier(dst, count);
|
||||||
|
}
|
||||||
|
|
||||||
// copy from high to low
|
// copy from high to low
|
||||||
__ cmpl(count, 2<<shift); // Short arrays (< 8 bytes) copy by element
|
__ cmpl(count, 2<<shift); // Short arrays (< 8 bytes) copy by element
|
||||||
__ jcc(Assembler::below, L_copy_4_bytes); // use unsigned cmp
|
__ jcc(Assembler::below, L_copy_4_bytes); // use unsigned cmp
|
||||||
|
@ -1451,8 +1454,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ movptr(to, to_arg);
|
__ movptr(to, to_arg);
|
||||||
__ movl2ptr(length, length_arg);
|
__ movl2ptr(length, length_arg);
|
||||||
|
|
||||||
*entry = __ pc(); // Entry point from generic arraycopy stub.
|
if (entry != NULL) {
|
||||||
BLOCK_COMMENT("Entry:");
|
*entry = __ pc(); // Entry point from generic arraycopy stub.
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// Assembler stub will be used for this call to arraycopy
|
// Assembler stub will be used for this call to arraycopy
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -1057,20 +1057,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
static address disjoint_byte_copy_entry;
|
|
||||||
static address disjoint_short_copy_entry;
|
|
||||||
static address disjoint_int_copy_entry;
|
|
||||||
static address disjoint_long_copy_entry;
|
|
||||||
static address disjoint_oop_copy_entry;
|
|
||||||
|
|
||||||
static address byte_copy_entry;
|
|
||||||
static address short_copy_entry;
|
|
||||||
static address int_copy_entry;
|
|
||||||
static address long_copy_entry;
|
|
||||||
static address oop_copy_entry;
|
|
||||||
|
|
||||||
static address checkcast_copy_entry;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Verify that a register contains clean 32-bits positive value
|
// Verify that a register contains clean 32-bits positive value
|
||||||
// (high 32-bits are 0) so it could be used in 64-bits shifts.
|
// (high 32-bits are 0) so it could be used in 64-bits shifts.
|
||||||
|
@ -1379,7 +1365,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// disjoint_byte_copy_entry is set to the no-overlap entry point
|
// disjoint_byte_copy_entry is set to the no-overlap entry point
|
||||||
// used by generate_conjoint_byte_copy().
|
// used by generate_conjoint_byte_copy().
|
||||||
//
|
//
|
||||||
address generate_disjoint_byte_copy(bool aligned, const char *name) {
|
address generate_disjoint_byte_copy(bool aligned, address* entry, const char *name) {
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", name);
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
@ -1399,9 +1385,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||||
assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int.
|
assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int.
|
||||||
|
|
||||||
disjoint_byte_copy_entry = __ pc();
|
if (entry != NULL) {
|
||||||
BLOCK_COMMENT("Entry:");
|
*entry = __ pc();
|
||||||
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
}
|
||||||
|
|
||||||
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
|
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
|
||||||
// r9 and r10 may be used to save non-volatile registers
|
// r9 and r10 may be used to save non-volatile registers
|
||||||
|
@ -1479,7 +1467,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// dwords or qwords that span cache line boundaries will still be loaded
|
// dwords or qwords that span cache line boundaries will still be loaded
|
||||||
// and stored atomically.
|
// and stored atomically.
|
||||||
//
|
//
|
||||||
address generate_conjoint_byte_copy(bool aligned, const char *name) {
|
address generate_conjoint_byte_copy(bool aligned, address nooverlap_target,
|
||||||
|
address* entry, const char *name) {
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", name);
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
@ -1494,11 +1483,13 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||||
assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int.
|
assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int.
|
||||||
|
|
||||||
byte_copy_entry = __ pc();
|
if (entry != NULL) {
|
||||||
BLOCK_COMMENT("Entry:");
|
*entry = __ pc();
|
||||||
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
}
|
||||||
|
|
||||||
array_overlap_test(disjoint_byte_copy_entry, Address::times_1);
|
array_overlap_test(nooverlap_target, Address::times_1);
|
||||||
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
|
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
|
||||||
// r9 and r10 may be used to save non-volatile registers
|
// r9 and r10 may be used to save non-volatile registers
|
||||||
|
|
||||||
|
@ -1574,7 +1565,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// disjoint_short_copy_entry is set to the no-overlap entry point
|
// disjoint_short_copy_entry is set to the no-overlap entry point
|
||||||
// used by generate_conjoint_short_copy().
|
// used by generate_conjoint_short_copy().
|
||||||
//
|
//
|
||||||
address generate_disjoint_short_copy(bool aligned, const char *name) {
|
address generate_disjoint_short_copy(bool aligned, address *entry, const char *name) {
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", name);
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
@ -1593,9 +1584,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||||
assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int.
|
assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int.
|
||||||
|
|
||||||
disjoint_short_copy_entry = __ pc();
|
if (entry != NULL) {
|
||||||
BLOCK_COMMENT("Entry:");
|
*entry = __ pc();
|
||||||
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
}
|
||||||
|
|
||||||
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
|
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
|
||||||
// r9 and r10 may be used to save non-volatile registers
|
// r9 and r10 may be used to save non-volatile registers
|
||||||
|
@ -1686,7 +1679,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// or qwords that span cache line boundaries will still be loaded
|
// or qwords that span cache line boundaries will still be loaded
|
||||||
// and stored atomically.
|
// and stored atomically.
|
||||||
//
|
//
|
||||||
address generate_conjoint_short_copy(bool aligned, const char *name) {
|
address generate_conjoint_short_copy(bool aligned, address nooverlap_target,
|
||||||
|
address *entry, const char *name) {
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", name);
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
@ -1701,11 +1695,13 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||||
assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int.
|
assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int.
|
||||||
|
|
||||||
short_copy_entry = __ pc();
|
if (entry != NULL) {
|
||||||
BLOCK_COMMENT("Entry:");
|
*entry = __ pc();
|
||||||
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
}
|
||||||
|
|
||||||
array_overlap_test(disjoint_short_copy_entry, Address::times_2);
|
array_overlap_test(nooverlap_target, Address::times_2);
|
||||||
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
|
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
|
||||||
// r9 and r10 may be used to save non-volatile registers
|
// r9 and r10 may be used to save non-volatile registers
|
||||||
|
|
||||||
|
@ -1773,7 +1769,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// disjoint_int_copy_entry is set to the no-overlap entry point
|
// disjoint_int_copy_entry is set to the no-overlap entry point
|
||||||
// used by generate_conjoint_int_oop_copy().
|
// used by generate_conjoint_int_oop_copy().
|
||||||
//
|
//
|
||||||
address generate_disjoint_int_oop_copy(bool aligned, bool is_oop, const char *name) {
|
address generate_disjoint_int_oop_copy(bool aligned, bool is_oop, address* entry, const char *name) {
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", name);
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
@ -1793,21 +1789,17 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||||
assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int.
|
assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int.
|
||||||
|
|
||||||
(is_oop ? disjoint_oop_copy_entry : disjoint_int_copy_entry) = __ pc();
|
if (entry != NULL) {
|
||||||
|
*entry = __ pc();
|
||||||
if (is_oop) {
|
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
||||||
// no registers are destroyed by this call
|
BLOCK_COMMENT("Entry:");
|
||||||
gen_write_ref_array_pre_barrier(/* dest */ c_rarg1, /* count */ c_rarg2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BLOCK_COMMENT("Entry:");
|
|
||||||
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
|
||||||
|
|
||||||
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
|
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
|
||||||
// r9 and r10 may be used to save non-volatile registers
|
// r9 and r10 may be used to save non-volatile registers
|
||||||
|
|
||||||
if (is_oop) {
|
if (is_oop) {
|
||||||
__ movq(saved_to, to);
|
__ movq(saved_to, to);
|
||||||
|
gen_write_ref_array_pre_barrier(to, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 'from', 'to' and 'count' are now valid
|
// 'from', 'to' and 'count' are now valid
|
||||||
|
@ -1867,7 +1859,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// the hardware handle it. The two dwords within qwords that span
|
// the hardware handle it. The two dwords within qwords that span
|
||||||
// cache line boundaries will still be loaded and stored atomicly.
|
// cache line boundaries will still be loaded and stored atomicly.
|
||||||
//
|
//
|
||||||
address generate_conjoint_int_oop_copy(bool aligned, bool is_oop, const char *name) {
|
address generate_conjoint_int_oop_copy(bool aligned, bool is_oop, address nooverlap_target,
|
||||||
|
address *entry, const char *name) {
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", name);
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
@ -1882,20 +1875,21 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||||
assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int.
|
assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int.
|
||||||
|
|
||||||
if (is_oop) {
|
if (entry != NULL) {
|
||||||
// no registers are destroyed by this call
|
*entry = __ pc();
|
||||||
gen_write_ref_array_pre_barrier(/* dest */ c_rarg1, /* count */ c_rarg2);
|
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
}
|
}
|
||||||
|
|
||||||
(is_oop ? oop_copy_entry : int_copy_entry) = __ pc();
|
array_overlap_test(nooverlap_target, Address::times_4);
|
||||||
BLOCK_COMMENT("Entry:");
|
|
||||||
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
|
||||||
|
|
||||||
array_overlap_test(is_oop ? disjoint_oop_copy_entry : disjoint_int_copy_entry,
|
|
||||||
Address::times_4);
|
|
||||||
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
|
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
|
||||||
// r9 and r10 may be used to save non-volatile registers
|
// r9 and r10 may be used to save non-volatile registers
|
||||||
|
|
||||||
|
if (is_oop) {
|
||||||
|
// no registers are destroyed by this call
|
||||||
|
gen_write_ref_array_pre_barrier(to, count);
|
||||||
|
}
|
||||||
|
|
||||||
assert_clean_int(count, rax); // Make sure 'count' is clean int.
|
assert_clean_int(count, rax); // Make sure 'count' is clean int.
|
||||||
// 'from', 'to' and 'count' are now valid
|
// 'from', 'to' and 'count' are now valid
|
||||||
__ movptr(dword_count, count);
|
__ movptr(dword_count, count);
|
||||||
|
@ -1959,7 +1953,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// disjoint_oop_copy_entry or disjoint_long_copy_entry is set to the
|
// disjoint_oop_copy_entry or disjoint_long_copy_entry is set to the
|
||||||
// no-overlap entry point used by generate_conjoint_long_oop_copy().
|
// no-overlap entry point used by generate_conjoint_long_oop_copy().
|
||||||
//
|
//
|
||||||
address generate_disjoint_long_oop_copy(bool aligned, bool is_oop, const char *name) {
|
address generate_disjoint_long_oop_copy(bool aligned, bool is_oop, address *entry, const char *name) {
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", name);
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
@ -1978,20 +1972,19 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// Save no-overlap entry point for generate_conjoint_long_oop_copy()
|
// Save no-overlap entry point for generate_conjoint_long_oop_copy()
|
||||||
assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int.
|
assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int.
|
||||||
|
|
||||||
if (is_oop) {
|
if (entry != NULL) {
|
||||||
disjoint_oop_copy_entry = __ pc();
|
*entry = __ pc();
|
||||||
// no registers are destroyed by this call
|
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
||||||
gen_write_ref_array_pre_barrier(/* dest */ c_rarg1, /* count */ c_rarg2);
|
BLOCK_COMMENT("Entry:");
|
||||||
} else {
|
|
||||||
disjoint_long_copy_entry = __ pc();
|
|
||||||
}
|
}
|
||||||
BLOCK_COMMENT("Entry:");
|
|
||||||
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
|
||||||
|
|
||||||
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
|
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
|
||||||
// r9 and r10 may be used to save non-volatile registers
|
// r9 and r10 may be used to save non-volatile registers
|
||||||
|
|
||||||
// 'from', 'to' and 'qword_count' are now valid
|
// 'from', 'to' and 'qword_count' are now valid
|
||||||
|
if (is_oop) {
|
||||||
|
// no registers are destroyed by this call
|
||||||
|
gen_write_ref_array_pre_barrier(to, qword_count);
|
||||||
|
}
|
||||||
|
|
||||||
// Copy from low to high addresses. Use 'to' as scratch.
|
// Copy from low to high addresses. Use 'to' as scratch.
|
||||||
__ lea(end_from, Address(from, qword_count, Address::times_8, -8));
|
__ lea(end_from, Address(from, qword_count, Address::times_8, -8));
|
||||||
|
@ -2045,7 +2038,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// c_rarg1 - destination array address
|
// c_rarg1 - destination array address
|
||||||
// c_rarg2 - element count, treated as ssize_t, can be zero
|
// c_rarg2 - element count, treated as ssize_t, can be zero
|
||||||
//
|
//
|
||||||
address generate_conjoint_long_oop_copy(bool aligned, bool is_oop, const char *name) {
|
address generate_conjoint_long_oop_copy(bool aligned, bool is_oop, address nooverlap_target,
|
||||||
|
address *entry, const char *name) {
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", name);
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
@ -2059,26 +2053,16 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||||
assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int.
|
assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int.
|
||||||
|
|
||||||
address disjoint_copy_entry = NULL;
|
if (entry != NULL) {
|
||||||
if (is_oop) {
|
*entry = __ pc();
|
||||||
assert(!UseCompressedOops, "shouldn't be called for compressed oops");
|
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
||||||
disjoint_copy_entry = disjoint_oop_copy_entry;
|
BLOCK_COMMENT("Entry:");
|
||||||
oop_copy_entry = __ pc();
|
|
||||||
array_overlap_test(disjoint_oop_copy_entry, Address::times_8);
|
|
||||||
} else {
|
|
||||||
disjoint_copy_entry = disjoint_long_copy_entry;
|
|
||||||
long_copy_entry = __ pc();
|
|
||||||
array_overlap_test(disjoint_long_copy_entry, Address::times_8);
|
|
||||||
}
|
}
|
||||||
BLOCK_COMMENT("Entry:");
|
|
||||||
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
|
||||||
|
|
||||||
array_overlap_test(disjoint_copy_entry, Address::times_8);
|
array_overlap_test(nooverlap_target, Address::times_8);
|
||||||
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
|
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
|
||||||
// r9 and r10 may be used to save non-volatile registers
|
// r9 and r10 may be used to save non-volatile registers
|
||||||
|
|
||||||
// 'from', 'to' and 'qword_count' are now valid
|
// 'from', 'to' and 'qword_count' are now valid
|
||||||
|
|
||||||
if (is_oop) {
|
if (is_oop) {
|
||||||
// Save to and count for store barrier
|
// Save to and count for store barrier
|
||||||
__ movptr(saved_count, qword_count);
|
__ movptr(saved_count, qword_count);
|
||||||
|
@ -2162,7 +2146,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// rax == 0 - success
|
// rax == 0 - success
|
||||||
// rax == -1^K - failure, where K is partial transfer count
|
// rax == -1^K - failure, where K is partial transfer count
|
||||||
//
|
//
|
||||||
address generate_checkcast_copy(const char *name) {
|
address generate_checkcast_copy(const char *name, address *entry) {
|
||||||
|
|
||||||
Label L_load_element, L_store_element, L_do_card_marks, L_done;
|
Label L_load_element, L_store_element, L_do_card_marks, L_done;
|
||||||
|
|
||||||
|
@ -2216,8 +2200,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Caller of this entry point must set up the argument registers.
|
// Caller of this entry point must set up the argument registers.
|
||||||
checkcast_copy_entry = __ pc();
|
if (entry != NULL) {
|
||||||
BLOCK_COMMENT("Entry:");
|
*entry = __ pc();
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
}
|
||||||
|
|
||||||
// allocate spill slots for r13, r14
|
// allocate spill slots for r13, r14
|
||||||
enum {
|
enum {
|
||||||
|
@ -2334,7 +2320,9 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// Examines the alignment of the operands and dispatches
|
// Examines the alignment of the operands and dispatches
|
||||||
// to a long, int, short, or byte copy loop.
|
// to a long, int, short, or byte copy loop.
|
||||||
//
|
//
|
||||||
address generate_unsafe_copy(const char *name) {
|
address generate_unsafe_copy(const char *name,
|
||||||
|
address byte_copy_entry, address short_copy_entry,
|
||||||
|
address int_copy_entry, address long_copy_entry) {
|
||||||
|
|
||||||
Label L_long_aligned, L_int_aligned, L_short_aligned;
|
Label L_long_aligned, L_int_aligned, L_short_aligned;
|
||||||
|
|
||||||
|
@ -2432,7 +2420,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// rax == 0 - success
|
// rax == 0 - success
|
||||||
// rax == -1^K - failure, where K is partial transfer count
|
// rax == -1^K - failure, where K is partial transfer count
|
||||||
//
|
//
|
||||||
address generate_generic_copy(const char *name) {
|
address generate_generic_copy(const char *name,
|
||||||
|
address byte_copy_entry, address short_copy_entry,
|
||||||
|
address int_copy_entry, address long_copy_entry,
|
||||||
|
address oop_copy_entry, address checkcast_copy_entry) {
|
||||||
|
|
||||||
Label L_failed, L_failed_0, L_objArray;
|
Label L_failed, L_failed_0, L_objArray;
|
||||||
Label L_copy_bytes, L_copy_shorts, L_copy_ints, L_copy_longs;
|
Label L_copy_bytes, L_copy_shorts, L_copy_ints, L_copy_longs;
|
||||||
|
@ -2725,33 +2716,60 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_arraycopy_stubs() {
|
void generate_arraycopy_stubs() {
|
||||||
// Call the conjoint generation methods immediately after
|
address entry;
|
||||||
// the disjoint ones so that short branches from the former
|
address entry_jbyte_arraycopy;
|
||||||
// to the latter can be generated.
|
address entry_jshort_arraycopy;
|
||||||
StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(false, "jbyte_disjoint_arraycopy");
|
address entry_jint_arraycopy;
|
||||||
StubRoutines::_jbyte_arraycopy = generate_conjoint_byte_copy(false, "jbyte_arraycopy");
|
address entry_oop_arraycopy;
|
||||||
|
address entry_jlong_arraycopy;
|
||||||
|
address entry_checkcast_arraycopy;
|
||||||
|
|
||||||
StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, "jshort_disjoint_arraycopy");
|
StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(false, &entry,
|
||||||
StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(false, "jshort_arraycopy");
|
"jbyte_disjoint_arraycopy");
|
||||||
|
StubRoutines::_jbyte_arraycopy = generate_conjoint_byte_copy(false, entry, &entry_jbyte_arraycopy,
|
||||||
|
"jbyte_arraycopy");
|
||||||
|
|
||||||
StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_oop_copy(false, false, "jint_disjoint_arraycopy");
|
StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, &entry,
|
||||||
StubRoutines::_jint_arraycopy = generate_conjoint_int_oop_copy(false, false, "jint_arraycopy");
|
"jshort_disjoint_arraycopy");
|
||||||
|
StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(false, entry, &entry_jshort_arraycopy,
|
||||||
|
"jshort_arraycopy");
|
||||||
|
|
||||||
StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, false, "jlong_disjoint_arraycopy");
|
StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_oop_copy(false, false, &entry,
|
||||||
StubRoutines::_jlong_arraycopy = generate_conjoint_long_oop_copy(false, false, "jlong_arraycopy");
|
"jint_disjoint_arraycopy");
|
||||||
|
StubRoutines::_jint_arraycopy = generate_conjoint_int_oop_copy(false, false, entry,
|
||||||
|
&entry_jint_arraycopy, "jint_arraycopy");
|
||||||
|
|
||||||
|
StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, false, &entry,
|
||||||
|
"jlong_disjoint_arraycopy");
|
||||||
|
StubRoutines::_jlong_arraycopy = generate_conjoint_long_oop_copy(false, false, entry,
|
||||||
|
&entry_jlong_arraycopy, "jlong_arraycopy");
|
||||||
|
|
||||||
|
|
||||||
if (UseCompressedOops) {
|
if (UseCompressedOops) {
|
||||||
StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_int_oop_copy(false, true, "oop_disjoint_arraycopy");
|
StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_int_oop_copy(false, true, &entry,
|
||||||
StubRoutines::_oop_arraycopy = generate_conjoint_int_oop_copy(false, true, "oop_arraycopy");
|
"oop_disjoint_arraycopy");
|
||||||
|
StubRoutines::_oop_arraycopy = generate_conjoint_int_oop_copy(false, true, entry,
|
||||||
|
&entry_oop_arraycopy, "oop_arraycopy");
|
||||||
} else {
|
} else {
|
||||||
StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, true, "oop_disjoint_arraycopy");
|
StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, true, &entry,
|
||||||
StubRoutines::_oop_arraycopy = generate_conjoint_long_oop_copy(false, true, "oop_arraycopy");
|
"oop_disjoint_arraycopy");
|
||||||
|
StubRoutines::_oop_arraycopy = generate_conjoint_long_oop_copy(false, true, entry,
|
||||||
|
&entry_oop_arraycopy, "oop_arraycopy");
|
||||||
}
|
}
|
||||||
|
|
||||||
StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy");
|
StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy);
|
||||||
StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy");
|
StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy",
|
||||||
StubRoutines::_generic_arraycopy = generate_generic_copy("generic_arraycopy");
|
entry_jbyte_arraycopy,
|
||||||
|
entry_jshort_arraycopy,
|
||||||
|
entry_jint_arraycopy,
|
||||||
|
entry_jlong_arraycopy);
|
||||||
|
StubRoutines::_generic_arraycopy = generate_generic_copy("generic_arraycopy",
|
||||||
|
entry_jbyte_arraycopy,
|
||||||
|
entry_jshort_arraycopy,
|
||||||
|
entry_jint_arraycopy,
|
||||||
|
entry_oop_arraycopy,
|
||||||
|
entry_jlong_arraycopy,
|
||||||
|
entry_checkcast_arraycopy);
|
||||||
|
|
||||||
StubRoutines::_jbyte_fill = generate_fill(T_BYTE, false, "jbyte_fill");
|
StubRoutines::_jbyte_fill = generate_fill(T_BYTE, false, "jbyte_fill");
|
||||||
StubRoutines::_jshort_fill = generate_fill(T_SHORT, false, "jshort_fill");
|
StubRoutines::_jshort_fill = generate_fill(T_SHORT, false, "jshort_fill");
|
||||||
|
@ -3069,20 +3087,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
}
|
}
|
||||||
}; // end class declaration
|
}; // end class declaration
|
||||||
|
|
||||||
address StubGenerator::disjoint_byte_copy_entry = NULL;
|
|
||||||
address StubGenerator::disjoint_short_copy_entry = NULL;
|
|
||||||
address StubGenerator::disjoint_int_copy_entry = NULL;
|
|
||||||
address StubGenerator::disjoint_long_copy_entry = NULL;
|
|
||||||
address StubGenerator::disjoint_oop_copy_entry = NULL;
|
|
||||||
|
|
||||||
address StubGenerator::byte_copy_entry = NULL;
|
|
||||||
address StubGenerator::short_copy_entry = NULL;
|
|
||||||
address StubGenerator::int_copy_entry = NULL;
|
|
||||||
address StubGenerator::long_copy_entry = NULL;
|
|
||||||
address StubGenerator::oop_copy_entry = NULL;
|
|
||||||
|
|
||||||
address StubGenerator::checkcast_copy_entry = NULL;
|
|
||||||
|
|
||||||
void StubGenerator_generate(CodeBuffer* code, bool all) {
|
void StubGenerator_generate(CodeBuffer* code, bool all) {
|
||||||
StubGenerator g(code, all);
|
StubGenerator g(code, all);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue