blob: afd2eff077c90c9a84bd30f63f65f7bd827ee5f5 [file] [log] [blame]
Ian Rogers776ac1f2012-04-13 23:36:36 -07001/*
2 * Copyright (C) 2012 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 "register_line.h"
18
19#include "method_verifier.h"
20
21namespace art {
22namespace verifier {
23
24bool RegisterLine::CheckConstructorReturn() const {
25 for (size_t i = 0; i < num_regs_; i++) {
Ian Rogersad0b3a32012-04-16 14:50:24 -070026 if (GetRegisterType(i).IsUninitializedThisReference() ||
27 GetRegisterType(i).IsUnresolvedAndUninitializedThisReference()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -070028 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT)
29 << "Constructor returning without calling superclass constructor";
30 return false;
31 }
32 }
33 return true;
34}
35
36bool RegisterLine::SetRegisterType(uint32_t vdst, const RegType& new_type) {
Ian Rogersad0b3a32012-04-16 14:50:24 -070037 DCHECK_LT(vdst, num_regs_);
Ian Rogers2bcb4a42012-11-08 10:39:18 -080038 if (new_type.IsLowHalf() || new_type.IsHighHalf()) {
39 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "Expected category1 register type not '"
40 << new_type << "'";
Ian Rogers776ac1f2012-04-13 23:36:36 -070041 return false;
42 } else if (new_type.IsConflict()) { // should only be set during a merge
43 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "Set register to unknown type " << new_type;
44 return false;
jeffhaob5c25fd2012-06-07 17:47:06 -070045 } else if (!Runtime::Current()->IsCompiler() && new_type.IsUnresolvedTypes()) {
46 // Unresolvable classes at runtime are bad and marked as a rewrite error.
47 verifier_->Fail(VERIFY_ERROR_NO_CLASS) << "Set register to unresolved class '"
48 << new_type << "' at runtime";
49 return false;
Ian Rogers776ac1f2012-04-13 23:36:36 -070050 } else {
51 line_[vdst] = new_type.GetId();
52 }
53 // Clear the monitor entry bits for this register.
54 ClearAllRegToLockDepths(vdst);
55 return true;
56}
57
Ian Rogers2bcb4a42012-11-08 10:39:18 -080058bool RegisterLine::SetRegisterTypeWide(uint32_t vdst, const RegType& new_type1,
59 const RegType& new_type2) {
60 DCHECK_LT(vdst, num_regs_);
61 if (!new_type1.CheckWidePair(new_type2)) {
62 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "Invalid wide pair '"
63 << new_type1 << "' '" << new_type2 << "'";
64 return false;
65 } else {
66 line_[vdst] = new_type1.GetId();
67 line_[vdst + 1] = new_type2.GetId();
68 }
69 // Clear the monitor entry bits for this register.
70 ClearAllRegToLockDepths(vdst);
71 ClearAllRegToLockDepths(vdst + 1);
72 return true;
73}
74
Ian Rogers776ac1f2012-04-13 23:36:36 -070075void RegisterLine::SetResultTypeToUnknown() {
Ian Rogersad0b3a32012-04-16 14:50:24 -070076 result_[0] = RegType::kRegTypeUndefined;
77 result_[1] = RegType::kRegTypeUndefined;
Ian Rogers776ac1f2012-04-13 23:36:36 -070078}
79
80void RegisterLine::SetResultRegisterType(const RegType& new_type) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -080081 DCHECK(!new_type.IsLowHalf());
82 DCHECK(!new_type.IsHighHalf());
Ian Rogers776ac1f2012-04-13 23:36:36 -070083 result_[0] = new_type.GetId();
Ian Rogers2bcb4a42012-11-08 10:39:18 -080084 result_[1] = RegType::kRegTypeUndefined;
Ian Rogers776ac1f2012-04-13 23:36:36 -070085 if (new_type.IsLowHalf()) {
86 DCHECK_EQ(new_type.HighHalf(verifier_->GetRegTypeCache()).GetId(), new_type.GetId() + 1);
87 result_[1] = new_type.GetId() + 1;
88 } else {
Ian Rogersad0b3a32012-04-16 14:50:24 -070089 result_[1] = RegType::kRegTypeUndefined;
Ian Rogers776ac1f2012-04-13 23:36:36 -070090 }
91}
92
Ian Rogers2bcb4a42012-11-08 10:39:18 -080093void RegisterLine::SetResultRegisterTypeWide(const RegType& new_type1, const RegType& new_type2) {
94 DCHECK(new_type1.CheckWidePair(new_type2));
95 result_[0] = new_type1.GetId();
96 result_[1] = new_type2.GetId();
97}
98
Ian Rogers776ac1f2012-04-13 23:36:36 -070099const RegType& RegisterLine::GetRegisterType(uint32_t vsrc) const {
100 // The register index was validated during the static pass, so we don't need to check it here.
101 DCHECK_LT(vsrc, num_regs_);
102 return verifier_->GetRegTypeCache()->GetFromId(line_[vsrc]);
103}
104
105const RegType& RegisterLine::GetInvocationThis(const DecodedInstruction& dec_insn) {
106 if (dec_insn.vA < 1) {
107 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invoke lacks 'this'";
Ian Rogersad0b3a32012-04-16 14:50:24 -0700108 return verifier_->GetRegTypeCache()->Conflict();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700109 }
110 /* get the element type of the array held in vsrc */
111 const RegType& this_type = GetRegisterType(dec_insn.vC);
112 if (!this_type.IsReferenceTypes()) {
113 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "tried to get class from non-reference register v"
114 << dec_insn.vC << " (type=" << this_type << ")";
Ian Rogersad0b3a32012-04-16 14:50:24 -0700115 return verifier_->GetRegTypeCache()->Conflict();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700116 }
117 return this_type;
118}
119
120bool RegisterLine::VerifyRegisterType(uint32_t vsrc, const RegType& check_type) {
121 // Verify the src register type against the check type refining the type of the register
122 const RegType& src_type = GetRegisterType(vsrc);
123 if (!check_type.IsAssignableFrom(src_type)) {
jeffhaoeb311132012-08-02 18:29:08 -0700124 // Hard fail if one of the types is primitive, since they are concretely known.
125 enum VerifyError fail_type = (!check_type.IsNonZeroReferenceTypes() ||
126 !src_type.IsNonZeroReferenceTypes()) ?
127 VERIFY_ERROR_BAD_CLASS_HARD : VERIFY_ERROR_BAD_CLASS_SOFT;
128 verifier_->Fail(fail_type) << "register v" << vsrc << " has type " << src_type
129 << " but expected " << check_type;
Ian Rogers776ac1f2012-04-13 23:36:36 -0700130 return false;
131 }
132 if (check_type.IsLowHalf()) {
133 const RegType& src_type_h = GetRegisterType(vsrc + 1);
134 if (!src_type.CheckWidePair(src_type_h)) {
jeffhaoeb311132012-08-02 18:29:08 -0700135 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "wide register v" << vsrc << " has type "
Ian Rogers776ac1f2012-04-13 23:36:36 -0700136 << src_type << "/" << src_type_h;
137 return false;
138 }
139 }
140 // The register at vsrc has a defined type, we know the lower-upper-bound, but this is less
141 // precise than the subtype in vsrc so leave it for reference types. For primitive types
142 // if they are a defined type then they are as precise as we can get, however, for constant
143 // types we may wish to refine them. Unfortunately constant propagation has rendered this useless.
144 return true;
145}
146
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800147bool RegisterLine::VerifyRegisterTypeWide(uint32_t vsrc, const RegType& check_type1,
148 const RegType& check_type2) {
149 DCHECK(check_type1.CheckWidePair(check_type2));
150 // Verify the src register type against the check type refining the type of the register
151 const RegType& src_type = GetRegisterType(vsrc);
152 if (!check_type1.IsAssignableFrom(src_type)) {
153 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "register v" << vsrc << " has type " << src_type
154 << " but expected " << check_type1;
155 return false;
156 }
157 const RegType& src_type_h = GetRegisterType(vsrc + 1);
158 if (!src_type.CheckWidePair(src_type_h)) {
159 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "wide register v" << vsrc << " has type "
160 << src_type << "/" << src_type_h;
161 return false;
162 }
163 // The register at vsrc has a defined type, we know the lower-upper-bound, but this is less
164 // precise than the subtype in vsrc so leave it for reference types. For primitive types
165 // if they are a defined type then they are as precise as we can get, however, for constant
166 // types we may wish to refine them. Unfortunately constant propagation has rendered this useless.
167 return true;
168}
169
Ian Rogers776ac1f2012-04-13 23:36:36 -0700170void RegisterLine::MarkRefsAsInitialized(const RegType& uninit_type) {
171 DCHECK(uninit_type.IsUninitializedTypes());
172 const RegType& init_type = verifier_->GetRegTypeCache()->FromUninitialized(uninit_type);
173 size_t changed = 0;
174 for (size_t i = 0; i < num_regs_; i++) {
175 if (GetRegisterType(i).Equals(uninit_type)) {
176 line_[i] = init_type.GetId();
177 changed++;
178 }
179 }
180 DCHECK_GT(changed, 0u);
181}
182
Ian Rogers529781d2012-07-23 17:24:29 -0700183std::string RegisterLine::Dump() const {
184 std::string result;
185 for (size_t i = 0; i < num_regs_; i++) {
186 result += StringPrintf("%zd:[", i);
187 result += GetRegisterType(i).Dump(verifier_->GetRegTypeCache());
188 result += "],";
189 }
190 typedef std::deque<uint32_t>::const_iterator It; // TODO: C++0x auto
191 for (It it = monitors_.begin(), end = monitors_.end(); it != end ; ++it) {
192 result += StringPrintf("{%d},", *it);
193 }
194 return result;
195}
196
Ian Rogers776ac1f2012-04-13 23:36:36 -0700197void RegisterLine::MarkUninitRefsAsInvalid(const RegType& uninit_type) {
198 for (size_t i = 0; i < num_regs_; i++) {
199 if (GetRegisterType(i).Equals(uninit_type)) {
200 line_[i] = verifier_->GetRegTypeCache()->Conflict().GetId();
201 ClearAllRegToLockDepths(i);
202 }
203 }
204}
205
206void RegisterLine::CopyRegister1(uint32_t vdst, uint32_t vsrc, TypeCategory cat) {
207 DCHECK(cat == kTypeCategory1nr || cat == kTypeCategoryRef);
208 const RegType& type = GetRegisterType(vsrc);
209 if (!SetRegisterType(vdst, type)) {
210 return;
211 }
212 if ((cat == kTypeCategory1nr && !type.IsCategory1Types()) ||
213 (cat == kTypeCategoryRef && !type.IsReferenceTypes())) {
214 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "copy1 v" << vdst << "<-v" << vsrc << " type=" << type
215 << " cat=" << static_cast<int>(cat);
216 } else if (cat == kTypeCategoryRef) {
217 CopyRegToLockDepth(vdst, vsrc);
218 }
219}
220
221void RegisterLine::CopyRegister2(uint32_t vdst, uint32_t vsrc) {
222 const RegType& type_l = GetRegisterType(vsrc);
223 const RegType& type_h = GetRegisterType(vsrc + 1);
224
225 if (!type_l.CheckWidePair(type_h)) {
226 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "copy2 v" << vdst << "<-v" << vsrc
227 << " type=" << type_l << "/" << type_h;
228 } else {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800229 SetRegisterTypeWide(vdst, type_l, type_h);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700230 }
231}
232
233void RegisterLine::CopyResultRegister1(uint32_t vdst, bool is_reference) {
234 const RegType& type = verifier_->GetRegTypeCache()->GetFromId(result_[0]);
235 if ((!is_reference && !type.IsCategory1Types()) ||
236 (is_reference && !type.IsReferenceTypes())) {
237 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD)
238 << "copyRes1 v" << vdst << "<- result0" << " type=" << type;
239 } else {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700240 DCHECK(verifier_->GetRegTypeCache()->GetFromId(result_[1]).IsUndefined());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700241 SetRegisterType(vdst, type);
Ian Rogersad0b3a32012-04-16 14:50:24 -0700242 result_[0] = RegType::kRegTypeUndefined;
Ian Rogers776ac1f2012-04-13 23:36:36 -0700243 }
244}
245
246/*
247 * Implement "move-result-wide". Copy the category-2 value from the result
248 * register to another register, and reset the result register.
249 */
250void RegisterLine::CopyResultRegister2(uint32_t vdst) {
251 const RegType& type_l = verifier_->GetRegTypeCache()->GetFromId(result_[0]);
252 const RegType& type_h = verifier_->GetRegTypeCache()->GetFromId(result_[1]);
253 if (!type_l.IsCategory2Types()) {
254 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD)
255 << "copyRes2 v" << vdst << "<- result0" << " type=" << type_l;
256 } else {
257 DCHECK(type_l.CheckWidePair(type_h)); // Set should never allow this case
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800258 SetRegisterTypeWide(vdst, type_l, type_h); // also sets the high
Ian Rogersad0b3a32012-04-16 14:50:24 -0700259 result_[0] = RegType::kRegTypeUndefined;
260 result_[1] = RegType::kRegTypeUndefined;
Ian Rogers776ac1f2012-04-13 23:36:36 -0700261 }
262}
263
264void RegisterLine::CheckUnaryOp(const DecodedInstruction& dec_insn,
265 const RegType& dst_type, const RegType& src_type) {
266 if (VerifyRegisterType(dec_insn.vB, src_type)) {
267 SetRegisterType(dec_insn.vA, dst_type);
268 }
269}
270
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800271void RegisterLine::CheckUnaryOpWide(const DecodedInstruction& dec_insn,
272 const RegType& dst_type1, const RegType& dst_type2,
273 const RegType& src_type1, const RegType& src_type2) {
274 if (VerifyRegisterTypeWide(dec_insn.vB, src_type1, src_type2)) {
275 SetRegisterTypeWide(dec_insn.vA, dst_type1, dst_type2);
276 }
277}
278
279void RegisterLine::CheckUnaryOpToWide(const DecodedInstruction& dec_insn,
280 const RegType& dst_type1, const RegType& dst_type2,
281 const RegType& src_type) {
282 if (VerifyRegisterType(dec_insn.vB, src_type)) {
283 SetRegisterTypeWide(dec_insn.vA, dst_type1, dst_type2);
284 }
285}
286
287void RegisterLine::CheckUnaryOpFromWide(const DecodedInstruction& dec_insn,
288 const RegType& dst_type,
289 const RegType& src_type1, const RegType& src_type2) {
290 if (VerifyRegisterTypeWide(dec_insn.vB, src_type1, src_type2)) {
291 SetRegisterType(dec_insn.vA, dst_type);
292 }
293}
294
Ian Rogers776ac1f2012-04-13 23:36:36 -0700295void RegisterLine::CheckBinaryOp(const DecodedInstruction& dec_insn,
296 const RegType& dst_type,
297 const RegType& src_type1, const RegType& src_type2,
298 bool check_boolean_op) {
299 if (VerifyRegisterType(dec_insn.vB, src_type1) &&
300 VerifyRegisterType(dec_insn.vC, src_type2)) {
301 if (check_boolean_op) {
302 DCHECK(dst_type.IsInteger());
303 if (GetRegisterType(dec_insn.vB).IsBooleanTypes() &&
304 GetRegisterType(dec_insn.vC).IsBooleanTypes()) {
305 SetRegisterType(dec_insn.vA, verifier_->GetRegTypeCache()->Boolean());
306 return;
307 }
308 }
309 SetRegisterType(dec_insn.vA, dst_type);
310 }
311}
312
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800313void RegisterLine::CheckBinaryOpWide(const DecodedInstruction& dec_insn,
314 const RegType& dst_type1, const RegType& dst_type2,
315 const RegType& src_type1_1, const RegType& src_type1_2,
316 const RegType& src_type2_1, const RegType& src_type2_2) {
317 if (VerifyRegisterTypeWide(dec_insn.vB, src_type1_1, src_type1_2) &&
318 VerifyRegisterTypeWide(dec_insn.vC, src_type2_1, src_type2_2)) {
319 SetRegisterTypeWide(dec_insn.vA, dst_type1, dst_type2);
320 }
321}
322
323void RegisterLine::CheckBinaryOpWideShift(const DecodedInstruction& dec_insn,
324 const RegType& long_lo_type, const RegType& long_hi_type,
325 const RegType& int_type) {
326 if (VerifyRegisterTypeWide(dec_insn.vB, long_lo_type, long_hi_type) &&
327 VerifyRegisterType(dec_insn.vC, int_type)) {
328 SetRegisterTypeWide(dec_insn.vA, long_lo_type, long_hi_type);
329 }
330}
331
Ian Rogers776ac1f2012-04-13 23:36:36 -0700332void RegisterLine::CheckBinaryOp2addr(const DecodedInstruction& dec_insn,
333 const RegType& dst_type, const RegType& src_type1,
334 const RegType& src_type2, bool check_boolean_op) {
335 if (VerifyRegisterType(dec_insn.vA, src_type1) &&
336 VerifyRegisterType(dec_insn.vB, src_type2)) {
337 if (check_boolean_op) {
338 DCHECK(dst_type.IsInteger());
339 if (GetRegisterType(dec_insn.vA).IsBooleanTypes() &&
340 GetRegisterType(dec_insn.vB).IsBooleanTypes()) {
341 SetRegisterType(dec_insn.vA, verifier_->GetRegTypeCache()->Boolean());
342 return;
343 }
344 }
345 SetRegisterType(dec_insn.vA, dst_type);
346 }
347}
348
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800349void RegisterLine::CheckBinaryOp2addrWide(const DecodedInstruction& dec_insn,
350 const RegType& dst_type1, const RegType& dst_type2,
351 const RegType& src_type1_1, const RegType& src_type1_2,
352 const RegType& src_type2_1, const RegType& src_type2_2) {
353 if (VerifyRegisterTypeWide(dec_insn.vA, src_type1_1, src_type1_2) &&
354 VerifyRegisterTypeWide(dec_insn.vB, src_type2_1, src_type2_2)) {
355 SetRegisterTypeWide(dec_insn.vA, dst_type1, dst_type2);
356 }
357}
358
359void RegisterLine::CheckBinaryOp2addrWideShift(const DecodedInstruction& dec_insn,
360 const RegType& long_lo_type, const RegType& long_hi_type,
361 const RegType& int_type) {
362 if (VerifyRegisterTypeWide(dec_insn.vA, long_lo_type, long_hi_type) &&
363 VerifyRegisterType(dec_insn.vB, int_type)) {
364 SetRegisterTypeWide(dec_insn.vA, long_lo_type, long_hi_type);
365 }
366}
367
Ian Rogers776ac1f2012-04-13 23:36:36 -0700368void RegisterLine::CheckLiteralOp(const DecodedInstruction& dec_insn,
369 const RegType& dst_type, const RegType& src_type,
370 bool check_boolean_op) {
371 if (VerifyRegisterType(dec_insn.vB, src_type)) {
372 if (check_boolean_op) {
373 DCHECK(dst_type.IsInteger());
374 /* check vB with the call, then check the constant manually */
375 if (GetRegisterType(dec_insn.vB).IsBooleanTypes() &&
376 (dec_insn.vC == 0 || dec_insn.vC == 1)) {
377 SetRegisterType(dec_insn.vA, verifier_->GetRegTypeCache()->Boolean());
378 return;
379 }
380 }
381 SetRegisterType(dec_insn.vA, dst_type);
382 }
383}
384
385void RegisterLine::PushMonitor(uint32_t reg_idx, int32_t insn_idx) {
386 const RegType& reg_type = GetRegisterType(reg_idx);
387 if (!reg_type.IsReferenceTypes()) {
388 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "monitor-enter on non-object (" << reg_type << ")";
389 } else if (monitors_.size() >= 32) {
390 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "monitor-enter stack overflow: " << monitors_.size();
391 } else {
392 SetRegToLockDepth(reg_idx, monitors_.size());
393 monitors_.push_back(insn_idx);
394 }
395}
396
397void RegisterLine::PopMonitor(uint32_t reg_idx) {
398 const RegType& reg_type = GetRegisterType(reg_idx);
399 if (!reg_type.IsReferenceTypes()) {
400 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "monitor-exit on non-object (" << reg_type << ")";
401 } else if (monitors_.empty()) {
402 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "monitor-exit stack underflow";
403 } else {
404 monitors_.pop_back();
405 if (!IsSetLockDepth(reg_idx, monitors_.size())) {
406 // Bug 3215458: Locks and unlocks are on objects, if that object is a literal then before
407 // format "036" the constant collector may create unlocks on the same object but referenced
408 // via different registers.
409 ((verifier_->DexFileVersion() >= 36) ? verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT)
410 : verifier_->LogVerifyInfo())
411 << "monitor-exit not unlocking the top of the monitor stack";
412 } else {
413 // Record the register was unlocked
414 ClearRegToLockDepth(reg_idx, monitors_.size());
415 }
416 }
417}
418
419bool RegisterLine::VerifyMonitorStackEmpty() {
420 if (MonitorStackDepth() != 0) {
421 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "expected empty monitor stack";
422 return false;
423 } else {
424 return true;
425 }
426}
427
428bool RegisterLine::MergeRegisters(const RegisterLine* incoming_line) {
429 bool changed = false;
430 for (size_t idx = 0; idx < num_regs_; idx++) {
431 if (line_[idx] != incoming_line->line_[idx]) {
432 const RegType& incoming_reg_type = incoming_line->GetRegisterType(idx);
433 const RegType& cur_type = GetRegisterType(idx);
434 const RegType& new_type = cur_type.Merge(incoming_reg_type, verifier_->GetRegTypeCache());
435 changed = changed || !cur_type.Equals(new_type);
436 line_[idx] = new_type.GetId();
437 }
438 }
439 if (monitors_.size() != incoming_line->monitors_.size()) {
440 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "mismatched stack depths (depth="
441 << MonitorStackDepth() << ", incoming depth=" << incoming_line->MonitorStackDepth() << ")";
442 } else if (reg_to_lock_depths_ != incoming_line->reg_to_lock_depths_) {
443 for (uint32_t idx = 0; idx < num_regs_; idx++) {
444 size_t depths = reg_to_lock_depths_.count(idx);
445 size_t incoming_depths = incoming_line->reg_to_lock_depths_.count(idx);
446 if (depths != incoming_depths) {
447 if (depths == 0 || incoming_depths == 0) {
448 reg_to_lock_depths_.erase(idx);
449 } else {
450 verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "mismatched stack depths for register v" << idx
451 << ": " << depths << " != " << incoming_depths;
452 break;
453 }
454 }
455 }
456 }
457 return changed;
458}
459
460void RegisterLine::WriteReferenceBitMap(std::vector<uint8_t>& data, size_t max_bytes) {
461 for (size_t i = 0; i < num_regs_; i += 8) {
462 uint8_t val = 0;
463 for (size_t j = 0; j < 8 && (i + j) < num_regs_; j++) {
464 // Note: we write 1 for a Reference but not for Null
465 if (GetRegisterType(i + j).IsNonZeroReferenceTypes()) {
466 val |= 1 << j;
467 }
468 }
469 if ((i / 8) >= max_bytes) {
470 DCHECK_EQ(0, val);
471 continue;
472 }
473 DCHECK_LT(i / 8, max_bytes) << "val=" << static_cast<uint32_t>(val);
474 data.push_back(val);
475 }
476}
477
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700478std::ostream& operator<<(std::ostream& os, const RegisterLine& rhs)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700479 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700480 os << rhs.Dump();
481 return os;
482}
483
484} // namespace verifier
485} // namespace art