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 17 #include "lambda/art_lambda_method.h" 18 19 #include "base/logging.h" 20 #include "lambda/shorty_field_type.h" 21 22 namespace art { 23 namespace lambda { 24 25 ArtLambdaMethod::ArtLambdaMethod(ArtMethod* target_method, 26 const char* captured_variables_type_descriptor, 27 const char* captured_variables_shorty, 28 bool innate_lambda) 29 : method_(target_method), 30 captured_variables_type_descriptor_(captured_variables_type_descriptor), 31 captured_variables_shorty_(captured_variables_shorty), 32 innate_lambda_(innate_lambda) { 33 DCHECK(target_method != nullptr); 34 DCHECK(captured_variables_type_descriptor != nullptr); 35 DCHECK(captured_variables_shorty != nullptr); 36 37 // Calculate the static closure size from the captured variables. 38 size_t size = sizeof(ArtLambdaMethod*); // Initial size is just this method. 39 bool static_size = true; 40 const char* shorty = captured_variables_shorty_; 41 while (shorty != nullptr && *shorty != '\0') { 42 // Each captured variable also appends to the size. 43 ShortyFieldType shorty_field{*shorty}; // NOLINT [readability/braces] [4] 44 size += shorty_field.GetStaticSize(); 45 static_size &= shorty_field.IsStaticSize(); 46 ++shorty; 47 } 48 closure_size_ = size; 49 50 // We determine whether or not the size is dynamic by checking for nested lambdas. 51 // 52 // This is conservative, since in theory an optimization could determine the size 53 // of the nested lambdas recursively. In practice it's probably better to flatten out 54 // nested lambdas and inline all their code if they are known statically. 55 dynamic_size_ = !static_size; 56 57 if (kIsDebugBuild) { 58 // Double check that the number of captured variables match in both strings. 59 size_t shorty_count = strlen(captured_variables_shorty); 60 61 size_t long_count = 0; 62 const char* long_type = captured_variables_type_descriptor; 63 ShortyFieldType out; 64 while ((long_type = ShortyFieldType::ParseFromFieldTypeDescriptor(long_type, &out)) 65 != nullptr) { 66 ++long_count; 67 } 68 69 DCHECK_EQ(shorty_count, long_count) 70 << "number of captured variables in long type '" << captured_variables_type_descriptor 71 << "' (" << long_count << ")" << " did not match short type '" 72 << captured_variables_shorty << "' (" << shorty_count << ")"; 73 } 74 } 75 76 } // namespace lambda 77 } // namespace art 78