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