# HG changeset patch # User goetz # Date 1485508939 -3600 # Node ID d1ca4e128d581a3d328d69b425b44778ccd1c1ad # Parent 348f3575f13378a8549ddadeec4d0b01ca6e6dbd 8173465: Introduce NearLabel for branches known to be short. diff --git a/src/cpu/s390/vm/assembler_s390.hpp b/src/cpu/s390/vm/assembler_s390.hpp --- a/src/cpu/s390/vm/assembler_s390.hpp +++ b/src/cpu/s390/vm/assembler_s390.hpp @@ -28,8 +28,6 @@ #undef LUCY_DBG -#define NearLabel Label - // Immediate is an abstraction to represent the various immediate // operands which exist on z/Architecture. Neither this class nor // instances hereof have an own state. It consists of methods only. diff --git a/src/cpu/s390/vm/macroAssembler_s390.cpp b/src/cpu/s390/vm/macroAssembler_s390.cpp --- a/src/cpu/s390/vm/macroAssembler_s390.cpp +++ b/src/cpu/s390/vm/macroAssembler_s390.cpp @@ -1616,6 +1616,8 @@ if (branch_target.is_bound()) { address branch_addr = target(branch_target); branch_optimized(cond, branch_addr); + } else if (branch_target.is_near()) { + z_brc(cond, branch_target); // Caller assures that the target will be in range for z_brc. } else { z_brcl(cond, branch_target); // Let's hope target is in range. Otherwise, we will abort at patch time. } @@ -1674,7 +1676,8 @@ bool has_sign) { address branch_origin = pc(); bool x2_imm8 = (has_sign && Immediate::is_simm8(x2)) || (!has_sign && Immediate::is_uimm8(x2)); - bool is_RelAddr16 = (branch_target.is_bound() && + bool is_RelAddr16 = branch_target.is_near() || + (branch_target.is_bound() && RelAddr::is_in_range_of_RelAddr16(target(branch_target), branch_origin)); unsigned int casenum = (len64?2:0)+(has_sign?0:1); @@ -1744,13 +1747,21 @@ Label& branch_target, bool len64, bool has_sign) { - unsigned int casenum = (len64?2:0)+(has_sign?0:1); + unsigned int casenum = (len64 ? 2 : 0) + (has_sign ? 0 : 1); if (branch_target.is_bound()) { address branch_addr = target(branch_target); compare_and_branch_optimized(r1, r2, cond, branch_addr, len64, has_sign); } else { - { + if (VM_Version::has_CompareBranch() && branch_target.is_near()) { + switch (casenum) { + case 0: z_crj( r1, r2, cond, branch_target); break; + case 1: z_clrj( r1, r2, cond, branch_target); break; + case 2: z_cgrj( r1, r2, cond, branch_target); break; + case 3: z_clgrj(r1, r2, cond, branch_target); break; + default: ShouldNotReachHere(); break; + } + } else { switch (casenum) { case 0: z_cr( r1, r2); break; case 1: z_clr(r1, r2); break; diff --git a/src/share/vm/asm/assembler.hpp b/src/share/vm/asm/assembler.hpp --- a/src/share/vm/asm/assembler.hpp +++ b/src/share/vm/asm/assembler.hpp @@ -93,6 +93,10 @@ GrowableArray* _patch_overflow; Label(const Label&) { ShouldNotReachHere(); } + protected: + + // The label will be bound to a location near its users. + unsigned int _is_near:1; public: @@ -126,6 +130,10 @@ bool is_unbound() const { return _loc == -1 && _patch_index > 0; } bool is_unused() const { return _loc == -1 && _patch_index == 0; } + // The label will be bound to a location near its users. Users can + // optimize on this information, e.g. generate short branches. + bool is_near() { return _is_near; } + /** * Adds a reference to an unresolved displacement instruction to * this unbound label @@ -145,6 +153,7 @@ _loc = -1; _patch_index = 0; _patch_overflow = NULL; + _is_near = false; } Label() { @@ -152,6 +161,13 @@ } }; +// A NearLabel must be bound to a location near its users. Users can +// optimize on this information, e.g. generate short branches. +class NearLabel : public Label { + public: + NearLabel() : Label() { _is_near = true; } +}; + // A union type for code which has to assemble both constant and // non-constant operands, when the distinction cannot be made // statically.