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

Lambda closures created with the 'create-lambda' instruction
(termed "innate lambdas") can be turned into an object with 'box-lambda'.

This CL enables support for those kinds of lambdas to work with
'invoke-interface' by generating a proxy class for the lambda.

Note: MIPS32/64 support not included.

Bug: 24618608
Bug: 25107649
Change-Id: Ic8f1bb66ebeaed4097e758a50becf1cff6ccaefb
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 9e416dc..a8685b8 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -695,7 +695,11 @@
 }
 
 inline const DexFile& Class::GetDexFile() {
-  return *GetDexCache()->GetDexFile();
+  DexCache* dex_cache = GetDexCache();
+  DCHECK(dex_cache != nullptr);
+  const DexFile* dex_file = dex_cache->GetDexFile();
+  DCHECK(dex_file != nullptr);
+  return *dex_file;
 }
 
 inline bool Class::DescriptorEquals(const char* match) {
@@ -703,8 +707,8 @@
     return match[0] == '[' && GetComponentType()->DescriptorEquals(match + 1);
   } else if (IsPrimitive()) {
     return strcmp(Primitive::Descriptor(GetPrimitiveType()), match) == 0;
-  } else if (IsProxyClass()) {
-    return ProxyDescriptorEquals(match);
+  } else if (IsAnyProxyClass()) {
+    return AnyProxyDescriptorEquals(match);
   } else {
     const DexFile& dex_file = GetDexFile();
     const DexFile::TypeId& type_id = dex_file.GetTypeId(GetClassDef()->class_idx_);
@@ -720,22 +724,32 @@
   }
 }
 
-inline ObjectArray<Class>* Class::GetInterfaces() {
-  CHECK(IsProxyClass());
+inline ObjectArray<Class>* Class::GetInterfacesForAnyProxy() {
+  CHECK(IsAnyProxyClass());
   // First static field.
   auto* field = GetStaticField(0);
   DCHECK_STREQ(field->GetName(), "interfaces");
   MemberOffset field_offset = field->GetOffset();
-  return GetFieldObject<ObjectArray<Class>>(field_offset);
+  ObjectArray<Class>* interfaces_array = GetFieldObject<ObjectArray<Class>>(field_offset);
+
+  CHECK(interfaces_array != nullptr);
+  if (UNLIKELY(IsLambdaProxyClass())) {
+    DCHECK_EQ(1, interfaces_array->GetLength())
+        << "Lambda proxies cannot have multiple direct interfaces implemented";
+  }
+  return interfaces_array;
 }
 
-inline ObjectArray<ObjectArray<Class>>* Class::GetThrows() {
-  CHECK(IsProxyClass());
+inline ObjectArray<ObjectArray<Class>>* Class::GetThrowsForAnyProxy() {
+  CHECK(IsAnyProxyClass());
   // Second static field.
   auto* field = GetStaticField(1);
   DCHECK_STREQ(field->GetName(), "throws");
+
   MemberOffset field_offset = field->GetOffset();
-  return GetFieldObject<ObjectArray<ObjectArray<Class>>>(field_offset);
+  auto* throws_array = GetFieldObject<ObjectArray<ObjectArray<Class>>>(field_offset);
+  CHECK(throws_array != nullptr);
+  return throws_array;
 }
 
 inline MemberOffset Class::GetDisableIntrinsicFlagOffset() {
@@ -796,8 +810,8 @@
     return 0;
   } else if (IsArrayClass()) {
     return 2;
-  } else if (IsProxyClass()) {
-    mirror::ObjectArray<mirror::Class>* interfaces = GetInterfaces();
+  } else if (IsAnyProxyClass()) {
+    mirror::ObjectArray<mirror::Class>* interfaces = GetInterfacesForAnyProxy();
     return interfaces != nullptr ? interfaces->GetLength() : 0;
   } else {
     const DexFile::TypeList* interfaces = GetInterfaceTypeList();
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 05a9039..b201293 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -538,6 +538,7 @@
 
 ArtMethod* Class::FindClassInitializer(size_t pointer_size) {
   for (ArtMethod& method : GetDirectMethods(pointer_size)) {
+    DCHECK(reinterpret_cast<volatile void*>(&method) != nullptr);
     if (method.IsClassInitializer()) {
       DCHECK_STREQ(method.GetName(), "<clinit>");
       DCHECK_STREQ(method.GetSignature().ToString().c_str(), "()V");
@@ -742,8 +743,8 @@
     return Primitive::Descriptor(GetPrimitiveType());
   } else if (IsArrayClass()) {
     return GetArrayDescriptor(storage);
-  } else if (IsProxyClass()) {
-    *storage = Runtime::Current()->GetClassLinker()->GetDescriptorForProxy(this);
+  } else if (IsAnyProxyClass()) {
+    *storage = Runtime::Current()->GetClassLinker()->GetDescriptorForAnyProxy(this);
     return storage->c_str();
   } else {
     const DexFile& dex_file = GetDexFile();
@@ -786,8 +787,10 @@
       DCHECK_EQ(1U, idx);
       return class_linker->FindSystemClass(self, "Ljava/io/Serializable;");
     }
-  } else if (klass->IsProxyClass()) {
-    mirror::ObjectArray<mirror::Class>* interfaces = klass.Get()->GetInterfaces();
+  } else if (klass->IsAnyProxyClass()) {
+    // Proxies don't have a dex cache, so look at the
+    // interfaces through the magic static field "interfaces" from the proxy class itself.
+    mirror::ObjectArray<mirror::Class>* interfaces = klass.Get()->GetInterfacesForAnyProxy();
     DCHECK(interfaces != nullptr);
     return interfaces->Get(idx);
   } else {
@@ -826,7 +829,7 @@
 
 std::string Class::GetLocation() {
   mirror::DexCache* dex_cache = GetDexCache();
-  if (dex_cache != nullptr && !IsProxyClass()) {
+  if (dex_cache != nullptr && !IsAnyProxyClass()) {
     return dex_cache->GetLocation()->ToModifiedUtf8();
   }
   // Arrays and proxies are generated and have no corresponding dex file location.
@@ -944,9 +947,9 @@
   return new_class->AsClass();
 }
 
-bool Class::ProxyDescriptorEquals(const char* match) {
-  DCHECK(IsProxyClass());
-  return Runtime::Current()->GetClassLinker()->GetDescriptorForProxy(this) == match;
+bool Class::AnyProxyDescriptorEquals(const char* match) {
+  DCHECK(IsAnyProxyClass());
+  return Runtime::Current()->GetClassLinker()->GetDescriptorForAnyProxy(this) == match;
 }
 
 // TODO: Move this to java_lang_Class.cc?
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 0ab5b97..fcfb4b9 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -352,8 +352,16 @@
   static String* ComputeName(Handle<Class> h_this) SHARED_REQUIRES(Locks::mutator_lock_)
       REQUIRES(!Roles::uninterruptible_);
 
+  // Is this either a java.lang.reflect.Proxy or a boxed lambda (java.lang.LambdaProxy)?
+  // -- Most code doesn't need to make the distinction, and this is the preferred thing to check.
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  bool IsProxyClass() SHARED_REQUIRES(Locks::mutator_lock_) {
+  bool IsAnyProxyClass() SHARED_REQUIRES(Locks::mutator_lock_) {
+    return IsReflectProxyClass() || IsLambdaProxyClass();
+  }
+
+  // Is this a java.lang.reflect.Proxy ?
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  bool IsReflectProxyClass() SHARED_REQUIRES(Locks::mutator_lock_) {
     // Read access flags without using getter as whether something is a proxy can be check in
     // any loaded state
     // TODO: switch to a check if the super class is java.lang.reflect.Proxy?
@@ -361,6 +369,17 @@
     return (access_flags & kAccClassIsProxy) != 0;
   }
 
+  // Is this a boxed lambda (java.lang.LambdaProxy)?
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  bool IsLambdaProxyClass() SHARED_REQUIRES(Locks::mutator_lock_) {
+    // Read access flags without using getter as whether something is a proxy can be check in
+    // any loaded state
+    // TODO: switch to a check if the super class is java.lang.reflect.Proxy?
+    uint32_t access_flags = GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_));
+    return (access_flags & kAccClassIsLambdaProxy) != 0;
+  }
+
+
   static MemberOffset PrimitiveTypeOffset() {
     return OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_);
   }
@@ -677,6 +696,8 @@
     return MemberOffset(OFFSETOF_MEMBER(Class, super_class_));
   }
 
+  // Returns the class's ClassLoader.
+  // A null value is returned if and only if this is a boot classpath class.
   ClassLoader* GetClassLoader() ALWAYS_INLINE SHARED_REQUIRES(Locks::mutator_lock_);
 
   void SetClassLoader(ClassLoader* new_cl) SHARED_REQUIRES(Locks::mutator_lock_);
@@ -1076,6 +1097,8 @@
 
   bool DescriptorEquals(const char* match) SHARED_REQUIRES(Locks::mutator_lock_);
 
+  // Returns the backing DexFile's class definition for this class.
+  // This returns null if and only if the class has no backing DexFile.
   const DexFile::ClassDef* GetClassDef() SHARED_REQUIRES(Locks::mutator_lock_);
 
   ALWAYS_INLINE uint32_t NumDirectInterfaces() SHARED_REQUIRES(Locks::mutator_lock_);
@@ -1102,11 +1125,15 @@
                 size_t pointer_size)
       SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
-  // For proxy class only.
-  ObjectArray<Class>* GetInterfaces() SHARED_REQUIRES(Locks::mutator_lock_);
+  // For any proxy class only. Returns list of directly implemented interfaces.
+  // The value returned is always non-null.
+  ObjectArray<Class>* GetInterfacesForAnyProxy() SHARED_REQUIRES(Locks::mutator_lock_);
 
-  // For proxy class only.
-  ObjectArray<ObjectArray<Class>>* GetThrows() SHARED_REQUIRES(Locks::mutator_lock_);
+  // For any proxy class only. Returns a 2d array of classes.
+  // -- The 0th dimension correponds to the vtable index.
+  // -- The 1st dimension is a list of checked exception classes.
+  // The value returned is always non-null.
+  ObjectArray<ObjectArray<Class>>* GetThrowsForAnyProxy() SHARED_REQUIRES(Locks::mutator_lock_);
 
   // For reference class only.
   MemberOffset GetDisableIntrinsicFlagOffset() SHARED_REQUIRES(Locks::mutator_lock_);
@@ -1194,7 +1221,7 @@
   IterationRange<StrideIterator<ArtField>> GetIFieldsUnchecked()
       SHARED_REQUIRES(Locks::mutator_lock_);
 
-  bool ProxyDescriptorEquals(const char* match) SHARED_REQUIRES(Locks::mutator_lock_);
+  bool AnyProxyDescriptorEquals(const char* match) SHARED_REQUIRES(Locks::mutator_lock_);
 
   // Check that the pointer size matches the one in the class linker.
   ALWAYS_INLINE static void CheckPointerSize(size_t pointer_size);
diff --git a/runtime/mirror/class_loader-inl.h b/runtime/mirror/class_loader-inl.h
index e22ddd7..3139117 100644
--- a/runtime/mirror/class_loader-inl.h
+++ b/runtime/mirror/class_loader-inl.h
@@ -21,6 +21,7 @@
 
 #include "base/mutex-inl.h"
 #include "class_table-inl.h"
+#include "lambda/box_class_table-inl.h"
 
 namespace art {
 namespace mirror {
@@ -35,6 +36,10 @@
   if (class_table != nullptr) {
     class_table->VisitRoots(visitor);
   }
+  lambda::BoxClassTable* const lambda_box_class_table = GetLambdaProxyCache();
+  if (lambda_box_class_table != nullptr) {
+    lambda_box_class_table->VisitRoots(visitor);
+  }
 }
 
 }  // namespace mirror
diff --git a/runtime/mirror/class_loader.h b/runtime/mirror/class_loader.h
index c2a65d6..9d4fe96 100644
--- a/runtime/mirror/class_loader.h
+++ b/runtime/mirror/class_loader.h
@@ -24,6 +24,12 @@
 struct ClassLoaderOffsets;
 class ClassTable;
 
+namespace lambda {
+
+class BoxClassTable;
+
+}  // namespace lambda
+
 namespace mirror {
 
 class Class;
@@ -60,6 +66,16 @@
                       reinterpret_cast<uint64_t>(allocator));
   }
 
+  lambda::BoxClassTable* GetLambdaProxyCache() SHARED_REQUIRES(Locks::mutator_lock_) {
+    return reinterpret_cast<lambda::BoxClassTable*>(
+        GetField64(OFFSET_OF_OBJECT_MEMBER(ClassLoader, lambda_proxy_cache_)));
+  }
+
+  void SetLambdaProxyCache(lambda::BoxClassTable* cache) SHARED_REQUIRES(Locks::mutator_lock_) {
+    SetField64<false>(OFFSET_OF_OBJECT_MEMBER(ClassLoader, lambda_proxy_cache_),
+                      reinterpret_cast<uint64_t>(cache));
+  }
+
  private:
   // Visit instance fields of the class loader as well as its associated classes.
   // Null class loader is handled by ClassLinker::VisitClassRoots.
@@ -76,6 +92,7 @@
   uint32_t padding_ ATTRIBUTE_UNUSED;
   uint64_t allocator_;
   uint64_t class_table_;
+  uint64_t lambda_proxy_cache_;
 
   friend struct art::ClassLoaderOffsets;  // for verifying offset information
   friend class Object;  // For VisitReferences
diff --git a/runtime/mirror/field-inl.h b/runtime/mirror/field-inl.h
index 8a0daec..49c443e 100644
--- a/runtime/mirror/field-inl.h
+++ b/runtime/mirror/field-inl.h
@@ -57,14 +57,15 @@
   const auto pointer_size = kTransactionActive ?
       Runtime::Current()->GetClassLinker()->GetImagePointerSize() : sizeof(void*);
   auto dex_field_index = field->GetDexFieldIndex();
-  auto* resolved_field = field->GetDexCache()->GetResolvedField(dex_field_index, pointer_size);
-  if (field->GetDeclaringClass()->IsProxyClass()) {
+  if (field->GetDeclaringClass()->IsAnyProxyClass()) {
     DCHECK(field->IsStatic());
     DCHECK_LT(dex_field_index, 2U);
     // The two static fields (interfaces, throws) of all proxy classes
     // share the same dex file indices 0 and 1. So, we can't resolve
     // them in the dex cache.
   } else {
+    ArtField* resolved_field =
+        field->GetDexCache()->GetResolvedField(dex_field_index, pointer_size);
     if (resolved_field != nullptr) {
       DCHECK_EQ(resolved_field, field);
     } else {
diff --git a/runtime/mirror/field.cc b/runtime/mirror/field.cc
index ff6847c..b02e5b5 100644
--- a/runtime/mirror/field.cc
+++ b/runtime/mirror/field.cc
@@ -56,7 +56,7 @@
 
 ArtField* Field::GetArtField() {
   mirror::Class* declaring_class = GetDeclaringClass();
-  if (UNLIKELY(declaring_class->IsProxyClass())) {
+  if (UNLIKELY(declaring_class->IsAnyProxyClass())) {
     DCHECK(IsStatic());
     DCHECK_EQ(declaring_class->NumStaticFields(), 2U);
     // 0 == Class[] interfaces; 1 == Class[][] throws;
diff --git a/runtime/mirror/lambda_proxy.h b/runtime/mirror/lambda_proxy.h
new file mode 100644
index 0000000..cff3a12
--- /dev/null
+++ b/runtime/mirror/lambda_proxy.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_LAMBDA_PROXY_H_
+#define ART_RUNTIME_MIRROR_LAMBDA_PROXY_H_
+
+#include "lambda/closure.h"
+#include "object.h"
+
+namespace art {
+
+struct LambdaProxyOffsets;
+
+namespace mirror {
+
+// C++ mirror of a lambda proxy. Does not yet have a Java-equivalent source file.
+class MANAGED LambdaProxy FINAL : public Object {
+ public:
+  // Note that the runtime subclasses generate the following static fields:
+
+  // private static java.lang.Class[] interfaces;  // Declared interfaces for the lambda interface.
+  static constexpr size_t kStaticFieldIndexInterfaces = 0;
+  // private static java.lang.Class[][] throws;    // Maps vtable id to list of classes.
+  static constexpr size_t kStaticFieldIndexThrows = 1;
+  static constexpr size_t kStaticFieldCount = 2;   // Number of fields total.
+
+  // The offset from the start of 'LambdaProxy' object, to the closure_ field, in bytes.
+  // -- This is exposed publically in order to avoid exposing 'closure_' publically.
+  // -- Only meant to be used in stubs and other compiled code, not in runtime.
+  static inline MemberOffset GetInstanceFieldOffsetClosure() {
+    return OFFSET_OF_OBJECT_MEMBER(LambdaProxy, closure_);
+  }
+
+  // Direct methods available on the class:
+  static constexpr size_t kDirectMethodIndexConstructor = 0;  // <init>()V
+  static constexpr size_t kDirectMethodCount = 1;             // Only the constructor.
+
+  // Accessors to the fields:
+
+  // Get the native closure pointer. Usually non-null outside of lambda proxy contexts.
+  lambda::Closure* GetClosure() SHARED_REQUIRES(Locks::mutator_lock_) {
+    return reinterpret_cast<lambda::Closure*>(
+        GetField64(GetInstanceFieldOffsetClosure()));
+  }
+
+  // Set the native closure pointer. Usually should be non-null outside of lambda proxy contexts.
+  void SetClosure(lambda::Closure* closure) SHARED_REQUIRES(Locks::mutator_lock_) {
+    SetField64<false>(GetInstanceFieldOffsetClosure(),
+                      reinterpret_cast<uint64_t>(closure));
+  }
+
+ private:
+  // Instance fields, present in the base class and every generated subclass:
+
+  // private long closure;
+  union {
+    lambda::Closure* actual;
+    uint64_t padding;         // Don't trip up GetObjectSize checks, since the Java code has a long.
+  } closure_;
+
+  // Friends for generating offset tests:
+  friend struct art::LambdaProxyOffsets;              // for verifying offset information
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(LambdaProxy);
+};
+
+}  // namespace mirror
+}  // namespace art
+
+#endif  // ART_RUNTIME_MIRROR_LAMBDA_PROXY_H_