/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ART_RUNTIME_LAMBDA_ART_LAMBDA_METHOD_H_ #define ART_RUNTIME_LAMBDA_ART_LAMBDA_METHOD_H_ #include "base/macros.h" #include "art_method.h" #include namespace art { namespace lambda { class ArtLambdaMethod { public: // Construct an art lambda method. // The target method is the one invoked by invoke-lambda. // The type descriptor describes the types of variables captured, e.g. "ZFLObject;\FI;[Z" // The shorty drops the object name and treats arrays as objects, e.g. "ZFL\L" // Innate lambda means that the lambda was originally created via invoke-lambda. // -- Non-innate lambdas (learned lambdas) come from a regular class that was boxed to lambda. // (Ownership of strings is retained by the caller and the lifetime should exceed this class). ArtLambdaMethod(ArtMethod* target_method, const char* captured_variables_type_descriptor, const char* captured_variables_shorty, bool innate_lambda = true); // Get the target method for this lambda that would be used by the invoke-lambda dex instruction. ArtMethod* GetArtMethod() const { return method_; } // Get the compile-time size of lambda closures for this method in bytes. // This is circular (that is, it includes the size of the ArtLambdaMethod pointer). // One should also check if the size is dynamic since nested lambdas have a runtime size. size_t GetStaticClosureSize() const { return closure_size_; } // Get the type descriptor for the list of captured variables. // e.g. "ZFLObject;\FI;[Z" means a captured int, float, class Object, lambda FI, array of ints const char* GetCapturedVariablesTypeDescriptor() const { return captured_variables_type_descriptor_; } // Get the shorty 'field' type descriptor list of captured variables. // This follows the same rules as a string of ShortyFieldType in the dex specification. // Every captured variable is represented by exactly one character. // - Objects become 'L'. // - Arrays become 'L'. // - Lambdas become '\'. const char* GetCapturedVariablesShortyTypeDescriptor() const { return captured_variables_shorty_; } // Will the size of this lambda change at runtime? // Only returns true if there is a nested lambda that we can't determine statically the size of. bool IsDynamicSize() const { return dynamic_size_; } // Will the size of this lambda always be constant at runtime? // This generally means there's no nested lambdas, or we were able to successfully determine // their size statically at compile time. bool IsStaticSize() const { return !IsDynamicSize(); } // Is this a lambda that was originally created via invoke-lambda? // -- Non-innate lambdas (learned lambdas) come from a regular class that was boxed to lambda. bool IsInnateLambda() const { return innate_lambda_; } // How many variables were captured? // (Each nested lambda counts as 1 captured var regardless of how many captures it itself has). size_t GetNumberOfCapturedVariables() const { return strlen(captured_variables_shorty_); } private: // TODO: ArtMethod, or at least the entry points should be inlined into this struct // to avoid an extra indirect load when doing invokes. // Target method that invoke-lambda will jump to. ArtMethod* method_; // How big the closure is (in bytes). Only includes the constant size. size_t closure_size_; // The type descriptor for the captured variables, e.g. "IS" for [int, short] const char* captured_variables_type_descriptor_; // The shorty type descriptor for captured vars, (e.g. using 'L' instead of 'LObject;') const char* captured_variables_shorty_; // Whether or not the size is dynamic. If it is, copiers need to read the Closure size at runtime. bool dynamic_size_; // True if this lambda was originally made with create-lambda, // false if it came from a class instance (through new-instance and then unbox-lambda). bool innate_lambda_; DISALLOW_COPY_AND_ASSIGN(ArtLambdaMethod); }; } // namespace lambda } // namespace art #endif // ART_RUNTIME_LAMBDA_ART_LAMBDA_METHOD_H_