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 "java_lang_System.h"
     18 
     19 #include "common_throws.h"
     20 #include "gc/accounting/card_table-inl.h"
     21 #include "jni_internal.h"
     22 #include "mirror/array.h"
     23 #include "mirror/class.h"
     24 #include "mirror/class-inl.h"
     25 #include "mirror/object-inl.h"
     26 #include "mirror/object_array-inl.h"
     27 #include "scoped_fast_native_object_access.h"
     28 
     29 namespace art {
     30 
     31 /*
     32  * We make guarantees about the atomicity of accesses to primitive variables.  These guarantees
     33  * also apply to elements of arrays. In particular, 8-bit, 16-bit, and 32-bit accesses must not
     34  * cause "word tearing".  Accesses to 64-bit array elements may be two 32-bit operations.
     35  * References are never torn regardless of the number of bits used to represent them.
     36  */
     37 
     38 static void ThrowArrayStoreException_NotAnArray(const char* identifier, mirror::Object* array)
     39     SHARED_REQUIRES(Locks::mutator_lock_) {
     40   std::string actualType(PrettyTypeOf(array));
     41   Thread* self = Thread::Current();
     42   self->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
     43                            "%s of type %s is not an array", identifier, actualType.c_str());
     44 }
     45 
     46 static void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst,
     47                              jint dstPos, jint length) {
     48   // The API is defined in terms of length, but length is somewhat overloaded so we use count.
     49   const jint count = length;
     50   ScopedFastNativeObjectAccess soa(env);
     51 
     52   // Null pointer checks.
     53   if (UNLIKELY(javaSrc == nullptr)) {
     54     ThrowNullPointerException("src == null");
     55     return;
     56   }
     57   if (UNLIKELY(javaDst == nullptr)) {
     58     ThrowNullPointerException("dst == null");
     59     return;
     60   }
     61 
     62   // Make sure source and destination are both arrays.
     63   mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc);
     64   if (UNLIKELY(!srcObject->IsArrayInstance())) {
     65     ThrowArrayStoreException_NotAnArray("source", srcObject);
     66     return;
     67   }
     68   mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
     69   if (UNLIKELY(!dstObject->IsArrayInstance())) {
     70     ThrowArrayStoreException_NotAnArray("destination", dstObject);
     71     return;
     72   }
     73   mirror::Array* srcArray = srcObject->AsArray();
     74   mirror::Array* dstArray = dstObject->AsArray();
     75 
     76   // Bounds checking.
     77   if (UNLIKELY(srcPos < 0) || UNLIKELY(dstPos < 0) || UNLIKELY(count < 0) ||
     78       UNLIKELY(srcPos > srcArray->GetLength() - count) ||
     79       UNLIKELY(dstPos > dstArray->GetLength() - count)) {
     80     soa.Self()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
     81                                    "src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d",
     82                                    srcArray->GetLength(), srcPos, dstArray->GetLength(), dstPos,
     83                                    count);
     84     return;
     85   }
     86 
     87   mirror::Class* dstComponentType = dstArray->GetClass()->GetComponentType();
     88   mirror::Class* srcComponentType = srcArray->GetClass()->GetComponentType();
     89   Primitive::Type dstComponentPrimitiveType = dstComponentType->GetPrimitiveType();
     90 
     91   if (LIKELY(srcComponentType == dstComponentType)) {
     92     // Trivial assignability.
     93     switch (dstComponentPrimitiveType) {
     94       case Primitive::kPrimVoid:
     95         LOG(FATAL) << "Unreachable, cannot have arrays of type void";
     96         UNREACHABLE();
     97       case Primitive::kPrimBoolean:
     98       case Primitive::kPrimByte:
     99         DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 1U);
    100         dstArray->AsByteSizedArray()->Memmove(dstPos, srcArray->AsByteSizedArray(), srcPos, count);
    101         return;
    102       case Primitive::kPrimChar:
    103       case Primitive::kPrimShort:
    104         DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 2U);
    105         dstArray->AsShortSizedArray()->Memmove(dstPos, srcArray->AsShortSizedArray(), srcPos, count);
    106         return;
    107       case Primitive::kPrimInt:
    108         DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 4U);
    109         dstArray->AsIntArray()->Memmove(dstPos, srcArray->AsIntArray(), srcPos, count);
    110         return;
    111       case Primitive::kPrimFloat:
    112         DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 4U);
    113         dstArray->AsFloatArray()->Memmove(dstPos, srcArray->AsFloatArray(), srcPos, count);
    114         return;
    115       case Primitive::kPrimLong:
    116         DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 8U);
    117         dstArray->AsLongArray()->Memmove(dstPos, srcArray->AsLongArray(), srcPos, count);
    118         return;
    119       case Primitive::kPrimDouble:
    120         DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 8U);
    121         dstArray->AsDoubleArray()->Memmove(dstPos, srcArray->AsDoubleArray(), srcPos, count);
    122         return;
    123       case Primitive::kPrimNot: {
    124         mirror::ObjectArray<mirror::Object>* dstObjArray = dstArray->AsObjectArray<mirror::Object>();
    125         mirror::ObjectArray<mirror::Object>* srcObjArray = srcArray->AsObjectArray<mirror::Object>();
    126         dstObjArray->AssignableMemmove(dstPos, srcObjArray, srcPos, count);
    127         return;
    128       }
    129       default:
    130         LOG(FATAL) << "Unknown array type: " << PrettyTypeOf(srcArray);
    131         UNREACHABLE();
    132     }
    133   }
    134   // If one of the arrays holds a primitive type the other array must hold the exact same type.
    135   if (UNLIKELY((dstComponentPrimitiveType != Primitive::kPrimNot) ||
    136                srcComponentType->IsPrimitive())) {
    137     std::string srcType(PrettyTypeOf(srcArray));
    138     std::string dstType(PrettyTypeOf(dstArray));
    139     soa.Self()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
    140                                    "Incompatible types: src=%s, dst=%s",
    141                                    srcType.c_str(), dstType.c_str());
    142     return;
    143   }
    144   // Arrays hold distinct types and so therefore can't alias - use memcpy instead of memmove.
    145   mirror::ObjectArray<mirror::Object>* dstObjArray = dstArray->AsObjectArray<mirror::Object>();
    146   mirror::ObjectArray<mirror::Object>* srcObjArray = srcArray->AsObjectArray<mirror::Object>();
    147   // If we're assigning into say Object[] then we don't need per element checks.
    148   if (dstComponentType->IsAssignableFrom(srcComponentType)) {
    149     dstObjArray->AssignableMemcpy(dstPos, srcObjArray, srcPos, count);
    150     return;
    151   }
    152   // This code is never run under a transaction.
    153   DCHECK(!Runtime::Current()->IsActiveTransaction());
    154   dstObjArray->AssignableCheckingMemcpy<false>(dstPos, srcObjArray, srcPos, count, true);
    155 }
    156 
    157 // Template to convert general array to that of its specific primitive type.
    158 template <typename T>
    159 inline T* AsPrimitiveArray(mirror::Array* array) {
    160   return down_cast<T*>(array);
    161 }
    162 
    163 template <typename T, Primitive::Type kPrimType>
    164 inline void System_arraycopyTUnchecked(JNIEnv* env, jobject javaSrc, jint srcPos,
    165                                        jobject javaDst, jint dstPos, jint count) {
    166   ScopedFastNativeObjectAccess soa(env);
    167   mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc);
    168   mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
    169   DCHECK(dstObject != nullptr);
    170   mirror::Array* srcArray = srcObject->AsArray();
    171   mirror::Array* dstArray = dstObject->AsArray();
    172   DCHECK_GE(count, 0);
    173   DCHECK_EQ(srcArray->GetClass(), dstArray->GetClass());
    174   DCHECK_EQ(srcArray->GetClass()->GetComponentType()->GetPrimitiveType(), kPrimType);
    175   AsPrimitiveArray<T>(dstArray)->Memmove(dstPos, AsPrimitiveArray<T>(srcArray), srcPos, count);
    176 }
    177 
    178 static void System_arraycopyCharUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos,
    179                                           jobject javaDst, jint dstPos, jint count) {
    180   System_arraycopyTUnchecked<mirror::CharArray, Primitive::kPrimChar>(env, javaSrc, srcPos,
    181       javaDst, dstPos, count);
    182 }
    183 
    184 static void System_arraycopyByteUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos,
    185                                           jobject javaDst, jint dstPos, jint count) {
    186   System_arraycopyTUnchecked<mirror::ByteArray, Primitive::kPrimByte>(env, javaSrc, srcPos,
    187       javaDst, dstPos, count);
    188 }
    189 
    190 static void System_arraycopyShortUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos,
    191                                            jobject javaDst, jint dstPos, jint count) {
    192   System_arraycopyTUnchecked<mirror::ShortArray, Primitive::kPrimShort>(env, javaSrc, srcPos,
    193       javaDst, dstPos, count);
    194 }
    195 
    196 static void System_arraycopyIntUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos,
    197                                          jobject javaDst, jint dstPos, jint count) {
    198   System_arraycopyTUnchecked<mirror::IntArray, Primitive::kPrimInt>(env, javaSrc, srcPos,
    199       javaDst, dstPos, count);
    200 }
    201 
    202 static void System_arraycopyLongUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos,
    203                                           jobject javaDst, jint dstPos, jint count) {
    204   System_arraycopyTUnchecked<mirror::LongArray, Primitive::kPrimLong>(env, javaSrc, srcPos,
    205       javaDst, dstPos, count);
    206 }
    207 
    208 static void System_arraycopyFloatUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos,
    209                                            jobject javaDst, jint dstPos, jint count) {
    210   System_arraycopyTUnchecked<mirror::FloatArray, Primitive::kPrimFloat>(env, javaSrc, srcPos,
    211       javaDst, dstPos, count);
    212 }
    213 
    214 static void System_arraycopyDoubleUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos,
    215                                             jobject javaDst, jint dstPos, jint count) {
    216   System_arraycopyTUnchecked<mirror::DoubleArray, Primitive::kPrimDouble>(env, javaSrc, srcPos,
    217       javaDst, dstPos, count);
    218 }
    219 
    220 static void System_arraycopyBooleanUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos,
    221                                              jobject javaDst, jint dstPos, jint count) {
    222   System_arraycopyTUnchecked<mirror::BooleanArray, Primitive::kPrimBoolean>(env, javaSrc, srcPos,
    223       javaDst, dstPos, count);
    224 }
    225 
    226 static jint System_identityHashCode(JNIEnv* env, jclass, jobject javaObject) {
    227   if (UNLIKELY(javaObject == nullptr)) {
    228     return 0;
    229   }
    230   ScopedFastNativeObjectAccess soa(env);
    231   mirror::Object* o = soa.Decode<mirror::Object*>(javaObject);
    232   return static_cast<jint>(o->IdentityHashCode());
    233 }
    234 
    235 static JNINativeMethod gMethods[] = {
    236   NATIVE_METHOD(System, arraycopy, "!(Ljava/lang/Object;ILjava/lang/Object;II)V"),
    237   NATIVE_METHOD(System, arraycopyCharUnchecked, "!([CI[CII)V"),
    238   NATIVE_METHOD(System, arraycopyByteUnchecked, "!([BI[BII)V"),
    239   NATIVE_METHOD(System, arraycopyShortUnchecked, "!([SI[SII)V"),
    240   NATIVE_METHOD(System, arraycopyIntUnchecked, "!([II[III)V"),
    241   NATIVE_METHOD(System, arraycopyLongUnchecked, "!([JI[JII)V"),
    242   NATIVE_METHOD(System, arraycopyFloatUnchecked, "!([FI[FII)V"),
    243   NATIVE_METHOD(System, arraycopyDoubleUnchecked, "!([DI[DII)V"),
    244   NATIVE_METHOD(System, arraycopyBooleanUnchecked, "!([ZI[ZII)V"),
    245   NATIVE_METHOD(System, identityHashCode, "!(Ljava/lang/Object;)I"),
    246 };
    247 
    248 void register_java_lang_System(JNIEnv* env) {
    249   REGISTER_NATIVE_METHODS("java/lang/System");
    250 }
    251 
    252 }  // namespace art
    253