Move arrayCopy / identityHashCode from OpenJdkJvm to System.

These functions are only ever called as the JNI implementation of
System.arrayCopy (and never directly from native code) so it's
cleaner to keep them as part of System's native implementation.

Moreover, this change fixes issues in debug mode where taking the
address of a function in a different shared library (potentially
compiled with different compilation flags) generates incorrect
code.

Change-Id: I0da147b9917eb1bb418d3f253fb2bfad46e53e0c
diff --git a/runtime/native/OpenjdkJvm.cc b/runtime/native/OpenjdkJvm.cc
index 25f1c55..24155da 100644
--- a/runtime/native/OpenjdkJvm.cc
+++ b/runtime/native/OpenjdkJvm.cc
@@ -462,130 +462,21 @@
   }
 }
 
-JNIEXPORT jint JVM_IHashCode(JNIEnv* env, jobject javaObject) {
-  if (UNLIKELY(javaObject == nullptr)) {
-    return 0;
-  }
-  art::ScopedFastNativeObjectAccess soa(env);
-  art::mirror::Object* o = soa.Decode<art::mirror::Object*>(javaObject);
-  return static_cast<jint>(o->IdentityHashCode());
+JNIEXPORT jint JVM_IHashCode(JNIEnv* env ATTRIBUTE_UNUSED,
+                             jobject javaObject ATTRIBUTE_UNUSED) {
+  UNIMPLEMENTED(FATAL) << "JVM_IHashCode is not implemented";
+  return 0;
 }
 
 JNIEXPORT jlong JVM_NanoTime(JNIEnv* env ATTRIBUTE_UNUSED, jclass unused ATTRIBUTE_UNUSED) {
-  timespec now;
-  clock_gettime(CLOCK_MONOTONIC, &now);
-  return now.tv_sec * 1000000000LL + now.tv_nsec;
+  UNIMPLEMENTED(FATAL) << "JVM_NanoTime is not implemented";
+  return 0L;
 }
 
-static void ThrowArrayStoreException_NotAnArray(const char* identifier, art::mirror::Object* array)
-    SHARED_LOCKS_REQUIRED(art::Locks::mutator_lock_) {
-  std::string actualType(art::PrettyTypeOf(array));
-  art::Thread* self = art::Thread::Current();
-  self->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
-                           "%s of type %s is not an array", identifier, actualType.c_str());
-}
-
-JNIEXPORT void JVM_ArrayCopy(JNIEnv* env, jclass unused ATTRIBUTE_UNUSED, jobject javaSrc,
-                             jint srcPos, jobject javaDst, jint dstPos, jint length) {
-  // The API is defined in terms of length, but length is somewhat overloaded so we use count.
-  const jint count = length;
-  art::ScopedFastNativeObjectAccess soa(env);
-
-  // Null pointer checks.
-  if (UNLIKELY(javaSrc == nullptr)) {
-    art::ThrowNullPointerException("src == null");
-    return;
-  }
-  if (UNLIKELY(javaDst == nullptr)) {
-    art::ThrowNullPointerException("dst == null");
-    return;
-  }
-
-  // Make sure source and destination are both arrays.
-  art::mirror::Object* srcObject = soa.Decode<art::mirror::Object*>(javaSrc);
-  if (UNLIKELY(!srcObject->IsArrayInstance())) {
-    ThrowArrayStoreException_NotAnArray("source", srcObject);
-    return;
-  }
-  art::mirror::Object* dstObject = soa.Decode<art::mirror::Object*>(javaDst);
-  if (UNLIKELY(!dstObject->IsArrayInstance())) {
-    ThrowArrayStoreException_NotAnArray("destination", dstObject);
-    return;
-  }
-  art::mirror::Array* srcArray = srcObject->AsArray();
-  art::mirror::Array* dstArray = dstObject->AsArray();
-
-  // Bounds checking.
-  if (UNLIKELY(srcPos < 0) || UNLIKELY(dstPos < 0) || UNLIKELY(count < 0) ||
-      UNLIKELY(srcPos > srcArray->GetLength() - count) ||
-      UNLIKELY(dstPos > dstArray->GetLength() - count)) {
-    soa.Self()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
-                                   "src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d",
-                                   srcArray->GetLength(), srcPos, dstArray->GetLength(), dstPos,
-                                   count);
-    return;
-  }
-
-  art::mirror::Class* dstComponentType = dstArray->GetClass()->GetComponentType();
-  art::mirror::Class* srcComponentType = srcArray->GetClass()->GetComponentType();
-  art::Primitive::Type dstComponentPrimitiveType = dstComponentType->GetPrimitiveType();
-
-  if (LIKELY(srcComponentType == dstComponentType)) {
-    // Trivial assignability.
-    switch (dstComponentPrimitiveType) {
-      case art::Primitive::kPrimVoid:
-        LOG(FATAL) << "Unreachable, cannot have arrays of type void";
-        return;
-      case art::Primitive::kPrimBoolean:
-      case art::Primitive::kPrimByte:
-        DCHECK_EQ(art::Primitive::ComponentSize(dstComponentPrimitiveType), 1U);
-        dstArray->AsByteSizedArray()->Memmove(dstPos, srcArray->AsByteSizedArray(), srcPos, count);
-        return;
-      case art::Primitive::kPrimChar:
-      case art::Primitive::kPrimShort:
-        DCHECK_EQ(art::Primitive::ComponentSize(dstComponentPrimitiveType), 2U);
-        dstArray->AsShortSizedArray()->Memmove(dstPos, srcArray->AsShortSizedArray(), srcPos, count);
-        return;
-      case art::Primitive::kPrimInt:
-      case art::Primitive::kPrimFloat:
-        DCHECK_EQ(art::Primitive::ComponentSize(dstComponentPrimitiveType), 4U);
-        dstArray->AsIntArray()->Memmove(dstPos, srcArray->AsIntArray(), srcPos, count);
-        return;
-      case art::Primitive::kPrimLong:
-      case art::Primitive::kPrimDouble:
-        DCHECK_EQ(art::Primitive::ComponentSize(dstComponentPrimitiveType), 8U);
-        dstArray->AsLongArray()->Memmove(dstPos, srcArray->AsLongArray(), srcPos, count);
-        return;
-      case art::Primitive::kPrimNot: {
-        art::mirror::ObjectArray<art::mirror::Object>* dstObjArray = dstArray->AsObjectArray<art::mirror::Object>();
-        art::mirror::ObjectArray<art::mirror::Object>* srcObjArray = srcArray->AsObjectArray<art::mirror::Object>();
-        dstObjArray->AssignableMemmove(dstPos, srcObjArray, srcPos, count);
-        return;
-      }
-      default:
-        LOG(FATAL) << "Unknown array type: " << art::PrettyTypeOf(srcArray);
-        return;
-    }
-  }
-  // If one of the arrays holds a primitive type the other array must hold the exact same type.
-  if (UNLIKELY((dstComponentPrimitiveType != art::Primitive::kPrimNot) ||
-               srcComponentType->IsPrimitive())) {
-    std::string srcType(art::PrettyTypeOf(srcArray));
-    std::string dstType(art::PrettyTypeOf(dstArray));
-    soa.Self()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
-                                   "Incompatible types: src=%s, dst=%s",
-                                   srcType.c_str(), dstType.c_str());
-    return;
-  }
-  // Arrays hold distinct types and so therefore can't alias - use memcpy instead of memmove.
-  art::mirror::ObjectArray<art::mirror::Object>* dstObjArray = dstArray->AsObjectArray<art::mirror::Object>();
-  art::mirror::ObjectArray<art::mirror::Object>* srcObjArray = srcArray->AsObjectArray<art::mirror::Object>();
-  // If we're assigning into say Object[] then we don't need per element checks.
-  if (dstComponentType->IsAssignableFrom(srcComponentType)) {
-    dstObjArray->AssignableMemcpy(dstPos, srcObjArray, srcPos, count);
-    return;
-  }
-  dstObjArray->AssignableCheckingMemcpy(dstPos, srcObjArray, srcPos, count, true);
+JNIEXPORT void JVM_ArrayCopy(JNIEnv* /* env */, jclass /* unused */, jobject /* javaSrc */,
+                             jint /* srcPos */, jobject /* javaDst */, jint /* dstPos */,
+                             jint /* length */) {
+  UNIMPLEMENTED(FATAL) << "JVM_ArrayCopy is not implemented";
 }
 
 JNIEXPORT jint JVM_FindSignal(const char* name ATTRIBUTE_UNUSED) {
diff --git a/runtime/native/java_lang_System.cc b/runtime/native/java_lang_System.cc
index 5447275..736b42b 100644
--- a/runtime/native/java_lang_System.cc
+++ b/runtime/native/java_lang_System.cc
@@ -28,6 +28,124 @@
 
 namespace art {
 
+/*
+ * We make guarantees about the atomicity of accesses to primitive variables.  These guarantees
+ * also apply to elements of arrays. In particular, 8-bit, 16-bit, and 32-bit accesses must not
+ * cause "word tearing".  Accesses to 64-bit array elements may be two 32-bit operations.
+ * References are never torn regardless of the number of bits used to represent them.
+ */
+
+static void ThrowArrayStoreException_NotAnArray(const char* identifier, mirror::Object* array)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  std::string actualType(PrettyTypeOf(array));
+  Thread* self = Thread::Current();
+  self->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
+                           "%s of type %s is not an array", identifier, actualType.c_str());
+}
+
+static void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst,
+                             jint dstPos, jint length) {
+  // The API is defined in terms of length, but length is somewhat overloaded so we use count.
+  const jint count = length;
+  ScopedFastNativeObjectAccess soa(env);
+
+  // Null pointer checks.
+  if (UNLIKELY(javaSrc == nullptr)) {
+    ThrowNullPointerException("src == null");
+    return;
+  }
+  if (UNLIKELY(javaDst == nullptr)) {
+    ThrowNullPointerException("dst == null");
+    return;
+  }
+
+  // Make sure source and destination are both arrays.
+  mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc);
+  if (UNLIKELY(!srcObject->IsArrayInstance())) {
+    ThrowArrayStoreException_NotAnArray("source", srcObject);
+    return;
+  }
+  mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
+  if (UNLIKELY(!dstObject->IsArrayInstance())) {
+    ThrowArrayStoreException_NotAnArray("destination", dstObject);
+    return;
+  }
+  mirror::Array* srcArray = srcObject->AsArray();
+  mirror::Array* dstArray = dstObject->AsArray();
+
+  // Bounds checking.
+  if (UNLIKELY(srcPos < 0) || UNLIKELY(dstPos < 0) || UNLIKELY(count < 0) ||
+      UNLIKELY(srcPos > srcArray->GetLength() - count) ||
+      UNLIKELY(dstPos > dstArray->GetLength() - count)) {
+    soa.Self()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
+                                   "src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d",
+                                   srcArray->GetLength(), srcPos, dstArray->GetLength(), dstPos,
+                                   count);
+    return;
+  }
+
+  mirror::Class* dstComponentType = dstArray->GetClass()->GetComponentType();
+  mirror::Class* srcComponentType = srcArray->GetClass()->GetComponentType();
+  Primitive::Type dstComponentPrimitiveType = dstComponentType->GetPrimitiveType();
+
+  if (LIKELY(srcComponentType == dstComponentType)) {
+    // Trivial assignability.
+    switch (dstComponentPrimitiveType) {
+      case Primitive::kPrimVoid:
+        LOG(FATAL) << "Unreachable, cannot have arrays of type void";
+        UNREACHABLE();
+      case Primitive::kPrimBoolean:
+      case Primitive::kPrimByte:
+        DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 1U);
+        dstArray->AsByteSizedArray()->Memmove(dstPos, srcArray->AsByteSizedArray(), srcPos, count);
+        return;
+      case Primitive::kPrimChar:
+      case Primitive::kPrimShort:
+        DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 2U);
+        dstArray->AsShortSizedArray()->Memmove(dstPos, srcArray->AsShortSizedArray(), srcPos, count);
+        return;
+      case Primitive::kPrimInt:
+      case Primitive::kPrimFloat:
+        DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 4U);
+        dstArray->AsIntArray()->Memmove(dstPos, srcArray->AsIntArray(), srcPos, count);
+        return;
+      case Primitive::kPrimLong:
+      case Primitive::kPrimDouble:
+        DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 8U);
+        dstArray->AsLongArray()->Memmove(dstPos, srcArray->AsLongArray(), srcPos, count);
+        return;
+      case Primitive::kPrimNot: {
+        mirror::ObjectArray<mirror::Object>* dstObjArray = dstArray->AsObjectArray<mirror::Object>();
+        mirror::ObjectArray<mirror::Object>* srcObjArray = srcArray->AsObjectArray<mirror::Object>();
+        dstObjArray->AssignableMemmove(dstPos, srcObjArray, srcPos, count);
+        return;
+      }
+      default:
+        LOG(FATAL) << "Unknown array type: " << PrettyTypeOf(srcArray);
+        UNREACHABLE();
+    }
+  }
+  // If one of the arrays holds a primitive type the other array must hold the exact same type.
+  if (UNLIKELY((dstComponentPrimitiveType != Primitive::kPrimNot) ||
+               srcComponentType->IsPrimitive())) {
+    std::string srcType(PrettyTypeOf(srcArray));
+    std::string dstType(PrettyTypeOf(dstArray));
+    soa.Self()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
+                                   "Incompatible types: src=%s, dst=%s",
+                                   srcType.c_str(), dstType.c_str());
+    return;
+  }
+  // Arrays hold distinct types and so therefore can't alias - use memcpy instead of memmove.
+  mirror::ObjectArray<mirror::Object>* dstObjArray = dstArray->AsObjectArray<mirror::Object>();
+  mirror::ObjectArray<mirror::Object>* srcObjArray = srcArray->AsObjectArray<mirror::Object>();
+  // If we're assigning into say Object[] then we don't need per element checks.
+  if (dstComponentType->IsAssignableFrom(srcComponentType)) {
+    dstObjArray->AssignableMemcpy(dstPos, srcObjArray, srcPos, count);
+    return;
+  }
+  dstObjArray->AssignableCheckingMemcpy(dstPos, srcObjArray, srcPos, count, true);
+}
+
 // Template to convert general array to that of its specific primitive type.
 template <typename T>
 inline T* AsPrimitiveArray(mirror::Array* array) {
@@ -97,7 +215,17 @@
       javaDst, dstPos, count);
 }
 
+static jint System_identityHashCode(JNIEnv* env, jclass, jobject javaObject) {
+  if (UNLIKELY(javaObject == nullptr)) {
+    return 0;
+  }
+  ScopedFastNativeObjectAccess soa(env);
+  mirror::Object* o = soa.Decode<mirror::Object*>(javaObject);
+  return static_cast<jint>(o->IdentityHashCode());
+}
+
 static JNINativeMethod gMethods[] = {
+  NATIVE_METHOD(System, arraycopy, "!(Ljava/lang/Object;ILjava/lang/Object;II)V"),
   NATIVE_METHOD(System, arraycopyCharUnchecked, "!([CI[CII)V"),
   NATIVE_METHOD(System, arraycopyByteUnchecked, "!([BI[BII)V"),
   NATIVE_METHOD(System, arraycopyShortUnchecked, "!([SI[SII)V"),
@@ -106,6 +234,7 @@
   NATIVE_METHOD(System, arraycopyFloatUnchecked, "!([FI[FII)V"),
   NATIVE_METHOD(System, arraycopyDoubleUnchecked, "!([DI[DII)V"),
   NATIVE_METHOD(System, arraycopyBooleanUnchecked, "!([ZI[ZII)V"),
+  NATIVE_METHOD(System, identityHashCode, "!(Ljava/lang/Object;)I"),
 };
 
 void register_java_lang_System(JNIEnv* env) {