--- a/hotspot/src/cpu/s390/vm/assembler_s390.hpp Wed Feb 15 22:59:57 2017 -0500
+++ b/hotspot/src/cpu/s390/vm/assembler_s390.hpp Fri Jan 27 10:22:19 2017 +0100
@@ -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.
--- a/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp Wed Feb 15 22:59:57 2017 -0500
+++ b/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp Fri Jan 27 10:22:19 2017 +0100
@@ -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;
--- a/hotspot/src/share/vm/asm/assembler.hpp Wed Feb 15 22:59:57 2017 -0500
+++ b/hotspot/src/share/vm/asm/assembler.hpp Fri Jan 27 10:22:19 2017 +0100
@@ -93,6 +93,10 @@
GrowableArray<int>* _patch_overflow;
Label(const Label&) { ShouldNotReachHere(); }
+ protected:
+
+ // The label will be bound to a location near its users.
+ bool _is_near;
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.