Merge "ART: Test for GVN skipping"
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index 6a08548..7c400ee 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -62,7 +62,7 @@
 
 JitCompiler::JitCompiler() : total_time_(0) {
   auto* pass_manager_options = new PassManagerOptions;
-  pass_manager_options->SetDisablePassList("GVN,DCE");
+  pass_manager_options->SetDisablePassList("GVN,DCE,GVNCleanup");
   compiler_options_.reset(new CompilerOptions(
       CompilerOptions::kDefaultCompilerFilter,
       CompilerOptions::kDefaultHugeMethodThreshold,
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index b0d923b..48a8bc7 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -29,6 +29,7 @@
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/string-inl.h"
+#include "reflection.h"
 #include "scoped_thread_state_change.h"
 #include "scoped_fast_native_object_access.h"
 #include "ScopedLocalRef.h"
@@ -391,8 +392,8 @@
       nullptr;
 }
 
-jobjectArray Class_getDeclaredMethodsUnchecked(JNIEnv* env, jobject javaThis,
-                                               jboolean publicOnly) {
+static jobjectArray Class_getDeclaredMethodsUnchecked(JNIEnv* env, jobject javaThis,
+                                                      jboolean publicOnly) {
   ScopedFastNativeObjectAccess soa(env);
   StackHandleScope<5> hs(soa.Self());
   auto* klass = DecodeClass(soa, javaThis);
@@ -457,6 +458,74 @@
   return soa.AddLocalReference<jobjectArray>(ret.Get());
 }
 
+static jobject Class_newInstance(JNIEnv* env, jobject javaThis) {
+  ScopedFastNativeObjectAccess soa(env);
+  StackHandleScope<4> hs(soa.Self());
+  auto klass = hs.NewHandle(DecodeClass(soa, javaThis));
+  if (UNLIKELY(klass->GetPrimitiveType() != 0 || klass->IsInterface() || klass->IsArrayClass() ||
+               klass->IsAbstract())) {
+    soa.Self()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
+                                   "%s cannot be instantiated", PrettyClass(klass.Get()).c_str());
+    return nullptr;
+  }
+  auto caller = hs.NewHandle<mirror::Class>(nullptr);
+  // Verify that we can access the class.
+  if (!klass->IsPublic()) {
+    caller.Assign(GetCallingClass(soa.Self(), 1));
+    if (caller.Get() != nullptr && !caller->CanAccess(klass.Get())) {
+      soa.Self()->ThrowNewExceptionF(
+          "Ljava/lang/IllegalAccessException;", "%s is not accessible from %s",
+          PrettyClass(klass.Get()).c_str(), PrettyClass(caller.Get()).c_str());
+      return nullptr;
+    }
+  }
+  auto* constructor = klass->GetDeclaredConstructor(
+      soa.Self(), NullHandle<mirror::ObjectArray<mirror::Class>>());
+  if (UNLIKELY(constructor == nullptr)) {
+    soa.Self()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
+                                   "%s has no zero argument constructor",
+                                   PrettyClass(klass.Get()).c_str());
+    return nullptr;
+  }
+  auto receiver = hs.NewHandle(klass->AllocObject(soa.Self()));
+  if (UNLIKELY(receiver.Get() == nullptr)) {
+    soa.Self()->AssertPendingOOMException();
+    return nullptr;
+  }
+  // Verify that we can access the constructor.
+  auto* declaring_class = constructor->GetDeclaringClass();
+  if (!constructor->IsPublic()) {
+    if (caller.Get() == nullptr) {
+      caller.Assign(GetCallingClass(soa.Self(), 1));
+    }
+    if (UNLIKELY(caller.Get() != nullptr && !VerifyAccess(
+        soa.Self(), receiver.Get(), declaring_class, constructor->GetAccessFlags(),
+        caller.Get()))) {
+      soa.Self()->ThrowNewExceptionF(
+          "Ljava/lang/IllegalAccessException;", "%s is not accessible from %s",
+          PrettyMethod(constructor).c_str(), PrettyClass(caller.Get()).c_str());
+      return nullptr;
+    }
+  }
+  // Ensure that we are initialized.
+  if (UNLIKELY(!declaring_class->IsInitialized())) {
+    if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(
+        soa.Self(), hs.NewHandle(declaring_class), true, true)) {
+      soa.Self()->AssertPendingException();
+      return nullptr;
+    }
+  }
+  // Invoke the constructor.
+  JValue result;
+  uint32_t args[1] = { static_cast<uint32_t>(reinterpret_cast<uintptr_t>(receiver.Get())) };
+  constructor->Invoke(soa.Self(), args, sizeof(args), &result, "V");
+  if (UNLIKELY(soa.Self()->IsExceptionPending())) {
+    return nullptr;
+  }
+  // Constructors are ()V methods, so we shouldn't touch the result of InvokeMethod.
+  return soa.AddLocalReference<jobject>(receiver.Get());
+}
+
 static JNINativeMethod gMethods[] = {
   NATIVE_METHOD(Class, classForName,
                 "!(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
@@ -474,6 +543,7 @@
   NATIVE_METHOD(Class, getNameNative, "!()Ljava/lang/String;"),
   NATIVE_METHOD(Class, getProxyInterfaces, "!()[Ljava/lang/Class;"),
   NATIVE_METHOD(Class, getPublicDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
+  NATIVE_METHOD(Class, newInstance, "!()Ljava/lang/Object;"),
 };
 
 void register_java_lang_Class(JNIEnv* env) {
diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc
index c33f81a..04d2e5e 100644
--- a/runtime/native/java_lang_reflect_Constructor.cc
+++ b/runtime/native/java_lang_reflect_Constructor.cc
@@ -29,29 +29,43 @@
 
 namespace art {
 
-static ALWAYS_INLINE inline jobject NewInstanceHelper(
-    JNIEnv* env, jobject javaMethod, jobjectArray javaArgs, size_t num_frames) {
+/*
+ * We get here through Constructor.newInstance().  The Constructor object
+ * would not be available if the constructor weren't public (per the
+ * definition of Class.getConstructor), so we can skip the method access
+ * check.  We can also safely assume the constructor isn't associated
+ * with an interface, array, or primitive class. If this is coming from
+ * native, it is OK to avoid access checks since JNI does not enforce them.
+ */
+static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs) {
   ScopedFastNativeObjectAccess soa(env);
   mirror::Method* m = soa.Decode<mirror::Method*>(javaMethod);
   StackHandleScope<1> hs(soa.Self());
   Handle<mirror::Class> c(hs.NewHandle(m->GetDeclaringClass()));
   if (UNLIKELY(c->IsAbstract())) {
-    soa.Self()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
-                                   "Can't instantiate %s %s",
+    soa.Self()->ThrowNewExceptionF("Ljava/lang/InstantiationException;", "Can't instantiate %s %s",
                                    c->IsInterface() ? "interface" : "abstract class",
                                    PrettyDescriptor(c.Get()).c_str());
     return nullptr;
   }
-
+  // Verify that we can access the class (only for debug since the above comment).
+  if (kIsDebugBuild && !c->IsPublic()) {
+    auto* caller = GetCallingClass(soa.Self(), 1);
+    // If caller is null, then we called from JNI, just avoid the check since JNI avoids most
+    // access checks anyways. TODO: Investigate if this the correct behavior.
+    if (caller != nullptr && !caller->CanAccess(c.Get())) {
+      soa.Self()->ThrowNewExceptionF(
+          "Ljava/lang/IllegalAccessException;", "%s is not accessible from %s",
+          PrettyClass(c.Get()).c_str(), PrettyClass(caller).c_str());
+      return nullptr;
+    }
+  }
   if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(soa.Self(), c, true, true)) {
     DCHECK(soa.Self()->IsExceptionPending());
     return nullptr;
   }
-
   bool movable = true;
-  if (!kMovingMethods && c->IsArtMethodClass()) {
-    movable = false;
-  } else if (!kMovingClasses && c->IsClassClass()) {
+  if (!kMovingClasses && c->IsClassClass()) {
     movable = false;
   }
   mirror::Object* receiver =
@@ -59,33 +73,14 @@
   if (receiver == nullptr) {
     return nullptr;
   }
-
   jobject javaReceiver = soa.AddLocalReference<jobject>(receiver);
-  InvokeMethod(soa, javaMethod, javaReceiver, javaArgs, num_frames);
-
+  InvokeMethod(soa, javaMethod, javaReceiver, javaArgs, 1);
   // Constructors are ()V methods, so we shouldn't touch the result of InvokeMethod.
   return javaReceiver;
 }
 
-/*
- * We get here through Constructor.newInstance().  The Constructor object
- * would not be available if the constructor weren't public (per the
- * definition of Class.getConstructor), so we can skip the method access
- * check.  We can also safely assume the constructor isn't associated
- * with an interface, array, or primitive class.
- */
-static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs) {
-  return NewInstanceHelper(env, javaMethod, javaArgs, 1);
-}
-
-static jobject Constructor_newInstanceTwoFrames(JNIEnv* env, jobject javaMethod,
-                                                jobjectArray javaArgs) {
-  return NewInstanceHelper(env, javaMethod, javaArgs, 2);
-}
-
 static JNINativeMethod gMethods[] = {
   NATIVE_METHOD(Constructor, newInstance, "!([Ljava/lang/Object;)Ljava/lang/Object;"),
-  NATIVE_METHOD(Constructor, newInstanceTwoFrames, "!([Ljava/lang/Object;)Ljava/lang/Object;"),
 };
 
 void register_java_lang_reflect_Constructor(JNIEnv* env) {
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 3099094..a2ce0cb 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -799,40 +799,48 @@
   return UnboxPrimitive(o, dst_class, f, unboxed_value);
 }
 
-bool UnboxPrimitiveForResult(mirror::Object* o,
-                             mirror::Class* dst_class, JValue* unboxed_value) {
+bool UnboxPrimitiveForResult(mirror::Object* o, mirror::Class* dst_class, JValue* unboxed_value) {
   return UnboxPrimitive(o, dst_class, nullptr, unboxed_value);
 }
 
+mirror::Class* GetCallingClass(Thread* self, size_t num_frames) {
+  NthCallerVisitor visitor(self, num_frames);
+  visitor.WalkStack();
+  return visitor.caller != nullptr ? visitor.caller->GetDeclaringClass() : nullptr;
+}
+
 bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_class,
                   uint32_t access_flags, mirror::Class** calling_class, size_t num_frames) {
   if ((access_flags & kAccPublic) != 0) {
     return true;
   }
-  NthCallerVisitor visitor(self, num_frames);
-  visitor.WalkStack();
-  if (UNLIKELY(visitor.caller == nullptr)) {
+  auto* klass = GetCallingClass(self, num_frames);
+  if (UNLIKELY(klass == nullptr)) {
     // The caller is an attached native thread.
     return false;
   }
-  mirror::Class* caller_class = visitor.caller->GetDeclaringClass();
-  if (caller_class == declaring_class) {
+  *calling_class = klass;
+  return VerifyAccess(self, obj, declaring_class, access_flags, klass);
+}
+
+bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_class,
+                  uint32_t access_flags, mirror::Class* calling_class) {
+  if (calling_class == declaring_class) {
     return true;
   }
   ScopedAssertNoThreadSuspension sants(self, "verify-access");
-  *calling_class = caller_class;
   if ((access_flags & kAccPrivate) != 0) {
     return false;
   }
   if ((access_flags & kAccProtected) != 0) {
-    if (obj != nullptr && !obj->InstanceOf(caller_class) &&
-        !declaring_class->IsInSamePackage(caller_class)) {
+    if (obj != nullptr && !obj->InstanceOf(calling_class) &&
+        !declaring_class->IsInSamePackage(calling_class)) {
       return false;
-    } else if (declaring_class->IsAssignableFrom(caller_class)) {
+    } else if (declaring_class->IsAssignableFrom(calling_class)) {
       return true;
     }
   }
-  return declaring_class->IsInSamePackage(caller_class);
+  return declaring_class->IsInSamePackage(calling_class);
 }
 
 void InvalidReceiverError(mirror::Object* o, mirror::Class* c) {
diff --git a/runtime/reflection.h b/runtime/reflection.h
index c63f858..6305d68 100644
--- a/runtime/reflection.h
+++ b/runtime/reflection.h
@@ -77,6 +77,15 @@
                   uint32_t access_flags, mirror::Class** calling_class, size_t num_frames)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+// This version takes a known calling class.
+bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_class,
+                  uint32_t access_flags, mirror::Class* calling_class)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+// Get the calling class by using a stack visitor, may return null for unattached native threads.
+mirror::Class* GetCallingClass(Thread* self, size_t num_frames)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
 void InvalidReceiverError(mirror::Object* o, mirror::Class* c)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);