in src/hotspot/src/share/vm/opto/parse2.cpp [1407:2388]
void Parse::do_one_bytecode() {
Node *a, *b, *c, *d; // Handy temps
BoolTest::mask btest;
int i;
assert(!has_exceptions(), "bytecode entry state must be clear of throws");
if (C->check_node_count(NodeLimitFudgeFactor * 5,
"out of nodes parsing method")) {
return;
}
#ifdef ASSERT
// for setting breakpoints
if (TraceOptoParse) {
tty->print(" @");
dump_bci(bci());
tty->cr();
}
#endif
switch (bc()) {
case Bytecodes::_nop:
// do nothing
break;
case Bytecodes::_lconst_0:
push_pair(longcon(0));
break;
case Bytecodes::_lconst_1:
push_pair(longcon(1));
break;
case Bytecodes::_fconst_0:
push(zerocon(T_FLOAT));
break;
case Bytecodes::_fconst_1:
push(makecon(TypeF::ONE));
break;
case Bytecodes::_fconst_2:
push(makecon(TypeF::make(2.0f)));
break;
case Bytecodes::_dconst_0:
push_pair(zerocon(T_DOUBLE));
break;
case Bytecodes::_dconst_1:
push_pair(makecon(TypeD::ONE));
break;
case Bytecodes::_iconst_m1:push(intcon(-1)); break;
case Bytecodes::_iconst_0: push(intcon( 0)); break;
case Bytecodes::_iconst_1: push(intcon( 1)); break;
case Bytecodes::_iconst_2: push(intcon( 2)); break;
case Bytecodes::_iconst_3: push(intcon( 3)); break;
case Bytecodes::_iconst_4: push(intcon( 4)); break;
case Bytecodes::_iconst_5: push(intcon( 5)); break;
case Bytecodes::_bipush: push(intcon(iter().get_constant_u1())); break;
case Bytecodes::_sipush: push(intcon(iter().get_constant_u2())); break;
case Bytecodes::_aconst_null: push(null()); break;
case Bytecodes::_ldc:
case Bytecodes::_ldc_w:
case Bytecodes::_ldc2_w:
// If the constant is unresolved, run this BC once in the interpreter.
{
ciConstant constant = iter().get_constant();
if (constant.basic_type() == T_OBJECT &&
!constant.as_object()->is_loaded()) {
int index = iter().get_constant_pool_index();
constantTag tag = iter().get_constant_pool_tag(index);
uncommon_trap(Deoptimization::make_trap_request
(Deoptimization::Reason_unloaded,
Deoptimization::Action_reinterpret,
index),
NULL, tag.internal_name());
break;
}
assert(constant.basic_type() != T_OBJECT || constant.as_object()->is_instance(),
"must be java_mirror of klass");
bool pushed = push_constant(constant, true);
guarantee(pushed, "must be possible to push this constant");
}
break;
case Bytecodes::_aload_0:
push( local(0) );
break;
case Bytecodes::_aload_1:
push( local(1) );
break;
case Bytecodes::_aload_2:
push( local(2) );
break;
case Bytecodes::_aload_3:
push( local(3) );
break;
case Bytecodes::_aload:
push( local(iter().get_index()) );
break;
case Bytecodes::_fload_0:
case Bytecodes::_iload_0:
push( local(0) );
break;
case Bytecodes::_fload_1:
case Bytecodes::_iload_1:
push( local(1) );
break;
case Bytecodes::_fload_2:
case Bytecodes::_iload_2:
push( local(2) );
break;
case Bytecodes::_fload_3:
case Bytecodes::_iload_3:
push( local(3) );
break;
case Bytecodes::_fload:
case Bytecodes::_iload:
push( local(iter().get_index()) );
break;
case Bytecodes::_lload_0:
push_pair_local( 0 );
break;
case Bytecodes::_lload_1:
push_pair_local( 1 );
break;
case Bytecodes::_lload_2:
push_pair_local( 2 );
break;
case Bytecodes::_lload_3:
push_pair_local( 3 );
break;
case Bytecodes::_lload:
push_pair_local( iter().get_index() );
break;
case Bytecodes::_dload_0:
push_pair_local(0);
break;
case Bytecodes::_dload_1:
push_pair_local(1);
break;
case Bytecodes::_dload_2:
push_pair_local(2);
break;
case Bytecodes::_dload_3:
push_pair_local(3);
break;
case Bytecodes::_dload:
push_pair_local(iter().get_index());
break;
case Bytecodes::_fstore_0:
case Bytecodes::_istore_0:
case Bytecodes::_astore_0:
set_local( 0, pop() );
break;
case Bytecodes::_fstore_1:
case Bytecodes::_istore_1:
case Bytecodes::_astore_1:
set_local( 1, pop() );
break;
case Bytecodes::_fstore_2:
case Bytecodes::_istore_2:
case Bytecodes::_astore_2:
set_local( 2, pop() );
break;
case Bytecodes::_fstore_3:
case Bytecodes::_istore_3:
case Bytecodes::_astore_3:
set_local( 3, pop() );
break;
case Bytecodes::_fstore:
case Bytecodes::_istore:
case Bytecodes::_astore:
set_local( iter().get_index(), pop() );
break;
// long stores
case Bytecodes::_lstore_0:
set_pair_local( 0, pop_pair() );
break;
case Bytecodes::_lstore_1:
set_pair_local( 1, pop_pair() );
break;
case Bytecodes::_lstore_2:
set_pair_local( 2, pop_pair() );
break;
case Bytecodes::_lstore_3:
set_pair_local( 3, pop_pair() );
break;
case Bytecodes::_lstore:
set_pair_local( iter().get_index(), pop_pair() );
break;
// double stores
case Bytecodes::_dstore_0:
set_pair_local( 0, dstore_rounding(pop_pair()) );
break;
case Bytecodes::_dstore_1:
set_pair_local( 1, dstore_rounding(pop_pair()) );
break;
case Bytecodes::_dstore_2:
set_pair_local( 2, dstore_rounding(pop_pair()) );
break;
case Bytecodes::_dstore_3:
set_pair_local( 3, dstore_rounding(pop_pair()) );
break;
case Bytecodes::_dstore:
set_pair_local( iter().get_index(), dstore_rounding(pop_pair()) );
break;
case Bytecodes::_pop: dec_sp(1); break;
case Bytecodes::_pop2: dec_sp(2); break;
case Bytecodes::_swap:
a = pop();
b = pop();
push(a);
push(b);
break;
case Bytecodes::_dup:
a = pop();
push(a);
push(a);
break;
case Bytecodes::_dup_x1:
a = pop();
b = pop();
push( a );
push( b );
push( a );
break;
case Bytecodes::_dup_x2:
a = pop();
b = pop();
c = pop();
push( a );
push( c );
push( b );
push( a );
break;
case Bytecodes::_dup2:
a = pop();
b = pop();
push( b );
push( a );
push( b );
push( a );
break;
case Bytecodes::_dup2_x1:
// before: .. c, b, a
// after: .. b, a, c, b, a
// not tested
a = pop();
b = pop();
c = pop();
push( b );
push( a );
push( c );
push( b );
push( a );
break;
case Bytecodes::_dup2_x2:
// before: .. d, c, b, a
// after: .. b, a, d, c, b, a
// not tested
a = pop();
b = pop();
c = pop();
d = pop();
push( b );
push( a );
push( d );
push( c );
push( b );
push( a );
break;
case Bytecodes::_arraylength: {
// Must do null-check with value on expression stack
Node *ary = null_check(peek(), T_ARRAY);
// Compile-time detect of null-exception?
if (stopped()) return;
a = pop();
push(load_array_length(a));
break;
}
case Bytecodes::_baload: array_load(T_BYTE); break;
case Bytecodes::_caload: array_load(T_CHAR); break;
case Bytecodes::_iaload: array_load(T_INT); break;
case Bytecodes::_saload: array_load(T_SHORT); break;
case Bytecodes::_faload: array_load(T_FLOAT); break;
case Bytecodes::_aaload: array_load(T_OBJECT); break;
case Bytecodes::_laload: {
a = array_addressing(T_LONG, 0);
if (stopped()) return; // guaranteed null or range check
dec_sp(2); // Pop array and index
push_pair(make_load(control(), a, TypeLong::LONG, T_LONG, TypeAryPtr::LONGS, MemNode::unordered));
break;
}
case Bytecodes::_daload: {
a = array_addressing(T_DOUBLE, 0);
if (stopped()) return; // guaranteed null or range check
dec_sp(2); // Pop array and index
push_pair(make_load(control(), a, Type::DOUBLE, T_DOUBLE, TypeAryPtr::DOUBLES, MemNode::unordered));
break;
}
case Bytecodes::_bastore: array_store(T_BYTE); break;
case Bytecodes::_castore: array_store(T_CHAR); break;
case Bytecodes::_iastore: array_store(T_INT); break;
case Bytecodes::_sastore: array_store(T_SHORT); break;
case Bytecodes::_fastore: array_store(T_FLOAT); break;
case Bytecodes::_aastore: {
d = array_addressing(T_OBJECT, 1);
if (stopped()) return; // guaranteed null or range check
array_store_check();
c = pop(); // Oop to store
b = pop(); // index (already used)
a = pop(); // the array itself
const TypeOopPtr* elemtype = _gvn.type(a)->is_aryptr()->elem()->make_oopptr();
const TypeAryPtr* adr_type = TypeAryPtr::OOPS;
Node* store = store_oop_to_array(control(), a, d, adr_type, c, elemtype, T_OBJECT, MemNode::release);
break;
}
case Bytecodes::_lastore: {
a = array_addressing(T_LONG, 2);
if (stopped()) return; // guaranteed null or range check
c = pop_pair();
dec_sp(2); // Pop array and index
store_to_memory(control(), a, c, T_LONG, TypeAryPtr::LONGS, MemNode::unordered);
break;
}
case Bytecodes::_dastore: {
a = array_addressing(T_DOUBLE, 2);
if (stopped()) return; // guaranteed null or range check
c = pop_pair();
dec_sp(2); // Pop array and index
c = dstore_rounding(c);
store_to_memory(control(), a, c, T_DOUBLE, TypeAryPtr::DOUBLES, MemNode::unordered);
break;
}
case Bytecodes::_getfield:
do_getfield();
break;
case Bytecodes::_getstatic:
do_getstatic();
break;
case Bytecodes::_putfield:
do_putfield();
break;
case Bytecodes::_putstatic:
do_putstatic();
break;
case Bytecodes::_irem:
do_irem();
break;
case Bytecodes::_idiv:
// Must keep both values on the expression-stack during null-check
zero_check_int(peek());
// Compile-time detect of null-exception?
if (stopped()) return;
b = pop();
a = pop();
push( _gvn.transform( new (C) DivINode(control(),a,b) ) );
break;
case Bytecodes::_imul:
b = pop(); a = pop();
push( _gvn.transform( new (C) MulINode(a,b) ) );
break;
case Bytecodes::_iadd:
b = pop(); a = pop();
push( _gvn.transform( new (C) AddINode(a,b) ) );
break;
case Bytecodes::_ineg:
a = pop();
push( _gvn.transform( new (C) SubINode(_gvn.intcon(0),a)) );
break;
case Bytecodes::_isub:
b = pop(); a = pop();
push( _gvn.transform( new (C) SubINode(a,b) ) );
break;
case Bytecodes::_iand:
b = pop(); a = pop();
push( _gvn.transform( new (C) AndINode(a,b) ) );
break;
case Bytecodes::_ior:
b = pop(); a = pop();
push( _gvn.transform( new (C) OrINode(a,b) ) );
break;
case Bytecodes::_ixor:
b = pop(); a = pop();
push( _gvn.transform( new (C) XorINode(a,b) ) );
break;
case Bytecodes::_ishl:
b = pop(); a = pop();
push( _gvn.transform( new (C) LShiftINode(a,b) ) );
break;
case Bytecodes::_ishr:
b = pop(); a = pop();
push( _gvn.transform( new (C) RShiftINode(a,b) ) );
break;
case Bytecodes::_iushr:
b = pop(); a = pop();
push( _gvn.transform( new (C) URShiftINode(a,b) ) );
break;
case Bytecodes::_fneg:
a = pop();
b = _gvn.transform(new (C) NegFNode (a));
push(b);
break;
case Bytecodes::_fsub:
b = pop();
a = pop();
c = _gvn.transform( new (C) SubFNode(a,b) );
d = precision_rounding(c);
push( d );
break;
case Bytecodes::_fadd:
b = pop();
a = pop();
c = _gvn.transform( new (C) AddFNode(a,b) );
d = precision_rounding(c);
push( d );
break;
case Bytecodes::_fmul:
b = pop();
a = pop();
c = _gvn.transform( new (C) MulFNode(a,b) );
d = precision_rounding(c);
push( d );
break;
case Bytecodes::_fdiv:
b = pop();
a = pop();
c = _gvn.transform( new (C) DivFNode(0,a,b) );
d = precision_rounding(c);
push( d );
break;
case Bytecodes::_frem:
if (Matcher::has_match_rule(Op_ModF)) {
// Generate a ModF node.
b = pop();
a = pop();
c = _gvn.transform( new (C) ModFNode(0,a,b) );
d = precision_rounding(c);
push( d );
}
else {
// Generate a call.
modf();
}
break;
case Bytecodes::_fcmpl:
b = pop();
a = pop();
c = _gvn.transform( new (C) CmpF3Node( a, b));
push(c);
break;
case Bytecodes::_fcmpg:
b = pop();
a = pop();
// Same as fcmpl but need to flip the unordered case. Swap the inputs,
// which negates the result sign except for unordered. Flip the unordered
// as well by using CmpF3 which implements unordered-lesser instead of
// unordered-greater semantics. Finally, commute the result bits. Result
// is same as using a CmpF3Greater except we did it with CmpF3 alone.
c = _gvn.transform( new (C) CmpF3Node( b, a));
c = _gvn.transform( new (C) SubINode(_gvn.intcon(0),c) );
push(c);
break;
case Bytecodes::_f2i:
a = pop();
push(_gvn.transform(new (C) ConvF2INode(a)));
break;
case Bytecodes::_d2i:
a = pop_pair();
b = _gvn.transform(new (C) ConvD2INode(a));
push( b );
break;
case Bytecodes::_f2d:
a = pop();
b = _gvn.transform( new (C) ConvF2DNode(a));
push_pair( b );
break;
case Bytecodes::_d2f:
a = pop_pair();
b = _gvn.transform( new (C) ConvD2FNode(a));
// This breaks _227_mtrt (speed & correctness) and _222_mpegaudio (speed)
//b = _gvn.transform(new (C) RoundFloatNode(0, b) );
push( b );
break;
case Bytecodes::_l2f:
if (Matcher::convL2FSupported()) {
a = pop_pair();
b = _gvn.transform( new (C) ConvL2FNode(a));
// For i486.ad, FILD doesn't restrict precision to 24 or 53 bits.
// Rather than storing the result into an FP register then pushing
// out to memory to round, the machine instruction that implements
// ConvL2D is responsible for rounding.
// c = precision_rounding(b);
c = _gvn.transform(b);
push(c);
} else {
l2f();
}
break;
case Bytecodes::_l2d:
a = pop_pair();
b = _gvn.transform( new (C) ConvL2DNode(a));
// For i486.ad, rounding is always necessary (see _l2f above).
// c = dprecision_rounding(b);
c = _gvn.transform(b);
push_pair(c);
break;
case Bytecodes::_f2l:
a = pop();
b = _gvn.transform( new (C) ConvF2LNode(a));
push_pair(b);
break;
case Bytecodes::_d2l:
a = pop_pair();
b = _gvn.transform( new (C) ConvD2LNode(a));
push_pair(b);
break;
case Bytecodes::_dsub:
b = pop_pair();
a = pop_pair();
c = _gvn.transform( new (C) SubDNode(a,b) );
d = dprecision_rounding(c);
push_pair( d );
break;
case Bytecodes::_dadd:
b = pop_pair();
a = pop_pair();
c = _gvn.transform( new (C) AddDNode(a,b) );
d = dprecision_rounding(c);
push_pair( d );
break;
case Bytecodes::_dmul:
b = pop_pair();
a = pop_pair();
c = _gvn.transform( new (C) MulDNode(a,b) );
d = dprecision_rounding(c);
push_pair( d );
break;
case Bytecodes::_ddiv:
b = pop_pair();
a = pop_pair();
c = _gvn.transform( new (C) DivDNode(0,a,b) );
d = dprecision_rounding(c);
push_pair( d );
break;
case Bytecodes::_dneg:
a = pop_pair();
b = _gvn.transform(new (C) NegDNode (a));
push_pair(b);
break;
case Bytecodes::_drem:
if (Matcher::has_match_rule(Op_ModD)) {
// Generate a ModD node.
b = pop_pair();
a = pop_pair();
// a % b
c = _gvn.transform( new (C) ModDNode(0,a,b) );
d = dprecision_rounding(c);
push_pair( d );
}
else {
// Generate a call.
modd();
}
break;
case Bytecodes::_dcmpl:
b = pop_pair();
a = pop_pair();
c = _gvn.transform( new (C) CmpD3Node( a, b));
push(c);
break;
case Bytecodes::_dcmpg:
b = pop_pair();
a = pop_pair();
// Same as dcmpl but need to flip the unordered case.
// Commute the inputs, which negates the result sign except for unordered.
// Flip the unordered as well by using CmpD3 which implements
// unordered-lesser instead of unordered-greater semantics.
// Finally, negate the result bits. Result is same as using a
// CmpD3Greater except we did it with CmpD3 alone.
c = _gvn.transform( new (C) CmpD3Node( b, a));
c = _gvn.transform( new (C) SubINode(_gvn.intcon(0),c) );
push(c);
break;
// Note for longs -> lo word is on TOS, hi word is on TOS - 1
case Bytecodes::_land:
b = pop_pair();
a = pop_pair();
c = _gvn.transform( new (C) AndLNode(a,b) );
push_pair(c);
break;
case Bytecodes::_lor:
b = pop_pair();
a = pop_pair();
c = _gvn.transform( new (C) OrLNode(a,b) );
push_pair(c);
break;
case Bytecodes::_lxor:
b = pop_pair();
a = pop_pair();
c = _gvn.transform( new (C) XorLNode(a,b) );
push_pair(c);
break;
case Bytecodes::_lshl:
b = pop(); // the shift count
a = pop_pair(); // value to be shifted
c = _gvn.transform( new (C) LShiftLNode(a,b) );
push_pair(c);
break;
case Bytecodes::_lshr:
b = pop(); // the shift count
a = pop_pair(); // value to be shifted
c = _gvn.transform( new (C) RShiftLNode(a,b) );
push_pair(c);
break;
case Bytecodes::_lushr:
b = pop(); // the shift count
a = pop_pair(); // value to be shifted
c = _gvn.transform( new (C) URShiftLNode(a,b) );
push_pair(c);
break;
case Bytecodes::_lmul:
b = pop_pair();
a = pop_pair();
c = _gvn.transform( new (C) MulLNode(a,b) );
push_pair(c);
break;
case Bytecodes::_lrem:
// Must keep both values on the expression-stack during null-check
assert(peek(0) == top(), "long word order");
zero_check_long(peek(1));
// Compile-time detect of null-exception?
if (stopped()) return;
b = pop_pair();
a = pop_pair();
c = _gvn.transform( new (C) ModLNode(control(),a,b) );
push_pair(c);
break;
case Bytecodes::_ldiv:
// Must keep both values on the expression-stack during null-check
assert(peek(0) == top(), "long word order");
zero_check_long(peek(1));
// Compile-time detect of null-exception?
if (stopped()) return;
b = pop_pair();
a = pop_pair();
c = _gvn.transform( new (C) DivLNode(control(),a,b) );
push_pair(c);
break;
case Bytecodes::_ladd:
b = pop_pair();
a = pop_pair();
c = _gvn.transform( new (C) AddLNode(a,b) );
push_pair(c);
break;
case Bytecodes::_lsub:
b = pop_pair();
a = pop_pair();
c = _gvn.transform( new (C) SubLNode(a,b) );
push_pair(c);
break;
case Bytecodes::_lcmp:
// Safepoints are now inserted _before_ branches. The long-compare
// bytecode painfully produces a 3-way value (-1,0,+1) which requires a
// slew of control flow. These are usually followed by a CmpI vs zero and
// a branch; this pattern then optimizes to the obvious long-compare and
// branch. However, if the branch is backwards there's a Safepoint
// inserted. The inserted Safepoint captures the JVM state at the
// pre-branch point, i.e. it captures the 3-way value. Thus if a
// long-compare is used to control a loop the debug info will force
// computation of the 3-way value, even though the generated code uses a
// long-compare and branch. We try to rectify the situation by inserting
// a SafePoint here and have it dominate and kill the safepoint added at a
// following backwards branch. At this point the JVM state merely holds 2
// longs but not the 3-way value.
if( UseLoopSafepoints ) {
switch( iter().next_bc() ) {
case Bytecodes::_ifgt:
case Bytecodes::_iflt:
case Bytecodes::_ifge:
case Bytecodes::_ifle:
case Bytecodes::_ifne:
case Bytecodes::_ifeq:
// If this is a backwards branch in the bytecodes, add Safepoint
maybe_add_safepoint(iter().next_get_dest());
}
}
b = pop_pair();
a = pop_pair();
c = _gvn.transform( new (C) CmpL3Node( a, b ));
push(c);
break;
case Bytecodes::_lneg:
a = pop_pair();
b = _gvn.transform( new (C) SubLNode(longcon(0),a));
push_pair(b);
break;
case Bytecodes::_l2i:
a = pop_pair();
push( _gvn.transform( new (C) ConvL2INode(a)));
break;
case Bytecodes::_i2l:
a = pop();
b = _gvn.transform( new (C) ConvI2LNode(a));
push_pair(b);
break;
case Bytecodes::_i2b:
// Sign extend
a = pop();
a = _gvn.transform( new (C) LShiftINode(a,_gvn.intcon(24)) );
a = _gvn.transform( new (C) RShiftINode(a,_gvn.intcon(24)) );
push( a );
break;
case Bytecodes::_i2s:
a = pop();
a = _gvn.transform( new (C) LShiftINode(a,_gvn.intcon(16)) );
a = _gvn.transform( new (C) RShiftINode(a,_gvn.intcon(16)) );
push( a );
break;
case Bytecodes::_i2c:
a = pop();
push( _gvn.transform( new (C) AndINode(a,_gvn.intcon(0xFFFF)) ) );
break;
case Bytecodes::_i2f:
a = pop();
b = _gvn.transform( new (C) ConvI2FNode(a) ) ;
c = precision_rounding(b);
push (b);
break;
case Bytecodes::_i2d:
a = pop();
b = _gvn.transform( new (C) ConvI2DNode(a));
push_pair(b);
break;
case Bytecodes::_iinc: // Increment local
i = iter().get_index(); // Get local index
set_local( i, _gvn.transform( new (C) AddINode( _gvn.intcon(iter().get_iinc_con()), local(i) ) ) );
break;
// Exit points of synchronized methods must have an unlock node
case Bytecodes::_return:
return_current(NULL);
break;
case Bytecodes::_ireturn:
case Bytecodes::_areturn:
case Bytecodes::_freturn:
return_current(pop());
break;
case Bytecodes::_lreturn:
return_current(pop_pair());
break;
case Bytecodes::_dreturn:
return_current(pop_pair());
break;
case Bytecodes::_athrow:
// null exception oop throws NULL pointer exception
null_check(peek());
if (stopped()) return;
// Hook the thrown exception directly to subsequent handlers.
if (BailoutToInterpreterForThrows) {
// Keep method interpreted from now on.
uncommon_trap(Deoptimization::Reason_unhandled,
Deoptimization::Action_make_not_compilable);
return;
}
if (env()->jvmti_can_post_on_exceptions()) {
// check if we must post exception events, take uncommon trap if so (with must_throw = false)
uncommon_trap_if_should_post_on_exceptions(Deoptimization::Reason_unhandled, false);
}
// Here if either can_post_on_exceptions or should_post_on_exceptions is false
add_exception_state(make_exception_state(peek()));
break;
case Bytecodes::_goto: // fall through
case Bytecodes::_goto_w: {
int target_bci = (bc() == Bytecodes::_goto) ? iter().get_dest() : iter().get_far_dest();
// If this is a backwards branch in the bytecodes, add Safepoint
maybe_add_safepoint(target_bci);
// Update method data
profile_taken_branch(target_bci);
// Merge the current control into the target basic block
merge(target_bci);
// See if we can get some profile data and hand it off to the next block
Block *target_block = block()->successor_for_bci(target_bci);
if (target_block->pred_count() != 1) break;
ciMethodData* methodData = method()->method_data();
if (!methodData->is_mature()) break;
ciProfileData* data = methodData->bci_to_data(bci());
assert( data->is_JumpData(), "" );
int taken = ((ciJumpData*)data)->taken();
taken = method()->scale_count(taken);
target_block->set_count(taken);
break;
}
case Bytecodes::_ifnull: btest = BoolTest::eq; goto handle_if_null;
case Bytecodes::_ifnonnull: btest = BoolTest::ne; goto handle_if_null;
handle_if_null:
// If this is a backwards branch in the bytecodes, add Safepoint
maybe_add_safepoint(iter().get_dest());
a = null();
b = pop();
c = _gvn.transform( new (C) CmpPNode(b, a) );
do_ifnull(btest, c);
break;
case Bytecodes::_if_acmpeq: btest = BoolTest::eq; goto handle_if_acmp;
case Bytecodes::_if_acmpne: btest = BoolTest::ne; goto handle_if_acmp;
handle_if_acmp:
// If this is a backwards branch in the bytecodes, add Safepoint
maybe_add_safepoint(iter().get_dest());
a = pop();
b = pop();
c = _gvn.transform( new (C) CmpPNode(b, a) );
c = optimize_cmp_with_klass(c);
do_if(btest, c);
break;
case Bytecodes::_ifeq: btest = BoolTest::eq; goto handle_ifxx;
case Bytecodes::_ifne: btest = BoolTest::ne; goto handle_ifxx;
case Bytecodes::_iflt: btest = BoolTest::lt; goto handle_ifxx;
case Bytecodes::_ifle: btest = BoolTest::le; goto handle_ifxx;
case Bytecodes::_ifgt: btest = BoolTest::gt; goto handle_ifxx;
case Bytecodes::_ifge: btest = BoolTest::ge; goto handle_ifxx;
handle_ifxx:
// If this is a backwards branch in the bytecodes, add Safepoint
maybe_add_safepoint(iter().get_dest());
a = _gvn.intcon(0);
b = pop();
c = _gvn.transform( new (C) CmpINode(b, a) );
do_if(btest, c);
break;
case Bytecodes::_if_icmpeq: btest = BoolTest::eq; goto handle_if_icmp;
case Bytecodes::_if_icmpne: btest = BoolTest::ne; goto handle_if_icmp;
case Bytecodes::_if_icmplt: btest = BoolTest::lt; goto handle_if_icmp;
case Bytecodes::_if_icmple: btest = BoolTest::le; goto handle_if_icmp;
case Bytecodes::_if_icmpgt: btest = BoolTest::gt; goto handle_if_icmp;
case Bytecodes::_if_icmpge: btest = BoolTest::ge; goto handle_if_icmp;
handle_if_icmp:
// If this is a backwards branch in the bytecodes, add Safepoint
maybe_add_safepoint(iter().get_dest());
a = pop();
b = pop();
c = _gvn.transform( new (C) CmpINode( b, a ) );
do_if(btest, c);
break;
case Bytecodes::_tableswitch:
do_tableswitch();
break;
case Bytecodes::_lookupswitch:
do_lookupswitch();
break;
case Bytecodes::_invokestatic:
case Bytecodes::_invokedynamic:
case Bytecodes::_invokespecial:
case Bytecodes::_invokevirtual:
case Bytecodes::_invokeinterface:
do_call();
break;
case Bytecodes::_checkcast:
do_checkcast();
break;
case Bytecodes::_instanceof:
do_instanceof();
break;
case Bytecodes::_anewarray:
do_anewarray();
break;
case Bytecodes::_newarray:
do_newarray((BasicType)iter().get_index());
break;
case Bytecodes::_multianewarray:
do_multianewarray();
break;
case Bytecodes::_new:
do_new();
break;
case Bytecodes::_jsr:
case Bytecodes::_jsr_w:
do_jsr();
break;
case Bytecodes::_ret:
do_ret();
break;
case Bytecodes::_monitorenter:
do_monitor_enter();
break;
case Bytecodes::_monitorexit:
do_monitor_exit();
break;
case Bytecodes::_breakpoint:
// Breakpoint set concurrently to compile
// %%% use an uncommon trap?
C->record_failure("breakpoint in method");
return;
default:
#ifndef PRODUCT
map()->dump(99);
#endif
tty->print("\nUnhandled bytecode %s\n", Bytecodes::name(bc()) );
ShouldNotReachHere();
}
#ifndef PRODUCT
IdealGraphPrinter *printer = IdealGraphPrinter::printer();
if(printer) {
char buffer[256];
sprintf(buffer, "Bytecode %d: %s", bci(), Bytecodes::name(bc()));
bool old = printer->traverse_outs();
printer->set_traverse_outs(true);
printer->print_method(C, buffer, 4);
printer->set_traverse_outs(old);
}
#endif
}