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