More fixes for vm-tests.
Failing to open a dex file is no longer a fatal error.
SetRegisterType in the verifier returns true/false for success/failure
to prevent Fail from being called twice.
Verifier checks that all catch blocks begin with a move-exception.
Gc maps can now support 65536 registers, with the size using some bits
that were usused in the format.
Change-Id: Idfa92c627efff8fd8360e933f54def397c953688
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index 23c7416..a27b76e 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -387,10 +387,10 @@
const char* dex_filename = dex_filenames[i];
const DexFile* dex_file = DexFile::Open(dex_filename, strip_location_prefix);
if (dex_file == NULL) {
- fprintf(stderr, "could not open .dex from file %s\n", dex_filename);
- exit(EXIT_FAILURE);
+ LOG(WARNING) << "could not open .dex from file " << dex_filename;
+ } else {
+ dex_files.push_back(dex_file);
}
- dex_files.push_back(dex_file);
}
}
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index dfaaf01..077bb32 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -575,7 +575,7 @@
return true;
}
-void RegisterLine::SetRegisterType(uint32_t vdst, const RegType& new_type) {
+bool RegisterLine::SetRegisterType(uint32_t vdst, const RegType& new_type) {
DCHECK(vdst < num_regs_);
if (new_type.IsLowHalf()) {
line_[vdst] = new_type.GetId();
@@ -583,13 +583,16 @@
} else if (new_type.IsHighHalf()) {
/* should never set these explicitly */
verifier_->Fail(VERIFY_ERROR_GENERIC) << "Explicit set of high register type";
+ return false;
} else if (new_type.IsConflict()) { // should only be set during a merge
verifier_->Fail(VERIFY_ERROR_GENERIC) << "Set register to unknown type " << new_type;
+ return false;
} else {
line_[vdst] = new_type.GetId();
}
// Clear the monitor entry bits for this register.
ClearAllRegToLockDepths(vdst);
+ return true;
}
void RegisterLine::SetResultTypeToUnknown() {
@@ -677,7 +680,9 @@
void RegisterLine::CopyRegister1(uint32_t vdst, uint32_t vsrc, TypeCategory cat) {
DCHECK(cat == kTypeCategory1nr || cat == kTypeCategoryRef);
const RegType& type = GetRegisterType(vsrc);
- SetRegisterType(vdst, type);
+ if (!SetRegisterType(vdst, type)) {
+ return;
+ }
if ((cat == kTypeCategory1nr && !type.IsCategory1Types()) ||
(cat == kTypeCategoryRef && !type.IsReferenceTypes())) {
verifier_->Fail(VERIFY_ERROR_GENERIC) << "copy1 v" << vdst << "<-v" << vsrc << " type=" << type
@@ -1125,6 +1130,12 @@
Fail(VERIFY_ERROR_GENERIC) << "exception handler starts at bad address (" << dex_pc << ")";
return false;
}
+ const Instruction* inst = Instruction::At(code_item_->insns_ + dex_pc);
+ if (inst->Opcode() != Instruction::MOVE_EXCEPTION) {
+ Fail(VERIFY_ERROR_GENERIC) << "exception handler doesn't start with move-exception ("
+ << dex_pc << ")";
+ return false;
+ }
insn_flags_[dex_pc].SetBranchTarget();
// Ensure exception types are resolved so that they don't need resolution to be delivered,
// unresolved exception types will be ignored by exception delivery
@@ -1966,9 +1977,8 @@
case Instruction::MOVE_EXCEPTION: {
/*
- * This statement can only appear as the first instruction in an exception handler (though not
- * all exception handlers need to have one of these). We verify that as part of extracting the
- * exception type from the catch block list.
+ * This statement can only appear as the first instruction in an exception handler. We verify
+ * that as part of extracting the exception type from the catch block list.
*/
const RegType& res_type = GetCaughtExceptionType();
work_line_->SetRegisterType(dec_insn.vA_, res_type);
@@ -3780,7 +3790,7 @@
size_t num_entries, ref_bitmap_bits, pc_bits;
ComputeGcMapSizes(&num_entries, &ref_bitmap_bits, &pc_bits);
// There's a single byte to encode the size of each bitmap
- if (ref_bitmap_bits >= (8 /* bits per byte */ * 256 /* max unsigned byte + 1 */ )) {
+ if (ref_bitmap_bits >= (8 /* bits per byte */ * 8192 /* 13-bit size */ )) {
// TODO: either a better GC map format or per method failures
Fail(VERIFY_ERROR_GENERIC) << "Cannot encode GC map for method with "
<< ref_bitmap_bits << " registers";
@@ -3815,8 +3825,8 @@
return NULL;
}
// Write table header
- table->push_back(format);
- table->push_back(ref_bitmap_bytes);
+ table->push_back(format | ((ref_bitmap_bytes >> kRegMapFormatShift) & ~kRegMapFormatMask));
+ table->push_back(ref_bitmap_bytes & 0xFF);
table->push_back(num_entries & 0xFF);
table->push_back((num_entries >> 8) & 0xFF);
// Write table data
diff --git a/src/dex_verifier.h b/src/dex_verifier.h
index 9933c60..41adff0 100644
--- a/src/dex_verifier.h
+++ b/src/dex_verifier.h
@@ -570,10 +570,12 @@
*/
enum RegisterMapFormat {
kRegMapFormatUnknown = 0,
- kRegMapFormatNone, /* indicates no map data follows */
- kRegMapFormatCompact8, /* compact layout, 8-bit addresses */
- kRegMapFormatCompact16, /* compact layout, 16-bit addresses */
+ kRegMapFormatNone = 1, /* indicates no map data follows */
+ kRegMapFormatCompact8 = 2, /* compact layout, 8-bit addresses */
+ kRegMapFormatCompact16 = 3, /* compact layout, 16-bit addresses */
};
+const int kRegMapFormatShift = 5;
+const uint8_t kRegMapFormatMask = 0x7;
// During verification, we associate one of these with every "interesting" instruction. We track
// the status of all registers, and (if the method has any monitor-enter instructions) maintain a
@@ -611,7 +613,7 @@
// Set the type of register N, verifying that the register is valid. If "newType" is the "Lo"
// part of a 64-bit value, register N+1 will be set to "newType+1".
// The register index was validated during the static pass, so we don't need to check it here.
- void SetRegisterType(uint32_t vdst, const RegType& new_type);
+ bool SetRegisterType(uint32_t vdst, const RegType& new_type);
/* Set the type of the "result" register. */
void SetResultRegisterType(const RegType& new_type);
@@ -1313,7 +1315,7 @@
// The number of bytes used to encode registers
size_t RegWidth() const {
- return GetData()[1];
+ return GetData()[1] | ((GetData()[0] & ~kRegMapFormatMask) << kRegMapFormatShift);
}
private:
@@ -1324,7 +1326,7 @@
// The format of the table of the PCs for the table
RegisterMapFormat Format() const {
- return static_cast<RegisterMapFormat>(GetData()[0]);
+ return static_cast<RegisterMapFormat>(GetData()[0] & kRegMapFormatMask);
}
// Number of bytes used to encode a dex pc