Revert "lambda: Add support for invoke-interface for boxed innate lambdas"

955-lambda is flaky

Bug: 24618608
Bug: 25107649

This reverts commit 457e874459ae638145cab6d572e34d48480e39d2.

(cherry picked from commit 3a0909248e04b22c3981cbf617bc2502ed5b6380)

Change-Id: I24884344d21d7a4262e53e3f5dba57032687ddb7
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index c875183..d2c1e58 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -56,7 +56,6 @@
 #include "interpreter/interpreter.h"
 #include "jit/jit.h"
 #include "jit/jit_code_cache.h"
-#include "lambda/box_class_table.h"
 #include "leb128.h"
 #include "linear_alloc.h"
 #include "mirror/class.h"
@@ -65,7 +64,6 @@
 #include "mirror/dex_cache-inl.h"
 #include "mirror/field.h"
 #include "mirror/iftable-inl.h"
-#include "mirror/lambda_proxy.h"
 #include "mirror/method.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
@@ -583,9 +581,6 @@
   // Create java.lang.reflect.Proxy root.
   SetClassRoot(kJavaLangReflectProxy, FindSystemClass(self, "Ljava/lang/reflect/Proxy;"));
 
-  // Create java.lang.LambdaProxy root.
-  SetClassRoot(kJavaLangLambdaProxy, FindSystemClass(self, "Ljava/lang/LambdaProxy;"));
-
   // Create java.lang.reflect.Field.class root.
   auto* class_root = FindSystemClass(self, "Ljava/lang/reflect/Field;");
   CHECK(class_root != nullptr);
@@ -1262,7 +1257,6 @@
   }
   delete data.allocator;
   delete data.class_table;
-  delete data.lambda_box_class_table;
 }
 
 mirror::PointerArray* ClassLinker::AllocPointerArray(Thread* self, size_t length) {
@@ -1904,10 +1898,8 @@
 // Special case to get oat code without overwriting a trampoline.
 const void* ClassLinker::GetQuickOatCodeFor(ArtMethod* method) {
   CHECK(method->IsInvokable()) << PrettyMethod(method);
-  if (method->IsReflectProxyMethod()) {
+  if (method->IsProxyMethod()) {
     return GetQuickProxyInvokeHandler();
-  } else if (method->IsLambdaProxyMethod()) {
-    return GetQuickLambdaProxyInvokeHandler();
   }
   bool found;
   OatFile::OatMethod oat_method = FindOatMethodFor(method, &found);
@@ -3265,7 +3257,7 @@
   klass->SetName(soa.Decode<mirror::String*>(name));
   klass->SetDexCache(GetClassRoot(kJavaLangReflectProxy)->GetDexCache());
   mirror::Class::SetStatus(klass, mirror::Class::kStatusIdx, self);
-  std::string descriptor(GetDescriptorForAnyProxy(klass.Get()));
+  std::string descriptor(GetDescriptorForProxy(klass.Get()));
   const size_t hash = ComputeModifiedUtf8Hash(descriptor.c_str());
 
   // Needs to be before we insert the class so that the allocator field is set.
@@ -3385,228 +3377,23 @@
                                                decoded_name->ToModifiedUtf8().c_str()));
     CHECK_EQ(PrettyField(klass->GetStaticField(1)), throws_field_name);
 
-    CHECK_EQ(klass.Get()->GetInterfacesForAnyProxy(),
+    CHECK_EQ(klass.Get()->GetInterfaces(),
              soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces));
-    CHECK_EQ(klass.Get()->GetThrowsForAnyProxy(),
+    CHECK_EQ(klass.Get()->GetThrows(),
              soa.Decode<mirror::ObjectArray<mirror::ObjectArray<mirror::Class>>*>(throws));
   }
   return klass.Get();
 }
 
-mirror::Class* ClassLinker::CreateLambdaProxyClass(ScopedObjectAccessAlreadyRunnable& soa,
-                                                   jstring name,
-                                                   jobjectArray interfaces,
-                                                   jobject loader,
-                                                   jobjectArray methods,
-                                                   jobjectArray throws,
-                                                   bool* already_exists) {
-  DCHECK(already_exists != nullptr);
-  *already_exists = false;
-
-  Thread* self = soa.Self();
-  StackHandleScope<10> hs(self);
-
-  // Allocate a new java.lang.Class object for a mirror::Proxy.
-  MutableHandle<mirror::Class> klass =
-      hs.NewHandle(AllocClass(self, GetClassRoot(kJavaLangClass), sizeof(mirror::Class)));
-  if (klass.Get() == nullptr) {
-    CHECK(self->IsExceptionPending());  // OOME.
-    return nullptr;
-  }
-  DCHECK(klass->GetClass() != nullptr);
-  klass->SetObjectSize(sizeof(mirror::LambdaProxy));
-
-  // Set the class access flags incl. preverified, so we do not try to set the flag on the methods.
-  klass->SetAccessFlags(kAccClassIsLambdaProxy | kAccPublic | kAccFinal | kAccPreverified);
-  klass->SetClassLoader(soa.Decode<mirror::ClassLoader*>(loader));
-  DCHECK_EQ(klass->GetPrimitiveType(), Primitive::kPrimNot);
-  klass->SetName(soa.Decode<mirror::String*>(name));
-  klass->SetDexCache(GetClassRoot(kJavaLangLambdaProxy)->GetDexCache());
-  // Set the status to be just before after loading it, but before anything is resolved.
-  mirror::Class::SetStatus(klass, mirror::Class::kStatusIdx, self);
-  // Convert "foo.bar.baz" string to "Lfoo/bar/baz;"
-  std::string type_descriptor(GetDescriptorForAnyProxy(klass.Get()));
-
-  mirror::Class* existing;
-  {
-    const size_t hash = ComputeModifiedUtf8Hash(type_descriptor.c_str());
-
-    // Insert the class before loading the fields as the field roots
-    // (ArtField::declaring_class_) are only visited from the class
-    // table. There can't be any suspend points between inserting the
-    // class and setting the field arrays below.
-    existing = InsertClass(type_descriptor.c_str(), klass.Get(), hash);
-  }
-  if (UNLIKELY(existing != nullptr)) {
-    // We had already made the lambda proxy previously. Return it.
-
-    *already_exists = true;
-    return existing;
-    // Let the GC clean up the class we had already allocated but isn't being used.
-  }
-
-  // Needs to be after we insert the class so that the allocator field is set.
-  LinearAlloc* const allocator = GetOrCreateAllocatorForClassLoader(klass->GetClassLoader());
-
-  // Instance fields are inherited, but we add a couple of static fields...
-  LengthPrefixedArray<ArtField>* sfields =
-      AllocArtFieldArray(self, allocator, mirror::LambdaProxy::kStaticFieldCount);
-  klass->SetSFieldsPtr(sfields);
-
-  // 1. Create a static field 'interfaces' that holds the _declared_ interfaces implemented by
-  // our proxy, so Class.getInterfaces doesn't return the flattened set.
-  // -- private static java.lang.Class[] interfaces;  // list of declared interfaces
-  ArtField& interfaces_sfield = sfields->At(mirror::LambdaProxy::kStaticFieldIndexInterfaces);
-  interfaces_sfield.SetDexFieldIndex(mirror::LambdaProxy::kStaticFieldIndexInterfaces);
-  interfaces_sfield.SetDeclaringClass(klass.Get());
-  interfaces_sfield.SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
-
-  // 2. Create a static field 'throws' that holds the classes of exceptions thrown by our methods.
-  // This is returned by java.lang.reflect.Method#getExceptionTypes()
-  // --- private static java.lang.Class[][] throws;  // maps vtable id to list of classes.
-  ArtField& throws_sfield = sfields->At(mirror::LambdaProxy::kStaticFieldIndexThrows);
-  throws_sfield.SetDexFieldIndex(mirror::LambdaProxy::kStaticFieldIndexThrows);
-  throws_sfield.SetDeclaringClass(klass.Get());
-  throws_sfield.SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
-
-  // Set up the Constructor method.
-  {
-    // Lambda proxies have 1 direct method, the constructor.
-    static constexpr size_t kNumDirectMethods = 1;
-    LengthPrefixedArray<ArtMethod>* directs = AllocArtMethodArray(self,
-                                                                  allocator,
-                                                                  kNumDirectMethods);
-    // Currently AllocArtMethodArray cannot return null, but the OOM logic is left there in case we
-    // want to throw OOM in the future.
-    if (UNLIKELY(directs == nullptr)) {
-      self->AssertPendingOOMException();
-      return nullptr;
-    }
-    klass->SetDirectMethodsPtr(directs);
-    CreateLambdaProxyConstructor(klass, klass->GetDirectMethodUnchecked(0, image_pointer_size_));
-  }
-
-  // Create virtual method using specified prototypes.
-  auto h_methods = hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Method>*>(methods));
-  DCHECK_EQ(h_methods->GetClass(), mirror::Method::ArrayClass())
-      << PrettyClass(h_methods->GetClass());
-  const size_t num_virtual_methods = h_methods->GetLength();
-  auto* virtuals = AllocArtMethodArray(self, allocator, num_virtual_methods);
-  // Currently AllocArtMethodArray cannot return null, but the OOM logic is left there in case we
-  // want to throw OOM in the future.
-  if (UNLIKELY(virtuals == nullptr)) {
-    self->AssertPendingOOMException();
-    return nullptr;
-  }
-  klass->SetVirtualMethodsPtr(virtuals);
-  size_t abstract_methods = 0;
-  for (size_t i = 0; i < num_virtual_methods; ++i) {
-    ArtMethod* virtual_method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
-    ArtMethod* prototype = h_methods->Get(i)->GetArtMethod();
-    if (UNLIKELY((prototype->GetAccessFlags() & kAccDefault) != 0)) {
-      UNIMPLEMENTED(FATAL) << "Lambda proxies don't support default methods yet";
-    }
-    if (prototype->IsAbstract()) {
-      abstract_methods++;
-    }
-    VLOG(class_linker) << "Creating lambda proxy method for " << PrettyMethod(prototype);
-
-    CreateLambdaProxyMethod(klass, prototype, virtual_method);
-    DCHECK(virtual_method->GetDeclaringClass() != nullptr);
-    DCHECK(prototype->GetDeclaringClass() != nullptr);
-  }
-  // Ignore any methods from Object and default methods, it doesn't matter.
-  // Sanity check that the prototype interface is indeed compatible with lambdas.
-  DCHECK_EQ(abstract_methods, 1u)
-      << "Interface must be a single-abstract-method type" << PrettyClass(klass.Get());
-
-  // The super class is java.lang.LambdaProxy
-  klass->SetSuperClass(GetClassRoot(kJavaLangLambdaProxy));
-  // Now effectively in the loaded state.
-  mirror::Class::SetStatus(klass, mirror::Class::kStatusLoaded, self);
-  self->AssertNoPendingException();
-
-  MutableHandle<mirror::Class> new_class = hs.NewHandle<mirror::Class>(nullptr);
-  {
-    // Must hold lock on object when resolved.
-    ObjectLock<mirror::Class> resolution_lock(self, klass);
-    // Link the fields and virtual methods, creating vtable and iftables.
-    // The new class will replace the old one in the class table.
-    Handle<mirror::ObjectArray<mirror::Class>> h_interfaces(
-        hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces)));
-
-    {
-      DCHECK_EQ(1, h_interfaces->GetLength()) << "Lambda proxies must implement 1 interface only";
-      mirror::Class* single_abstract_interface = h_interfaces->Get(0);
-      DCHECK(single_abstract_interface != nullptr);
-
-      // Use the dex cache from the interface, which will enable most of the
-      // dex-using mechanisms on the class and its methods will work.
-      klass->SetDexCache(single_abstract_interface->GetDexCache());
-    }
-
-    if (!LinkClass(self, type_descriptor.c_str(), klass, h_interfaces, &new_class)) {
-      mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self);
-      return nullptr;
-    }
-  }
-  CHECK(klass->IsRetired());
-  CHECK_NE(klass.Get(), new_class.Get());
-  klass.Assign(new_class.Get());
-
-  CHECK_EQ(interfaces_sfield.GetDeclaringClass(), klass.Get());
-  interfaces_sfield.SetObject<false>(klass.Get(),
-                                     soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces));
-
-  CHECK_EQ(throws_sfield.GetDeclaringClass(), klass.Get());
-  throws_sfield.SetObject<false>(
-      klass.Get(), soa.Decode<mirror::ObjectArray<mirror::ObjectArray<mirror::Class> >*>(throws));
-
-  {
-    // Lock on klass is released. Lock new class object.
-    ObjectLock<mirror::Class> initialization_lock(self, klass);
-    mirror::Class::SetStatus(klass, mirror::Class::kStatusInitialized, self);
-  }
-
-  // Sanity checks
-  if (kIsDebugBuild) {
-    CHECK(klass->GetIFieldsPtr() == nullptr);
-    CheckLambdaProxyConstructor(klass->GetDirectMethod(0, image_pointer_size_));
-
-    for (size_t i = 0; i < num_virtual_methods; ++i) {
-      ArtMethod* virtual_method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
-      ArtMethod* prototype = h_methods->Get(i++)->GetArtMethod();
-      CheckLambdaProxyMethod(virtual_method, prototype);
-    }
-
-    StackHandleScope<1> hs2(self);
-    Handle<mirror::String> decoded_name = hs2.NewHandle(soa.Decode<mirror::String*>(name));
-    std::string interfaces_field_name(StringPrintf("java.lang.Class[] %s.interfaces",
-                                                   decoded_name->ToModifiedUtf8().c_str()));
-    CHECK_EQ(PrettyField(klass->GetStaticField(0)), interfaces_field_name);
-
-    std::string throws_field_name(StringPrintf("java.lang.Class[][] %s.throws",
-                                               decoded_name->ToModifiedUtf8().c_str()));
-    CHECK_EQ(PrettyField(klass->GetStaticField(1)), throws_field_name);
-
-    CHECK_EQ(klass.Get()->GetInterfacesForAnyProxy(),
-             soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces));
-    CHECK_EQ(klass.Get()->GetThrowsForAnyProxy(),
-             soa.Decode<mirror::ObjectArray<mirror::ObjectArray<mirror::Class>>*>(throws));
-  }
-  return klass.Get();
-}
-
-std::string ClassLinker::GetDescriptorForAnyProxy(mirror::Class* proxy_class) {
-  DCHECK(proxy_class != nullptr);
-  DCHECK(proxy_class->IsAnyProxyClass());
+std::string ClassLinker::GetDescriptorForProxy(mirror::Class* proxy_class) {
+  DCHECK(proxy_class->IsProxyClass());
   mirror::String* name = proxy_class->GetName();
   DCHECK(name != nullptr);
   return DotToDescriptor(name->ToModifiedUtf8().c_str());
 }
 
 ArtMethod* ClassLinker::FindMethodForProxy(mirror::Class* proxy_class, ArtMethod* proxy_method) {
-  DCHECK(proxy_class->IsAnyProxyClass());
+  DCHECK(proxy_class->IsProxyClass());
   DCHECK(proxy_method->IsProxyMethod());
   {
     Thread* const self = Thread::Current();
@@ -3650,38 +3437,6 @@
   out->SetDeclaringClass(klass.Get());
 }
 
-void ClassLinker::CreateLambdaProxyConstructor(Handle<mirror::Class> klass,
-                                               /*out*/ArtMethod* method_constructor) {
-  DCHECK(klass.Get() != nullptr);
-  DCHECK(method_constructor != nullptr);
-
-  // Create constructor for Proxy that must initialize the method.
-  // Lambda proxy superclass only has 1 direct method, the constructor (<init>()V)
-  CHECK_EQ(GetClassRoot(kJavaLangLambdaProxy)->NumDirectMethods(),
-           mirror::LambdaProxy::kDirectMethodCount);
-  // Get the constructor method.
-  ArtMethod* proxy_constructor = GetClassRoot(kJavaLangLambdaProxy)->GetDirectMethodUnchecked(
-      mirror::LambdaProxy::kDirectMethodIndexConstructor,
-      image_pointer_size_);
-
-  // Verify constructor method is indeed a constructor.
-  CHECK(proxy_constructor != nullptr);
-
-  // Ensure constructor is in dex cache so that we can use the dex cache to look up the overridden
-  // constructor method.
-  GetClassRoot(kJavaLangLambdaProxy)->GetDexCache()->SetResolvedMethod(
-      proxy_constructor->GetDexMethodIndex(),
-      proxy_constructor,
-      image_pointer_size_);
-
-  // Clone the existing constructor of LambdaProxy
-  // (our constructor would just invoke it so steal its code_ too).
-  method_constructor->CopyFrom(proxy_constructor, image_pointer_size_);
-  // Make this constructor public and fix the class to be our LambdaProxy version
-  method_constructor->SetAccessFlags((method_constructor->GetAccessFlags() & ~kAccProtected) | kAccPublic);
-  method_constructor->SetDeclaringClass(klass.Get());
-}
-
 void ClassLinker::CheckProxyConstructor(ArtMethod* constructor) const {
   CHECK(constructor->IsConstructor());
   auto* np = constructor->GetInterfaceMethodIfProxy(image_pointer_size_);
@@ -3690,14 +3445,6 @@
   DCHECK(constructor->IsPublic());
 }
 
-void ClassLinker::CheckLambdaProxyConstructor(ArtMethod* constructor) const {
-  CHECK(constructor->IsConstructor());
-  auto* np = constructor->GetInterfaceMethodIfProxy(image_pointer_size_);
-  CHECK_STREQ(np->GetName(), "<init>");
-  CHECK_STREQ(np->GetSignature().ToString().c_str(), "()V");
-  DCHECK(constructor->IsPublic());
-}
-
 void ClassLinker::CreateProxyMethod(Handle<mirror::Class> klass, ArtMethod* prototype,
                                     ArtMethod* out) {
   // Ensure prototype is in dex cache so that we can use the dex cache to look up the overridden
@@ -3709,7 +3456,6 @@
     dex_cache->SetResolvedMethod(
         prototype->GetDexMethodIndex(), prototype, image_pointer_size_);
   }
-
   // We steal everything from the prototype (such as DexCache, invoke stub, etc.) then specialize
   // as necessary
   DCHECK(out != nullptr);
@@ -3725,42 +3471,6 @@
   out->SetEntryPointFromQuickCompiledCode(GetQuickProxyInvokeHandler());
 }
 
-void ClassLinker::CreateLambdaProxyMethod(Handle<mirror::Class> klass,
-                                          ArtMethod* prototype,
-                                          ArtMethod* out) {
-  DCHECK(prototype != nullptr);
-  DCHECK(out != nullptr);
-
-  // DO NOT go through the proxy invoke handler for the default methods. They have no idea
-  // how to handle the raw closure, so they must get the regular object when invoked.
-  CHECK_EQ(prototype->GetAccessFlags() & kAccDefault, 0u) << "Default methods must not be proxied";
-
-  // Ensure prototype is in dex cache so that we can use the dex cache to look up the overridden
-  // prototype method
-  auto* dex_cache = prototype->GetDeclaringClass()->GetDexCache();
-  // Avoid dirtying the dex cache unless we need to.
-  if (dex_cache->GetResolvedMethod(prototype->GetDexMethodIndex(), image_pointer_size_) !=
-      prototype) {
-    dex_cache->SetResolvedMethod(
-        prototype->GetDexMethodIndex(), prototype, image_pointer_size_);
-  }
-  // We steal everything from the prototype (such as DexCache, invoke stub, etc.) then specialize
-  // as necessary
-  out->CopyFrom(prototype, image_pointer_size_);
-
-  // Set class to be the concrete proxy class and clear the abstract flag, modify exceptions to
-  // the intersection of throw exceptions as defined in Proxy
-  out->SetDeclaringClass(klass.Get());
-  out->SetAccessFlags((out->GetAccessFlags() & ~kAccAbstract) | kAccFinal);
-
-  // Setting the entry point isn't safe for AOT since ASLR loads it anywhere at runtime.
-  CHECK(!Runtime::Current()->IsAotCompiler());
-
-  // At runtime the method looks like a reference and argument saving method, clone the code
-  // related parameters from this method.
-  out->SetEntryPointFromQuickCompiledCode(GetQuickLambdaProxyInvokeHandler());
-}
-
 void ClassLinker::CheckProxyMethod(ArtMethod* method, ArtMethod* prototype) const {
   // Basic sanity
   CHECK(!prototype->IsFinal());
@@ -3782,11 +3492,6 @@
            prototype->GetReturnType(true /* resolve */, image_pointer_size_));
 }
 
-void ClassLinker::CheckLambdaProxyMethod(ArtMethod* method, ArtMethod* prototype) const {
-  // same as above.
-  return CheckProxyMethod(method, prototype);
-}
-
 bool ClassLinker::CanWeInitializeClass(mirror::Class* klass, bool can_init_statics,
                                        bool can_init_parents) {
   if (can_init_statics && can_init_parents) {
@@ -4418,9 +4123,7 @@
     class_loader->SetClassTable(data.class_table);
     // Should have been set when we registered the dex file.
     data.allocator = class_loader->GetAllocator();
-    CHECK(class_loader->GetLambdaProxyCache() == nullptr);
-    data.lambda_box_class_table = new lambda::BoxClassTable();
-    class_loader->SetLambdaProxyCache(data.lambda_box_class_table);
+    CHECK(data.allocator != nullptr);
     class_loaders_.push_back(data);
   }
   return class_table;
@@ -6863,7 +6566,6 @@
     "Ljava/lang/reflect/Field;",
     "Ljava/lang/reflect/Method;",
     "Ljava/lang/reflect/Proxy;",
-    "Ljava/lang/LambdaProxy;",
     "[Ljava/lang/String;",
     "[Ljava/lang/reflect/Constructor;",
     "[Ljava/lang/reflect/Field;",