blob: 542e12afaa15eb55450e2e41be1831b52c4c6c23 [file] [log] [blame]
Igor Murashkinfc1ccd72015-07-30 15:11:09 -07001/*
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
27namespace art {
28class ArtMethod; // forward declaration
29
30namespace mirror {
31class Object; // forward declaration
32} // namespace mirror
33
34namespace lambda {
35class 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.
43class ClosureBuilder : ValueObject {
44 public:
45 using ShortyTypeEnum = decltype(ShortyFieldType::kByte);
46
47
48 // Mark this primitive value to be captured as the specified type.
49 template <typename T, ShortyTypeEnum kShortyType>
50 void CaptureVariablePrimitive(T value);
51
52 // Mark this object reference to be captured.
53 void CaptureVariableObject(mirror::Object* object) SHARED_REQUIRES(Locks::mutator_lock_);
54
55 // Mark this lambda closure to be captured.
56 void CaptureVariableLambda(Closure* closure);
57
58 // Get the size (in bytes) of the closure.
59 // This size is used to be able to allocate memory large enough to write the closure into.
60 // Call 'CreateInPlace' to actually write the closure out.
61 size_t GetSize() const;
62
63 // Returns how many variables have been captured so far.
64 size_t GetCaptureCount() const;
65
66 // Creates a closure in-place and writes out the data into 'memory'.
67 // Memory must be at least 'GetSize' bytes large.
68 // All previously marked data to be captured is now written out.
69 Closure* CreateInPlace(void* memory, ArtLambdaMethod* target_method) const
70 SHARED_REQUIRES(Locks::mutator_lock_);
71
72 // Locks need to be held for entire lifetime of ClosureBuilder.
73 ClosureBuilder() SHARED_REQUIRES(Locks::mutator_lock_)
74 {}
75
76 // Locks need to be held for entire lifetime of ClosureBuilder.
77 ~ClosureBuilder() SHARED_REQUIRES(Locks::mutator_lock_)
78 {}
79
80 private:
81 // Initial size a closure starts out before any variables are written.
82 // Header size only.
83 static constexpr size_t kInitialSize = sizeof(ArtLambdaMethod*);
84
85 // Write a Closure's variables field from the captured variables.
86 // variables_size specified in bytes, and only includes enough room to write variables into.
87 // Returns the calculated actual size of the closure.
88 size_t WriteValues(ArtLambdaMethod* target_method,
89 uint8_t variables[],
90 size_t header_size,
91 size_t variables_size) const SHARED_REQUIRES(Locks::mutator_lock_);
92
93 size_t size_ = kInitialSize;
94 bool is_dynamic_size_ = false;
95 std::vector<ShortyFieldTypeTraits::MaxType> values_;
96};
97
98} // namespace lambda
99} // namespace art
100
101#endif // ART_RUNTIME_LAMBDA_CLOSURE_BUILDER_H_