blob: 289f52695bf2cd021d0c8e0f2513891bf4658b1e [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"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070010#include "dex_cache.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070011#include "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
Carl Shapiroe2d373e2011-07-25 15:20:06 -0700128 } else if (param == 0) {
129 return false; // this argument
Ian Rogersb033c752011-07-20 12:22:35 -0700130 }
131 return (shorty_[param] == 'J') || (shorty_[param] == 'D');
132}
133
Ian Rogersdf20fe02011-07-20 20:34:16 -0700134static size_t ShortyCharToSize(char x) {
135 switch (x) {
Ian Rogers45a76cb2011-07-21 22:00:15 -0700136 case 'V': return 0;
Ian Rogersb033c752011-07-20 12:22:35 -0700137 case '[': return kPointerSize;
138 case 'L': return kPointerSize;
139 case 'D': return 8;
140 case 'J': return 8;
141 default: return 4;
142 }
143}
144
Ian Rogersdf20fe02011-07-20 20:34:16 -0700145size_t Method::ParamSize(unsigned int param) const {
146 CHECK_LT(param, NumArgs());
147 if (IsStatic()) {
148 param++; // 0th argument must skip return value at start of the shorty
149 } else if (param == 0) {
150 return kPointerSize; // this argument
151 }
152 return ShortyCharToSize(shorty_[param]);
153}
154
155size_t Method::ReturnSize() const {
156 return ShortyCharToSize(shorty_[0]);
157}
158
Ian Rogersb033c752011-07-20 12:22:35 -0700159Method* Class::FindDirectMethod(const StringPiece& name) const {
160 Method* result = NULL;
161 for (size_t i = 0; i < NumDirectMethods(); i++) {
162 Method* method = GetDirectMethod(i);
163 if (method->GetName().compare(name) == 0) {
164 result = method;
165 break;
166 }
167 }
168 return result;
169}
170
171Method* Class::FindVirtualMethod(const StringPiece& name) const {
172 Method* result = NULL;
173 for (size_t i = 0; i < NumVirtualMethods(); i++) {
174 Method* method = GetVirtualMethod(i);
175 if (method->GetName().compare(name) == 0) {
176 result = method;
177 break;
178 }
179 }
180 return result;
181}
182
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700183Method* Class::FindDirectMethodLocally(const StringPiece& name,
184 const StringPiece& descriptor) const {
185 return NULL; // TODO
186}
187
Elliott Hughes1f359b02011-07-17 14:27:17 -0700188static const char* kClassStatusNames[] = {
189 "Error",
190 "NotReady",
191 "Idx",
192 "Loaded",
193 "Resolved",
194 "Verifying",
195 "Verified",
196 "Initializing",
197 "Initialized"
198};
199std::ostream& operator<<(std::ostream& os, const Class::Status& rhs) {
200 if (rhs >= Class::kStatusError && rhs <= Class::kStatusInitialized) {
201 os << kClassStatusNames[rhs - 1];
202 } else {
Ian Rogersb033c752011-07-20 12:22:35 -0700203 os << "Class::Status[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -0700204 }
205 return os;
206}
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700207
Carl Shapiro3ee755d2011-06-28 12:11:04 -0700208} // namespace art