Igor Murashkin | fc1ccd7 | 2015-07-30 15:11:09 -0700 | [diff] [blame] | 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, |
Igor Murashkin | 6918bf1 | 2015-09-27 19:19:06 -0700 | [diff] [blame] | 38 | const char* captured_variables_shorty, |
Igor Murashkin | fc1ccd7 | 2015-07-30 15:11:09 -0700 | [diff] [blame] | 39 | bool innate_lambda = true); |
| 40 | |
| 41 | // Get the target method for this lambda that would be used by the invoke-lambda dex instruction. |
| 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. |
| 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 |
| 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 '\'. |
| 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. |
| 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. |
| 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. |
| 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). |
| 89 | size_t GetNumberOfCapturedVariables() const { |
| 90 | return strlen(captured_variables_shorty_); |
| 91 | } |
| 92 | |
Igor Murashkin | fc1ccd7 | 2015-07-30 15:11:09 -0700 | [diff] [blame] | 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_ |