提交 31c60d0d 编写于 作者: N never

Merge

...@@ -630,10 +630,16 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan ...@@ -630,10 +630,16 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
switch (ek) { switch (ek) {
case _adapter_opt_i2i: case _adapter_opt_i2i:
case _adapter_opt_l2i:
__ unimplemented(entry_name(ek));
value = vmarg; value = vmarg;
break; break;
case _adapter_opt_l2i:
{
// just delete the extra slot
__ add(Gargs, __ argument_offset(O0_argslot), O0_argslot);
remove_arg_slots(_masm, -stack_move_unit(), O0_argslot, O1_scratch, O2_scratch, O3_scratch);
value = vmarg = Address(O0_argslot, 0);
}
break;
case _adapter_opt_unboxi: case _adapter_opt_unboxi:
{ {
// Load the value up from the heap. // Load the value up from the heap.
......
...@@ -178,15 +178,11 @@ class Compilation: public StackObj { ...@@ -178,15 +178,11 @@ class Compilation: public StackObj {
return (int) NMethodSizeLimit; // default 256K or 512K return (int) NMethodSizeLimit; // default 256K or 512K
#else #else
// conditional branches on PPC are restricted to 16 bit signed // conditional branches on PPC are restricted to 16 bit signed
return MAX2((unsigned int)NMethodSizeLimit,32*K); return MIN2((unsigned int)NMethodSizeLimit,32*K);
#endif #endif
} }
static int desired_max_constant_size() { static int desired_max_constant_size() {
#ifndef PPC return desired_max_code_buffer_size() / 10;
return (int) NMethodSizeLimit / 10; // about 25K
#else
return (MAX2((unsigned int)NMethodSizeLimit, 32*K)) / 10;
#endif
} }
static void setup_code_buffer(CodeBuffer* cb, int call_stub_estimate); static void setup_code_buffer(CodeBuffer* cb, int call_stub_estimate);
......
...@@ -321,7 +321,7 @@ class UseCountComputer: public ValueVisitor, BlockClosure { ...@@ -321,7 +321,7 @@ class UseCountComputer: public ValueVisitor, BlockClosure {
void visit(Value* n) { void visit(Value* n) {
// Local instructions and Phis for expression stack values at the // Local instructions and Phis for expression stack values at the
// start of basic blocks are not added to the instruction list // start of basic blocks are not added to the instruction list
if (!(*n)->is_linked()&& (*n)->can_be_linked()) { if (!(*n)->is_linked() && (*n)->can_be_linked()) {
assert(false, "a node was not appended to the graph"); assert(false, "a node was not appended to the graph");
Compilation::current()->bailout("a node was not appended to the graph"); Compilation::current()->bailout("a node was not appended to the graph");
} }
......
...@@ -415,28 +415,26 @@ bool Constant::is_equal(Value v) const { ...@@ -415,28 +415,26 @@ bool Constant::is_equal(Value v) const {
return false; return false;
} }
Constant::CompareResult Constant::compare(Instruction::Condition cond, Value right) const {
BlockBegin* Constant::compare(Instruction::Condition cond, Value right,
BlockBegin* true_sux, BlockBegin* false_sux) {
Constant* rc = right->as_Constant(); Constant* rc = right->as_Constant();
// other is not a constant // other is not a constant
if (rc == NULL) return NULL; if (rc == NULL) return not_comparable;
ValueType* lt = type(); ValueType* lt = type();
ValueType* rt = rc->type(); ValueType* rt = rc->type();
// different types // different types
if (lt->base() != rt->base()) return NULL; if (lt->base() != rt->base()) return not_comparable;
switch (lt->tag()) { switch (lt->tag()) {
case intTag: { case intTag: {
int x = lt->as_IntConstant()->value(); int x = lt->as_IntConstant()->value();
int y = rt->as_IntConstant()->value(); int y = rt->as_IntConstant()->value();
switch (cond) { switch (cond) {
case If::eql: return x == y ? true_sux : false_sux; case If::eql: return x == y ? cond_true : cond_false;
case If::neq: return x != y ? true_sux : false_sux; case If::neq: return x != y ? cond_true : cond_false;
case If::lss: return x < y ? true_sux : false_sux; case If::lss: return x < y ? cond_true : cond_false;
case If::leq: return x <= y ? true_sux : false_sux; case If::leq: return x <= y ? cond_true : cond_false;
case If::gtr: return x > y ? true_sux : false_sux; case If::gtr: return x > y ? cond_true : cond_false;
case If::geq: return x >= y ? true_sux : false_sux; case If::geq: return x >= y ? cond_true : cond_false;
} }
break; break;
} }
...@@ -444,12 +442,12 @@ BlockBegin* Constant::compare(Instruction::Condition cond, Value right, ...@@ -444,12 +442,12 @@ BlockBegin* Constant::compare(Instruction::Condition cond, Value right,
jlong x = lt->as_LongConstant()->value(); jlong x = lt->as_LongConstant()->value();
jlong y = rt->as_LongConstant()->value(); jlong y = rt->as_LongConstant()->value();
switch (cond) { switch (cond) {
case If::eql: return x == y ? true_sux : false_sux; case If::eql: return x == y ? cond_true : cond_false;
case If::neq: return x != y ? true_sux : false_sux; case If::neq: return x != y ? cond_true : cond_false;
case If::lss: return x < y ? true_sux : false_sux; case If::lss: return x < y ? cond_true : cond_false;
case If::leq: return x <= y ? true_sux : false_sux; case If::leq: return x <= y ? cond_true : cond_false;
case If::gtr: return x > y ? true_sux : false_sux; case If::gtr: return x > y ? cond_true : cond_false;
case If::geq: return x >= y ? true_sux : false_sux; case If::geq: return x >= y ? cond_true : cond_false;
} }
break; break;
} }
...@@ -459,14 +457,14 @@ BlockBegin* Constant::compare(Instruction::Condition cond, Value right, ...@@ -459,14 +457,14 @@ BlockBegin* Constant::compare(Instruction::Condition cond, Value right,
assert(xvalue != NULL && yvalue != NULL, "not constants"); assert(xvalue != NULL && yvalue != NULL, "not constants");
if (xvalue->is_loaded() && yvalue->is_loaded()) { if (xvalue->is_loaded() && yvalue->is_loaded()) {
switch (cond) { switch (cond) {
case If::eql: return xvalue == yvalue ? true_sux : false_sux; case If::eql: return xvalue == yvalue ? cond_true : cond_false;
case If::neq: return xvalue != yvalue ? true_sux : false_sux; case If::neq: return xvalue != yvalue ? cond_true : cond_false;
} }
} }
break; break;
} }
} }
return NULL; return not_comparable;
} }
......
...@@ -443,7 +443,7 @@ class Instruction: public CompilationResourceObj { ...@@ -443,7 +443,7 @@ class Instruction: public CompilationResourceObj {
// generic // generic
virtual Instruction* as_Instruction() { return this; } // to satisfy HASHING1 macro virtual Instruction* as_Instruction() { return this; } // to satisfy HASHING1 macro
virtual Phi* as_Phi() { return NULL; } virtual Phi* as_Phi() { return NULL; }
virtual Local* as_Local() { return NULL; } virtual Local* as_Local() { return NULL; }
virtual Constant* as_Constant() { return NULL; } virtual Constant* as_Constant() { return NULL; }
virtual AccessField* as_AccessField() { return NULL; } virtual AccessField* as_AccessField() { return NULL; }
...@@ -650,8 +650,24 @@ LEAF(Constant, Instruction) ...@@ -650,8 +650,24 @@ LEAF(Constant, Instruction)
virtual intx hash() const; virtual intx hash() const;
virtual bool is_equal(Value v) const; virtual bool is_equal(Value v) const;
virtual BlockBegin* compare(Instruction::Condition condition, Value right,
BlockBegin* true_sux, BlockBegin* false_sux); enum CompareResult { not_comparable = -1, cond_false, cond_true };
virtual CompareResult compare(Instruction::Condition condition, Value right) const;
BlockBegin* compare(Instruction::Condition cond, Value right,
BlockBegin* true_sux, BlockBegin* false_sux) const {
switch (compare(cond, right)) {
case not_comparable:
return NULL;
case cond_false:
return false_sux;
case cond_true:
return true_sux;
default:
ShouldNotReachHere();
return NULL;
}
}
}; };
......
...@@ -38,18 +38,20 @@ class CE_Eliminator: public BlockClosure { ...@@ -38,18 +38,20 @@ class CE_Eliminator: public BlockClosure {
private: private:
IR* _hir; IR* _hir;
int _cee_count; // the number of CEs successfully eliminated int _cee_count; // the number of CEs successfully eliminated
int _ifop_count; // the number of IfOps successfully simplified
int _has_substitution; int _has_substitution;
public: public:
CE_Eliminator(IR* hir) : _cee_count(0), _hir(hir) { CE_Eliminator(IR* hir) : _cee_count(0), _ifop_count(0), _hir(hir) {
_has_substitution = false; _has_substitution = false;
_hir->iterate_preorder(this); _hir->iterate_preorder(this);
if (_has_substitution) { if (_has_substitution) {
// substituted some phis so resolve the substitution // substituted some ifops/phis, so resolve the substitution
SubstitutionResolver sr(_hir); SubstitutionResolver sr(_hir);
} }
} }
int cee_count() const { return _cee_count; } int cee_count() const { return _cee_count; }
int ifop_count() const { return _ifop_count; }
void adjust_exception_edges(BlockBegin* block, BlockBegin* sux) { void adjust_exception_edges(BlockBegin* block, BlockBegin* sux) {
int e = sux->number_of_exception_handlers(); int e = sux->number_of_exception_handlers();
...@@ -68,156 +70,214 @@ class CE_Eliminator: public BlockClosure { ...@@ -68,156 +70,214 @@ class CE_Eliminator: public BlockClosure {
} }
} }
virtual void block_do(BlockBegin* block) { virtual void block_do(BlockBegin* block);
// 1) find conditional expression
// check if block ends with an If
If* if_ = block->end()->as_If();
if (if_ == NULL) return;
// check if If works on int or object types
// (we cannot handle If's working on long, float or doubles yet,
// since IfOp doesn't support them - these If's show up if cmp
// operations followed by If's are eliminated)
ValueType* if_type = if_->x()->type();
if (!if_type->is_int() && !if_type->is_object()) return;
BlockBegin* t_block = if_->tsux();
BlockBegin* f_block = if_->fsux();
Instruction* t_cur = t_block->next();
Instruction* f_cur = f_block->next();
// one Constant may be present between BlockBegin and BlockEnd
Value t_const = NULL;
Value f_const = NULL;
if (t_cur->as_Constant() != NULL && !t_cur->can_trap()) {
t_const = t_cur;
t_cur = t_cur->next();
}
if (f_cur->as_Constant() != NULL && !f_cur->can_trap()) {
f_const = f_cur;
f_cur = f_cur->next();
}
// check if both branches end with a goto private:
Goto* t_goto = t_cur->as_Goto(); Value make_ifop(Value x, Instruction::Condition cond, Value y, Value tval, Value fval);
if (t_goto == NULL) return; };
Goto* f_goto = f_cur->as_Goto();
if (f_goto == NULL) return; void CE_Eliminator::block_do(BlockBegin* block) {
// 1) find conditional expression
// check if both gotos merge into the same block // check if block ends with an If
BlockBegin* sux = t_goto->default_sux(); If* if_ = block->end()->as_If();
if (sux != f_goto->default_sux()) return; if (if_ == NULL) return;
// check if at least one word was pushed on sux_state // check if If works on int or object types
ValueStack* sux_state = sux->state(); // (we cannot handle If's working on long, float or doubles yet,
if (sux_state->stack_size() <= if_->state()->stack_size()) return; // since IfOp doesn't support them - these If's show up if cmp
// operations followed by If's are eliminated)
// check if phi function is present at end of successor stack and that ValueType* if_type = if_->x()->type();
// only this phi was pushed on the stack if (!if_type->is_int() && !if_type->is_object()) return;
Value sux_phi = sux_state->stack_at(if_->state()->stack_size());
if (sux_phi == NULL || sux_phi->as_Phi() == NULL || sux_phi->as_Phi()->block() != sux) return; BlockBegin* t_block = if_->tsux();
if (sux_phi->type()->size() != sux_state->stack_size() - if_->state()->stack_size()) return; BlockBegin* f_block = if_->fsux();
Instruction* t_cur = t_block->next();
// get the values that were pushed in the true- and false-branch Instruction* f_cur = f_block->next();
Value t_value = t_goto->state()->stack_at(if_->state()->stack_size());
Value f_value = f_goto->state()->stack_at(if_->state()->stack_size()); // one Constant may be present between BlockBegin and BlockEnd
Value t_const = NULL;
// backend does not support floats Value f_const = NULL;
assert(t_value->type()->base() == f_value->type()->base(), "incompatible types"); if (t_cur->as_Constant() != NULL && !t_cur->can_trap()) {
if (t_value->type()->is_float_kind()) return; t_const = t_cur;
t_cur = t_cur->next();
// check that successor has no other phi functions but sux_phi }
// this can happen when t_block or f_block contained additonal stores to local variables if (f_cur->as_Constant() != NULL && !f_cur->can_trap()) {
// that are no longer represented by explicit instructions f_const = f_cur;
for_each_phi_fun(sux, phi, f_cur = f_cur->next();
if (phi != sux_phi) return; }
);
// true and false blocks can't have phis
for_each_phi_fun(t_block, phi, return; );
for_each_phi_fun(f_block, phi, return; );
// 2) substitute conditional expression
// with an IfOp followed by a Goto
// cut if_ away and get node before
Instruction* cur_end = if_->prev(block);
// append constants of true- and false-block if necessary
// clone constants because original block must not be destroyed
assert((t_value != f_const && f_value != t_const) || t_const == f_const, "mismatch");
if (t_value == t_const) {
t_value = new Constant(t_const->type());
NOT_PRODUCT(t_value->set_printable_bci(if_->printable_bci()));
cur_end = cur_end->set_next(t_value);
}
if (f_value == f_const) {
f_value = new Constant(f_const->type());
NOT_PRODUCT(f_value->set_printable_bci(if_->printable_bci()));
cur_end = cur_end->set_next(f_value);
}
// it is very unlikely that the condition can be statically decided // check if both branches end with a goto
// (this was checked previously by the Canonicalizer), so always Goto* t_goto = t_cur->as_Goto();
// append IfOp if (t_goto == NULL) return;
Value result = new IfOp(if_->x(), if_->cond(), if_->y(), t_value, f_value); Goto* f_goto = f_cur->as_Goto();
if (f_goto == NULL) return;
// check if both gotos merge into the same block
BlockBegin* sux = t_goto->default_sux();
if (sux != f_goto->default_sux()) return;
// check if at least one word was pushed on sux_state
ValueStack* sux_state = sux->state();
if (sux_state->stack_size() <= if_->state()->stack_size()) return;
// check if phi function is present at end of successor stack and that
// only this phi was pushed on the stack
Value sux_phi = sux_state->stack_at(if_->state()->stack_size());
if (sux_phi == NULL || sux_phi->as_Phi() == NULL || sux_phi->as_Phi()->block() != sux) return;
if (sux_phi->type()->size() != sux_state->stack_size() - if_->state()->stack_size()) return;
// get the values that were pushed in the true- and false-branch
Value t_value = t_goto->state()->stack_at(if_->state()->stack_size());
Value f_value = f_goto->state()->stack_at(if_->state()->stack_size());
// backend does not support floats
assert(t_value->type()->base() == f_value->type()->base(), "incompatible types");
if (t_value->type()->is_float_kind()) return;
// check that successor has no other phi functions but sux_phi
// this can happen when t_block or f_block contained additonal stores to local variables
// that are no longer represented by explicit instructions
for_each_phi_fun(sux, phi,
if (phi != sux_phi) return;
);
// true and false blocks can't have phis
for_each_phi_fun(t_block, phi, return; );
for_each_phi_fun(f_block, phi, return; );
// 2) substitute conditional expression
// with an IfOp followed by a Goto
// cut if_ away and get node before
Instruction* cur_end = if_->prev(block);
// append constants of true- and false-block if necessary
// clone constants because original block must not be destroyed
assert((t_value != f_const && f_value != t_const) || t_const == f_const, "mismatch");
if (t_value == t_const) {
t_value = new Constant(t_const->type());
NOT_PRODUCT(t_value->set_printable_bci(if_->printable_bci()));
cur_end = cur_end->set_next(t_value);
}
if (f_value == f_const) {
f_value = new Constant(f_const->type());
NOT_PRODUCT(f_value->set_printable_bci(if_->printable_bci()));
cur_end = cur_end->set_next(f_value);
}
Value result = make_ifop(if_->x(), if_->cond(), if_->y(), t_value, f_value);
assert(result != NULL, "make_ifop must return a non-null instruction");
if (!result->is_linked() && result->can_be_linked()) {
NOT_PRODUCT(result->set_printable_bci(if_->printable_bci())); NOT_PRODUCT(result->set_printable_bci(if_->printable_bci()));
cur_end = cur_end->set_next(result); cur_end = cur_end->set_next(result);
}
// append Goto to successor // append Goto to successor
ValueStack* state_before = if_->is_safepoint() ? if_->state_before() : NULL; ValueStack* state_before = if_->is_safepoint() ? if_->state_before() : NULL;
Goto* goto_ = new Goto(sux, state_before, if_->is_safepoint() || t_goto->is_safepoint() || f_goto->is_safepoint()); Goto* goto_ = new Goto(sux, state_before, if_->is_safepoint() || t_goto->is_safepoint() || f_goto->is_safepoint());
// prepare state for Goto // prepare state for Goto
ValueStack* goto_state = if_->state(); ValueStack* goto_state = if_->state();
while (sux_state->scope() != goto_state->scope()) { while (sux_state->scope() != goto_state->scope()) {
goto_state = goto_state->caller_state(); goto_state = goto_state->caller_state();
assert(goto_state != NULL, "states do not match up"); assert(goto_state != NULL, "states do not match up");
} }
goto_state = goto_state->copy(ValueStack::StateAfter, goto_state->bci()); goto_state = goto_state->copy(ValueStack::StateAfter, goto_state->bci());
goto_state->push(result->type(), result); goto_state->push(result->type(), result);
assert(goto_state->is_same(sux_state), "states must match now"); assert(goto_state->is_same(sux_state), "states must match now");
goto_->set_state(goto_state); goto_->set_state(goto_state);
cur_end = cur_end->set_next(goto_, goto_state->bci()); cur_end = cur_end->set_next(goto_, goto_state->bci());
// Adjust control flow graph // Adjust control flow graph
BlockBegin::disconnect_edge(block, t_block); BlockBegin::disconnect_edge(block, t_block);
BlockBegin::disconnect_edge(block, f_block); BlockBegin::disconnect_edge(block, f_block);
if (t_block->number_of_preds() == 0) { if (t_block->number_of_preds() == 0) {
BlockBegin::disconnect_edge(t_block, sux); BlockBegin::disconnect_edge(t_block, sux);
} }
adjust_exception_edges(block, t_block); adjust_exception_edges(block, t_block);
if (f_block->number_of_preds() == 0) { if (f_block->number_of_preds() == 0) {
BlockBegin::disconnect_edge(f_block, sux); BlockBegin::disconnect_edge(f_block, sux);
} }
adjust_exception_edges(block, f_block); adjust_exception_edges(block, f_block);
// update block end // update block end
block->set_end(goto_); block->set_end(goto_);
// substitute the phi if possible // substitute the phi if possible
if (sux_phi->as_Phi()->operand_count() == 1) { if (sux_phi->as_Phi()->operand_count() == 1) {
assert(sux_phi->as_Phi()->operand_at(0) == result, "screwed up phi"); assert(sux_phi->as_Phi()->operand_at(0) == result, "screwed up phi");
sux_phi->set_subst(result); sux_phi->set_subst(result);
_has_substitution = true; _has_substitution = true;
} }
// 3) successfully eliminated a conditional expression // 3) successfully eliminated a conditional expression
_cee_count++; _cee_count++;
if (PrintCEE) { if (PrintCEE) {
tty->print_cr("%d. CEE in B%d (B%d B%d)", cee_count(), block->block_id(), t_block->block_id(), f_block->block_id()); tty->print_cr("%d. CEE in B%d (B%d B%d)", cee_count(), block->block_id(), t_block->block_id(), f_block->block_id());
} tty->print_cr("%d. IfOp in B%d", ifop_count(), block->block_id());
}
_hir->verify(); _hir->verify();
}
Value CE_Eliminator::make_ifop(Value x, Instruction::Condition cond, Value y, Value tval, Value fval) {
if (!OptimizeIfOps) {
return new IfOp(x, cond, y, tval, fval);
} }
};
tval = tval->subst();
fval = fval->subst();
if (tval == fval) {
_ifop_count++;
return tval;
}
x = x->subst();
y = y->subst();
Constant* y_const = y->as_Constant();
if (y_const != NULL) {
IfOp* x_ifop = x->as_IfOp();
if (x_ifop != NULL) { // x is an ifop, y is a constant
Constant* x_tval_const = x_ifop->tval()->subst()->as_Constant();
Constant* x_fval_const = x_ifop->fval()->subst()->as_Constant();
if (x_tval_const != NULL && x_fval_const != NULL) {
Instruction::Condition x_ifop_cond = x_ifop->cond();
Constant::CompareResult t_compare_res = x_tval_const->compare(cond, y_const);
Constant::CompareResult f_compare_res = x_fval_const->compare(cond, y_const);
guarantee(t_compare_res != Constant::not_comparable && f_compare_res != Constant::not_comparable, "incomparable constants in IfOp");
Value new_tval = t_compare_res == Constant::cond_true ? tval : fval;
Value new_fval = f_compare_res == Constant::cond_true ? tval : fval;
_ifop_count++;
if (new_tval == new_fval) {
return new_tval;
} else {
return new IfOp(x_ifop->x(), x_ifop_cond, x_ifop->y(), new_tval, new_fval);
}
}
} else {
Constant* x_const = x->as_Constant();
if (x_const != NULL) { // x and y are constants
Constant::CompareResult x_compare_res = x_const->compare(cond, y_const);
guarantee(x_compare_res != Constant::not_comparable, "incomparable constants in IfOp");
_ifop_count++;
return x_compare_res == Constant::cond_true ? tval : fval;
}
}
}
return new IfOp(x, cond, y, tval, fval);
}
void Optimizer::eliminate_conditional_expressions() { void Optimizer::eliminate_conditional_expressions() {
// find conditional expressions & replace them with IfOps // find conditional expressions & replace them with IfOps
CE_Eliminator ce(ir()); CE_Eliminator ce(ir());
} }
class BlockMerger: public BlockClosure { class BlockMerger: public BlockClosure {
private: private:
IR* _hir; IR* _hir;
......
...@@ -75,6 +75,9 @@ ...@@ -75,6 +75,9 @@
develop(bool, SelectivePhiFunctions, true, \ develop(bool, SelectivePhiFunctions, true, \
"create phi functions at loop headers only when necessary") \ "create phi functions at loop headers only when necessary") \
\ \
develop(bool, OptimizeIfOps, true, \
"Optimize multiple IfOps") \
\
develop(bool, DoCEE, true, \ develop(bool, DoCEE, true, \
"Do Conditional Expression Elimination to simplify CFG") \ "Do Conditional Expression Elimination to simplify CFG") \
\ \
......
...@@ -78,7 +78,11 @@ ZIP = zip ...@@ -78,7 +78,11 @@ ZIP = zip
TEST_ROOT := $(shell pwd) TEST_ROOT := $(shell pwd)
# Root of all test results # Root of all test results
ABS_BUILD_ROOT = $(TEST_ROOT)/../build/$(PLATFORM)-$(ARCH) ifdef ALT_OUTPUTDIR
ABS_BUILD_ROOT = $(ALT_OUTPUTDIR)/$(PLATFORM)-$(ARCH)
else
ABS_BUILD_ROOT = $(TEST_ROOT)/../build/$(PLATFORM)-$(ARCH)
endif
ABS_TEST_OUTPUT_DIR = $(ABS_BUILD_ROOT)/testoutput ABS_TEST_OUTPUT_DIR = $(ABS_BUILD_ROOT)/testoutput
# Expect JPRT to set PRODUCT_HOME (the product or jdk in this case to test) # Expect JPRT to set PRODUCT_HOME (the product or jdk in this case to test)
......
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/**
* @test
* @bug 6991596
* @summary JSR 292 unimplemented adapter_opt_i2i and adapter_opt_l2i on SPARC
*
* @run main/othervm -ea -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles -XX:+EnableInvokeDynamic -XX:+UnlockDiagnosticVMOptions -XX:+VerifyMethodHandles Test6991596
*/
import java.dyn.*;
public class Test6991596 {
private static final Class CLASS = Test6991596.class;
private static final String NAME = "foo";
private static final boolean DEBUG = false;
public static void main(String[] args) throws Throwable {
testboolean();
testbyte();
testchar();
testshort();
testint();
testlong();
}
// Helpers to get various methods.
static MethodHandle getmh1(Class ret, Class arg) {
return MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(ret, arg));
}
static MethodHandle getmh2(MethodHandle mh1, Class ret, Class arg) {
return MethodHandles.convertArguments(mh1, MethodType.methodType(ret, arg));
}
static MethodHandle getmh3(MethodHandle mh1, Class ret, Class arg) {
return MethodHandles.convertArguments(mh1, MethodType.methodType(ret, arg));
}
// test adapter_opt_i2i
static void testboolean() throws Throwable {
boolean[] a = new boolean[] {
true,
false
};
for (int i = 0; i < a.length; i++) {
doboolean(a[i]);
}
}
static void doboolean(boolean x) throws Throwable {
if (DEBUG) System.out.println("boolean=" + x);
// boolean
{
MethodHandle mh1 = getmh1( boolean.class, boolean.class);
MethodHandle mh2 = getmh2(mh1, boolean.class, boolean.class);
// TODO add this for all cases when the bugs are fixed.
//MethodHandle mh3 = getmh3(mh1, boolean.class, boolean.class);
boolean a = mh1.<boolean>invokeExact((boolean) x);
boolean b = mh2.<boolean>invokeExact(x);
//boolean c = mh3.<boolean>invokeExact((boolean) x);
assert a == b : a + " != " + b;
//assert c == x : c + " != " + x;
}
// byte
{
MethodHandle mh1 = getmh1( byte.class, byte.class );
MethodHandle mh2 = getmh2(mh1, byte.class, boolean.class);
byte a = mh1.<byte>invokeExact((byte) (x ? 1 : 0));
byte b = mh2.<byte>invokeExact(x);
assert a == b : a + " != " + b;
}
// char
{
MethodHandle mh1 = getmh1( char.class, char.class);
MethodHandle mh2 = getmh2(mh1, char.class, boolean.class);
char a = mh1.<char>invokeExact((char) (x ? 1 : 0));
char b = mh2.<char>invokeExact(x);
assert a == b : a + " != " + b;
}
// short
{
MethodHandle mh1 = getmh1( short.class, short.class);
MethodHandle mh2 = getmh2(mh1, short.class, boolean.class);
short a = mh1.<short>invokeExact((short) (x ? 1 : 0));
short b = mh2.<short>invokeExact(x);
assert a == b : a + " != " + b;
}
}
static void testbyte() throws Throwable {
byte[] a = new byte[] {
Byte.MIN_VALUE,
Byte.MIN_VALUE + 1,
-0x0F,
-1,
0,
1,
0x0F,
Byte.MAX_VALUE - 1,
Byte.MAX_VALUE
};
for (int i = 0; i < a.length; i++) {
dobyte(a[i]);
}
}
static void dobyte(byte x) throws Throwable {
if (DEBUG) System.out.println("byte=" + x);
// boolean
{
MethodHandle mh1 = getmh1( boolean.class, boolean.class);
MethodHandle mh2 = getmh2(mh1, boolean.class, byte.class);
boolean a = mh1.<boolean>invokeExact((x & 1) == 1);
boolean b = mh2.<boolean>invokeExact(x);
assert a == b : a + " != " + b;
}
// byte
{
MethodHandle mh1 = getmh1( byte.class, byte.class);
MethodHandle mh2 = getmh2(mh1, byte.class, byte.class);
byte a = mh1.<byte>invokeExact((byte) x);
byte b = mh2.<byte>invokeExact(x);
assert a == b : a + " != " + b;
}
// char
{
MethodHandle mh1 = getmh1( char.class, char.class);
MethodHandle mh2 = getmh2(mh1, char.class, byte.class);
char a = mh1.<char>invokeExact((char) x);
char b = mh2.<char>invokeExact(x);
assert a == b : a + " != " + b;
}
// short
{
MethodHandle mh1 = getmh1( short.class, short.class);
MethodHandle mh2 = getmh2(mh1, short.class, byte.class);
short a = mh1.<short>invokeExact((short) x);
short b = mh2.<short>invokeExact(x);
assert a == b : a + " != " + b;
}
}
static void testchar() throws Throwable {
char[] a = new char[] {
Character.MIN_VALUE,
Character.MIN_VALUE + 1,
0x000F,
0x00FF,
0x0FFF,
Character.MAX_VALUE - 1,
Character.MAX_VALUE
};
for (int i = 0; i < a.length; i++) {
dochar(a[i]);
}
}
static void dochar(char x) throws Throwable {
if (DEBUG) System.out.println("char=" + x);
// boolean
{
MethodHandle mh1 = getmh1( boolean.class, boolean.class);
MethodHandle mh2 = getmh2(mh1, boolean.class, char.class);
boolean a = mh1.<boolean>invokeExact((x & 1) == 1);
boolean b = mh2.<boolean>invokeExact(x);
assert a == b : a + " != " + b;
}
// byte
{
MethodHandle mh1 = getmh1( byte.class, byte.class);
MethodHandle mh2 = getmh2(mh1, byte.class, char.class);
byte a = mh1.<byte>invokeExact((byte) x);
byte b = mh2.<byte>invokeExact(x);
assert a == b : a + " != " + b;
}
// char
{
MethodHandle mh1 = getmh1( char.class, char.class);
MethodHandle mh2 = getmh2(mh1, char.class, char.class);
char a = mh1.<char>invokeExact((char) x);
char b = mh2.<char>invokeExact(x);
assert a == b : a + " != " + b;
}
// short
{
MethodHandle mh1 = getmh1( short.class, short.class);
MethodHandle mh2 = getmh2(mh1, short.class, char.class);
short a = mh1.<short>invokeExact((short) x);
short b = mh2.<short>invokeExact(x);
assert a == b : a + " != " + b;
}
}
static void testshort() throws Throwable {
short[] a = new short[] {
Short.MIN_VALUE,
Short.MIN_VALUE + 1,
-0x0FFF,
-0x00FF,
-0x000F,
-1,
0,
1,
0x000F,
0x00FF,
0x0FFF,
Short.MAX_VALUE - 1,
Short.MAX_VALUE
};
for (int i = 0; i < a.length; i++) {
doshort(a[i]);
}
}
static void doshort(short x) throws Throwable {
if (DEBUG) System.out.println("short=" + x);
// boolean
{
MethodHandle mh1 = getmh1( boolean.class, boolean.class);
MethodHandle mh2 = getmh2(mh1, boolean.class, short.class);
boolean a = mh1.<boolean>invokeExact((x & 1) == 1);
boolean b = mh2.<boolean>invokeExact(x);
assert a == b : a + " != " + b;
}
// byte
{
MethodHandle mh1 = getmh1( byte.class, byte.class);
MethodHandle mh2 = getmh2(mh1, byte.class, short.class);
byte a = mh1.<byte>invokeExact((byte) x);
byte b = mh2.<byte>invokeExact(x);
assert a == b : a + " != " + b;
}
// char
{
MethodHandle mh1 = getmh1( char.class, char.class);
MethodHandle mh2 = getmh2(mh1, char.class, short.class);
char a = mh1.<char>invokeExact((char) x);
char b = mh2.<char>invokeExact(x);
assert a == b : a + " != " + b;
}
// short
{
MethodHandle mh1 = getmh1( short.class, short.class);
MethodHandle mh2 = getmh2(mh1, short.class, short.class);
short a = mh1.<short>invokeExact((short) x);
short b = mh2.<short>invokeExact(x);
assert a == b : a + " != " + b;
}
}
static void testint() throws Throwable {
int[] a = new int[] {
Integer.MIN_VALUE,
Integer.MIN_VALUE + 1,
-0x0FFFFFFF,
-0x00FFFFFF,
-0x000FFFFF,
-0x0000FFFF,
-0x00000FFF,
-0x000000FF,
-0x0000000F,
-1,
0,
1,
0x0000000F,
0x000000FF,
0x00000FFF,
0x0000FFFF,
0x000FFFFF,
0x00FFFFFF,
0x0FFFFFFF,
Integer.MAX_VALUE - 1,
Integer.MAX_VALUE
};
for (int i = 0; i < a.length; i++) {
doint(a[i]);
}
}
static void doint(int x) throws Throwable {
if (DEBUG) System.out.println("int=" + x);
// boolean
{
MethodHandle mh1 = getmh1( boolean.class, boolean.class);
MethodHandle mh2 = getmh2(mh1, boolean.class, int.class);
boolean a = mh1.<boolean>invokeExact((x & 1) == 1);
boolean b = mh2.<boolean>invokeExact(x);
assert a == b : a + " != " + b;
}
// byte
{
MethodHandle mh1 = getmh1( byte.class, byte.class);
MethodHandle mh2 = getmh2(mh1, byte.class, int.class);
byte a = mh1.<byte>invokeExact((byte) x);
byte b = mh2.<byte>invokeExact(x);
assert a == b : a + " != " + b;
}
// char
{
MethodHandle mh1 = getmh1( char.class, char.class);
MethodHandle mh2 = getmh2(mh1, char.class, int.class);
char a = mh1.<char>invokeExact((char) x);
char b = mh2.<char>invokeExact(x);
assert a == b : a + " != " + b;
}
// short
{
MethodHandle mh1 = getmh1( short.class, short.class);
MethodHandle mh2 = getmh2(mh1, short.class, int.class);
short a = mh1.<short>invokeExact((short) x);
short b = mh2.<short>invokeExact(x);
assert a == b : a + " != " + b;
}
// int
{
MethodHandle mh1 = getmh1( int.class, int.class);
MethodHandle mh2 = getmh2(mh1, int.class, int.class);
int a = mh1.<int>invokeExact((int) x);
int b = mh2.<int>invokeExact(x);
assert a == b : a + " != " + b;
}
}
// test adapter_opt_l2i
static void testlong() throws Throwable {
long[] a = new long[] {
Long.MIN_VALUE,
Long.MIN_VALUE + 1,
-0x000000000FFFFFFFL,
-0x0000000000FFFFFFL,
-0x00000000000FFFFFL,
-0x000000000000FFFFL,
-0x0000000000000FFFL,
-0x00000000000000FFL,
-0x000000000000000FL,
-1L,
0L,
1L,
0x000000000000000FL,
0x00000000000000FFL,
0x0000000000000FFFL,
0x0000000000000FFFL,
0x000000000000FFFFL,
0x00000000000FFFFFL,
0x0000000000FFFFFFL,
0x000000000FFFFFFFL,
Long.MAX_VALUE - 1,
Long.MAX_VALUE
};
for (int i = 0; i < a.length; i++) {
dolong(a[i]);
}
}
static void dolong(long x) throws Throwable {
if (DEBUG) System.out.println("long=" + x);
// boolean
{
MethodHandle mh1 = getmh1( boolean.class, boolean.class);
MethodHandle mh2 = getmh2(mh1, boolean.class, long.class);
boolean a = mh1.<boolean>invokeExact((x & 1L) == 1L);
boolean b = mh2.<boolean>invokeExact(x);
assert a == b : a + " != " + b;
}
// byte
{
MethodHandle mh1 = getmh1( byte.class, byte.class);
MethodHandle mh2 = getmh2(mh1, byte.class, long.class);
byte a = mh1.<byte>invokeExact((byte) x);
byte b = mh2.<byte>invokeExact(x);
assert a == b : a + " != " + b;
}
// char
{
MethodHandle mh1 = getmh1( char.class, char.class);
MethodHandle mh2 = getmh2(mh1, char.class, long.class);
char a = mh1.<char>invokeExact((char) x);
char b = mh2.<char>invokeExact(x);
assert a == b : a + " != " + b;
}
// short
{
MethodHandle mh1 = getmh1( short.class, short.class);
MethodHandle mh2 = getmh2(mh1, short.class, long.class);
short a = mh1.<short>invokeExact((short) x);
short b = mh2.<short>invokeExact(x);
assert a == b : a + " != " + b;
}
// int
{
MethodHandle mh1 = getmh1( int.class, int.class);
MethodHandle mh2 = getmh2(mh1, int.class, long.class);
int a = mh1.<int>invokeExact((int) x);
int b = mh2.<int>invokeExact(x);
assert a == b : a + " != " + b;
}
}
// to int
public static boolean foo(boolean i) { return i; }
public static byte foo(byte i) { return i; }
public static char foo(char i) { return i; }
public static short foo(short i) { return i; }
public static int foo(int i) { return i; }
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册