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_BUILDER_H_ 17 #define ART_RUNTIME_LAMBDA_CLOSURE_BUILDER_H_ 18 19 #include "base/macros.h" 20 #include "base/mutex.h" // For Locks::mutator_lock_. 21 #include "base/value_object.h" 22 #include "lambda/shorty_field_type.h" 23 24 #include <stdint.h> 25 #include <vector> 26 27 namespace art { 28 class ArtMethod; // forward declaration 29 30 namespace mirror { 31 class Object; // forward declaration 32 } // namespace mirror 33 34 namespace lambda { 35 class ArtLambdaMethod; // forward declaration 36 37 // Build a closure by capturing variables one at a time. 38 // When all variables have been marked captured, the closure can be created in-place into 39 // a target memory address. 40 // 41 // The mutator lock must be held for the duration of the lifetime of this object, 42 // since it needs to temporarily store heap references into an internal list. 43 class ClosureBuilder { 44 public: 45 using ShortyTypeEnum = decltype(ShortyFieldType::kByte); 46 47 // Mark this primitive value to be captured as the specified type. 48 template <typename T, ShortyTypeEnum kShortyType = ShortyFieldTypeSelectEnum<T>::value> 49 void CaptureVariablePrimitive(T value); 50 51 // Mark this object reference to be captured. 52 void CaptureVariableObject(mirror::Object* object) SHARED_REQUIRES(Locks::mutator_lock_); 53 54 // Mark this lambda closure to be captured. 55 void CaptureVariableLambda(Closure* closure); 56 57 // Get the size (in bytes) of the closure. 58 // This size is used to be able to allocate memory large enough to write the closure into. 59 // Call 'CreateInPlace' to actually write the closure out. 60 size_t GetSize() const; 61 62 // Returns how many variables have been captured so far. 63 size_t GetCaptureCount() const; 64 65 // Get the list of captured variables' shorty field types. 66 const std::string& GetCapturedVariableShortyTypes() const; 67 68 // Creates a closure in-place and writes out the data into 'memory'. 69 // Memory must be at least 'GetSize' bytes large. 70 // All previously marked data to be captured is now written out. 71 Closure* CreateInPlace(void* memory, ArtLambdaMethod* target_method) const 72 SHARED_REQUIRES(Locks::mutator_lock_); 73 74 // Locks need to be held for entire lifetime of ClosureBuilder. SHARED_REQUIRES(Locks::mutator_lock_)75 ClosureBuilder() SHARED_REQUIRES(Locks::mutator_lock_) 76 {} 77 78 // Locks need to be held for entire lifetime of ClosureBuilder. SHARED_REQUIRES(Locks::mutator_lock_)79 ~ClosureBuilder() SHARED_REQUIRES(Locks::mutator_lock_) 80 {} 81 82 private: 83 // Initial size a closure starts out before any variables are written. 84 // Header size only. 85 static constexpr size_t kInitialSize = sizeof(ArtLambdaMethod*); 86 87 // Write a Closure's variables field from the captured variables. 88 // variables_size specified in bytes, and only includes enough room to write variables into. 89 // Returns the calculated actual size of the closure. 90 size_t WriteValues(ArtLambdaMethod* target_method, 91 uint8_t variables[], 92 size_t header_size, 93 size_t variables_size) const SHARED_REQUIRES(Locks::mutator_lock_); 94 95 size_t size_ = kInitialSize; 96 bool is_dynamic_size_ = false; 97 std::vector<ShortyFieldTypeTraits::MaxType> values_; 98 std::string shorty_types_; 99 }; 100 101 } // namespace lambda 102 } // namespace art 103 104 #endif // ART_RUNTIME_LAMBDA_CLOSURE_BUILDER_H_ 105