# HG changeset patch # User aph # Date 1444215931 0 # Wed Oct 07 11:05:31 2015 +0000 # Node ID 2b604a98df1ea3c366c8397d81953bff1991d466 # Parent 324ea1a2419aad27f7c256eb6d61430ac98a894c 8139041: Redundant DMB instructions Summary: merge consecutive DMB intstructions Reviewd-by: kvn diff --git a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp --- a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp +++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp @@ -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) diff --git a/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp b/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp --- a/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp +++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp @@ -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); diff --git a/src/cpu/aarch64/vm/nativeInst_aarch64.hpp b/src/cpu/aarch64/vm/nativeInst_aarch64.hpp --- a/src/cpu/aarch64/vm/nativeInst_aarch64.hpp +++ b/src/cpu/aarch64/vm/nativeInst_aarch64.hpp @@ -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 diff --git a/src/share/vm/asm/codeBuffer.hpp b/src/share/vm/asm/codeBuffer.hpp --- a/src/share/vm/asm/codeBuffer.hpp +++ b/src/share/vm/asm/codeBuffer.hpp @@ -375,6 +375,10 @@ OopRecorder _default_oop_recorder; // override with initialize_oop_recorder Arena* _overflow_arena; +#ifdef AARCH64 + address _last_membar; // used to merge consecutive memory barriers +#endif + address _decode_begin; // start address for decode address decode_begin(); @@ -388,6 +392,9 @@ _decode_begin = NULL; _overflow_arena = NULL; _code_strings = CodeStrings(); +#ifdef AARCH64 + _last_membar = NULL; +#endif } void initialize(address code_start, csize_t code_size) { @@ -576,6 +583,12 @@ OopRecorder* oop_recorder() const { return _oop_recorder; } CodeStrings& strings() { return _code_strings; } +#ifdef AARCH64 + address last_membar() const { return _last_membar; } + void set_last_membar(address a) { _last_membar = a; } + void clear_last_membar() { set_last_membar(NULL); } +#endif + void free_strings() { if (!_code_strings.is_null()) { _code_strings.free(); // sets _strings Null as a side-effect.