Home | History | Annotate | Download | only in lambda
      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.
     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 
     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