mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 19:14:38 +02:00
8058744: Crash in C1 OSRed method w/ Unsafe usage
Fix UnsafeRawOp optimizations Reviewed-by: kvn, drchase, vlivanov
This commit is contained in:
parent
a899525147
commit
ce1c41a15b
2 changed files with 139 additions and 82 deletions
|
@ -327,7 +327,7 @@ void Canonicalizer::do_ShiftOp (ShiftOp* x) {
|
|||
if (t2->is_constant()) {
|
||||
switch (t2->tag()) {
|
||||
case intTag : if (t2->as_IntConstant()->value() == 0) set_canonical(x->x()); return;
|
||||
case longTag : if (t2->as_IntConstant()->value() == 0) set_canonical(x->x()); return;
|
||||
case longTag : if (t2->as_LongConstant()->value() == (jlong)0) set_canonical(x->x()); return;
|
||||
default : ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
@ -808,28 +808,41 @@ void Canonicalizer::do_ExceptionObject(ExceptionObject* x) {}
|
|||
|
||||
static bool match_index_and_scale(Instruction* instr,
|
||||
Instruction** index,
|
||||
int* log2_scale,
|
||||
Instruction** instr_to_unpin) {
|
||||
*instr_to_unpin = NULL;
|
||||
|
||||
// Skip conversion ops
|
||||
int* log2_scale) {
|
||||
// Skip conversion ops. This works only on 32bit because of the implicit l2i that the
|
||||
// unsafe performs.
|
||||
#ifndef _LP64
|
||||
Convert* convert = instr->as_Convert();
|
||||
if (convert != NULL) {
|
||||
if (convert != NULL && convert->op() == Bytecodes::_i2l) {
|
||||
assert(convert->value()->type() == intType, "invalid input type");
|
||||
instr = convert->value();
|
||||
}
|
||||
#endif
|
||||
|
||||
ShiftOp* shift = instr->as_ShiftOp();
|
||||
if (shift != NULL) {
|
||||
if (shift->is_pinned()) {
|
||||
*instr_to_unpin = shift;
|
||||
if (shift->op() == Bytecodes::_lshl) {
|
||||
assert(shift->x()->type() == longType, "invalid input type");
|
||||
} else {
|
||||
#ifndef _LP64
|
||||
if (shift->op() == Bytecodes::_ishl) {
|
||||
assert(shift->x()->type() == intType, "invalid input type");
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Constant shift value?
|
||||
Constant* con = shift->y()->as_Constant();
|
||||
if (con == NULL) return false;
|
||||
// Well-known type and value?
|
||||
IntConstant* val = con->type()->as_IntConstant();
|
||||
if (val == NULL) return false;
|
||||
if (shift->x()->type() != intType) return false;
|
||||
assert(val != NULL, "Should be an int constant");
|
||||
|
||||
*index = shift->x();
|
||||
int tmp_scale = val->value();
|
||||
if (tmp_scale >= 0 && tmp_scale < 4) {
|
||||
|
@ -842,31 +855,42 @@ static bool match_index_and_scale(Instruction* instr,
|
|||
|
||||
ArithmeticOp* arith = instr->as_ArithmeticOp();
|
||||
if (arith != NULL) {
|
||||
if (arith->is_pinned()) {
|
||||
*instr_to_unpin = arith;
|
||||
// See if either arg is a known constant
|
||||
Constant* con = arith->x()->as_Constant();
|
||||
if (con != NULL) {
|
||||
*index = arith->y();
|
||||
} else {
|
||||
con = arith->y()->as_Constant();
|
||||
if (con == NULL) return false;
|
||||
*index = arith->x();
|
||||
}
|
||||
long const_value;
|
||||
// Check for integer multiply
|
||||
if (arith->op() == Bytecodes::_imul) {
|
||||
// See if either arg is a known constant
|
||||
Constant* con = arith->x()->as_Constant();
|
||||
if (con != NULL) {
|
||||
*index = arith->y();
|
||||
if (arith->op() == Bytecodes::_lmul) {
|
||||
assert((*index)->type() == longType, "invalid input type");
|
||||
LongConstant* val = con->type()->as_LongConstant();
|
||||
assert(val != NULL, "expecting a long constant");
|
||||
const_value = val->value();
|
||||
} else {
|
||||
#ifndef _LP64
|
||||
if (arith->op() == Bytecodes::_imul) {
|
||||
assert((*index)->type() == intType, "invalid input type");
|
||||
IntConstant* val = con->type()->as_IntConstant();
|
||||
assert(val != NULL, "expecting an int constant");
|
||||
const_value = val->value();
|
||||
} else {
|
||||
con = arith->y()->as_Constant();
|
||||
if (con == NULL) return false;
|
||||
*index = arith->x();
|
||||
}
|
||||
if ((*index)->type() != intType) return false;
|
||||
// Well-known type and value?
|
||||
IntConstant* val = con->type()->as_IntConstant();
|
||||
if (val == NULL) return false;
|
||||
switch (val->value()) {
|
||||
case 1: *log2_scale = 0; return true;
|
||||
case 2: *log2_scale = 1; return true;
|
||||
case 4: *log2_scale = 2; return true;
|
||||
case 8: *log2_scale = 3; return true;
|
||||
default: return false;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
switch (const_value) {
|
||||
case 1: *log2_scale = 0; return true;
|
||||
case 2: *log2_scale = 1; return true;
|
||||
case 4: *log2_scale = 2; return true;
|
||||
case 8: *log2_scale = 3; return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -879,29 +903,37 @@ static bool match(UnsafeRawOp* x,
|
|||
Instruction** base,
|
||||
Instruction** index,
|
||||
int* log2_scale) {
|
||||
Instruction* instr_to_unpin = NULL;
|
||||
ArithmeticOp* root = x->base()->as_ArithmeticOp();
|
||||
if (root == NULL) return false;
|
||||
// Limit ourselves to addition for now
|
||||
if (root->op() != Bytecodes::_ladd) return false;
|
||||
|
||||
bool match_found = false;
|
||||
// Try to find shift or scale op
|
||||
if (match_index_and_scale(root->y(), index, log2_scale, &instr_to_unpin)) {
|
||||
if (match_index_and_scale(root->y(), index, log2_scale)) {
|
||||
*base = root->x();
|
||||
} else if (match_index_and_scale(root->x(), index, log2_scale, &instr_to_unpin)) {
|
||||
match_found = true;
|
||||
} else if (match_index_and_scale(root->x(), index, log2_scale)) {
|
||||
*base = root->y();
|
||||
} else if (root->y()->as_Convert() != NULL) {
|
||||
match_found = true;
|
||||
} else if (NOT_LP64(root->y()->as_Convert() != NULL) LP64_ONLY(false)) {
|
||||
// Skipping i2l works only on 32bit because of the implicit l2i that the unsafe performs.
|
||||
// 64bit needs a real sign-extending conversion.
|
||||
Convert* convert = root->y()->as_Convert();
|
||||
if (convert->op() == Bytecodes::_i2l && convert->value()->type() == intType) {
|
||||
if (convert->op() == Bytecodes::_i2l) {
|
||||
assert(convert->value()->type() == intType, "should be an int");
|
||||
// pick base and index, setting scale at 1
|
||||
*base = root->x();
|
||||
*index = convert->value();
|
||||
*log2_scale = 0;
|
||||
} else {
|
||||
return false;
|
||||
match_found = true;
|
||||
}
|
||||
} else {
|
||||
// doesn't match any expected sequences
|
||||
return false;
|
||||
}
|
||||
// The default solution
|
||||
if (!match_found) {
|
||||
*base = root->x();
|
||||
*index = root->y();
|
||||
*log2_scale = 0;
|
||||
}
|
||||
|
||||
// If the value is pinned then it will be always be computed so
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue