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