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