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