publicclass Main { publicstaticvoid main(String[] args) throws Exception { if (testOddLow1(5L)) { thrownew Error();
}
if (testNonFollowingHigh(5)) { thrownew Error();
}
if (testOddLow2()) { thrownew Error();
}
}
publicstaticboolean testOddLow1(long a /* ECX-EDX */) { // class instance is in EBP long b = myLongField1; // ESI-EDI int f = myField1; // EBX int e = myField2; // EAX int g = myField3; // ESI (by spilling ESI-EDI, see below) int h = myField4; // EDI
myLongField2 = a; // Make sure ESI-EDI gets spilled and not ECX-EDX
myField2 = f; // use of EBX
myField1 = e; // use of EAX
myField3 = h; // use of ESI
myField4 = g; // use if EDI
// At this point `b` has been spilled and needs to have a pair. The ordering // in the register allocator triggers the allocation of `res` before `b`. // `res` being used after the `doCall`, we want a callee saved register. // // EBP is taken by the class instance and EDI is taken by `g` (both used in the `myField4` // assignment below). So we end up allocating ESI for `res`. // // When we try to allocate a pair for `b` we're in the following situation: // EAX is free // ECX is taken // EDX is taken // EBX is free // ESP is blocked // EBP could be spilled // ESI is taken // EDI could be spilled // // So there is no consecutive registers available to please the register allocator. // The compiler used to trip then because of a bogus implementation of trying to split // an unaligned register pair (here ECX and EDX). The implementation would not find // a register and the register allocator would then complain about not having // enough registers for the operation. boolean res = a == b;
$noinline$doCall();
myField4 = g; return res;
}
publicstaticboolean testNonFollowingHigh(int i) { // class instance is in EBP long b = myLongField1; // ESI-EDI long a = (long)i; // EAX-EDX int f = myField1; // EBX int e = myField2; // ECX int g = myField3; // ESI (by spilling ESI-EDI, see below) int h = myField4; // EDI
myLongField2 = a; // Make sure ESI-EDI gets spilled and not ECX-EDX
myField2 = f; // use of EBX
myField1 = e; // use of ECX
myField3 = h; // use of EDI
myField4 = g; // use of ESI
// At this point `b` has been spilled and needs to have a pair. The ordering // in the register allocator triggers the allocation of `res` before `b`. // `res` being used after the `doCall`, we want a callee saved register. // // EBP is taken by the class instance and ESI is taken by `g` (both used in the `myField4` // assignment below). So we end up allocating EDI for `res`. // // When we try to allocate a pair for `b` we're in the following situation: // EAX is taken // ECX is free // EDX is taken // EBX is free // ESP is blocked // EBP could be spilled // ESI is taken // EDI could be spilled // // So there is no consecutive registers available to please the register allocator. // The compiler used to be in a bad state because of a bogus implementation of trying // to split an unaligned register pair (here EAX and EDX). boolean res = a == b;
$noinline$doCall();
myField4 = g; return res;
}
publicstaticboolean testOddLow2() { // class instance is in EBP long b = myLongField1; // ECX-EDX (hint due to call below). long a = myLongField2; // ESI-EDI int f = myField1; // EBX int e = myField2; // EAX int g = myField3; // ECX int h = myField4; // EDX int i = myField5; // ESI - callee saved due to assignment after call to $noinline$doCall.
myField2 = f; // use of EBX
myField1 = e; // use of EAX
myField3 = h; // use of EDX
myField4 = i; // use of ESI
myField5 = g; // use of ECX
// At this point `a` and `b` have been spilled and need to have a pairs. The ordering // in the register allocator triggers the allocation of `res` before `a` and `b`. // `res` being used after the `doCall`, we want a callee saved register. // // EBP is taken by the class instance and ESI is taken by `i` (both used in the `myField4` // assignment below). So we end up allocating EDI for `res`. // // We first try to allocator a pair for `b`. We're in the following situation: // EAX is free // ECX is free // EDX is free // EBX is free // ESP is blocked // EBP could be spilled // ESI could be spilled // EDI is taken // // Because `b` is used as a first argument to a call, we take its hint and allocate // ECX-EDX to it. // // We then try to allocate a pair for `a`. We're in the following situation: // EAX is free // ECX could be spilled // EDX could be spilled // EBX is free // ESP is blocked // EBP could be spilled // ESI could be spilled // EDI is taken // // So no consecutive two free registers are available. When trying to find a slot, we pick // the first unaligned or non-pair interval. In this case, this is the unaligned ECX-EDX. // The compiler used to then trip because it forgot to remove the high interval containing // the pair from the active list.
boolean res = a == b;
$noinline$doCall(b);
myField4 = i; // use of ESI return res;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.