Home | History | Annotate | Download | only in native
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "common_throws.h"
     18 #include "gc/accounting/card_table-inl.h"
     19 #include "jni_internal.h"
     20 #include "mirror/array.h"
     21 #include "mirror/class.h"
     22 #include "mirror/class-inl.h"
     23 #include "mirror/object-inl.h"
     24 #include "mirror/object_array-inl.h"
     25 #include "scoped_thread_state_change.h"
     26 
     27 /*
     28  * We make guarantees about the atomicity of accesses to primitive
     29  * variables.  These guarantees also apply to elements of arrays.
     30  * In particular, 8-bit, 16-bit, and 32-bit accesses must be atomic and
     31  * must not cause "word tearing".  Accesses to 64-bit array elements must
     32  * either be atomic or treated as two 32-bit operations.  References are
     33  * always read and written atomically, regardless of the number of bits
     34  * used to represent them.
     35  *
     36  * We can't rely on standard libc functions like memcpy(3) and memmove(3)
     37  * in our implementation of System.arraycopy, because they may copy
     38  * byte-by-byte (either for the full run or for "unaligned" parts at the
     39  * start or end).  We need to use functions that guarantee 16-bit or 32-bit
     40  * atomicity as appropriate.
     41  *
     42  * System.arraycopy() is heavily used, so having an efficient implementation
     43  * is important.  The bionic libc provides a platform-optimized memory move
     44  * function that should be used when possible.  If it's not available,
     45  * the trivial "reference implementation" versions below can be used until
     46  * a proper version can be written.
     47  *
     48  * For these functions, The caller must guarantee that dst/src are aligned
     49  * appropriately for the element type, and that n is a multiple of the
     50  * element size.
     51  */
     52 
     53 /*
     54  * Works like memmove(), except:
     55  * - if all arguments are at least 32-bit aligned, we guarantee that we
     56  *   will use operations that preserve atomicity of 32-bit values
     57  * - if not, we guarantee atomicity of 16-bit values
     58  *
     59  * If all three arguments are not at least 16-bit aligned, the behavior
     60  * of this function is undefined.  (We could remove this restriction by
     61  * testing for unaligned values and punting to memmove(), but that's
     62  * not currently useful.)
     63  *
     64  * TODO: add loop for 64-bit alignment
     65  * TODO: use __builtin_prefetch
     66  * TODO: write ARM/MIPS/x86 optimized versions
     67  */
     68 void MemmoveWords(void* dst, const void* src, size_t n) {
     69   DCHECK_EQ((((uintptr_t) dst | (uintptr_t) src | n) & 0x01), 0U);
     70 
     71   char* d = reinterpret_cast<char*>(dst);
     72   const char* s = reinterpret_cast<const char*>(src);
     73   size_t copyCount;
     74 
     75   // If the source and destination pointers are the same, this is
     76   // an expensive no-op.  Testing for an empty move now allows us
     77   // to skip a check later.
     78   if (n == 0 || d == s) {
     79     return;
     80   }
     81 
     82   // Determine if the source and destination buffers will overlap if
     83   // we copy data forward (i.e. *dst++ = *src++).
     84   //
     85   // It's okay if the destination buffer starts before the source and
     86   // there is some overlap, because the reader is always ahead of the
     87   // writer.
     88   if (LIKELY((d < s) || ((size_t)(d - s) >= n))) {
     89     // Copy forward.  We prefer 32-bit loads and stores even for 16-bit
     90     // data, so sort that out.
     91     if (((reinterpret_cast<uintptr_t>(d) | reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
     92       // Not 32-bit aligned.  Two possibilities:
     93       // (1) Congruent, we can align to 32-bit by copying one 16-bit val
     94       // (2) Non-congruent, we can do one of:
     95       //   a. copy whole buffer as a series of 16-bit values
     96       //   b. load/store 32 bits, using shifts to ensure alignment
     97       //   c. just copy the as 32-bit values and assume the CPU
     98       //      will do a reasonable job
     99       //
    100       // We're currently using (a), which is suboptimal.
    101       if (((reinterpret_cast<uintptr_t>(d) ^ reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
    102         copyCount = n;
    103       } else {
    104         copyCount = 2;
    105       }
    106       n -= copyCount;
    107       copyCount /= sizeof(uint16_t);
    108 
    109       while (copyCount--) {
    110         *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
    111         d += sizeof(uint16_t);
    112         s += sizeof(uint16_t);
    113       }
    114     }
    115 
    116     // Copy 32-bit aligned words.
    117     copyCount = n / sizeof(uint32_t);
    118     while (copyCount--) {
    119       *reinterpret_cast<uint32_t*>(d) = *reinterpret_cast<const uint32_t*>(s);
    120       d += sizeof(uint32_t);
    121       s += sizeof(uint32_t);
    122     }
    123 
    124     // Check for leftovers.  Either we finished exactly, or we have one remaining 16-bit chunk.
    125     if ((n & 0x02) != 0) {
    126       *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
    127     }
    128   } else {
    129     // Copy backward, starting at the end.
    130     d += n;
    131     s += n;
    132 
    133     if (((reinterpret_cast<uintptr_t>(d) | reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
    134       // try for 32-bit alignment.
    135       if (((reinterpret_cast<uintptr_t>(d) ^ reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
    136         copyCount = n;
    137       } else {
    138         copyCount = 2;
    139       }
    140       n -= copyCount;
    141       copyCount /= sizeof(uint16_t);
    142 
    143       while (copyCount--) {
    144         d -= sizeof(uint16_t);
    145         s -= sizeof(uint16_t);
    146         *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
    147       }
    148     }
    149 
    150     // Copy 32-bit aligned words.
    151     copyCount = n / sizeof(uint32_t);
    152     while (copyCount--) {
    153       d -= sizeof(uint32_t);
    154       s -= sizeof(uint32_t);
    155       *reinterpret_cast<uint32_t*>(d) = *reinterpret_cast<const uint32_t*>(s);
    156     }
    157 
    158     // Copy leftovers.
    159     if ((n & 0x02) != 0) {
    160       d -= sizeof(uint16_t);
    161       s -= sizeof(uint16_t);
    162       *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
    163     }
    164   }
    165 }
    166 
    167 #define move16 MemmoveWords
    168 #define move32 MemmoveWords
    169 
    170 namespace art {
    171 
    172 static void ThrowArrayStoreException_NotAnArray(const char* identifier, mirror::Object* array)
    173     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    174   std::string actualType(PrettyTypeOf(array));
    175   Thread* self = Thread::Current();
    176   ThrowLocation throw_location = self->GetCurrentLocationForThrow();
    177   self->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
    178                            "%s of type %s is not an array", identifier, actualType.c_str());
    179 }
    180 
    181 static void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst, jint dstPos, jint length) {
    182   ScopedObjectAccess soa(env);
    183 
    184   // Null pointer checks.
    185   if (UNLIKELY(javaSrc == NULL)) {
    186     ThrowNullPointerException(NULL, "src == null");
    187     return;
    188   }
    189   if (UNLIKELY(javaDst == NULL)) {
    190     ThrowNullPointerException(NULL, "dst == null");
    191     return;
    192   }
    193 
    194   // Make sure source and destination are both arrays.
    195   mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc);
    196   mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
    197   if (UNLIKELY(!srcObject->IsArrayInstance())) {
    198     ThrowArrayStoreException_NotAnArray("source", srcObject);
    199     return;
    200   }
    201   if (UNLIKELY(!dstObject->IsArrayInstance())) {
    202     ThrowArrayStoreException_NotAnArray("destination", dstObject);
    203     return;
    204   }
    205   mirror::Array* srcArray = srcObject->AsArray();
    206   mirror::Array* dstArray = dstObject->AsArray();
    207   mirror::Class* srcComponentType = srcArray->GetClass()->GetComponentType();
    208   mirror::Class* dstComponentType = dstArray->GetClass()->GetComponentType();
    209 
    210   // Bounds checking.
    211   if (UNLIKELY(srcPos < 0 || dstPos < 0 || length < 0 || srcPos > srcArray->GetLength() - length || dstPos > dstArray->GetLength() - length)) {
    212     ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
    213     soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayIndexOutOfBoundsException;",
    214                                    "src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d",
    215                                    srcArray->GetLength(), srcPos, dstArray->GetLength(), dstPos, length);
    216     return;
    217   }
    218 
    219   // Handle primitive arrays.
    220   if (srcComponentType->IsPrimitive() || dstComponentType->IsPrimitive()) {
    221     // If one of the arrays holds a primitive type the other array must hold the exact same type.
    222     if (UNLIKELY(srcComponentType != dstComponentType)) {
    223       std::string srcType(PrettyTypeOf(srcArray));
    224       std::string dstType(PrettyTypeOf(dstArray));
    225       ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
    226       soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
    227                                      "Incompatible types: src=%s, dst=%s",
    228                                      srcType.c_str(), dstType.c_str());
    229       return;
    230     }
    231 
    232     size_t width = srcArray->GetClass()->GetComponentSize();
    233     uint8_t* dstBytes = reinterpret_cast<uint8_t*>(dstArray->GetRawData(width));
    234     const uint8_t* srcBytes = reinterpret_cast<const uint8_t*>(srcArray->GetRawData(width));
    235 
    236     switch (width) {
    237     case 1:
    238       memmove(dstBytes + dstPos, srcBytes + srcPos, length);
    239       break;
    240     case 2:
    241       move16(dstBytes + dstPos * 2, srcBytes + srcPos * 2, length * 2);
    242       break;
    243     case 4:
    244       move32(dstBytes + dstPos * 4, srcBytes + srcPos * 4, length * 4);
    245       break;
    246     case 8:
    247       // We don't need to guarantee atomicity of the entire 64-bit word.
    248       move32(dstBytes + dstPos * 8, srcBytes + srcPos * 8, length * 8);
    249       break;
    250     default:
    251       LOG(FATAL) << "Unknown primitive array type: " << PrettyTypeOf(srcArray);
    252     }
    253 
    254     return;
    255   }
    256 
    257   // Neither class is primitive. Are the types trivially compatible?
    258   const size_t width = sizeof(mirror::Object*);
    259   uint8_t* dstBytes = reinterpret_cast<uint8_t*>(dstArray->GetRawData(width));
    260   const uint8_t* srcBytes = reinterpret_cast<const uint8_t*>(srcArray->GetRawData(width));
    261   if (dstArray == srcArray || dstComponentType->IsAssignableFrom(srcComponentType)) {
    262     // Yes. Bulk copy.
    263     COMPILE_ASSERT(sizeof(width) == sizeof(uint32_t), move32_assumes_Object_references_are_32_bit);
    264     move32(dstBytes + dstPos * width, srcBytes + srcPos * width, length * width);
    265     Runtime::Current()->GetHeap()->WriteBarrierArray(dstArray, dstPos, length);
    266     return;
    267   }
    268 
    269   // The arrays are not trivially compatible. However, we may still be able to copy some or all of
    270   // the elements if the source objects are compatible (for example, copying an Object[] to
    271   // String[], the Objects being copied might actually be Strings).
    272   // We can't do a bulk move because that would introduce a check-use race condition, so we copy
    273   // elements one by one.
    274 
    275   // We already dealt with overlapping copies, so we don't need to cope with that case below.
    276   CHECK_NE(dstArray, srcArray);
    277 
    278   mirror::Object* const * srcObjects =
    279       reinterpret_cast<mirror::Object* const *>(srcBytes + srcPos * width);
    280   mirror::Object** dstObjects = reinterpret_cast<mirror::Object**>(dstBytes + dstPos * width);
    281   mirror::Class* dstClass = dstArray->GetClass()->GetComponentType();
    282 
    283   // We want to avoid redundant IsAssignableFrom checks where possible, so we cache a class that
    284   // we know is assignable to the destination array's component type.
    285   mirror::Class* lastAssignableElementClass = dstClass;
    286 
    287   mirror::Object* o = NULL;
    288   int i = 0;
    289   for (; i < length; ++i) {
    290     o = srcObjects[i];
    291     if (o != NULL) {
    292       mirror::Class* oClass = o->GetClass();
    293       if (lastAssignableElementClass == oClass) {
    294         dstObjects[i] = o;
    295       } else if (dstClass->IsAssignableFrom(oClass)) {
    296         lastAssignableElementClass = oClass;
    297         dstObjects[i] = o;
    298       } else {
    299         // Can't put this element into the array.
    300         break;
    301       }
    302     } else {
    303       dstObjects[i] = NULL;
    304     }
    305   }
    306 
    307   Runtime::Current()->GetHeap()->WriteBarrierArray(dstArray, dstPos, length);
    308   if (UNLIKELY(i != length)) {
    309     std::string actualSrcType(PrettyTypeOf(o));
    310     std::string dstType(PrettyTypeOf(dstArray));
    311     ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
    312     soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
    313                                    "source[%d] of type %s cannot be stored in destination array of type %s",
    314                                    srcPos + i, actualSrcType.c_str(), dstType.c_str());
    315     return;
    316   }
    317 }
    318 
    319 static jint System_identityHashCode(JNIEnv* env, jclass, jobject javaObject) {
    320   ScopedObjectAccess soa(env);
    321   mirror::Object* o = soa.Decode<mirror::Object*>(javaObject);
    322   return static_cast<jint>(o->IdentityHashCode());
    323 }
    324 
    325 static JNINativeMethod gMethods[] = {
    326   NATIVE_METHOD(System, arraycopy, "(Ljava/lang/Object;ILjava/lang/Object;II)V"),
    327   NATIVE_METHOD(System, identityHashCode, "(Ljava/lang/Object;)I"),
    328 };
    329 
    330 void register_java_lang_System(JNIEnv* env) {
    331   REGISTER_NATIVE_METHODS("java/lang/System");
    332 }
    333 
    334 }  // namespace art
    335