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_LOCKS_REQUIRED(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       case Primitive::kPrimFloat:
    109         DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 4U);
    110         dstArray->AsIntArray()->Memmove(dstPos, srcArray->AsIntArray(), srcPos, count);
    111         return;
    112       case Primitive::kPrimLong:
    113       case Primitive::kPrimDouble:
    114         DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 8U);
    115         dstArray->AsLongArray()->Memmove(dstPos, srcArray->AsLongArray(), srcPos, count);
    116         return;
    117       case Primitive::kPrimNot: {
    118         mirror::ObjectArray<mirror::Object>* dstObjArray = dstArray->AsObjectArray<mirror::Object>();
    119         mirror::ObjectArray<mirror::Object>* srcObjArray = srcArray->AsObjectArray<mirror::Object>();
    120         dstObjArray->AssignableMemmove(dstPos, srcObjArray, srcPos, count);
    121         return;
    122       }
    123       default:
    124         LOG(FATAL) << "Unknown array type: " << PrettyTypeOf(srcArray);
    125         UNREACHABLE();
    126     }
    127   }
    128   // If one of the arrays holds a primitive type the other array must hold the exact same type.
    129   if (UNLIKELY((dstComponentPrimitiveType != Primitive::kPrimNot) ||
    130                srcComponentType->IsPrimitive())) {
    131     std::string srcType(PrettyTypeOf(srcArray));
    132     std::string dstType(PrettyTypeOf(dstArray));
    133     soa.Self()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
    134                                    "Incompatible types: src=%s, dst=%s",
    135                                    srcType.c_str(), dstType.c_str());
    136     return;
    137   }
    138   // Arrays hold distinct types and so therefore can't alias - use memcpy instead of memmove.
    139   mirror::ObjectArray<mirror::Object>* dstObjArray = dstArray->AsObjectArray<mirror::Object>();
    140   mirror::ObjectArray<mirror::Object>* srcObjArray = srcArray->AsObjectArray<mirror::Object>();
    141   // If we're assigning into say Object[] then we don't need per element checks.
    142   if (dstComponentType->IsAssignableFrom(srcComponentType)) {
    143     dstObjArray->AssignableMemcpy(dstPos, srcObjArray, srcPos, count);
    144     return;
    145   }
    146   dstObjArray->AssignableCheckingMemcpy(dstPos, srcObjArray, srcPos, count, true);
    147 }
    148 
    149 // Template to convert general array to that of its specific primitive type.
    150 template <typename T>
    151 inline T* AsPrimitiveArray(mirror::Array* array) {
    152   return down_cast<T*>(array);
    153 }
    154 
    155 template <typename T, Primitive::Type kPrimType>
    156 inline void System_arraycopyTUnchecked(JNIEnv* env, jobject javaSrc, jint srcPos,
    157                                        jobject javaDst, jint dstPos, jint count) {
    158   ScopedFastNativeObjectAccess soa(env);
    159   mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc);
    160   mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
    161   DCHECK(dstObject != nullptr);
    162   mirror::Array* srcArray = srcObject->AsArray();
    163   mirror::Array* dstArray = dstObject->AsArray();
    164   DCHECK_GE(count, 0);
    165   DCHECK_EQ(srcArray->GetClass(), dstArray->GetClass());
    166   DCHECK_EQ(srcArray->GetClass()->GetComponentType()->GetPrimitiveType(), kPrimType);
    167   AsPrimitiveArray<T>(dstArray)->Memmove(dstPos, AsPrimitiveArray<T>(srcArray), srcPos, count);
    168 }
    169 
    170 static void System_arraycopyCharUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos,
    171                                           jobject javaDst, jint dstPos, jint count) {
    172   System_arraycopyTUnchecked<mirror::CharArray, Primitive::kPrimChar>(env, javaSrc, srcPos,
    173       javaDst, dstPos, count);
    174 }
    175 
    176 static void System_arraycopyByteUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos,
    177                                           jobject javaDst, jint dstPos, jint count) {
    178   System_arraycopyTUnchecked<mirror::ByteArray, Primitive::kPrimByte>(env, javaSrc, srcPos,
    179       javaDst, dstPos, count);
    180 }
    181 
    182 static void System_arraycopyShortUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos,
    183                                            jobject javaDst, jint dstPos, jint count) {
    184   System_arraycopyTUnchecked<mirror::ShortArray, Primitive::kPrimShort>(env, javaSrc, srcPos,
    185       javaDst, dstPos, count);
    186 }
    187 
    188 static void System_arraycopyIntUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos,
    189                                          jobject javaDst, jint dstPos, jint count) {
    190   System_arraycopyTUnchecked<mirror::IntArray, Primitive::kPrimInt>(env, javaSrc, srcPos,
    191       javaDst, dstPos, count);
    192 }
    193 
    194 static void System_arraycopyLongUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos,
    195                                           jobject javaDst, jint dstPos, jint count) {
    196   System_arraycopyTUnchecked<mirror::LongArray, Primitive::kPrimLong>(env, javaSrc, srcPos,
    197       javaDst, dstPos, count);
    198 }
    199 
    200 static void System_arraycopyFloatUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos,
    201                                            jobject javaDst, jint dstPos, jint count) {
    202   System_arraycopyTUnchecked<mirror::FloatArray, Primitive::kPrimFloat>(env, javaSrc, srcPos,
    203       javaDst, dstPos, count);
    204 }
    205 
    206 static void System_arraycopyDoubleUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos,
    207                                             jobject javaDst, jint dstPos, jint count) {
    208   System_arraycopyTUnchecked<mirror::DoubleArray, Primitive::kPrimDouble>(env, javaSrc, srcPos,
    209       javaDst, dstPos, count);
    210 }
    211 
    212 static void System_arraycopyBooleanUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos,
    213                                              jobject javaDst, jint dstPos, jint count) {
    214   System_arraycopyTUnchecked<mirror::BooleanArray, Primitive::kPrimBoolean>(env, javaSrc, srcPos,
    215       javaDst, dstPos, count);
    216 }
    217 
    218 static jint System_identityHashCode(JNIEnv* env, jclass, jobject javaObject) {
    219   if (UNLIKELY(javaObject == nullptr)) {
    220     return 0;
    221   }
    222   ScopedFastNativeObjectAccess soa(env);
    223   mirror::Object* o = soa.Decode<mirror::Object*>(javaObject);
    224   return static_cast<jint>(o->IdentityHashCode());
    225 }
    226 
    227 static JNINativeMethod gMethods[] = {
    228   NATIVE_METHOD(System, arraycopy, "!(Ljava/lang/Object;ILjava/lang/Object;II)V"),
    229   NATIVE_METHOD(System, arraycopyCharUnchecked, "!([CI[CII)V"),
    230   NATIVE_METHOD(System, arraycopyByteUnchecked, "!([BI[BII)V"),
    231   NATIVE_METHOD(System, arraycopyShortUnchecked, "!([SI[SII)V"),
    232   NATIVE_METHOD(System, arraycopyIntUnchecked, "!([II[III)V"),
    233   NATIVE_METHOD(System, arraycopyLongUnchecked, "!([JI[JII)V"),
    234   NATIVE_METHOD(System, arraycopyFloatUnchecked, "!([FI[FII)V"),
    235   NATIVE_METHOD(System, arraycopyDoubleUnchecked, "!([DI[DII)V"),
    236   NATIVE_METHOD(System, arraycopyBooleanUnchecked, "!([ZI[ZII)V"),
    237   NATIVE_METHOD(System, identityHashCode, "!(Ljava/lang/Object;)I"),
    238 };
    239 
    240 void register_java_lang_System(JNIEnv* env) {
    241   REGISTER_NATIVE_METHODS("java/lang/System");
    242 }
    243 
    244 }  // namespace art
    245