blob: fb80fb96e1b80e7dddbe34b216ec4796eab6b0fa [file] [log] [blame]
Carl Shapiro3ee755d2011-06-28 12:11:04 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07003#include "object.h"
4
Ian Rogersb033c752011-07-20 12:22:35 -07005#include <string.h>
Ian Rogersdf20fe02011-07-20 20:34:16 -07006#include <algorithm>
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07007
8#include "globals.h"
9#include "logging.h"
10#include "dex_file.h"
11#include "raw_dex_file.h"
Carl Shapiro3ee755d2011-06-28 12:11:04 -070012
13namespace art {
14
Ian Rogersb033c752011-07-20 12:22:35 -070015bool Class::IsInSamePackage(const StringPiece& descriptor1,
16 const StringPiece& descriptor2) {
Carl Shapiro894d0fa2011-06-30 14:48:49 -070017 size_t i = 0;
18 while (descriptor1[i] != '\0' && descriptor1[i] == descriptor2[i]) {
19 ++i;
20 }
Brian Carlstrom6cc18452011-07-18 15:10:33 -070021 if (descriptor1.find('/', i) != StringPiece::npos ||
22 descriptor2.find('/', i) != StringPiece::npos) {
Carl Shapiro894d0fa2011-06-30 14:48:49 -070023 return false;
24 } else {
25 return true;
26 }
27}
28
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070029#if 0
Ian Rogersb033c752011-07-20 12:22:35 -070030bool Class::IsInSamePackage(const StringPiece& descriptor1,
31 const StringPiece& descriptor2) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070032 size_t size = std::min(descriptor1.size(), descriptor2.size());
Brian Carlstrom6cc18452011-07-18 15:10:33 -070033 std::pair<StringPiece::const_iterator, StringPiece::const_iterator> pos;
Ian Rogersb033c752011-07-20 12:22:35 -070034 pos = std::mismatch(descriptor1.begin(), descriptor1.begin() + size,
35 descriptor2.begin());
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070036 return !(*(pos.second).rfind('/') != npos && descriptor2.rfind('/') != npos);
37}
38#endif
39
Carl Shapiro894d0fa2011-06-30 14:48:49 -070040bool Class::IsInSamePackage(const Class* that) const {
41 const Class* klass1 = this;
42 const Class* klass2 = that;
43 if (klass1 == klass2) {
44 return true;
45 }
46 // Class loaders must match.
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070047 if (klass1->GetClassLoader() != klass2->GetClassLoader()) {
Carl Shapiro894d0fa2011-06-30 14:48:49 -070048 return false;
49 }
50 // Arrays are in the same package when their element classes are.
51 if (klass1->IsArray()) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070052 klass1 = klass1->GetComponentType();
Carl Shapiro894d0fa2011-06-30 14:48:49 -070053 }
54 if (klass2->IsArray()) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070055 klass2 = klass2->GetComponentType();
Carl Shapiro894d0fa2011-06-30 14:48:49 -070056 }
57 // Compare the package part of the descriptor string.
Brian Carlstrom6cc18452011-07-18 15:10:33 -070058 return IsInSamePackage(klass1->descriptor_, klass2->descriptor_);
Carl Shapiro894d0fa2011-06-30 14:48:49 -070059}
60
Carl Shapiro3ee755d2011-06-28 12:11:04 -070061uint32_t Method::NumArgRegisters() {
62 CHECK(shorty_ != NULL);
63 uint32_t num_registers = 0;
Carl Shapiro565f5072011-07-10 13:39:43 -070064 for (int i = 1; i < shorty_.length(); ++i) {
Carl Shapiro3ee755d2011-06-28 12:11:04 -070065 char ch = shorty_[i];
66 if (ch == 'D' || ch == 'J') {
67 num_registers += 2;
68 } else {
69 num_registers += 1;
70 }
71 }
72 return num_registers;
73}
74
Ian Rogersb033c752011-07-20 12:22:35 -070075// The number of reference arguments to this method including implicit this
76// pointer
77size_t Method::NumReferenceArgs() const {
78 size_t result = IsStatic() ? 0 : 1;
79 for (int i = 1; i < shorty_.length(); i++) {
80 if ((shorty_[i] == 'L') || (shorty_[i] == '[')) {
81 result++;
82 }
83 }
84 return result;
85}
86
87// The number of long or double arguments
88size_t Method::NumLongOrDoubleArgs() const {
89 size_t result = 0;
90 for (int i = 1; i < shorty_.length(); i++) {
91 if ((shorty_[i] == 'D') || (shorty_[i] == 'J')) {
92 result++;
93 }
94 }
95 return result;
96}
97
98// The number of reference arguments to this method before the given parameter
99// index
100size_t Method::NumReferenceArgsBefore(unsigned int param) const {
101 CHECK_LT(param, NumArgs());
102 unsigned int result = IsStatic() ? 0 : 1;
103 for (unsigned int i = 1; (i < (unsigned int)shorty_.length()) &&
104 (i < (param + 1)); i++) {
105 if ((shorty_[i] == 'L') || (shorty_[i] == '[')) {
106 result++;
107 }
108 }
109 return result;
110}
111
112// Is the given method parameter a reference?
113bool Method::IsParamAReference(unsigned int param) const {
114 CHECK_LT(param, NumArgs());
115 if (IsStatic()) {
116 param++; // 0th argument must skip return value at start of the shorty
117 } else if (param == 0) {
118 return true; // this argument
119 }
120 return ((shorty_[param] == 'L') || (shorty_[param] == '['));
121}
122
123// Is the given method parameter a long or double?
124bool Method::IsParamALongOrDouble(unsigned int param) const {
125 CHECK_LT(param, NumArgs());
126 if (IsStatic()) {
127 param++; // 0th argument must skip return value at start of the shorty
128 }
129 return (shorty_[param] == 'J') || (shorty_[param] == 'D');
130}
131
Ian Rogersdf20fe02011-07-20 20:34:16 -0700132static size_t ShortyCharToSize(char x) {
133 switch (x) {
Ian Rogers45a76cb2011-07-21 22:00:15 -0700134 case 'V': return 0;
Ian Rogersb033c752011-07-20 12:22:35 -0700135 case '[': return kPointerSize;
136 case 'L': return kPointerSize;
137 case 'D': return 8;
138 case 'J': return 8;
139 default: return 4;
140 }
141}
142
Ian Rogersdf20fe02011-07-20 20:34:16 -0700143size_t Method::ParamSize(unsigned int param) const {
144 CHECK_LT(param, NumArgs());
145 if (IsStatic()) {
146 param++; // 0th argument must skip return value at start of the shorty
147 } else if (param == 0) {
148 return kPointerSize; // this argument
149 }
150 return ShortyCharToSize(shorty_[param]);
151}
152
153size_t Method::ReturnSize() const {
154 return ShortyCharToSize(shorty_[0]);
155}
156
Ian Rogersb033c752011-07-20 12:22:35 -0700157Method* Class::FindDirectMethod(const StringPiece& name) const {
158 Method* result = NULL;
159 for (size_t i = 0; i < NumDirectMethods(); i++) {
160 Method* method = GetDirectMethod(i);
161 if (method->GetName().compare(name) == 0) {
162 result = method;
163 break;
164 }
165 }
166 return result;
167}
168
169Method* Class::FindVirtualMethod(const StringPiece& name) const {
170 Method* result = NULL;
171 for (size_t i = 0; i < NumVirtualMethods(); i++) {
172 Method* method = GetVirtualMethod(i);
173 if (method->GetName().compare(name) == 0) {
174 result = method;
175 break;
176 }
177 }
178 return result;
179}
180
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700181Method* Class::FindDirectMethodLocally(const StringPiece& name,
182 const StringPiece& descriptor) const {
183 return NULL; // TODO
184}
185
Elliott Hughes1f359b02011-07-17 14:27:17 -0700186static const char* kClassStatusNames[] = {
187 "Error",
188 "NotReady",
189 "Idx",
190 "Loaded",
191 "Resolved",
192 "Verifying",
193 "Verified",
194 "Initializing",
195 "Initialized"
196};
197std::ostream& operator<<(std::ostream& os, const Class::Status& rhs) {
198 if (rhs >= Class::kStatusError && rhs <= Class::kStatusInitialized) {
199 os << kClassStatusNames[rhs - 1];
200 } else {
Ian Rogersb033c752011-07-20 12:22:35 -0700201 os << "Class::Status[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -0700202 }
203 return os;
204}
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700205
Carl Shapiro3ee755d2011-06-28 12:11:04 -0700206} // namespace art