Reduced memory usage of primitive fields smaller than 4-bytes
Reduced memory used by byte and boolean fields from 4 bytes down to a
single byte and shorts and chars down to two bytes. Fields are now
arranged as Reference followed by decreasing component sizes, with
fields shuffled forward as needed.
Bug: 8135266
Change-Id: I65eaf31ed27e5bd5ba0c7d4606454b720b074752
diff --git a/runtime/transaction.cc b/runtime/transaction.cc
index cc02a8d..0cfdfc5 100644
--- a/runtime/transaction.cc
+++ b/runtime/transaction.cc
@@ -57,6 +57,40 @@
}
}
+void Transaction::RecordWriteFieldBoolean(mirror::Object* obj, MemberOffset field_offset,
+ uint8_t value, bool is_volatile) {
+ DCHECK(obj != nullptr);
+ MutexLock mu(Thread::Current(), log_lock_);
+ ObjectLog& object_log = object_logs_[obj];
+ object_log.LogBooleanValue(field_offset, value, is_volatile);
+}
+
+void Transaction::RecordWriteFieldByte(mirror::Object* obj, MemberOffset field_offset,
+ int8_t value, bool is_volatile) {
+ DCHECK(obj != nullptr);
+ MutexLock mu(Thread::Current(), log_lock_);
+ ObjectLog& object_log = object_logs_[obj];
+ object_log.LogByteValue(field_offset, value, is_volatile);
+}
+
+void Transaction::RecordWriteFieldChar(mirror::Object* obj, MemberOffset field_offset,
+ uint16_t value, bool is_volatile) {
+ DCHECK(obj != nullptr);
+ MutexLock mu(Thread::Current(), log_lock_);
+ ObjectLog& object_log = object_logs_[obj];
+ object_log.LogCharValue(field_offset, value, is_volatile);
+}
+
+
+void Transaction::RecordWriteFieldShort(mirror::Object* obj, MemberOffset field_offset,
+ int16_t value, bool is_volatile) {
+ DCHECK(obj != nullptr);
+ MutexLock mu(Thread::Current(), log_lock_);
+ ObjectLog& object_log = object_logs_[obj];
+ object_log.LogShortValue(field_offset, value, is_volatile);
+}
+
+
void Transaction::RecordWriteField32(mirror::Object* obj, MemberOffset field_offset, uint32_t value,
bool is_volatile) {
DCHECK(obj != nullptr);
@@ -223,35 +257,42 @@
}
}
+void Transaction::ObjectLog::LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile) {
+ LogValue(ObjectLog::kBoolean, offset, value, is_volatile);
+}
+
+void Transaction::ObjectLog::LogByteValue(MemberOffset offset, int8_t value, bool is_volatile) {
+ LogValue(ObjectLog::kByte, offset, value, is_volatile);
+}
+
+void Transaction::ObjectLog::LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile) {
+ LogValue(ObjectLog::kChar, offset, value, is_volatile);
+}
+
+void Transaction::ObjectLog::LogShortValue(MemberOffset offset, int16_t value, bool is_volatile) {
+ LogValue(ObjectLog::kShort, offset, value, is_volatile);
+}
+
void Transaction::ObjectLog::Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile) {
- auto it = field_values_.find(offset.Uint32Value());
- if (it == field_values_.end()) {
- ObjectLog::FieldValue field_value;
- field_value.value = value;
- field_value.is_volatile = is_volatile;
- field_value.kind = ObjectLog::k32Bits;
- field_values_.insert(std::make_pair(offset.Uint32Value(), field_value));
- }
+ LogValue(ObjectLog::k32Bits, offset, value, is_volatile);
}
void Transaction::ObjectLog::Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile) {
+ LogValue(ObjectLog::k64Bits, offset, value, is_volatile);
+}
+
+void Transaction::ObjectLog::LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile) {
+ LogValue(ObjectLog::kReference, offset, reinterpret_cast<uintptr_t>(obj), is_volatile);
+}
+
+void Transaction::ObjectLog::LogValue(ObjectLog::FieldValueKind kind,
+ MemberOffset offset, uint64_t value, bool is_volatile) {
auto it = field_values_.find(offset.Uint32Value());
if (it == field_values_.end()) {
ObjectLog::FieldValue field_value;
field_value.value = value;
field_value.is_volatile = is_volatile;
- field_value.kind = ObjectLog::k64Bits;
- field_values_.insert(std::make_pair(offset.Uint32Value(), field_value));
- }
-}
-
-void Transaction::ObjectLog::LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile) {
- auto it = field_values_.find(offset.Uint32Value());
- if (it == field_values_.end()) {
- ObjectLog::FieldValue field_value;
- field_value.value = reinterpret_cast<uintptr_t>(obj);
- field_value.is_volatile = is_volatile;
- field_value.kind = ObjectLog::kReference;
+ field_value.kind = kind;
field_values_.insert(std::make_pair(offset.Uint32Value(), field_value));
}
}
@@ -281,6 +322,42 @@
// we'd need to disable the check.
constexpr bool kCheckTransaction = true;
switch (field_value.kind) {
+ case kBoolean:
+ if (UNLIKELY(field_value.is_volatile)) {
+ obj->SetFieldBooleanVolatile<false, kCheckTransaction>(field_offset,
+ static_cast<bool>(field_value.value));
+ } else {
+ obj->SetFieldBoolean<false, kCheckTransaction>(field_offset,
+ static_cast<bool>(field_value.value));
+ }
+ break;
+ case kByte:
+ if (UNLIKELY(field_value.is_volatile)) {
+ obj->SetFieldByteVolatile<false, kCheckTransaction>(field_offset,
+ static_cast<int8_t>(field_value.value));
+ } else {
+ obj->SetFieldByte<false, kCheckTransaction>(field_offset,
+ static_cast<int8_t>(field_value.value));
+ }
+ break;
+ case kChar:
+ if (UNLIKELY(field_value.is_volatile)) {
+ obj->SetFieldCharVolatile<false, kCheckTransaction>(field_offset,
+ static_cast<uint16_t>(field_value.value));
+ } else {
+ obj->SetFieldChar<false, kCheckTransaction>(field_offset,
+ static_cast<uint16_t>(field_value.value));
+ }
+ break;
+ case kShort:
+ if (UNLIKELY(field_value.is_volatile)) {
+ obj->SetFieldShortVolatile<false, kCheckTransaction>(field_offset,
+ static_cast<int16_t>(field_value.value));
+ } else {
+ obj->SetFieldShort<false, kCheckTransaction>(field_offset,
+ static_cast<int16_t>(field_value.value));
+ }
+ break;
case k32Bits:
if (UNLIKELY(field_value.is_volatile)) {
obj->SetField32Volatile<false, kCheckTransaction>(field_offset,