/* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2008, 2009, 2010 Red Hat, Inc. * 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. * */ #include "precompiled.hpp" #include "interpreter/bytecodes.hpp" #include "shark/llvmHeaders.hpp" #include "shark/llvmValue.hpp" #include "shark/sharkBlock.hpp" #include "shark/sharkBuilder.hpp" #include "shark/sharkConstant.hpp" #include "shark/sharkState.hpp" #include "shark/sharkValue.hpp" #include "shark/shark_globals.hpp" #include "utilities/debug.hpp" using namespace llvm; void SharkBlock::parse_bytecode(int start, int limit) { SharkValue *a, *b, *c, *d; int i; // Ensure the current state is initialized before we emit any code, // so that any setup code for the state is at the start of the block current_state(); // Parse the bytecodes iter()->reset_to_bci(start); while (iter()->next_bci() < limit) { NOT_PRODUCT(a = b = c = d = NULL); iter()->next(); if (SharkTraceBytecodes) tty->print_cr("%4d: %s", bci(), Bytecodes::name(bc())); if (has_trap() && trap_bci() == bci()) { do_trap(trap_request()); return; } if (UseLoopSafepoints) { // XXX if a lcmp is followed by an if_?? then C2 maybe-inserts // the safepoint before the lcmp rather than before the if. // Maybe we should do this too. See parse2.cpp for details. switch (bc()) { case Bytecodes::_goto: case Bytecodes::_ifnull: case Bytecodes::_ifnonnull: case Bytecodes::_if_acmpeq: case Bytecodes::_if_acmpne: case Bytecodes::_ifeq: case Bytecodes::_ifne: case Bytecodes::_iflt: case Bytecodes::_ifle: case Bytecodes::_ifgt: case Bytecodes::_ifge: case Bytecodes::_if_icmpeq: case Bytecodes::_if_icmpne: case Bytecodes::_if_icmplt: case Bytecodes::_if_icmple: case Bytecodes::_if_icmpgt: case Bytecodes::_if_icmpge: if (iter()->get_dest() <= bci()) maybe_add_backedge_safepoint(); break; case Bytecodes::_goto_w: if (iter()->get_far_dest() <= bci()) maybe_add_backedge_safepoint(); break; case Bytecodes::_tableswitch: case Bytecodes::_lookupswitch: if (switch_default_dest() <= bci()) { maybe_add_backedge_safepoint(); break; } int len = switch_table_length(); for (int i = 0; i < len; i++) { if (switch_dest(i) <= bci()) { maybe_add_backedge_safepoint(); break; } } break; } } switch (bc()) { case Bytecodes::_nop: break; case Bytecodes::_aconst_null: push(SharkValue::null()); break; case Bytecodes::_iconst_m1: push(SharkValue::jint_constant(-1)); break; case Bytecodes::_iconst_0: push(SharkValue::jint_constant(0)); break; case Bytecodes::_iconst_1: push(SharkValue::jint_constant(1)); break; case Bytecodes::_iconst_2: push(SharkValue::jint_constant(2)); break; case Bytecodes::_iconst_3: push(SharkValue::jint_constant(3)); break; case Bytecodes::_iconst_4: push(SharkValue::jint_constant(4)); break; case Bytecodes::_iconst_5: push(SharkValue::jint_constant(5)); break; case Bytecodes::_lconst_0: push(SharkValue::jlong_constant(0)); break; case Bytecodes::_lconst_1: push(SharkValue::jlong_constant(1)); break; case Bytecodes::_fconst_0: push(SharkValue::jfloat_constant(0)); break; case Bytecodes::_fconst_1: push(SharkValue::jfloat_constant(1)); break; case Bytecodes::_fconst_2: push(SharkValue::jfloat_constant(2)); break; case Bytecodes::_dconst_0: push(SharkValue::jdouble_constant(0)); break; case Bytecodes::_dconst_1: push(SharkValue::jdouble_constant(1)); break; case Bytecodes::_bipush: push(SharkValue::jint_constant(iter()->get_constant_u1())); break; case Bytecodes::_sipush: push(SharkValue::jint_constant(iter()->get_constant_u2())); break; case Bytecodes::_ldc: case Bytecodes::_ldc_w: case Bytecodes::_ldc2_w: { SharkConstant* constant = SharkConstant::for_ldc(iter()); assert(constant->is_loaded(), "trap should handle unloaded classes"); push(constant->value(builder())); break; } case Bytecodes::_iload_0: case Bytecodes::_lload_0: case Bytecodes::_fload_0: case Bytecodes::_dload_0: case Bytecodes::_aload_0: push(local(0)); break; case Bytecodes::_iload_1: case Bytecodes::_lload_1: case Bytecodes::_fload_1: case Bytecodes::_dload_1: case Bytecodes::_aload_1: push(local(1)); break; case Bytecodes::_iload_2: case Bytecodes::_lload_2: case Bytecodes::_fload_2: case Bytecodes::_dload_2: case Bytecodes::_aload_2: push(local(2)); break; case Bytecodes::_iload_3: case Bytecodes::_lload_3: case Bytecodes::_fload_3: case Bytecodes::_dload_3: case Bytecodes::_aload_3: push(local(3)); break; case Bytecodes::_iload: case Bytecodes::_lload: case Bytecodes::_fload: case Bytecodes::_dload: case Bytecodes::_aload: push(local(iter()->get_index())); break; case Bytecodes::_baload: do_aload(T_BYTE); break; case Bytecodes::_caload: do_aload(T_CHAR); break; case Bytecodes::_saload: do_aload(T_SHORT); break; case Bytecodes::_iaload: do_aload(T_INT); break; case Bytecodes::_laload: do_aload(T_LONG); break; case Bytecodes::_faload: do_aload(T_FLOAT); break; case Bytecodes::_daload: do_aload(T_DOUBLE); break; case Bytecodes::_aaload: do_aload(T_OBJECT); break; case Bytecodes::_istore_0: case Bytecodes::_lstore_0: case Bytecodes::_fstore_0: case Bytecodes::_dstore_0: case Bytecodes::_astore_0: set_local(0, pop()); break; case Bytecodes::_istore_1: case Bytecodes::_lstore_1: case Bytecodes::_fstore_1: case Bytecodes::_dstore_1: case Bytecodes::_astore_1: set_local(1, pop()); break; case Bytecodes::_istore_2: case Bytecodes::_lstore_2: case Bytecodes::_fstore_2: case Bytecodes::_dstore_2: case Bytecodes::_astore_2: set_local(2, pop()); break; case Bytecodes::_istore_3: case Bytecodes::_lstore_3: case Bytecodes::_fstore_3: case Bytecodes::_dstore_3: case Bytecodes::_astore_3: set_local(3, pop()); break; case Bytecodes::_istore: case Bytecodes::_lstore: case Bytecodes::_fstore: case Bytecodes::_dstore: case Bytecodes::_astore: set_local(iter()->get_index(), pop()); break; case Bytecodes::_bastore: do_astore(T_BYTE); break; case Bytecodes::_castore: do_astore(T_CHAR); break; case Bytecodes::_sastore: do_astore(T_SHORT); break; case Bytecodes::_iastore: do_astore(T_INT); break; case Bytecodes::_lastore: do_astore(T_LONG); break; case Bytecodes::_fastore: do_astore(T_FLOAT); break; case Bytecodes::_dastore: do_astore(T_DOUBLE); break; case Bytecodes::_aastore: do_astore(T_OBJECT); break; case Bytecodes::_pop: xpop(); break; case Bytecodes::_pop2: xpop(); xpop(); break; case Bytecodes::_swap: a = xpop(); b = xpop(); xpush(a); xpush(b); break; case Bytecodes::_dup: a = xpop(); xpush(a); xpush(a); break; case Bytecodes::_dup_x1: a = xpop(); b = xpop(); xpush(a); xpush(b); xpush(a); break; case Bytecodes::_dup_x2: a = xpop(); b = xpop(); c = xpop(); xpush(a); xpush(c); xpush(b); xpush(a); break; case Bytecodes::_dup2: a = xpop(); b = xpop(); xpush(b); xpush(a); xpush(b); xpush(a); break; case Bytecodes::_dup2_x1: a = xpop(); b = xpop(); c = xpop(); xpush(b); xpush(a); xpush(c); xpush(b); xpush(a); break; case Bytecodes::_dup2_x2: a = xpop(); b = xpop(); c = xpop(); d = xpop(); xpush(b); xpush(a); xpush(d); xpush(c); xpush(b); xpush(a); break; case Bytecodes::_arraylength: do_arraylength(); 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::_iadd: b = pop(); a = pop(); push(SharkValue::create_jint( builder()->CreateAdd(a->jint_value(), b->jint_value()), false)); break; case Bytecodes::_isub: b = pop(); a = pop(); push(SharkValue::create_jint( builder()->CreateSub(a->jint_value(), b->jint_value()), false)); break; case Bytecodes::_imul: b = pop(); a = pop(); push(SharkValue::create_jint( builder()->CreateMul(a->jint_value(), b->jint_value()), false)); break; case Bytecodes::_idiv: do_idiv(); break; case Bytecodes::_irem: do_irem(); break; case Bytecodes::_ineg: a = pop(); push(SharkValue::create_jint( builder()->CreateNeg(a->jint_value()), a->zero_checked())); break; case Bytecodes::_ishl: b = pop(); a = pop(); push(SharkValue::create_jint( builder()->CreateShl( a->jint_value(), builder()->CreateAnd( b->jint_value(), LLVMValue::jint_constant(0x1f))), false)); break; case Bytecodes::_ishr: b = pop(); a = pop(); push(SharkValue::create_jint( builder()->CreateAShr( a->jint_value(), builder()->CreateAnd( b->jint_value(), LLVMValue::jint_constant(0x1f))), false)); break; case Bytecodes::_iushr: b = pop(); a = pop(); push(SharkValue::create_jint( builder()->CreateLShr( a->jint_value(), builder()->CreateAnd( b->jint_value(), LLVMValue::jint_constant(0x1f))), false)); break; case Bytecodes::_iand: b = pop(); a = pop(); push(SharkValue::create_jint( builder()->CreateAnd(a->jint_value(), b->jint_value()), false)); break; case Bytecodes::_ior: b = pop(); a = pop(); push(SharkValue::create_jint( builder()->CreateOr(a->jint_value(), b->jint_value()), a->zero_checked() && b->zero_checked())); break; case Bytecodes::_ixor: b = pop(); a = pop(); push(SharkValue::create_jint( builder()->CreateXor(a->jint_value(), b->jint_value()), false)); break; case Bytecodes::_ladd: b = pop(); a = pop(); push(SharkValue::create_jlong( builder()->CreateAdd(a->jlong_value(), b->jlong_value()), false)); break; case Bytecodes::_lsub: b = pop(); a = pop(); push(SharkValue::create_jlong( builder()->CreateSub(a->jlong_value(), b->jlong_value()), false)); break; case Bytecodes::_lmul: b = pop(); a = pop(); push(SharkValue::create_jlong( builder()->CreateMul(a->jlong_value(), b->jlong_value()), false)); break; case Bytecodes::_ldiv: do_ldiv(); break; case Bytecodes::_lrem: do_lrem(); break; case Bytecodes::_lneg: a = pop(); push(SharkValue::create_jlong( builder()->CreateNeg(a->jlong_value()), a->zero_checked())); break; case Bytecodes::_lshl: b = pop(); a = pop(); push(SharkValue::create_jlong( builder()->CreateShl( a->jlong_value(), builder()->CreateIntCast( builder()->CreateAnd( b->jint_value(), LLVMValue::jint_constant(0x3f)), SharkType::jlong_type(), true)), false)); break; case Bytecodes::_lshr: b = pop(); a = pop(); push(SharkValue::create_jlong( builder()->CreateAShr( a->jlong_value(), builder()->CreateIntCast( builder()->CreateAnd( b->jint_value(), LLVMValue::jint_constant(0x3f)), SharkType::jlong_type(), true)), false)); break; case Bytecodes::_lushr: b = pop(); a = pop(); push(SharkValue::create_jlong( builder()->CreateLShr( a->jlong_value(), builder()->CreateIntCast( builder()->CreateAnd( b->jint_value(), LLVMValue::jint_constant(0x3f)), SharkType::jlong_type(), true)), false)); break; case Bytecodes::_land: b = pop(); a = pop(); push(SharkValue::create_jlong( builder()->CreateAnd(a->jlong_value(), b->jlong_value()), false)); break; case Bytecodes::_lor: b = pop(); a = pop(); push(SharkValue::create_jlong( builder()->CreateOr(a->jlong_value(), b->jlong_value()), a->zero_checked() && b->zero_checked())); break; case Bytecodes::_lxor: b = pop(); a = pop(); push(SharkValue::create_jlong( builder()->CreateXor(a->jlong_value(), b->jlong_value()), false)); break; case Bytecodes::_fadd: b = pop(); a = pop(); push(SharkValue::create_jfloat( builder()->CreateFAdd(a->jfloat_value(), b->jfloat_value()))); break; case Bytecodes::_fsub: b = pop(); a = pop(); push(SharkValue::create_jfloat( builder()->CreateFSub(a->jfloat_value(), b->jfloat_value()))); break; case Bytecodes::_fmul: b = pop(); a = pop(); push(SharkValue::create_jfloat( builder()->CreateFMul(a->jfloat_value(), b->jfloat_value()))); break; case Bytecodes::_fdiv: b = pop(); a = pop(); push(SharkValue::create_jfloat( builder()->CreateFDiv(a->jfloat_value(), b->jfloat_value()))); break; case Bytecodes::_frem: b = pop(); a = pop(); push(SharkValue::create_jfloat( builder()->CreateFRem(a->jfloat_value(), b->jfloat_value()))); break; case Bytecodes::_fneg: a = pop(); push(SharkValue::create_jfloat( builder()->CreateFNeg(a->jfloat_value()))); break; case Bytecodes::_dadd: b = pop(); a = pop(); push(SharkValue::create_jdouble( builder()->CreateFAdd(a->jdouble_value(), b->jdouble_value()))); break; case Bytecodes::_dsub: b = pop(); a = pop(); push(SharkValue::create_jdouble( builder()->CreateFSub(a->jdouble_value(), b->jdouble_value()))); break; case Bytecodes::_dmul: b = pop(); a = pop(); push(SharkValue::create_jdouble( builder()->CreateFMul(a->jdouble_value(), b->jdouble_value()))); break; case Bytecodes::_ddiv: b = pop(); a = pop(); push(SharkValue::create_jdouble( builder()->CreateFDiv(a->jdouble_value(), b->jdouble_value()))); break; case Bytecodes::_drem: b = pop(); a = pop(); push(SharkValue::create_jdouble( builder()->CreateFRem(a->jdouble_value(), b->jdouble_value()))); break; case Bytecodes::_dneg: a = pop(); push(SharkValue::create_jdouble( builder()->CreateFNeg(a->jdouble_value()))); break; case Bytecodes::_iinc: i = iter()->get_index(); set_local( i, SharkValue::create_jint( builder()->CreateAdd( LLVMValue::jint_constant(iter()->get_iinc_con()), local(i)->jint_value()), false)); break; case Bytecodes::_lcmp: do_lcmp(); break; case Bytecodes::_fcmpl: do_fcmp(false, false); break; case Bytecodes::_fcmpg: do_fcmp(false, true); break; case Bytecodes::_dcmpl: do_fcmp(true, false); break; case Bytecodes::_dcmpg: do_fcmp(true, true); break; case Bytecodes::_i2l: a = pop(); push(SharkValue::create_jlong( builder()->CreateIntCast( a->jint_value(), SharkType::jlong_type(), true), a->zero_checked())); break; case Bytecodes::_i2f: push(SharkValue::create_jfloat( builder()->CreateSIToFP( pop()->jint_value(), SharkType::jfloat_type()))); break; case Bytecodes::_i2d: push(SharkValue::create_jdouble( builder()->CreateSIToFP( pop()->jint_value(), SharkType::jdouble_type()))); break; case Bytecodes::_l2i: push(SharkValue::create_jint( builder()->CreateIntCast( pop()->jlong_value(), SharkType::jint_type(), true), false)); break; case Bytecodes::_l2f: push(SharkValue::create_jfloat( builder()->CreateSIToFP( pop()->jlong_value(), SharkType::jfloat_type()))); break; case Bytecodes::_l2d: push(SharkValue::create_jdouble( builder()->CreateSIToFP( pop()->jlong_value(), SharkType::jdouble_type()))); break; case Bytecodes::_f2i: push(SharkValue::create_jint( builder()->CreateCall( builder()->f2i(), pop()->jfloat_value()), false)); break; case Bytecodes::_f2l: push(SharkValue::create_jlong( builder()->CreateCall( builder()->f2l(), pop()->jfloat_value()), false)); break; case Bytecodes::_f2d: push(SharkValue::create_jdouble( builder()->CreateFPExt( pop()->jfloat_value(), SharkType::jdouble_type()))); break; case Bytecodes::_d2i: push(SharkValue::create_jint( builder()->CreateCall( builder()->d2i(), pop()->jdouble_value()), false)); break; case Bytecodes::_d2l: push(SharkValue::create_jlong( builder()->CreateCall( builder()->d2l(), pop()->jdouble_value()), false)); break; case Bytecodes::_d2f: push(SharkValue::create_jfloat( builder()->CreateFPTrunc( pop()->jdouble_value(), SharkType::jfloat_type()))); break; case Bytecodes::_i2b: push(SharkValue::create_jint( builder()->CreateAShr( builder()->CreateShl( pop()->jint_value(), LLVMValue::jint_constant(24)), LLVMValue::jint_constant(24)), false)); break; case Bytecodes::_i2c: push(SharkValue::create_jint( builder()->CreateAnd( pop()->jint_value(), LLVMValue::jint_constant(0xffff)), false)); break; case Bytecodes::_i2s: push(SharkValue::create_jint( builder()->CreateAShr( builder()->CreateShl( pop()->jint_value(), LLVMValue::jint_constant(16)), LLVMValue::jint_constant(16)), false)); break; case Bytecodes::_return: do_return(T_VOID); break; case Bytecodes::_ireturn: do_return(T_INT); break; case Bytecodes::_lreturn: do_return(T_LONG); break; case Bytecodes::_freturn: do_return(T_FLOAT); break; case Bytecodes::_dreturn: do_return(T_DOUBLE); break; case Bytecodes::_areturn: do_return(T_OBJECT); break; case Bytecodes::_athrow: do_athrow(); break; case Bytecodes::_goto: case Bytecodes::_goto_w: do_goto(); break; case Bytecodes::_jsr: case Bytecodes::_jsr_w: do_jsr(); break; case Bytecodes::_ret: do_ret(); break; case Bytecodes::_ifnull: do_if(ICmpInst::ICMP_EQ, SharkValue::null(), pop()); break; case Bytecodes::_ifnonnull: do_if(ICmpInst::ICMP_NE, SharkValue::null(), pop()); break; case Bytecodes::_if_acmpeq: b = pop(); a = pop(); do_if(ICmpInst::ICMP_EQ, b, a); break; case Bytecodes::_if_acmpne: b = pop(); a = pop(); do_if(ICmpInst::ICMP_NE, b, a); break; case Bytecodes::_ifeq: do_if(ICmpInst::ICMP_EQ, SharkValue::jint_constant(0), pop()); break; case Bytecodes::_ifne: do_if(ICmpInst::ICMP_NE, SharkValue::jint_constant(0), pop()); break; case Bytecodes::_iflt: do_if(ICmpInst::ICMP_SLT, SharkValue::jint_constant(0), pop()); break; case Bytecodes::_ifle: do_if(ICmpInst::ICMP_SLE, SharkValue::jint_constant(0), pop()); break; case Bytecodes::_ifgt: do_if(ICmpInst::ICMP_SGT, SharkValue::jint_constant(0), pop()); break; case Bytecodes::_ifge: do_if(ICmpInst::ICMP_SGE, SharkValue::jint_constant(0), pop()); break; case Bytecodes::_if_icmpeq: b = pop(); a = pop(); do_if(ICmpInst::ICMP_EQ, b, a); break; case Bytecodes::_if_icmpne: b = pop(); a = pop(); do_if(ICmpInst::ICMP_NE, b, a); break; case Bytecodes::_if_icmplt: b = pop(); a = pop(); do_if(ICmpInst::ICMP_SLT, b, a); break; case Bytecodes::_if_icmple: b = pop(); a = pop(); do_if(ICmpInst::ICMP_SLE, b, a); break; case Bytecodes::_if_icmpgt: b = pop(); a = pop(); do_if(ICmpInst::ICMP_SGT, b, a); break; case Bytecodes::_if_icmpge: b = pop(); a = pop(); do_if(ICmpInst::ICMP_SGE, b, a); break; case Bytecodes::_tableswitch: case Bytecodes::_lookupswitch: do_switch(); break; case Bytecodes::_invokestatic: case Bytecodes::_invokespecial: case Bytecodes::_invokevirtual: case Bytecodes::_invokeinterface: do_call(); break; case Bytecodes::_instanceof: // This is a very common construct: // // if (object instanceof Klass) { // something = (Klass) object; // ... // } // // which gets compiled to something like this: // // 28: aload 9 // 30: instanceof // 33: ifeq 52 // 36: aload 9 // 38: checkcast // // Handling both bytecodes at once allows us // to eliminate the checkcast. if (iter()->next_bci() < limit && (iter()->next_bc() == Bytecodes::_ifeq || iter()->next_bc() == Bytecodes::_ifne) && (!UseLoopSafepoints || iter()->next_get_dest() > iter()->next_bci())) { if (maybe_do_instanceof_if()) { iter()->next(); if (SharkTraceBytecodes) tty->print_cr("%4d: %s", bci(), Bytecodes::name(bc())); break; } } // fall through case Bytecodes::_checkcast: do_instance_check(); break; case Bytecodes::_new: do_new(); break; case Bytecodes::_newarray: do_newarray(); break; case Bytecodes::_anewarray: do_anewarray(); break; case Bytecodes::_multianewarray: do_multianewarray(); break; case Bytecodes::_monitorenter: do_monitorenter(); break; case Bytecodes::_monitorexit: do_monitorexit(); break; default: ShouldNotReachHere(); } } } SharkState* SharkBlock::initial_current_state() { return entry_state()->copy(); } int SharkBlock::switch_default_dest() { return iter()->get_dest_table(0); } int SharkBlock::switch_table_length() { switch(bc()) { case Bytecodes::_tableswitch: return iter()->get_int_table(2) - iter()->get_int_table(1) + 1; case Bytecodes::_lookupswitch: return iter()->get_int_table(1); default: ShouldNotReachHere(); } } int SharkBlock::switch_key(int i) { switch(bc()) { case Bytecodes::_tableswitch: return iter()->get_int_table(1) + i; case Bytecodes::_lookupswitch: return iter()->get_int_table(2 + 2 * i); default: ShouldNotReachHere(); } } int SharkBlock::switch_dest(int i) { switch(bc()) { case Bytecodes::_tableswitch: return iter()->get_dest_table(i + 3); case Bytecodes::_lookupswitch: return iter()->get_dest_table(2 + 2 * i + 1); default: ShouldNotReachHere(); } } void SharkBlock::do_div_or_rem(bool is_long, bool is_rem) { SharkValue *sb = pop(); SharkValue *sa = pop(); check_divide_by_zero(sb); Value *a, *b, *p, *q; if (is_long) { a = sa->jlong_value(); b = sb->jlong_value(); p = LLVMValue::jlong_constant(0x8000000000000000LL); q = LLVMValue::jlong_constant(-1); } else { a = sa->jint_value(); b = sb->jint_value(); p = LLVMValue::jint_constant(0x80000000); q = LLVMValue::jint_constant(-1); } BasicBlock *ip = builder()->GetBlockInsertionPoint(); BasicBlock *special_case = builder()->CreateBlock(ip, "special_case"); BasicBlock *general_case = builder()->CreateBlock(ip, "general_case"); BasicBlock *done = builder()->CreateBlock(ip, "done"); builder()->CreateCondBr( builder()->CreateAnd( builder()->CreateICmpEQ(a, p), builder()->CreateICmpEQ(b, q)), special_case, general_case); builder()->SetInsertPoint(special_case); Value *special_result; if (is_rem) { if (is_long) special_result = LLVMValue::jlong_constant(0); else special_result = LLVMValue::jint_constant(0); } else { special_result = a; } builder()->CreateBr(done); builder()->SetInsertPoint(general_case); Value *general_result; if (is_rem) general_result = builder()->CreateSRem(a, b); else general_result = builder()->CreateSDiv(a, b); builder()->CreateBr(done); builder()->SetInsertPoint(done); PHINode *result; if (is_long) result = builder()->CreatePHI(SharkType::jlong_type(), 0, "result"); else result = builder()->CreatePHI(SharkType::jint_type(), 0, "result"); result->addIncoming(special_result, special_case); result->addIncoming(general_result, general_case); if (is_long) push(SharkValue::create_jlong(result, false)); else push(SharkValue::create_jint(result, false)); } void SharkBlock::do_field_access(bool is_get, bool is_field) { bool will_link; ciField *field = iter()->get_field(will_link); assert(will_link, "typeflow responsibility"); assert(is_field != field->is_static(), "mismatch"); // Pop the value off the stack where necessary SharkValue *value = NULL; if (!is_get) value = pop(); // Find the object we're accessing, if necessary Value *object = NULL; if (is_field) { SharkValue *value = pop(); check_null(value); object = value->generic_value(); } if (is_get && field->is_constant()) { SharkConstant *constant = SharkConstant::for_field(iter()); if (constant->is_loaded()) value = constant->value(builder()); } if (!is_get || value == NULL) { if (!is_field) { object = builder()->CreateInlineOop(field->holder()->java_mirror()); } BasicType basic_type = field->type()->basic_type(); Type *stack_type = SharkType::to_stackType(basic_type); Type *field_type = SharkType::to_arrayType(basic_type); Value *addr = builder()->CreateAddressOfStructEntry( object, in_ByteSize(field->offset_in_bytes()), PointerType::getUnqual(field_type), "addr"); // Do the access if (is_get) { Value* field_value; if (field->is_volatile()) { #if SHARK_LLVM_VERSION <= 31 field_value = builder()->CreateLoad(addr); #else field_value = builder()->CreateAtomicLoad(addr); #endif } else { field_value = builder()->CreateLoad(addr); } if (field_type != stack_type) { field_value = builder()->CreateIntCast( field_value, stack_type, basic_type != T_CHAR); } value = SharkValue::create_generic(field->type(), field_value, false); } else { Value *field_value = value->generic_value(); if (field_type != stack_type) { field_value = builder()->CreateIntCast( field_value, field_type, basic_type != T_CHAR); } if (field->is_volatile()) { #if SHARK_LLVM_VERSION <= 31 builder()->CreateStore(field_value, addr); #else builder()->CreateAtomicStore(field_value, addr); #endif } else { builder()->CreateStore(field_value, addr); } if (!field->type()->is_primitive_type()) { builder()->CreateUpdateBarrierSet(oopDesc::bs(), addr); } #if SHARK_LLVM_VERSION <= 31 if (field->is_volatile()) { builder()->CreateMemoryBarrier(SharkBuilder::BARRIER_STORELOAD); } #endif } } // Push the value onto the stack where necessary if (is_get) push(value); } void SharkBlock::do_lcmp() { Value *b = pop()->jlong_value(); Value *a = pop()->jlong_value(); BasicBlock *ip = builder()->GetBlockInsertionPoint(); BasicBlock *ne = builder()->CreateBlock(ip, "lcmp_ne"); BasicBlock *lt = builder()->CreateBlock(ip, "lcmp_lt"); BasicBlock *gt = builder()->CreateBlock(ip, "lcmp_gt"); BasicBlock *done = builder()->CreateBlock(ip, "done"); BasicBlock *eq = builder()->GetInsertBlock(); builder()->CreateCondBr(builder()->CreateICmpEQ(a, b), done, ne); builder()->SetInsertPoint(ne); builder()->CreateCondBr(builder()->CreateICmpSLT(a, b), lt, gt); builder()->SetInsertPoint(lt); builder()->CreateBr(done); builder()->SetInsertPoint(gt); builder()->CreateBr(done); builder()->SetInsertPoint(done); PHINode *result = builder()->CreatePHI(SharkType::jint_type(), 0, "result"); result->addIncoming(LLVMValue::jint_constant(-1), lt); result->addIncoming(LLVMValue::jint_constant(0), eq); result->addIncoming(LLVMValue::jint_constant(1), gt); push(SharkValue::create_jint(result, false)); } void SharkBlock::do_fcmp(bool is_double, bool unordered_is_greater) { Value *a, *b; if (is_double) { b = pop()->jdouble_value(); a = pop()->jdouble_value(); } else { b = pop()->jfloat_value(); a = pop()->jfloat_value(); } BasicBlock *ip = builder()->GetBlockInsertionPoint(); BasicBlock *ordered = builder()->CreateBlock(ip, "ordered"); BasicBlock *ge = builder()->CreateBlock(ip, "fcmp_ge"); BasicBlock *lt = builder()->CreateBlock(ip, "fcmp_lt"); BasicBlock *eq = builder()->CreateBlock(ip, "fcmp_eq"); BasicBlock *gt = builder()->CreateBlock(ip, "fcmp_gt"); BasicBlock *done = builder()->CreateBlock(ip, "done"); builder()->CreateCondBr( builder()->CreateFCmpUNO(a, b), unordered_is_greater ? gt : lt, ordered); builder()->SetInsertPoint(ordered); builder()->CreateCondBr(builder()->CreateFCmpULT(a, b), lt, ge); builder()->SetInsertPoint(ge); builder()->CreateCondBr(builder()->CreateFCmpUGT(a, b), gt, eq); builder()->SetInsertPoint(lt); builder()->CreateBr(done); builder()->SetInsertPoint(gt); builder()->CreateBr(done); builder()->SetInsertPoint(eq); builder()->CreateBr(done); builder()->SetInsertPoint(done); PHINode *result = builder()->CreatePHI(SharkType::jint_type(), 0, "result"); result->addIncoming(LLVMValue::jint_constant(-1), lt); result->addIncoming(LLVMValue::jint_constant(0), eq); result->addIncoming(LLVMValue::jint_constant(1), gt); push(SharkValue::create_jint(result, false)); } void SharkBlock::emit_IR() { ShouldNotCallThis(); } SharkState* SharkBlock::entry_state() { ShouldNotCallThis(); } void SharkBlock::do_zero_check(SharkValue* value) { ShouldNotCallThis(); } void SharkBlock::maybe_add_backedge_safepoint() { ShouldNotCallThis(); } bool SharkBlock::has_trap() { return false; } int SharkBlock::trap_request() { ShouldNotCallThis(); } int SharkBlock::trap_bci() { ShouldNotCallThis(); } void SharkBlock::do_trap(int trap_request) { ShouldNotCallThis(); } void SharkBlock::do_arraylength() { ShouldNotCallThis(); } void SharkBlock::do_aload(BasicType basic_type) { ShouldNotCallThis(); } void SharkBlock::do_astore(BasicType basic_type) { ShouldNotCallThis(); } void SharkBlock::do_return(BasicType type) { ShouldNotCallThis(); } void SharkBlock::do_athrow() { ShouldNotCallThis(); } void SharkBlock::do_goto() { ShouldNotCallThis(); } void SharkBlock::do_jsr() { ShouldNotCallThis(); } void SharkBlock::do_ret() { ShouldNotCallThis(); } void SharkBlock::do_if(ICmpInst::Predicate p, SharkValue* b, SharkValue* a) { ShouldNotCallThis(); } void SharkBlock::do_switch() { ShouldNotCallThis(); } void SharkBlock::do_call() { ShouldNotCallThis(); } void SharkBlock::do_instance_check() { ShouldNotCallThis(); } bool SharkBlock::maybe_do_instanceof_if() { ShouldNotCallThis(); } void SharkBlock::do_new() { ShouldNotCallThis(); } void SharkBlock::do_newarray() { ShouldNotCallThis(); } void SharkBlock::do_anewarray() { ShouldNotCallThis(); } void SharkBlock::do_multianewarray() { ShouldNotCallThis(); } void SharkBlock::do_monitorenter() { ShouldNotCallThis(); } void SharkBlock::do_monitorexit() { ShouldNotCallThis(); }