src/share/vm/runtime/stubRoutines.cpp

changeset 0
f90c822e73f8
child 6876
710a3c8b516e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/runtime/stubRoutines.cpp	Wed Apr 27 01:25:04 2016 +0800
     1.3 @@ -0,0 +1,523 @@
     1.4 +/*
     1.5 + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.23 + * or visit www.oracle.com if you need additional information or have any
    1.24 + * questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include "precompiled.hpp"
    1.29 +#include "asm/codeBuffer.hpp"
    1.30 +#include "memory/resourceArea.hpp"
    1.31 +#include "oops/oop.inline.hpp"
    1.32 +#include "runtime/interfaceSupport.hpp"
    1.33 +#include "runtime/sharedRuntime.hpp"
    1.34 +#include "runtime/stubRoutines.hpp"
    1.35 +#include "runtime/timer.hpp"
    1.36 +#include "utilities/copy.hpp"
    1.37 +#ifdef COMPILER2
    1.38 +#include "opto/runtime.hpp"
    1.39 +#endif
    1.40 +
    1.41 +
    1.42 +// Implementation of StubRoutines - for a description
    1.43 +// of how to extend it, see the header file.
    1.44 +
    1.45 +// Class Variables
    1.46 +
    1.47 +BufferBlob* StubRoutines::_code1                                = NULL;
    1.48 +BufferBlob* StubRoutines::_code2                                = NULL;
    1.49 +
    1.50 +address StubRoutines::_call_stub_return_address                 = NULL;
    1.51 +address StubRoutines::_call_stub_entry                          = NULL;
    1.52 +
    1.53 +address StubRoutines::_catch_exception_entry                    = NULL;
    1.54 +address StubRoutines::_forward_exception_entry                  = NULL;
    1.55 +address StubRoutines::_throw_AbstractMethodError_entry          = NULL;
    1.56 +address StubRoutines::_throw_IncompatibleClassChangeError_entry = NULL;
    1.57 +address StubRoutines::_throw_NullPointerException_at_call_entry = NULL;
    1.58 +address StubRoutines::_throw_StackOverflowError_entry           = NULL;
    1.59 +address StubRoutines::_handler_for_unsafe_access_entry          = NULL;
    1.60 +jint    StubRoutines::_verify_oop_count                         = 0;
    1.61 +address StubRoutines::_verify_oop_subroutine_entry              = NULL;
    1.62 +address StubRoutines::_atomic_xchg_entry                        = NULL;
    1.63 +address StubRoutines::_atomic_xchg_ptr_entry                    = NULL;
    1.64 +address StubRoutines::_atomic_store_entry                       = NULL;
    1.65 +address StubRoutines::_atomic_store_ptr_entry                   = NULL;
    1.66 +address StubRoutines::_atomic_cmpxchg_entry                     = NULL;
    1.67 +address StubRoutines::_atomic_cmpxchg_ptr_entry                 = NULL;
    1.68 +address StubRoutines::_atomic_cmpxchg_long_entry                = NULL;
    1.69 +address StubRoutines::_atomic_add_entry                         = NULL;
    1.70 +address StubRoutines::_atomic_add_ptr_entry                     = NULL;
    1.71 +address StubRoutines::_fence_entry                              = NULL;
    1.72 +address StubRoutines::_d2i_wrapper                              = NULL;
    1.73 +address StubRoutines::_d2l_wrapper                              = NULL;
    1.74 +
    1.75 +jint    StubRoutines::_fpu_cntrl_wrd_std                        = 0;
    1.76 +jint    StubRoutines::_fpu_cntrl_wrd_24                         = 0;
    1.77 +jint    StubRoutines::_fpu_cntrl_wrd_64                         = 0;
    1.78 +jint    StubRoutines::_fpu_cntrl_wrd_trunc                      = 0;
    1.79 +jint    StubRoutines::_mxcsr_std                                = 0;
    1.80 +jint    StubRoutines::_fpu_subnormal_bias1[3]                   = { 0, 0, 0 };
    1.81 +jint    StubRoutines::_fpu_subnormal_bias2[3]                   = { 0, 0, 0 };
    1.82 +
    1.83 +// Compiled code entry points default values
    1.84 +// The default functions don't have separate disjoint versions.
    1.85 +address StubRoutines::_jbyte_arraycopy          = CAST_FROM_FN_PTR(address, StubRoutines::jbyte_copy);
    1.86 +address StubRoutines::_jshort_arraycopy         = CAST_FROM_FN_PTR(address, StubRoutines::jshort_copy);
    1.87 +address StubRoutines::_jint_arraycopy           = CAST_FROM_FN_PTR(address, StubRoutines::jint_copy);
    1.88 +address StubRoutines::_jlong_arraycopy          = CAST_FROM_FN_PTR(address, StubRoutines::jlong_copy);
    1.89 +address StubRoutines::_oop_arraycopy            = CAST_FROM_FN_PTR(address, StubRoutines::oop_copy);
    1.90 +address StubRoutines::_oop_arraycopy_uninit     = CAST_FROM_FN_PTR(address, StubRoutines::oop_copy_uninit);
    1.91 +address StubRoutines::_jbyte_disjoint_arraycopy          = CAST_FROM_FN_PTR(address, StubRoutines::jbyte_copy);
    1.92 +address StubRoutines::_jshort_disjoint_arraycopy         = CAST_FROM_FN_PTR(address, StubRoutines::jshort_copy);
    1.93 +address StubRoutines::_jint_disjoint_arraycopy           = CAST_FROM_FN_PTR(address, StubRoutines::jint_copy);
    1.94 +address StubRoutines::_jlong_disjoint_arraycopy          = CAST_FROM_FN_PTR(address, StubRoutines::jlong_copy);
    1.95 +address StubRoutines::_oop_disjoint_arraycopy            = CAST_FROM_FN_PTR(address, StubRoutines::oop_copy);
    1.96 +address StubRoutines::_oop_disjoint_arraycopy_uninit     = CAST_FROM_FN_PTR(address, StubRoutines::oop_copy_uninit);
    1.97 +
    1.98 +address StubRoutines::_arrayof_jbyte_arraycopy  = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jbyte_copy);
    1.99 +address StubRoutines::_arrayof_jshort_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jshort_copy);
   1.100 +address StubRoutines::_arrayof_jint_arraycopy   = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jint_copy);
   1.101 +address StubRoutines::_arrayof_jlong_arraycopy  = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jlong_copy);
   1.102 +address StubRoutines::_arrayof_oop_arraycopy    = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_oop_copy);
   1.103 +address StubRoutines::_arrayof_oop_arraycopy_uninit      = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_oop_copy_uninit);
   1.104 +address StubRoutines::_arrayof_jbyte_disjoint_arraycopy  = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jbyte_copy);
   1.105 +address StubRoutines::_arrayof_jshort_disjoint_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jshort_copy);
   1.106 +address StubRoutines::_arrayof_jint_disjoint_arraycopy   = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jint_copy);
   1.107 +address StubRoutines::_arrayof_jlong_disjoint_arraycopy  = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jlong_copy);
   1.108 +address StubRoutines::_arrayof_oop_disjoint_arraycopy    = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_oop_copy);
   1.109 +address StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit  = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_oop_copy_uninit);
   1.110 +
   1.111 +address StubRoutines::_zero_aligned_words = CAST_FROM_FN_PTR(address, Copy::zero_to_words);
   1.112 +
   1.113 +address StubRoutines::_checkcast_arraycopy               = NULL;
   1.114 +address StubRoutines::_checkcast_arraycopy_uninit        = NULL;
   1.115 +address StubRoutines::_unsafe_arraycopy                  = NULL;
   1.116 +address StubRoutines::_generic_arraycopy                 = NULL;
   1.117 +
   1.118 +
   1.119 +address StubRoutines::_jbyte_fill;
   1.120 +address StubRoutines::_jshort_fill;
   1.121 +address StubRoutines::_jint_fill;
   1.122 +address StubRoutines::_arrayof_jbyte_fill;
   1.123 +address StubRoutines::_arrayof_jshort_fill;
   1.124 +address StubRoutines::_arrayof_jint_fill;
   1.125 +
   1.126 +address StubRoutines::_aescrypt_encryptBlock               = NULL;
   1.127 +address StubRoutines::_aescrypt_decryptBlock               = NULL;
   1.128 +address StubRoutines::_cipherBlockChaining_encryptAESCrypt = NULL;
   1.129 +address StubRoutines::_cipherBlockChaining_decryptAESCrypt = NULL;
   1.130 +
   1.131 +address StubRoutines::_updateBytesCRC32 = NULL;
   1.132 +address StubRoutines::_crc_table_adr = NULL;
   1.133 +
   1.134 +double (* StubRoutines::_intrinsic_log   )(double) = NULL;
   1.135 +double (* StubRoutines::_intrinsic_log10 )(double) = NULL;
   1.136 +double (* StubRoutines::_intrinsic_exp   )(double) = NULL;
   1.137 +double (* StubRoutines::_intrinsic_pow   )(double, double) = NULL;
   1.138 +double (* StubRoutines::_intrinsic_sin   )(double) = NULL;
   1.139 +double (* StubRoutines::_intrinsic_cos   )(double) = NULL;
   1.140 +double (* StubRoutines::_intrinsic_tan   )(double) = NULL;
   1.141 +
   1.142 +address StubRoutines::_safefetch32_entry                 = NULL;
   1.143 +address StubRoutines::_safefetch32_fault_pc              = NULL;
   1.144 +address StubRoutines::_safefetch32_continuation_pc       = NULL;
   1.145 +address StubRoutines::_safefetchN_entry                  = NULL;
   1.146 +address StubRoutines::_safefetchN_fault_pc               = NULL;
   1.147 +address StubRoutines::_safefetchN_continuation_pc        = NULL;
   1.148 +
   1.149 +// Initialization
   1.150 +//
   1.151 +// Note: to break cycle with universe initialization, stubs are generated in two phases.
   1.152 +// The first one generates stubs needed during universe init (e.g., _handle_must_compile_first_entry).
   1.153 +// The second phase includes all other stubs (which may depend on universe being initialized.)
   1.154 +
   1.155 +extern void StubGenerator_generate(CodeBuffer* code, bool all); // only interface to generators
   1.156 +
   1.157 +void StubRoutines::initialize1() {
   1.158 +  if (_code1 == NULL) {
   1.159 +    ResourceMark rm;
   1.160 +    TraceTime timer("StubRoutines generation 1", TraceStartupTime);
   1.161 +    _code1 = BufferBlob::create("StubRoutines (1)", code_size1);
   1.162 +    if (_code1 == NULL) {
   1.163 +      vm_exit_out_of_memory(code_size1, OOM_MALLOC_ERROR, "CodeCache: no room for StubRoutines (1)");
   1.164 +    }
   1.165 +    CodeBuffer buffer(_code1);
   1.166 +    StubGenerator_generate(&buffer, false);
   1.167 +  }
   1.168 +}
   1.169 +
   1.170 +
   1.171 +#ifdef ASSERT
   1.172 +typedef void (*arraycopy_fn)(address src, address dst, int count);
   1.173 +
   1.174 +// simple tests of generated arraycopy functions
   1.175 +static void test_arraycopy_func(address func, int alignment) {
   1.176 +  int v = 0xcc;
   1.177 +  int v2 = 0x11;
   1.178 +  jlong lbuffer[8];
   1.179 +  jlong lbuffer2[8];
   1.180 +  address fbuffer  = (address) lbuffer;
   1.181 +  address fbuffer2 = (address) lbuffer2;
   1.182 +  unsigned int i;
   1.183 +  for (i = 0; i < sizeof(lbuffer); i++) {
   1.184 +    fbuffer[i] = v; fbuffer2[i] = v2;
   1.185 +  }
   1.186 +  // C++ does not guarantee jlong[] array alignment to 8 bytes.
   1.187 +  // Use middle of array to check that memory before it is not modified.
   1.188 +  address buffer  = (address) round_to((intptr_t)&lbuffer[4], BytesPerLong);
   1.189 +  address buffer2 = (address) round_to((intptr_t)&lbuffer2[4], BytesPerLong);
   1.190 +  // do an aligned copy
   1.191 +  ((arraycopy_fn)func)(buffer, buffer2, 0);
   1.192 +  for (i = 0; i < sizeof(lbuffer); i++) {
   1.193 +    assert(fbuffer[i] == v && fbuffer2[i] == v2, "shouldn't have copied anything");
   1.194 +  }
   1.195 +  // adjust destination alignment
   1.196 +  ((arraycopy_fn)func)(buffer, buffer2 + alignment, 0);
   1.197 +  for (i = 0; i < sizeof(lbuffer); i++) {
   1.198 +    assert(fbuffer[i] == v && fbuffer2[i] == v2, "shouldn't have copied anything");
   1.199 +  }
   1.200 +  // adjust source alignment
   1.201 +  ((arraycopy_fn)func)(buffer + alignment, buffer2, 0);
   1.202 +  for (i = 0; i < sizeof(lbuffer); i++) {
   1.203 +    assert(fbuffer[i] == v && fbuffer2[i] == v2, "shouldn't have copied anything");
   1.204 +  }
   1.205 +}
   1.206 +#endif
   1.207 +
   1.208 +
   1.209 +void StubRoutines::initialize2() {
   1.210 +  if (_code2 == NULL) {
   1.211 +    ResourceMark rm;
   1.212 +    TraceTime timer("StubRoutines generation 2", TraceStartupTime);
   1.213 +    _code2 = BufferBlob::create("StubRoutines (2)", code_size2);
   1.214 +    if (_code2 == NULL) {
   1.215 +      vm_exit_out_of_memory(code_size2, OOM_MALLOC_ERROR, "CodeCache: no room for StubRoutines (2)");
   1.216 +    }
   1.217 +    CodeBuffer buffer(_code2);
   1.218 +    StubGenerator_generate(&buffer, true);
   1.219 +  }
   1.220 +
   1.221 +#ifdef ASSERT
   1.222 +
   1.223 +#define TEST_ARRAYCOPY(type)                                                    \
   1.224 +  test_arraycopy_func(          type##_arraycopy(),          sizeof(type));     \
   1.225 +  test_arraycopy_func(          type##_disjoint_arraycopy(), sizeof(type));     \
   1.226 +  test_arraycopy_func(arrayof_##type##_arraycopy(),          sizeof(HeapWord)); \
   1.227 +  test_arraycopy_func(arrayof_##type##_disjoint_arraycopy(), sizeof(HeapWord))
   1.228 +
   1.229 +  // Make sure all the arraycopy stubs properly handle zero count
   1.230 +  TEST_ARRAYCOPY(jbyte);
   1.231 +  TEST_ARRAYCOPY(jshort);
   1.232 +  TEST_ARRAYCOPY(jint);
   1.233 +  TEST_ARRAYCOPY(jlong);
   1.234 +
   1.235 +#undef TEST_ARRAYCOPY
   1.236 +
   1.237 +#define TEST_FILL(type)                                                                      \
   1.238 +  if (_##type##_fill != NULL) {                                                              \
   1.239 +    union {                                                                                  \
   1.240 +      double d;                                                                              \
   1.241 +      type body[96];                                                                         \
   1.242 +    } s;                                                                                     \
   1.243 +                                                                                             \
   1.244 +    int v = 32;                                                                              \
   1.245 +    for (int offset = -2; offset <= 2; offset++) {                                           \
   1.246 +      for (int i = 0; i < 96; i++) {                                                         \
   1.247 +        s.body[i] = 1;                                                                       \
   1.248 +      }                                                                                      \
   1.249 +      type* start = s.body + 8 + offset;                                                     \
   1.250 +      for (int aligned = 0; aligned < 2; aligned++) {                                        \
   1.251 +        if (aligned) {                                                                       \
   1.252 +          if (((intptr_t)start) % HeapWordSize == 0) {                                       \
   1.253 +            ((void (*)(type*, int, int))StubRoutines::_arrayof_##type##_fill)(start, v, 80); \
   1.254 +          } else {                                                                           \
   1.255 +            continue;                                                                        \
   1.256 +          }                                                                                  \
   1.257 +        } else {                                                                             \
   1.258 +          ((void (*)(type*, int, int))StubRoutines::_##type##_fill)(start, v, 80);           \
   1.259 +        }                                                                                    \
   1.260 +        for (int i = 0; i < 96; i++) {                                                       \
   1.261 +          if (i < (8 + offset) || i >= (88 + offset)) {                                      \
   1.262 +            assert(s.body[i] == 1, "what?");                                                 \
   1.263 +          } else {                                                                           \
   1.264 +            assert(s.body[i] == 32, "what?");                                                \
   1.265 +          }                                                                                  \
   1.266 +        }                                                                                    \
   1.267 +      }                                                                                      \
   1.268 +    }                                                                                        \
   1.269 +  }                                                                                          \
   1.270 +
   1.271 +  TEST_FILL(jbyte);
   1.272 +  TEST_FILL(jshort);
   1.273 +  TEST_FILL(jint);
   1.274 +
   1.275 +#undef TEST_FILL
   1.276 +
   1.277 +#define TEST_COPYRTN(type) \
   1.278 +  test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::conjoint_##type##s_atomic),  sizeof(type)); \
   1.279 +  test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::arrayof_conjoint_##type##s), (int)MAX2(sizeof(HeapWord), sizeof(type)))
   1.280 +
   1.281 +  // Make sure all the copy runtime routines properly handle zero count
   1.282 +  TEST_COPYRTN(jbyte);
   1.283 +  TEST_COPYRTN(jshort);
   1.284 +  TEST_COPYRTN(jint);
   1.285 +  TEST_COPYRTN(jlong);
   1.286 +
   1.287 +#undef TEST_COPYRTN
   1.288 +
   1.289 +  test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::conjoint_words), sizeof(HeapWord));
   1.290 +  test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::disjoint_words), sizeof(HeapWord));
   1.291 +  test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::disjoint_words_atomic), sizeof(HeapWord));
   1.292 +  // Aligned to BytesPerLong
   1.293 +  test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::aligned_conjoint_words), sizeof(jlong));
   1.294 +  test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::aligned_disjoint_words), sizeof(jlong));
   1.295 +
   1.296 +#endif
   1.297 +}
   1.298 +
   1.299 +
   1.300 +void stubRoutines_init1() { StubRoutines::initialize1(); }
   1.301 +void stubRoutines_init2() { StubRoutines::initialize2(); }
   1.302 +
   1.303 +//
   1.304 +// Default versions of arraycopy functions
   1.305 +//
   1.306 +
   1.307 +static void gen_arraycopy_barrier_pre(oop* dest, size_t count, bool dest_uninitialized) {
   1.308 +    assert(count != 0, "count should be non-zero");
   1.309 +    assert(count <= (size_t)max_intx, "count too large");
   1.310 +    BarrierSet* bs = Universe::heap()->barrier_set();
   1.311 +    assert(bs->has_write_ref_array_pre_opt(), "Must have pre-barrier opt");
   1.312 +    bs->write_ref_array_pre(dest, (int)count, dest_uninitialized);
   1.313 +}
   1.314 +
   1.315 +static void gen_arraycopy_barrier(oop* dest, size_t count) {
   1.316 +    assert(count != 0, "count should be non-zero");
   1.317 +    BarrierSet* bs = Universe::heap()->barrier_set();
   1.318 +    assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt");
   1.319 +    bs->write_ref_array((HeapWord*)dest, count);
   1.320 +}
   1.321 +
   1.322 +JRT_LEAF(void, StubRoutines::jbyte_copy(jbyte* src, jbyte* dest, size_t count))
   1.323 +#ifndef PRODUCT
   1.324 +  SharedRuntime::_jbyte_array_copy_ctr++;      // Slow-path byte array copy
   1.325 +#endif // !PRODUCT
   1.326 +  Copy::conjoint_jbytes_atomic(src, dest, count);
   1.327 +JRT_END
   1.328 +
   1.329 +JRT_LEAF(void, StubRoutines::jshort_copy(jshort* src, jshort* dest, size_t count))
   1.330 +#ifndef PRODUCT
   1.331 +  SharedRuntime::_jshort_array_copy_ctr++;     // Slow-path short/char array copy
   1.332 +#endif // !PRODUCT
   1.333 +  Copy::conjoint_jshorts_atomic(src, dest, count);
   1.334 +JRT_END
   1.335 +
   1.336 +JRT_LEAF(void, StubRoutines::jint_copy(jint* src, jint* dest, size_t count))
   1.337 +#ifndef PRODUCT
   1.338 +  SharedRuntime::_jint_array_copy_ctr++;       // Slow-path int/float array copy
   1.339 +#endif // !PRODUCT
   1.340 +  Copy::conjoint_jints_atomic(src, dest, count);
   1.341 +JRT_END
   1.342 +
   1.343 +JRT_LEAF(void, StubRoutines::jlong_copy(jlong* src, jlong* dest, size_t count))
   1.344 +#ifndef PRODUCT
   1.345 +  SharedRuntime::_jlong_array_copy_ctr++;      // Slow-path long/double array copy
   1.346 +#endif // !PRODUCT
   1.347 +  Copy::conjoint_jlongs_atomic(src, dest, count);
   1.348 +JRT_END
   1.349 +
   1.350 +JRT_LEAF(void, StubRoutines::oop_copy(oop* src, oop* dest, size_t count))
   1.351 +#ifndef PRODUCT
   1.352 +  SharedRuntime::_oop_array_copy_ctr++;        // Slow-path oop array copy
   1.353 +#endif // !PRODUCT
   1.354 +  assert(count != 0, "count should be non-zero");
   1.355 +  gen_arraycopy_barrier_pre(dest, count, /*dest_uninitialized*/false);
   1.356 +  Copy::conjoint_oops_atomic(src, dest, count);
   1.357 +  gen_arraycopy_barrier(dest, count);
   1.358 +JRT_END
   1.359 +
   1.360 +JRT_LEAF(void, StubRoutines::oop_copy_uninit(oop* src, oop* dest, size_t count))
   1.361 +#ifndef PRODUCT
   1.362 +  SharedRuntime::_oop_array_copy_ctr++;        // Slow-path oop array copy
   1.363 +#endif // !PRODUCT
   1.364 +  assert(count != 0, "count should be non-zero");
   1.365 +  gen_arraycopy_barrier_pre(dest, count, /*dest_uninitialized*/true);
   1.366 +  Copy::conjoint_oops_atomic(src, dest, count);
   1.367 +  gen_arraycopy_barrier(dest, count);
   1.368 +JRT_END
   1.369 +
   1.370 +JRT_LEAF(void, StubRoutines::arrayof_jbyte_copy(HeapWord* src, HeapWord* dest, size_t count))
   1.371 +#ifndef PRODUCT
   1.372 +  SharedRuntime::_jbyte_array_copy_ctr++;      // Slow-path byte array copy
   1.373 +#endif // !PRODUCT
   1.374 +  Copy::arrayof_conjoint_jbytes(src, dest, count);
   1.375 +JRT_END
   1.376 +
   1.377 +JRT_LEAF(void, StubRoutines::arrayof_jshort_copy(HeapWord* src, HeapWord* dest, size_t count))
   1.378 +#ifndef PRODUCT
   1.379 +  SharedRuntime::_jshort_array_copy_ctr++;     // Slow-path short/char array copy
   1.380 +#endif // !PRODUCT
   1.381 +  Copy::arrayof_conjoint_jshorts(src, dest, count);
   1.382 +JRT_END
   1.383 +
   1.384 +JRT_LEAF(void, StubRoutines::arrayof_jint_copy(HeapWord* src, HeapWord* dest, size_t count))
   1.385 +#ifndef PRODUCT
   1.386 +  SharedRuntime::_jint_array_copy_ctr++;       // Slow-path int/float array copy
   1.387 +#endif // !PRODUCT
   1.388 +  Copy::arrayof_conjoint_jints(src, dest, count);
   1.389 +JRT_END
   1.390 +
   1.391 +JRT_LEAF(void, StubRoutines::arrayof_jlong_copy(HeapWord* src, HeapWord* dest, size_t count))
   1.392 +#ifndef PRODUCT
   1.393 +  SharedRuntime::_jlong_array_copy_ctr++;       // Slow-path int/float array copy
   1.394 +#endif // !PRODUCT
   1.395 +  Copy::arrayof_conjoint_jlongs(src, dest, count);
   1.396 +JRT_END
   1.397 +
   1.398 +JRT_LEAF(void, StubRoutines::arrayof_oop_copy(HeapWord* src, HeapWord* dest, size_t count))
   1.399 +#ifndef PRODUCT
   1.400 +  SharedRuntime::_oop_array_copy_ctr++;        // Slow-path oop array copy
   1.401 +#endif // !PRODUCT
   1.402 +  assert(count != 0, "count should be non-zero");
   1.403 +  gen_arraycopy_barrier_pre((oop *) dest, count, /*dest_uninitialized*/false);
   1.404 +  Copy::arrayof_conjoint_oops(src, dest, count);
   1.405 +  gen_arraycopy_barrier((oop *) dest, count);
   1.406 +JRT_END
   1.407 +
   1.408 +JRT_LEAF(void, StubRoutines::arrayof_oop_copy_uninit(HeapWord* src, HeapWord* dest, size_t count))
   1.409 +#ifndef PRODUCT
   1.410 +  SharedRuntime::_oop_array_copy_ctr++;        // Slow-path oop array copy
   1.411 +#endif // !PRODUCT
   1.412 +  assert(count != 0, "count should be non-zero");
   1.413 +  gen_arraycopy_barrier_pre((oop *) dest, count, /*dest_uninitialized*/true);
   1.414 +  Copy::arrayof_conjoint_oops(src, dest, count);
   1.415 +  gen_arraycopy_barrier((oop *) dest, count);
   1.416 +JRT_END
   1.417 +
   1.418 +address StubRoutines::select_fill_function(BasicType t, bool aligned, const char* &name) {
   1.419 +#define RETURN_STUB(xxx_fill) { \
   1.420 +  name = #xxx_fill; \
   1.421 +  return StubRoutines::xxx_fill(); }
   1.422 +
   1.423 +  switch (t) {
   1.424 +  case T_BYTE:
   1.425 +  case T_BOOLEAN:
   1.426 +    if (!aligned) RETURN_STUB(jbyte_fill);
   1.427 +    RETURN_STUB(arrayof_jbyte_fill);
   1.428 +  case T_CHAR:
   1.429 +  case T_SHORT:
   1.430 +    if (!aligned) RETURN_STUB(jshort_fill);
   1.431 +    RETURN_STUB(arrayof_jshort_fill);
   1.432 +  case T_INT:
   1.433 +  case T_FLOAT:
   1.434 +    if (!aligned) RETURN_STUB(jint_fill);
   1.435 +    RETURN_STUB(arrayof_jint_fill);
   1.436 +  case T_DOUBLE:
   1.437 +  case T_LONG:
   1.438 +  case T_ARRAY:
   1.439 +  case T_OBJECT:
   1.440 +  case T_NARROWOOP:
   1.441 +  case T_NARROWKLASS:
   1.442 +  case T_ADDRESS:
   1.443 +    // Currently unsupported
   1.444 +    return NULL;
   1.445 +
   1.446 +  default:
   1.447 +    ShouldNotReachHere();
   1.448 +    return NULL;
   1.449 +  }
   1.450 +
   1.451 +#undef RETURN_STUB
   1.452 +}
   1.453 +
   1.454 +// constants for computing the copy function
   1.455 +enum {
   1.456 +  COPYFUNC_UNALIGNED = 0,
   1.457 +  COPYFUNC_ALIGNED = 1,                 // src, dest aligned to HeapWordSize
   1.458 +  COPYFUNC_CONJOINT = 0,
   1.459 +  COPYFUNC_DISJOINT = 2                 // src != dest, or transfer can descend
   1.460 +};
   1.461 +
   1.462 +// Note:  The condition "disjoint" applies also for overlapping copies
   1.463 +// where an descending copy is permitted (i.e., dest_offset <= src_offset).
   1.464 +address
   1.465 +StubRoutines::select_arraycopy_function(BasicType t, bool aligned, bool disjoint, const char* &name, bool dest_uninitialized) {
   1.466 +  int selector =
   1.467 +    (aligned  ? COPYFUNC_ALIGNED  : COPYFUNC_UNALIGNED) +
   1.468 +    (disjoint ? COPYFUNC_DISJOINT : COPYFUNC_CONJOINT);
   1.469 +
   1.470 +#define RETURN_STUB(xxx_arraycopy) { \
   1.471 +  name = #xxx_arraycopy; \
   1.472 +  return StubRoutines::xxx_arraycopy(); }
   1.473 +
   1.474 +#define RETURN_STUB_PARM(xxx_arraycopy, parm) {           \
   1.475 +  name = #xxx_arraycopy; \
   1.476 +  return StubRoutines::xxx_arraycopy(parm); }
   1.477 +
   1.478 +  switch (t) {
   1.479 +  case T_BYTE:
   1.480 +  case T_BOOLEAN:
   1.481 +    switch (selector) {
   1.482 +    case COPYFUNC_CONJOINT | COPYFUNC_UNALIGNED:  RETURN_STUB(jbyte_arraycopy);
   1.483 +    case COPYFUNC_CONJOINT | COPYFUNC_ALIGNED:    RETURN_STUB(arrayof_jbyte_arraycopy);
   1.484 +    case COPYFUNC_DISJOINT | COPYFUNC_UNALIGNED:  RETURN_STUB(jbyte_disjoint_arraycopy);
   1.485 +    case COPYFUNC_DISJOINT | COPYFUNC_ALIGNED:    RETURN_STUB(arrayof_jbyte_disjoint_arraycopy);
   1.486 +    }
   1.487 +  case T_CHAR:
   1.488 +  case T_SHORT:
   1.489 +    switch (selector) {
   1.490 +    case COPYFUNC_CONJOINT | COPYFUNC_UNALIGNED:  RETURN_STUB(jshort_arraycopy);
   1.491 +    case COPYFUNC_CONJOINT | COPYFUNC_ALIGNED:    RETURN_STUB(arrayof_jshort_arraycopy);
   1.492 +    case COPYFUNC_DISJOINT | COPYFUNC_UNALIGNED:  RETURN_STUB(jshort_disjoint_arraycopy);
   1.493 +    case COPYFUNC_DISJOINT | COPYFUNC_ALIGNED:    RETURN_STUB(arrayof_jshort_disjoint_arraycopy);
   1.494 +    }
   1.495 +  case T_INT:
   1.496 +  case T_FLOAT:
   1.497 +    switch (selector) {
   1.498 +    case COPYFUNC_CONJOINT | COPYFUNC_UNALIGNED:  RETURN_STUB(jint_arraycopy);
   1.499 +    case COPYFUNC_CONJOINT | COPYFUNC_ALIGNED:    RETURN_STUB(arrayof_jint_arraycopy);
   1.500 +    case COPYFUNC_DISJOINT | COPYFUNC_UNALIGNED:  RETURN_STUB(jint_disjoint_arraycopy);
   1.501 +    case COPYFUNC_DISJOINT | COPYFUNC_ALIGNED:    RETURN_STUB(arrayof_jint_disjoint_arraycopy);
   1.502 +    }
   1.503 +  case T_DOUBLE:
   1.504 +  case T_LONG:
   1.505 +    switch (selector) {
   1.506 +    case COPYFUNC_CONJOINT | COPYFUNC_UNALIGNED:  RETURN_STUB(jlong_arraycopy);
   1.507 +    case COPYFUNC_CONJOINT | COPYFUNC_ALIGNED:    RETURN_STUB(arrayof_jlong_arraycopy);
   1.508 +    case COPYFUNC_DISJOINT | COPYFUNC_UNALIGNED:  RETURN_STUB(jlong_disjoint_arraycopy);
   1.509 +    case COPYFUNC_DISJOINT | COPYFUNC_ALIGNED:    RETURN_STUB(arrayof_jlong_disjoint_arraycopy);
   1.510 +    }
   1.511 +  case T_ARRAY:
   1.512 +  case T_OBJECT:
   1.513 +    switch (selector) {
   1.514 +    case COPYFUNC_CONJOINT | COPYFUNC_UNALIGNED:  RETURN_STUB_PARM(oop_arraycopy, dest_uninitialized);
   1.515 +    case COPYFUNC_CONJOINT | COPYFUNC_ALIGNED:    RETURN_STUB_PARM(arrayof_oop_arraycopy, dest_uninitialized);
   1.516 +    case COPYFUNC_DISJOINT | COPYFUNC_UNALIGNED:  RETURN_STUB_PARM(oop_disjoint_arraycopy, dest_uninitialized);
   1.517 +    case COPYFUNC_DISJOINT | COPYFUNC_ALIGNED:    RETURN_STUB_PARM(arrayof_oop_disjoint_arraycopy, dest_uninitialized);
   1.518 +    }
   1.519 +  default:
   1.520 +    ShouldNotReachHere();
   1.521 +    return NULL;
   1.522 +  }
   1.523 +
   1.524 +#undef RETURN_STUB
   1.525 +#undef RETURN_STUB_PARM
   1.526 +}

mercurial