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_ART_LAMBDA_METHOD_H_ 17 #define ART_RUNTIME_LAMBDA_ART_LAMBDA_METHOD_H_ 18 19 #include "base/macros.h" 20 #include "art_method.h" 21 22 #include <stdint.h> 23 24 namespace art { 25 namespace lambda { 26 27 class ArtLambdaMethod { 28 public: 29 // Construct an art lambda method. 30 // The target method is the one invoked by invoke-lambda. 31 // The type descriptor describes the types of variables captured, e.g. "ZFLObject;\FI;[Z" 32 // The shorty drops the object name and treats arrays as objects, e.g. "ZFL\L" 33 // Innate lambda means that the lambda was originally created via invoke-lambda. 34 // -- Non-innate lambdas (learned lambdas) come from a regular class that was boxed to lambda. 35 // (Ownership of strings is retained by the caller and the lifetime should exceed this class). 36 ArtLambdaMethod(ArtMethod* target_method, 37 const char* captured_variables_type_descriptor, 38 const char* captured_variables_shorty, 39 bool innate_lambda = true); 40 41 // Get the target method for this lambda that would be used by the invoke-lambda dex instruction. GetArtMethod()42 ArtMethod* GetArtMethod() const { 43 return method_; 44 } 45 46 // Get the compile-time size of lambda closures for this method in bytes. 47 // This is circular (that is, it includes the size of the ArtLambdaMethod pointer). 48 // One should also check if the size is dynamic since nested lambdas have a runtime size. GetStaticClosureSize()49 size_t GetStaticClosureSize() const { 50 return closure_size_; 51 } 52 53 // Get the type descriptor for the list of captured variables. 54 // e.g. "ZFLObject;\FI;[Z" means a captured int, float, class Object, lambda FI, array of ints GetCapturedVariablesTypeDescriptor()55 const char* GetCapturedVariablesTypeDescriptor() const { 56 return captured_variables_type_descriptor_; 57 } 58 59 // Get the shorty 'field' type descriptor list of captured variables. 60 // This follows the same rules as a string of ShortyFieldType in the dex specification. 61 // Every captured variable is represented by exactly one character. 62 // - Objects become 'L'. 63 // - Arrays become 'L'. 64 // - Lambdas become '\'. GetCapturedVariablesShortyTypeDescriptor()65 const char* GetCapturedVariablesShortyTypeDescriptor() const { 66 return captured_variables_shorty_; 67 } 68 69 // Will the size of this lambda change at runtime? 70 // Only returns true if there is a nested lambda that we can't determine statically the size of. IsDynamicSize()71 bool IsDynamicSize() const { 72 return dynamic_size_; 73 } 74 75 // Will the size of this lambda always be constant at runtime? 76 // This generally means there's no nested lambdas, or we were able to successfully determine 77 // their size statically at compile time. IsStaticSize()78 bool IsStaticSize() const { 79 return !IsDynamicSize(); 80 } 81 // Is this a lambda that was originally created via invoke-lambda? 82 // -- Non-innate lambdas (learned lambdas) come from a regular class that was boxed to lambda. IsInnateLambda()83 bool IsInnateLambda() const { 84 return innate_lambda_; 85 } 86 87 // How many variables were captured? 88 // (Each nested lambda counts as 1 captured var regardless of how many captures it itself has). GetNumberOfCapturedVariables()89 size_t GetNumberOfCapturedVariables() const { 90 return strlen(captured_variables_shorty_); 91 } 92 93 private: 94 // TODO: ArtMethod, or at least the entry points should be inlined into this struct 95 // to avoid an extra indirect load when doing invokes. 96 // Target method that invoke-lambda will jump to. 97 ArtMethod* method_; 98 // How big the closure is (in bytes). Only includes the constant size. 99 size_t closure_size_; 100 // The type descriptor for the captured variables, e.g. "IS" for [int, short] 101 const char* captured_variables_type_descriptor_; 102 // The shorty type descriptor for captured vars, (e.g. using 'L' instead of 'LObject;') 103 const char* captured_variables_shorty_; 104 // Whether or not the size is dynamic. If it is, copiers need to read the Closure size at runtime. 105 bool dynamic_size_; 106 // True if this lambda was originally made with create-lambda, 107 // false if it came from a class instance (through new-instance and then unbox-lambda). 108 bool innate_lambda_; 109 110 DISALLOW_COPY_AND_ASSIGN(ArtLambdaMethod); 111 }; 112 113 } // namespace lambda 114 } // namespace art 115 116 #endif // ART_RUNTIME_LAMBDA_ART_LAMBDA_METHOD_H_ 117