# HG changeset patch # User kvn # Date 1266017256 28800 # Node ID 7b4415a18c8afb70569c8188db8a85f6154a8948 # Parent 95d21201c29ac4943b77287cd335294221304e97# Parent c09ee209b65c742568e86da87f2335701423a445 Merge diff -r 95d21201c29a -r 7b4415a18c8a src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp --- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -2730,9 +2730,6 @@ } Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()) - mdo_offset_bias); - __ lduw(counter_addr, tmp1); - __ add(tmp1, DataLayout::counter_increment, tmp1); - __ stw(tmp1, counter_addr); Bytecodes::Code bc = method->java_code_at_bci(bci); // Perform additional virtual call profiling for invokevirtual and // invokeinterface bytecodes @@ -2822,15 +2819,23 @@ __ set(DataLayout::counter_increment, tmp1); __ st_ptr(tmp1, mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)) - mdo_offset_bias); - if (i < (VirtualCallData::row_limit() - 1)) { - __ br(Assembler::always, false, Assembler::pt, update_done); - __ delayed()->nop(); - } + __ br(Assembler::always, false, Assembler::pt, update_done); + __ delayed()->nop(); __ bind(next_test); } + // Receiver did not match any saved receiver and there is no empty row for it. + // Increment total counter to indicate polymorphic case. + __ lduw(counter_addr, tmp1); + __ add(tmp1, DataLayout::counter_increment, tmp1); + __ stw(tmp1, counter_addr); __ bind(update_done); } + } else { + // Static call + __ lduw(counter_addr, tmp1); + __ add(tmp1, DataLayout::counter_increment, tmp1); + __ stw(tmp1, counter_addr); } } diff -r 95d21201c29a -r 7b4415a18c8a src/cpu/sparc/vm/interp_masm_sparc.cpp --- a/src/cpu/sparc/vm/interp_masm_sparc.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/cpu/sparc/vm/interp_masm_sparc.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. 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 @@ -1733,7 +1733,7 @@ brx(Assembler::zero, false, Assembler::pn, found_null); delayed()->nop(); // Receiver did not match any saved receiver and there is no empty row for it. - // Increment total counter to indicate polimorphic case. + // Increment total counter to indicate polymorphic case. increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch); ba(false, done); delayed()->nop(); diff -r 95d21201c29a -r 7b4415a18c8a src/cpu/sparc/vm/sharedRuntime_sparc.cpp --- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -851,10 +851,10 @@ __ set(reg2offset(r_1) + extraspace + bias, ld_off); #else int ld_off = reg2offset(r_1) + extraspace + bias; +#endif // _LP64 #ifdef ASSERT G1_forced = true; #endif // ASSERT -#endif // _LP64 r_1 = G1_scratch->as_VMReg();// as part of the load/store shuffle if (!r_2->is_valid()) __ ld (base, ld_off, G1_scratch); else __ ldx(base, ld_off, G1_scratch); @@ -865,9 +865,11 @@ if (sig_bt[i] == T_OBJECT || sig_bt[i] == T_ARRAY) { store_c2i_object(r, base, st_off); } else if (sig_bt[i] == T_LONG || sig_bt[i] == T_DOUBLE) { +#ifndef _LP64 if (TieredCompilation) { assert(G1_forced || sig_bt[i] != T_LONG, "should not use register args for longs"); } +#endif // _LP64 store_c2i_long(r, base, st_off, r_2->is_stack()); } else { store_c2i_int(r, base, st_off); diff -r 95d21201c29a -r 7b4415a18c8a src/cpu/x86/vm/c1_LIRAssembler_x86.cpp --- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -3279,7 +3279,7 @@ __ bind(next_test); } // Receiver did not match any saved receiver and there is no empty row for it. - // Increment total counter to indicate polimorphic case. + // Increment total counter to indicate polymorphic case. __ addl(counter_addr, DataLayout::counter_increment); __ bind(update_done); diff -r 95d21201c29a -r 7b4415a18c8a src/cpu/x86/vm/frame_x86.inline.hpp --- a/src/cpu/x86/vm/frame_x86.inline.hpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/cpu/x86/vm/frame_x86.inline.hpp Fri Feb 12 15:27:36 2010 -0800 @@ -233,7 +233,8 @@ } else { // sp() may have been extended or shrunk by an adapter. At least // check that we don't fall behind the legal region. - assert(last_sp < (intptr_t*) interpreter_frame_monitor_begin(), "bad tos"); + // For top deoptimized frame last_sp == interpreter_frame_monitor_end. + assert(last_sp <= (intptr_t*) interpreter_frame_monitor_end(), "bad tos"); return last_sp; } } diff -r 95d21201c29a -r 7b4415a18c8a src/cpu/x86/vm/interp_masm_x86_32.cpp --- a/src/cpu/x86/vm/interp_masm_x86_32.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/cpu/x86/vm/interp_masm_x86_32.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. 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 @@ -1308,7 +1308,7 @@ if (is_virtual_call) { jccb(Assembler::zero, found_null); // Receiver did not match any saved receiver and there is no empty row for it. - // Increment total counter to indicate polimorphic case. + // Increment total counter to indicate polymorphic case. increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); jmp(done); bind(found_null); diff -r 95d21201c29a -r 7b4415a18c8a src/cpu/x86/vm/interp_masm_x86_64.cpp --- a/src/cpu/x86/vm/interp_masm_x86_64.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2010 Sun Microsystems, Inc. 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 @@ -1341,7 +1341,7 @@ if (is_virtual_call) { jccb(Assembler::zero, found_null); // Receiver did not match any saved receiver and there is no empty row for it. - // Increment total counter to indicate polimorphic case. + // Increment total counter to indicate polymorphic case. increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); jmp(done); bind(found_null); diff -r 95d21201c29a -r 7b4415a18c8a src/cpu/zero/vm/cppInterpreter_zero.cpp --- a/src/cpu/zero/vm/cppInterpreter_zero.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/cpu/zero/vm/cppInterpreter_zero.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -1,6 +1,6 @@ /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. - * Copyright 2007, 2008, 2009 Red Hat, Inc. + * Copyright 2007, 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 @@ -145,7 +145,7 @@ } else if (istate->msg() == BytecodeInterpreter::return_from_method) { // Copy the result into the caller's frame - result_slots = type2size[method->result_type()]; + result_slots = type2size[result_type_of(method)]; assert(result_slots >= 0 && result_slots <= 2, "what?"); result = istate->stack() + result_slots; break; @@ -394,9 +394,10 @@ // Push our result if (!HAS_PENDING_EXCEPTION) { - stack->set_sp(stack->sp() - type2size[method->result_type()]); + BasicType type = result_type_of(method); + stack->set_sp(stack->sp() - type2size[type]); - switch (method->result_type()) { + switch (type) { case T_VOID: break; @@ -707,6 +708,26 @@ return i; } +BasicType CppInterpreter::result_type_of(methodOop method) { + BasicType t; + switch (method->result_index()) { + case 0 : t = T_BOOLEAN; break; + case 1 : t = T_CHAR; break; + case 2 : t = T_BYTE; break; + case 3 : t = T_SHORT; break; + case 4 : t = T_INT; break; + case 5 : t = T_LONG; break; + case 6 : t = T_VOID; break; + case 7 : t = T_FLOAT; break; + case 8 : t = T_DOUBLE; break; + case 9 : t = T_OBJECT; break; + default: ShouldNotReachHere(); + } + assert(AbstractInterpreter::BasicType_as_index(t) == method->result_index(), + "out of step with AbstractInterpreter::BasicType_as_index"); + return t; +} + address InterpreterGenerator::generate_empty_entry() { if (!UseFastEmptyMethods) return NULL; diff -r 95d21201c29a -r 7b4415a18c8a src/cpu/zero/vm/cppInterpreter_zero.hpp --- a/src/cpu/zero/vm/cppInterpreter_zero.hpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/cpu/zero/vm/cppInterpreter_zero.hpp Fri Feb 12 15:27:36 2010 -0800 @@ -1,6 +1,6 @@ /* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. - * Copyright 2007, 2008 Red Hat, Inc. + * Copyright 2007, 2008, 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 @@ -41,3 +41,7 @@ private: // Stack overflow checks static bool stack_overflow_imminent(JavaThread *thread); + + private: + // Fast result type determination + static BasicType result_type_of(methodOop method); diff -r 95d21201c29a -r 7b4415a18c8a src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp --- a/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. 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 @@ -730,11 +730,12 @@ st->print(", RSI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSI]); st->print(", RDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDI]); st->cr(); - st->print(", R8=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]); + st->print( "R8=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]); st->print(", R9=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R9]); st->print(", R10=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R10]); st->print(", R11=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R11]); - st->print(", R12=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R12]); + st->cr(); + st->print( "R12=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R12]); st->print(", R13=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R13]); st->print(", R14=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R14]); st->print(", R15=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R15]); diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/c1/c1_IR.hpp --- a/src/share/vm/c1/c1_IR.hpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/c1/c1_IR.hpp Fri Feb 12 15:27:36 2010 -0800 @@ -253,7 +253,8 @@ // reexecute allowed only for the topmost frame bool reexecute = topmost ? should_reexecute() : false; bool is_method_handle_invoke = false; - recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, locvals, expvals, monvals); + bool return_oop = false; // This flag will be ignored since it used only for C2 with escape analysis. + recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, return_oop, locvals, expvals, monvals); } }; diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/ci/ciMethod.cpp --- a/src/share/vm/ci/ciMethod.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/ci/ciMethod.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -445,7 +445,8 @@ (morphism == ciCallProfile::MorphismLimit && count == 0)) { #ifdef ASSERT if (count > 0) { - tty->print_cr("bci: %d", bci); + this->print_short_name(tty); + tty->print_cr(" @ bci:%d", bci); this->print_codes(); assert(false, "this call site should not be polymorphic"); } diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/code/debugInfoRec.cpp --- a/src/share/vm/code/debugInfoRec.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/code/debugInfoRec.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -282,6 +282,7 @@ int bci, bool reexecute, bool is_method_handle_invoke, + bool return_oop, DebugToken* locals, DebugToken* expressions, DebugToken* monitors) { @@ -296,6 +297,7 @@ // Record flags into pcDesc. last_pd->set_should_reexecute(reexecute); last_pd->set_is_method_handle_invoke(is_method_handle_invoke); + last_pd->set_return_oop(return_oop); // serialize sender stream offest stream()->write_int(sender_stream_offset); diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/code/debugInfoRec.hpp --- a/src/share/vm/code/debugInfoRec.hpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/code/debugInfoRec.hpp Fri Feb 12 15:27:36 2010 -0800 @@ -89,6 +89,7 @@ int bci, bool reexecute, bool is_method_handle_invoke = false, + bool return_oop = false, DebugToken* locals = NULL, DebugToken* expressions = NULL, DebugToken* monitors = NULL); diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/code/nmethod.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -988,7 +988,8 @@ PcDesc* pd = pc_desc_at(pc); guarantee(pd != NULL, "scope must be present"); return new ScopeDesc(this, pd->scope_decode_offset(), - pd->obj_decode_offset(), pd->should_reexecute()); + pd->obj_decode_offset(), pd->should_reexecute(), + pd->return_oop()); } @@ -2010,7 +2011,10 @@ print_pcs(); } #endif - guarantee(cont_offset != 0, "unhandled implicit exception in compiled code"); + if (cont_offset == 0) { + // Let the normal error handling report the exception + return NULL; + } return instructions_begin() + cont_offset; } @@ -2156,7 +2160,8 @@ PcDesc* pd = pc_desc_at(ic->end_of_call()); assert(pd != NULL, "PcDesc must exist"); for (ScopeDesc* sd = new ScopeDesc(this, pd->scope_decode_offset(), - pd->obj_decode_offset(), pd->should_reexecute()); + pd->obj_decode_offset(), pd->should_reexecute(), + pd->return_oop()); !sd->is_top(); sd = sd->sender()) { sd->verify(); } @@ -2421,7 +2426,8 @@ PcDesc* p = pc_desc_near(begin+1); if (p != NULL && p->real_pc(this) <= end) { return new ScopeDesc(this, p->scope_decode_offset(), - p->obj_decode_offset(), p->should_reexecute()); + p->obj_decode_offset(), p->should_reexecute(), + p->return_oop()); } return NULL; } diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/code/pcDesc.cpp --- a/src/share/vm/code/pcDesc.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/code/pcDesc.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. 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 @@ -52,7 +52,8 @@ tty->print(" "); sd->method()->print_short_name(tty); tty->print(" @%d", sd->bci()); - tty->print(" reexecute=%s", sd->should_reexecute()?"true":"false"); + if (sd->should_reexecute()) + tty->print(" reexecute=true"); tty->cr(); } #endif diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/code/pcDesc.hpp --- a/src/share/vm/code/pcDesc.hpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/code/pcDesc.hpp Fri Feb 12 15:27:36 2010 -0800 @@ -39,6 +39,7 @@ struct { unsigned int reexecute: 1; unsigned int is_method_handle_invoke: 1; + unsigned int return_oop: 1; } bits; bool operator ==(const PcDescFlags& other) { return word == other.word; } } _flags; @@ -76,6 +77,9 @@ bool is_method_handle_invoke() const { return _flags.bits.is_method_handle_invoke; } void set_is_method_handle_invoke(bool z) { _flags.bits.is_method_handle_invoke = z; } + bool return_oop() const { return _flags.bits.return_oop; } + void set_return_oop(bool z) { _flags.bits.return_oop = z; } + // Returns the real pc address real_pc(const nmethod* code) const; diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/code/scopeDesc.cpp --- a/src/share/vm/code/scopeDesc.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/code/scopeDesc.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -26,19 +26,21 @@ # include "incls/_scopeDesc.cpp.incl" -ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute) { +ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool return_oop) { _code = code; _decode_offset = decode_offset; _objects = decode_object_values(obj_decode_offset); _reexecute = reexecute; + _return_oop = return_oop; decode_body(); } -ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute) { +ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool return_oop) { _code = code; _decode_offset = decode_offset; _objects = decode_object_values(DebugInformationRecorder::serialized_null); _reexecute = reexecute; + _return_oop = return_oop; decode_body(); } @@ -48,6 +50,7 @@ _decode_offset = parent->_sender_decode_offset; _objects = parent->_objects; _reexecute = false; //reexecute only applies to the first scope + _return_oop = false; decode_body(); } diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/code/scopeDesc.hpp --- a/src/share/vm/code/scopeDesc.hpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/code/scopeDesc.hpp Fri Feb 12 15:27:36 2010 -0800 @@ -52,17 +52,18 @@ class ScopeDesc : public ResourceObj { public: // Constructor - ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute); + ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool return_oop); // Calls above, giving default value of "serialized_null" to the // "obj_decode_offset" argument. (We don't use a default argument to // avoid a .hpp-.hpp dependency.) - ScopeDesc(const nmethod* code, int decode_offset, bool reexecute); + ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool return_oop); // JVM state methodHandle method() const { return _method; } int bci() const { return _bci; } bool should_reexecute() const { return _reexecute; } + bool return_oop() const { return _return_oop; } GrowableArray* locals(); GrowableArray* expressions(); @@ -88,6 +89,7 @@ methodHandle _method; int _bci; bool _reexecute; + bool _return_oop; // Decoding offsets int _decode_offset; diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/includeDB_core --- a/src/share/vm/includeDB_core Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/includeDB_core Fri Feb 12 15:27:36 2010 -0800 @@ -1484,6 +1484,7 @@ deoptimization.cpp vframe.hpp deoptimization.cpp vframeArray.hpp deoptimization.cpp vframe_hp.hpp +deoptimization.cpp vmreg_.inline.hpp deoptimization.cpp xmlstream.hpp deoptimization.hpp allocation.hpp diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/oops/methodDataOop.hpp --- a/src/share/vm/oops/methodDataOop.hpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/oops/methodDataOop.hpp Fri Feb 12 15:27:36 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 Sun Microsystems, Inc. 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 @@ -545,6 +545,10 @@ return cell_offset(counter_cell_count); } + void set_count(uint count) { + set_uint_at(count_off, count); + } + #ifndef PRODUCT void print_data_on(outputStream* st); #endif @@ -692,6 +696,23 @@ void clear_row(uint row) { assert(row < row_limit(), "oob"); + // Clear total count - indicator of polymorphic call site. + // The site may look like as monomorphic after that but + // it allow to have more accurate profiling information because + // there was execution phase change since klasses were unloaded. + // If the site is still polymorphic then MDO will be updated + // to reflect it. But it could be the case that the site becomes + // only bimorphic. Then keeping total count not 0 will be wrong. + // Even if we use monomorphic (when it is not) for compilation + // we will only have trap, deoptimization and recompile again + // with updated MDO after executing method in Interpreter. + // An additional receiver will be recorded in the cleaned row + // during next call execution. + // + // Note: our profiling logic works with empty rows in any slot. + // We do sorting a profiling info (ciCallProfile) for compilation. + // + set_count(0); set_receiver(row, NULL); set_receiver_count(row, 0); } diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/opto/doCall.cpp --- a/src/share/vm/opto/doCall.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/opto/doCall.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2010 Sun Microsystems, Inc. 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 @@ -70,7 +70,7 @@ CompileLog* log = this->log(); if (log != NULL) { int rid = (receiver_count >= 0)? log->identify(profile.receiver(0)): -1; - int r2id = (profile.morphism() == 2)? log->identify(profile.receiver(1)):-1; + int r2id = (rid != -1 && profile.has_receiver(1))? log->identify(profile.receiver(1)):-1; log->begin_elem("call method='%d' count='%d' prof_factor='%g'", log->identify(call_method), site_count, prof_factor); if (call_is_virtual) log->print(" virtual='1'"); diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/opto/graphKit.cpp --- a/src/share/vm/opto/graphKit.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/opto/graphKit.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -780,12 +780,20 @@ // Helper function for enforcing certain bytecodes to reexecute if // deoptimization happens -static bool should_reexecute_implied_by_bytecode(JVMState *jvms) { +static bool should_reexecute_implied_by_bytecode(JVMState *jvms, bool is_anewarray) { ciMethod* cur_method = jvms->method(); int cur_bci = jvms->bci(); if (cur_method != NULL && cur_bci != InvocationEntryBci) { Bytecodes::Code code = cur_method->java_code_at_bci(cur_bci); - return Interpreter::bytecode_should_reexecute(code); + return Interpreter::bytecode_should_reexecute(code) || + is_anewarray && code == Bytecodes::_multianewarray; + // Reexecute _multianewarray bytecode which was replaced with + // sequence of [a]newarray. See Parse::do_multianewarray(). + // + // Note: interpreter should not have it set since this optimization + // is limited by dimensions and guarded by flag so in some cases + // multianewarray() runtime calls will be generated and + // the bytecode should not be reexecutes (stack will not be reset). } else return false; } @@ -836,7 +844,7 @@ // For a known set of bytecodes, the interpreter should reexecute them if // deoptimization happens. We set the reexecute state for them here if (out_jvms->is_reexecute_undefined() && //don't change if already specified - should_reexecute_implied_by_bytecode(out_jvms)) { + should_reexecute_implied_by_bytecode(out_jvms, call->is_AllocateArray())) { out_jvms->set_should_reexecute(true); //NOTE: youngest_jvms not changed } diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/opto/loopopts.cpp --- a/src/share/vm/opto/loopopts.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/opto/loopopts.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. 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 @@ -47,7 +47,7 @@ int offset = t_oop->offset(); phi = new (C,region->req()) PhiNode(region, type, NULL, iid, index, offset); } else { - phi = new (C,region->req()) PhiNode(region, type); + phi = PhiNode::make_blank(region, n); } uint old_unique = C->unique(); for( uint i = 1; i < region->req(); i++ ) { diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/opto/output.cpp --- a/src/share/vm/opto/output.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/opto/output.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -795,6 +795,7 @@ int safepoint_pc_offset = current_offset; bool is_method_handle_invoke = false; + bool return_oop = false; // Add the safepoint in the DebugInfoRecorder if( !mach->is_MachCall() ) { @@ -807,6 +808,11 @@ if (mcall->is_MachCallJava()) is_method_handle_invoke = mcall->as_MachCallJava()->_method_handle_invoke; + // Check if a call returns an object. + if (mcall->return_value_is_used() && + mcall->tf()->range()->field_at(TypeFunc::Parms)->isa_ptr()) { + return_oop = true; + } safepoint_pc_offset += mcall->ret_addr_offset(); debug_info()->add_safepoint(safepoint_pc_offset, mcall->_oop_map); } @@ -919,7 +925,7 @@ assert(jvms->bci() >= InvocationEntryBci && jvms->bci() <= 0x10000, "must be a valid or entry BCI"); assert(!jvms->should_reexecute() || depth == max_depth, "reexecute allowed only for the youngest"); // Now we can describe the scope. - debug_info()->describe_scope(safepoint_pc_offset, scope_method, jvms->bci(), jvms->should_reexecute(), is_method_handle_invoke, locvals, expvals, monvals); + debug_info()->describe_scope(safepoint_pc_offset, scope_method, jvms->bci(), jvms->should_reexecute(), is_method_handle_invoke, return_oop, locvals, expvals, monvals); } // End jvms loop // Mark the end of the scope set. diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/opto/parse3.cpp --- a/src/share/vm/opto/parse3.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/opto/parse3.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2010 Sun Microsystems, Inc. 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 @@ -439,8 +439,18 @@ // Can use multianewarray instead of [a]newarray if only one dimension, // or if all non-final dimensions are small constants. - if (expand_count == 1 || (1 <= expand_count && expand_count <= expand_limit)) { - Node* obj = expand_multianewarray(array_klass, &length[0], ndimensions, ndimensions); + if (ndimensions == 1 || (1 <= expand_count && expand_count <= expand_limit)) { + Node* obj = NULL; + // Set the original stack and the reexecute bit for the interpreter + // to reexecute the multianewarray bytecode if deoptimization happens. + // Do it unconditionally even for one dimension multianewarray. + // Note: the reexecute bit will be set in GraphKit::add_safepoint_edges() + // when AllocateArray node for newarray is created. + { PreserveReexecuteState preexecs(this); + _sp += ndimensions; + // Pass 0 as nargs since uncommon trap code does not need to restore stack. + obj = expand_multianewarray(array_klass, &length[0], ndimensions, 0); + } //original reexecute and sp are set back here push(obj); return; } diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/opto/runtime.cpp --- a/src/share/vm/opto/runtime.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/opto/runtime.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -708,7 +708,7 @@ *(mdp + count_off) = DataLayout::counter_increment; } else { // Receiver did not match any saved receiver and there is no empty row for it. - // Increment total counter to indicate polimorphic case. + // Increment total counter to indicate polymorphic case. intptr_t* count_p = (intptr_t*)(((byte*)(data)) + in_bytes(CounterData::count_offset())); *count_p += DataLayout::counter_increment; } diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/opto/stringopts.cpp --- a/src/share/vm/opto/stringopts.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/opto/stringopts.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2009-2010 Sun Microsystems, Inc. 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 @@ -1073,7 +1073,7 @@ kit.set_control(head); kit.set_memory(mem, char_adr_idx); - Node* q = __ DivI(kit.null(), i_phi, __ intcon(10)); + Node* q = __ DivI(NULL, i_phi, __ intcon(10)); Node* r = __ SubI(i_phi, __ AddI(__ LShiftI(q, __ intcon(3)), __ LShiftI(q, __ intcon(1)))); Node* m1 = __ SubI(charPos, __ intcon(1)); @@ -1270,14 +1270,15 @@ // length = length + (s.count - s.offset); RegionNode *r = new (C, 3) RegionNode(3); kit.gvn().set_type(r, Type::CONTROL); - Node *phi = new (C, 3) PhiNode(r, type->join(TypeInstPtr::NOTNULL)); + Node *phi = new (C, 3) PhiNode(r, type); kit.gvn().set_type(phi, phi->bottom_type()); Node* p = __ Bool(__ CmpP(arg, kit.null()), BoolTest::ne); IfNode* iff = kit.create_and_map_if(kit.control(), p, PROB_MIN, COUNT_UNKNOWN); Node* notnull = __ IfTrue(iff); Node* isnull = __ IfFalse(iff); + kit.set_control(notnull); // set control for the cast_not_null r->init_req(1, notnull); - phi->init_req(1, arg); + phi->init_req(1, kit.cast_not_null(arg, false)); r->init_req(2, isnull); phi->init_req(2, null_string); kit.set_control(r); diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/prims/jvmtiCodeBlobEvents.cpp --- a/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -402,7 +402,7 @@ address scopes_data = nm->scopes_data_begin(); for( pcd = nm->scopes_pcs_begin(); pcd < nm->scopes_pcs_end(); ++pcd ) { - ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute()); + ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute(), pcd->return_oop()); ScopeDesc *sd = &sc0; while( !sd->is_top() ) { sd = sd->sender(); } int bci = sd->bci(); diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/runtime/arguments.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. 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 @@ -2524,6 +2524,9 @@ SOLARIS_ONLY(FLAG_SET_DEFAULT(UseISM, false)); } + // Tiered compilation is undefined with C1. + TieredCompilation = false; + #else if (!FLAG_IS_DEFAULT(OptoLoopAlignment) && FLAG_IS_DEFAULT(MaxLoopPad)) { FLAG_SET_DEFAULT(MaxLoopPad, OptoLoopAlignment-1); diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/runtime/deoptimization.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -145,6 +145,27 @@ if (EliminateAllocations) { assert (chunk->at(0)->scope() != NULL,"expect only compiled java frames"); GrowableArray* objects = chunk->at(0)->scope()->objects(); + + // The flag return_oop() indicates call sites which return oop + // in compiled code. Such sites include java method calls, + // runtime calls (for example, used to allocate new objects/arrays + // on slow code path) and any other calls generated in compiled code. + // It is not guaranteed that we can get such information here only + // by analyzing bytecode in deoptimized frames. This is why this flag + // is set during method compilation (see Compile::Process_OopMap_Node()). + bool save_oop_result = chunk->at(0)->scope()->return_oop(); + Handle return_value; + if (save_oop_result) { + // Reallocation may trigger GC. If deoptimization happened on return from + // call which returns oop we need to save it since it is not in oopmap. + oop result = deoptee.saved_oop_result(&map); + assert(result == NULL || result->is_oop(), "must be oop"); + return_value = Handle(thread, result); + assert(Universe::heap()->is_in_or_null(result), "must be heap pointer"); + if (TraceDeoptimization) { + tty->print_cr("SAVED OOP RESULT " INTPTR_FORMAT " in thread " INTPTR_FORMAT, result, thread); + } + } bool reallocated = false; if (objects != NULL) { JRT_BLOCK @@ -158,8 +179,12 @@ ttyLocker ttyl; tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, thread); print_objects(objects); + } +#endif } -#endif + if (save_oop_result) { + // Restore result. + deoptee.set_saved_oop_result(&map, return_value()); } } if (EliminateLocks) { @@ -913,21 +938,6 @@ if (TraceDeoptimization) { ttyLocker ttyl; tty->print_cr(" Created vframeArray " INTPTR_FORMAT, array); - if (Verbose) { - int count = 0; - // this used to leak deoptimizedVFrame like it was going out of style!!! - for (int index = 0; index < array->frames(); index++ ) { - vframeArrayElement* e = array->element(index); - e->print(tty); - - /* - No printing yet. - array->vframe_at(index)->print_activation(count++); - // better as... - array->print_activation_for(index, count++); - */ - } - } } #endif // PRODUCT diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/runtime/frame.cpp --- a/src/share/vm/runtime/frame.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/runtime/frame.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -606,12 +606,12 @@ for (BasicObjectLock* current = interpreter_frame_monitor_end(); current < interpreter_frame_monitor_begin(); current = next_monitor_in_interpreter_frame(current)) { - st->print_cr(" [ - obj "); + st->print(" - obj ["); current->obj()->print_value_on(st); - st->cr(); - st->print_cr(" - lock "); + st->print_cr("]"); + st->print(" - lock ["); current->lock()->print_on(st); - st->cr(); + st->print_cr("]"); } // monitor st->print_cr(" - monitor[" INTPTR_FORMAT "]", interpreter_frame_monitor_begin()); diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/runtime/sharedRuntime.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -607,7 +607,9 @@ _implicit_null_throws++; #endif target_pc = nm->continuation_for_implicit_exception(pc); - guarantee(target_pc != 0, "must have a continuation point"); + // If there's an unexpected fault, target_pc might be NULL, + // in which case we want to fall through into the normal + // error handling code. } break; // fall through @@ -621,14 +623,15 @@ _implicit_div0_throws++; #endif target_pc = nm->continuation_for_implicit_exception(pc); - guarantee(target_pc != 0, "must have a continuation point"); + // If there's an unexpected fault, target_pc might be NULL, + // in which case we want to fall through into the normal + // error handling code. break; // fall through } default: ShouldNotReachHere(); } - guarantee(target_pc != NULL, "must have computed destination PC for implicit exception"); assert(exception_kind == IMPLICIT_NULL || exception_kind == IMPLICIT_DIVIDE_BY_ZERO, "wrong implicit exception kind"); // for AbortVMOnException flag diff -r 95d21201c29a -r 7b4415a18c8a src/share/vm/runtime/vframeArray.cpp --- a/src/share/vm/runtime/vframeArray.cpp Thu Feb 11 10:48:10 2010 -0800 +++ b/src/share/vm/runtime/vframeArray.cpp Fri Feb 12 15:27:36 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. 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 @@ -186,7 +186,7 @@ int popframe_preserved_args_size_in_bytes = 0; int popframe_preserved_args_size_in_words = 0; if (is_top_frame) { - JvmtiThreadState *state = thread->jvmti_thread_state(); + JvmtiThreadState *state = thread->jvmti_thread_state(); if (JvmtiExport::can_pop_frame() && (thread->has_pending_popframe() || thread->popframe_forcing_deopt_reexecution())) { if (thread->has_pending_popframe()) { @@ -381,7 +381,6 @@ RegisterMap map(thread); vframe* f = vframe::new_vframe(iframe(), &map, thread); f->print(); - iframe()->interpreter_frame_print_on(tty); tty->print_cr("locals size %d", locals()->size()); tty->print_cr("expression size %d", expressions()->size()); @@ -582,7 +581,7 @@ } void vframeArrayElement::print(outputStream* st) { - st->print_cr(" - interpreter_frame -> sp: ", INTPTR_FORMAT, iframe()->sp()); + st->print_cr(" - interpreter_frame -> sp: " INTPTR_FORMAT, iframe()->sp()); } void vframeArray::print_value_on(outputStream* st) const { diff -r 95d21201c29a -r 7b4415a18c8a test/compiler/6910605/Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6910605/Test.java Fri Feb 12 15:27:36 2010 -0800 @@ -0,0 +1,78 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +/** + * @test + * @bug 6910605 + * @summary C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used + * + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+DeoptimizeALot -Xbatch Test + * + * original test: nsk/coverage/runtime/runtime007 + */ + +import java.io.*; + +public class Test { + public static int buf=0; + + public static void main( String argv[] ) { + System.exit(run(argv, System.out)+95); + } + + public static int run(String argv[],PrintStream out) { + int ret=0, retx=0, bad=0; + + for( int i=0; (i < 100000) && (bad < 10) ; i++ ) { + retx = OptoRuntime_f2i_Type(out); + ret += retx; + if( retx !=0 ) { + out.println("i="+i); + bad++; + } + } + return ret==0 ? 0 : 2 ; + } + + public static int OptoRuntime_f2i_Type(PrintStream out) { + int c1=2, c2=3, c3=4, c4=5, c5=6; + int j=0, k=0; + try { + int[][] iii=(int[][])(new int[c1][c2]); + + for( j=0; j