1 /* 2 * Copyright (C) 2015 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 #ifndef ART_RUNTIME_LAMBDA_CLOSURE_H_ 17 #define ART_RUNTIME_LAMBDA_CLOSURE_H_ 18 19 #include "base/macros.h" 20 #include "base/mutex.h" // For Locks::mutator_lock_. 21 #include "lambda/shorty_field_type.h" 22 23 #include <stdint.h> 24 25 namespace art { 26 class ArtMethod; // forward declaration 27 28 namespace mirror { 29 class Object; // forward declaration 30 } // namespace mirror 31 32 namespace lambda { 33 class ArtLambdaMethod; // forward declaration 34 class ClosureBuilder; // forward declaration 35 36 // Inline representation of a lambda closure. 37 // Contains the target method and the set of packed captured variables as a copy. 38 // 39 // The closure itself is logically immutable, although in practice any object references 40 // it (recursively) contains can be moved and updated by the GC. 41 struct PACKED(sizeof(ArtLambdaMethod*)) Closure { 42 // Get the size of the Closure in bytes. 43 // This is necessary in order to allocate a large enough area to copy the Closure into. 44 // Do *not* copy the closure with memcpy, since references also need to get moved. 45 size_t GetSize() const; 46 47 // Copy this closure into the target, whose memory size is specified by target_size. 48 // Any object references are fixed up during the copy (if there was a read barrier). 49 // The target_size must be at least as large as GetSize(). 50 void CopyTo(void* target, size_t target_size) const; 51 52 // Get the target method, i.e. the method that will be dispatched into with invoke-lambda. 53 ArtMethod* GetTargetMethod() const; 54 55 // Calculates the hash code. Value is recomputed each time. 56 uint32_t GetHashCode() const SHARED_REQUIRES(Locks::mutator_lock_); 57 58 // Is this the same closure as other? e.g. same target method, same variables captured. 59 // 60 // Determines whether the two Closures are interchangeable instances. 61 // Does *not* call Object#equals recursively. If two Closures compare ReferenceEquals true that 62 // means that they are interchangeable values (usually for the purpose of boxing/unboxing). 63 bool ReferenceEquals(const Closure* other) const SHARED_REQUIRES(Locks::mutator_lock_); 64 65 // How many variables were captured? 66 size_t GetNumberOfCapturedVariables() const; 67 68 // Returns a type descriptor string that represents each captured variable. 69 // e.g. "Ljava/lang/Object;ZB" would mean a capture tuple of (Object, boolean, byte) 70 const char* GetCapturedVariablesTypeDescriptor() const; 71 72 // Returns the short type for the captured variable at index. 73 // Index must be less than the number of captured variables. 74 ShortyFieldType GetCapturedShortyType(size_t index) const; 75 76 // Returns the 32-bit representation of a non-wide primitive at the captured variable index. 77 // Smaller types are zero extended. 78 // Index must be less than the number of captured variables. 79 uint32_t GetCapturedPrimitiveNarrow(size_t index) const; 80 // Returns the 64-bit representation of a wide primitive at the captured variable index. 81 // Smaller types are zero extended. 82 // Index must be less than the number of captured variables. 83 uint64_t GetCapturedPrimitiveWide(size_t index) const; 84 // Returns the object reference at the captured variable index. 85 // The type at the index *must* be an object reference or a CHECK failure will occur. 86 // Index must be less than the number of captured variables. 87 mirror::Object* GetCapturedObject(size_t index) const SHARED_REQUIRES(Locks::mutator_lock_); 88 89 // Gets the size of a nested capture closure in bytes, at the captured variable index. 90 // The type at the index *must* be a lambda closure or a CHECK failure will occur. 91 size_t GetCapturedClosureSize(size_t index) const; 92 93 // Copies a nested lambda closure at the captured variable index. 94 // The destination must have enough room for the closure (see GetCapturedClosureSize). 95 void CopyCapturedClosure(size_t index, void* destination, size_t destination_room) const; 96 97 private: 98 // Read out any non-lambda value as a copy. 99 template <typename T> 100 T GetCapturedVariable(size_t index) const; 101 102 // Reconstruct the closure's captured variable info at runtime. 103 struct VariableInfo { 104 size_t index_; 105 ShortyFieldType variable_type_; 106 size_t offset_; 107 size_t count_; 108 109 enum Flags { 110 kIndex = 0x1, 111 kVariableType = 0x2, 112 kOffset = 0x4, 113 kCount = 0x8, 114 }; 115 116 // Traverse to the end of the type descriptor list instead of stopping at some particular index. 117 static constexpr size_t kUpToIndexMax = static_cast<size_t>(-1); 118 }; 119 120 // Parse a type descriptor, stopping at index "upto_index". 121 // Returns only the information requested in flags. All other fields are indeterminate. 122 template <VariableInfo::Flags flags> 123 inline VariableInfo ALWAYS_INLINE ParseTypeDescriptor(const char* type_descriptor, 124 size_t upto_index) const; 125 126 // Convenience function to call ParseTypeDescriptor with just the type and offset. 127 void GetCapturedVariableTypeAndOffset(size_t index, 128 ShortyFieldType* out_type, 129 size_t* out_offset) const; 130 131 // How many bytes do the captured variables take up? Runtime sizeof(captured_variables). 132 size_t GetCapturedVariablesSize() const; 133 // Get the size in bytes of the variable_type which is potentially stored at offset. 134 size_t GetCapturedVariableSize(ShortyFieldType variable_type, size_t offset) const; 135 // Get the starting offset (in bytes) for the 0th captured variable. 136 // All offsets are relative to 'captured_'. 137 size_t GetStartingOffset() const; 138 // Get the offset for this index. 139 // All offsets are relative to 'captuerd_'. 140 size_t GetCapturedVariableOffset(size_t index) const; 141 142 // Cast the data at '(char*)captured_[offset]' into T, returning its address. 143 // This value should not be de-referenced directly since its unaligned. 144 template <typename T> 145 inline const uint8_t* GetUnsafeAtOffset(size_t offset) const; 146 147 // Copy the data at the offset into the destination. DCHECKs that 148 // the destination_room is large enough (in bytes) to fit the data. 149 template <typename T> 150 inline void CopyUnsafeAtOffset(size_t offset, 151 void* destination, 152 size_t src_size = sizeof(T), 153 size_t destination_room = sizeof(T)) const; 154 155 // Get the closure size from an unaligned (i.e. interior) closure pointer. 156 static size_t GetClosureSize(const uint8_t* closure); 157 158 /////////////////////////////////////////////////////////////////////////////////// 159 160 // Compile-time known lambda information such as the type descriptor and size. 161 ArtLambdaMethod* lambda_info_; 162 163 // A contiguous list of captured variables, and possibly the closure size. 164 // The runtime size can always be determined through GetSize(). 165 union { 166 // Read from here if the closure size is static (ArtLambdaMethod::IsStatic) 167 uint8_t static_variables_[0]; 168 struct { 169 // Read from here if the closure size is dynamic (ArtLambdaMethod::IsDynamic) 170 size_t size_; // The lambda_info_ and the size_ itself is also included as part of the size. 171 uint8_t variables_[0]; 172 } dynamic_; 173 } captured_[0]; 174 // captured_ will always consist of one array element at runtime. 175 // Set to [0] so that 'size_' is not counted in sizeof(Closure). 176 177 friend class ClosureBuilder; 178 friend class ClosureTest; 179 }; 180 181 } // namespace lambda 182 } // namespace art 183 184 #endif // ART_RUNTIME_LAMBDA_CLOSURE_H_ 185