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
ArtLambdaMethod(ArtMethod * target_method,const char * captured_variables_type_descriptor,const char * captured_variables_shorty,bool innate_lambda)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