Volatile support in Portable compiler.
Bug: 8209406
This CL adds volatile support in iget/iput/sget/sput instructions. For now,
we emit LLVM fence instructions at the right place. While it may not generate
the best code for each target, it provides correctness at least.
In the future, we'd like to replace the use of fence with atomic load/store
instructions. With the current state of LLVM, this should work for ARM and X86
but not on MIPS due to their atomic load/store implementation. We should track
this and once the MIPS target fits to our needs, replace the fences by atomic
load/store instructions.
Change-Id: I33fd688cf5a18619e0af102fb8fe749565be2a49
diff --git a/src/compiler/llvm/gbc_expander.cc b/src/compiler/llvm/gbc_expander.cc
index 4e1a91d..fd3fc13 100644
--- a/src/compiler/llvm/gbc_expander.cc
+++ b/src/compiler/llvm/gbc_expander.cc
@@ -1431,10 +1431,12 @@
llvm::Value* field_addr =
irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
- // TODO: Check is_volatile. We need to generate atomic load instruction
- // when is_volatile is true.
field_value = irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
field_value = SignOrZeroExtendCat1Types(field_value, field_jty);
+
+ if (is_volatile) {
+ irb_.CreateMemoryBarrier(art::kLoadLoad);
+ }
}
return field_value;
@@ -1486,6 +1488,10 @@
} else {
DCHECK_GE(field_offset, 0);
+ if (is_volatile) {
+ irb_.CreateMemoryBarrier(art::kStoreStore);
+ }
+
llvm::PointerType* field_type =
irb_.getJType(field_jty)->getPointerTo();
@@ -1494,11 +1500,13 @@
llvm::Value* field_addr =
irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
- // TODO: Check is_volatile. We need to generate atomic store instruction
- // when is_volatile is true.
new_value = TruncateCat1Types(new_value, field_jty);
irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
+ if (is_volatile) {
+ irb_.CreateMemoryBarrier(art::kLoadLoad);
+ }
+
if (field_jty == kObject) { // If put an object, mark the GC card table.
EmitMarkGCCard(new_value, object_addr);
}
@@ -1710,10 +1718,12 @@
irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
irb_.getJType(field_jty)->getPointerTo());
- // TODO: Check is_volatile. We need to generate atomic load instruction
- // when is_volatile is true.
static_field_value = irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
static_field_value = SignOrZeroExtendCat1Types(static_field_value, field_jty);
+
+ if (is_volatile) {
+ irb_.CreateMemoryBarrier(art::kLoadLoad);
+ }
}
return static_field_value;
@@ -1787,17 +1797,23 @@
static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
}
+ if (is_volatile) {
+ irb_.CreateMemoryBarrier(art::kStoreStore);
+ }
+
llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
llvm::Value* static_field_addr =
irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
irb_.getJType(field_jty)->getPointerTo());
- // TODO: Check is_volatile. We need to generate atomic store instruction
- // when is_volatile is true.
new_value = TruncateCat1Types(new_value, field_jty);
irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
+ if (is_volatile) {
+ irb_.CreateMemoryBarrier(art::kStoreLoad);
+ }
+
if (field_jty == kObject) { // If put an object, mark the GC card table.
EmitMarkGCCard(new_value, static_storage_addr);
}