1fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin/*
2fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin * Copyright (C) 2015 The Android Open Source Project
3fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin *
4fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin * Licensed under the Apache License, Version 2.0 (the "License");
5fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin * you may not use this file except in compliance with the License.
6fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin * You may obtain a copy of the License at
7fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin *
8fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin *      http://www.apache.org/licenses/LICENSE-2.0
9fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin *
10fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin * Unless required by applicable law or agreed to in writing, software
11fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin * distributed under the License is distributed on an "AS IS" BASIS,
12fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin * See the License for the specific language governing permissions and
14fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin * limitations under the License.
15fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin */
16fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin#ifndef ART_RUNTIME_LAMBDA_CLOSURE_BUILDER_H_
17fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin#define ART_RUNTIME_LAMBDA_CLOSURE_BUILDER_H_
18fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
19fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin#include "base/macros.h"
20fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin#include "base/mutex.h"  // For Locks::mutator_lock_.
21fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin#include "base/value_object.h"
22fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin#include "lambda/shorty_field_type.h"
23fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
24fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin#include <stdint.h>
25fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin#include <vector>
26fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
27fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkinnamespace art {
28fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkinclass ArtMethod;  // forward declaration
29fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
30fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkinnamespace mirror {
31fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkinclass Object;  // forward declaration
32fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin}  // namespace mirror
33fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
34fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkinnamespace lambda {
35fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkinclass ArtLambdaMethod;  // forward declaration
36fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
37fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin// Build a closure by capturing variables one at a time.
38fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin// When all variables have been marked captured, the closure can be created in-place into
39fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin// a target memory address.
40fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin//
41fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin// The mutator lock must be held for the duration of the lifetime of this object,
42fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin// since it needs to temporarily store heap references into an internal list.
436918bf13eb855b3aa8ccdddda2d27ae8c60cec56Igor Murashkinclass ClosureBuilder {
44fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin public:
45fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  using ShortyTypeEnum = decltype(ShortyFieldType::kByte);
46fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
47fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  // Mark this primitive value to be captured as the specified type.
486918bf13eb855b3aa8ccdddda2d27ae8c60cec56Igor Murashkin  template <typename T, ShortyTypeEnum kShortyType = ShortyFieldTypeSelectEnum<T>::value>
49fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  void CaptureVariablePrimitive(T value);
50fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
51fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  // Mark this object reference to be captured.
52fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  void CaptureVariableObject(mirror::Object* object) SHARED_REQUIRES(Locks::mutator_lock_);
53fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
54fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  // Mark this lambda closure to be captured.
55fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  void CaptureVariableLambda(Closure* closure);
56fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
57fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  // Get the size (in bytes) of the closure.
58fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  // This size is used to be able to allocate memory large enough to write the closure into.
59fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  // Call 'CreateInPlace' to actually write the closure out.
60fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  size_t GetSize() const;
61fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
62fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  // Returns how many variables have been captured so far.
63fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  size_t GetCaptureCount() const;
64fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
656918bf13eb855b3aa8ccdddda2d27ae8c60cec56Igor Murashkin  // Get the list of captured variables' shorty field types.
666918bf13eb855b3aa8ccdddda2d27ae8c60cec56Igor Murashkin  const std::string& GetCapturedVariableShortyTypes() const;
676918bf13eb855b3aa8ccdddda2d27ae8c60cec56Igor Murashkin
68fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  // Creates a closure in-place and writes out the data into 'memory'.
69fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  // Memory must be at least 'GetSize' bytes large.
70fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  // All previously marked data to be captured is now written out.
71fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  Closure* CreateInPlace(void* memory, ArtLambdaMethod* target_method) const
72fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin      SHARED_REQUIRES(Locks::mutator_lock_);
73fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
74fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  // Locks need to be held for entire lifetime of ClosureBuilder.
75fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  ClosureBuilder() SHARED_REQUIRES(Locks::mutator_lock_)
76fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  {}
77fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
78fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  // Locks need to be held for entire lifetime of ClosureBuilder.
79fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  ~ClosureBuilder() SHARED_REQUIRES(Locks::mutator_lock_)
80fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  {}
81fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
82fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin private:
83fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  // Initial size a closure starts out before any variables are written.
84fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  // Header size only.
85fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  static constexpr size_t kInitialSize = sizeof(ArtLambdaMethod*);
86fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
87fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  // Write a Closure's variables field from the captured variables.
88fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  // variables_size specified in bytes, and only includes enough room to write variables into.
89fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  // Returns the calculated actual size of the closure.
90fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  size_t WriteValues(ArtLambdaMethod* target_method,
91fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin                     uint8_t variables[],
92fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin                     size_t header_size,
93fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin                     size_t variables_size) const SHARED_REQUIRES(Locks::mutator_lock_);
94fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
95fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  size_t size_ = kInitialSize;
96fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  bool is_dynamic_size_ = false;
97fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin  std::vector<ShortyFieldTypeTraits::MaxType> values_;
986918bf13eb855b3aa8ccdddda2d27ae8c60cec56Igor Murashkin  std::string shorty_types_;
99fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin};
100fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
101fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin}  // namespace lambda
102fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin}  // namespace art
103fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin
104fc1ccd740b7c8e96dfac675cfc580122cd1b40a6Igor Murashkin#endif  // ART_RUNTIME_LAMBDA_CLOSURE_BUILDER_H_
105