8139041: Redundant DMB instructions
Summary: Merge consecutive DMB intstructions
Reviewed-by: roland, kvn, twisti
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Fri Oct 16 02:05:54 2015 +0300
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Tue Oct 13 16:25:50 2015 +0000
@@ -1709,6 +1709,20 @@
return idivq_offset;
}
+void MacroAssembler::membar(Membar_mask_bits order_constraint) {
+ address prev = pc() - NativeMembar::instruction_size;
+ if (prev == code()->last_membar()) {
+ NativeMembar *bar = NativeMembar_at(prev);
+ // We are merging two memory barrier instructions. On AArch64 we
+ // can do this simply by ORing them together.
+ bar->set_kind(bar->get_kind() | order_constraint);
+ BLOCK_COMMENT("merged membar");
+ } else {
+ code()->set_last_membar(pc());
+ dmb(Assembler::barrier(order_constraint));
+ }
+}
+
// MacroAssembler routines found actually to be needed
void MacroAssembler::push(Register src)
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Fri Oct 16 02:05:54 2015 +0300
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Tue Oct 13 16:25:50 2015 +0000
@@ -152,6 +152,13 @@
strw(scratch, a);
}
+ void bind(Label& L) {
+ Assembler::bind(L);
+ code()->clear_last_membar();
+ }
+
+ void membar(Membar_mask_bits order_constraint);
+
// Frame creation and destruction shared between JITs.
void build_frame(int framesize);
void remove_frame(int framesize);
--- a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp Fri Oct 16 02:05:54 2015 +0300
+++ b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp Tue Oct 13 16:25:50 2015 +0000
@@ -101,6 +101,12 @@
static bool maybe_cpool_ref(address instr) {
return is_adrp_at(instr) || is_ldr_literal_at(instr);
}
+
+ bool is_Membar() {
+ unsigned int insn = uint_at(0);
+ return Instruction_aarch64::extract(insn, 31, 12) == 0b11010101000000110011 &&
+ Instruction_aarch64::extract(insn, 7, 0) == 0b10111111;
+ }
};
inline NativeInstruction* nativeInstruction_at(address address) {
@@ -487,4 +493,15 @@
return (NativeCallTrampolineStub*)addr;
}
+class NativeMembar : public NativeInstruction {
+public:
+ unsigned int get_kind() { return Instruction_aarch64::extract(uint_at(0), 11, 8); }
+ void set_kind(int order_kind) { Instruction_aarch64::patch(addr_at(0), 11, 8, order_kind); }
+};
+
+inline NativeMembar *NativeMembar_at(address addr) {
+ assert(nativeInstruction_at(addr)->is_Membar(), "no membar found");
+ return (NativeMembar*)addr;
+}
+
#endif // CPU_AARCH64_VM_NATIVEINST_AARCH64_HPP
--- a/hotspot/src/share/vm/asm/codeBuffer.hpp Fri Oct 16 02:05:54 2015 +0300
+++ b/hotspot/src/share/vm/asm/codeBuffer.hpp Tue Oct 13 16:25:50 2015 +0000
@@ -375,6 +375,8 @@
OopRecorder _default_oop_recorder; // override with initialize_oop_recorder
Arena* _overflow_arena;
+ address _last_membar; // used to merge consecutive memory barriers
+
address _decode_begin; // start address for decode
address decode_begin();
@@ -388,6 +390,7 @@
_decode_begin = NULL;
_overflow_arena = NULL;
_code_strings = CodeStrings();
+ _last_membar = NULL;
}
void initialize(address code_start, csize_t code_size) {
@@ -577,6 +580,10 @@
OopRecorder* oop_recorder() const { return _oop_recorder; }
CodeStrings& strings() { return _code_strings; }
+ address last_membar() const { return _last_membar; }
+ void set_last_membar(address a) { _last_membar = a; }
+ void clear_last_membar() { set_last_membar(NULL); }
+
void free_strings() {
if (!_code_strings.is_null()) {
_code_strings.free(); // sets _strings Null as a side-effect.