--- old/src/share/vm/c1/c1_IR.hpp Mon Jul 6 17:13:46 2009 +++ new/src/share/vm/c1/c1_IR.hpp Mon Jul 6 17:13:46 2009 @@ -247,7 +247,7 @@ DebugToken* locvals = recorder->create_scope_values(locals()); DebugToken* expvals = recorder->create_scope_values(expressions()); DebugToken* monvals = recorder->create_monitor_values(monitors()); - recorder->describe_scope(pc_offset, scope()->method(), bci(), locvals, expvals, monvals); + recorder->describe_scope(pc_offset, scope()->method(), bci(), false, locvals, expvals, monvals); } }; --- old/src/share/vm/c1/c1_LIRAssembler.cpp Mon Jul 6 17:13:47 2009 +++ new/src/share/vm/c1/c1_LIRAssembler.cpp Mon Jul 6 17:13:46 2009 @@ -379,7 +379,7 @@ ValueStack* s = nth_oldest(vstack, n, s_bci); if (s == NULL) break; IRScope* scope = s->scope(); - debug_info->describe_scope(pc_offset, scope->method(), s_bci); + debug_info->describe_scope(pc_offset, scope->method(), s_bci, false); } debug_info->end_non_safepoint(pc_offset); --- old/src/share/vm/classfile/javaClasses.cpp Mon Jul 6 17:13:47 2009 +++ new/src/share/vm/classfile/javaClasses.cpp Mon Jul 6 17:13:47 2009 @@ -1229,10 +1229,11 @@ // Compiled java method case. if (decode_offset != 0) { + bool restart = false; DebugInfoReadStream stream(nm, decode_offset); decode_offset = stream.read_int(); method = (methodOop)nm->oop_at(stream.read_int()); - bci = stream.read_bci(); + bci = stream.read_bci_and_restart(restart); //dummy restart bit } else { if (fr.is_first_frame()) break; address pc = fr.pc(); --- old/src/share/vm/code/debugInfo.hpp Mon Jul 6 17:13:48 2009 +++ new/src/share/vm/code/debugInfo.hpp Mon Jul 6 17:13:48 2009 @@ -255,7 +255,8 @@ ScopeValue* read_object_value(); ScopeValue* get_cached_object(); // BCI encoding is mostly unsigned, but -1 is a distinguished value - int read_bci() { return read_int() + InvocationEntryBci; } + // Decoding based on encoding: bci = InvocationEntryBci + read_int()/2; restart = read_int()%2 == 1 ? true : false; + int read_bci_and_restart(bool& restart) { int i = read_int(); restart = (i & 1) ? true : false; return (i >> 1) + InvocationEntryBci; } }; // DebugInfoWriteStream specializes CompressedWriteStream for @@ -268,5 +269,6 @@ public: DebugInfoWriteStream(DebugInformationRecorder* recorder, int initial_size); void write_handle(jobject h); - void write_bci(int bci) { write_int(bci - InvocationEntryBci); } + //Encoding bci and restart into one word as (bci - InvocationEntryBci)*2 + restart + void write_bci_and_restart(int bci, bool restart) { write_int(((bci - InvocationEntryBci) << 1) + (restart ? 1 : 0)); } }; --- old/src/share/vm/code/debugInfoRec.cpp Mon Jul 6 17:13:49 2009 +++ new/src/share/vm/code/debugInfoRec.cpp Mon Jul 6 17:13:49 2009 @@ -280,6 +280,7 @@ void DebugInformationRecorder::describe_scope(int pc_offset, ciMethod* method, int bci, + bool re_execute, DebugToken* locals, DebugToken* expressions, DebugToken* monitors) { @@ -297,7 +298,7 @@ // serialize scope jobject method_enc = (method == NULL)? NULL: method->encoding(); stream()->write_int(oop_recorder()->find_index(method_enc)); - stream()->write_bci(bci); + stream()->write_bci_and_restart(bci, re_execute); assert(method == NULL || (method->is_native() && bci == 0) || (!method->is_native() && 0 <= bci && bci < method->code_size()) || --- old/src/share/vm/code/debugInfoRec.hpp Mon Jul 6 17:13:50 2009 +++ new/src/share/vm/code/debugInfoRec.hpp Mon Jul 6 17:13:50 2009 @@ -87,6 +87,7 @@ void describe_scope(int pc_offset, ciMethod* method, int bci, + bool re_execute, DebugToken* locals = NULL, DebugToken* expressions = NULL, DebugToken* monitors = NULL); --- old/src/share/vm/code/scopeDesc.cpp Mon Jul 6 17:13:51 2009 +++ new/src/share/vm/code/scopeDesc.cpp Mon Jul 6 17:13:50 2009 @@ -56,6 +56,7 @@ _sender_decode_offset = DebugInformationRecorder::serialized_null; _method = methodHandle(_code->method()); _bci = InvocationEntryBci; + _restart = false; _locals_decode_offset = DebugInformationRecorder::serialized_null; _expressions_decode_offset = DebugInformationRecorder::serialized_null; _monitors_decode_offset = DebugInformationRecorder::serialized_null; @@ -65,7 +66,7 @@ _sender_decode_offset = stream->read_int(); _method = methodHandle((methodOop) stream->read_oop()); - _bci = stream->read_bci(); + _bci = stream->read_bci_and_restart(_restart); // decode offsets for body and sender _locals_decode_offset = stream->read_int(); _expressions_decode_offset = stream->read_int(); --- old/src/share/vm/code/scopeDesc.hpp Mon Jul 6 17:13:51 2009 +++ new/src/share/vm/code/scopeDesc.hpp Mon Jul 6 17:13:51 2009 @@ -39,7 +39,8 @@ DebugInfoReadStream buffer(code, pc_desc->scope_decode_offset()); int ignore_sender = buffer.read_int(); _method = methodOop(buffer.read_oop()); - _bci = buffer.read_bci(); + bool dummy_restart; + _bci = buffer.read_bci_and_restart(dummy_restart); } methodOop method() { return _method; } @@ -62,6 +63,7 @@ // JVM state methodHandle method() const { return _method; } int bci() const { return _bci; } + bool is_restart() { return _restart; } GrowableArray* locals(); GrowableArray* expressions(); @@ -86,6 +88,7 @@ // JVM state methodHandle _method; int _bci; + bool _restart; // Decoding offsets int _decode_offset; --- old/src/share/vm/opto/bytecodeInfo.cpp Mon Jul 6 17:13:52 2009 +++ new/src/share/vm/opto/bytecodeInfo.cpp Mon Jul 6 17:13:52 2009 @@ -37,6 +37,7 @@ // Keep a private copy of the caller_jvms: _caller_jvms = new (C) JVMState(caller_jvms->method(), caller_tree->caller_jvms()); _caller_jvms->set_bci(caller_jvms->bci()); + assert(!caller_jvms->is_restart(), "there should be no restart bytecode with inlining"); } assert(_caller_jvms->same_calls_as(caller_jvms), "consistent JVMS"); assert((caller_tree == NULL ? 0 : caller_tree->inline_depth() + 1) == inline_depth(), "correct (redundant) depth parameter"); --- old/src/share/vm/opto/callnode.cpp Mon Jul 6 17:13:53 2009 +++ new/src/share/vm/opto/callnode.cpp Mon Jul 6 17:13:53 2009 @@ -223,6 +223,7 @@ JVMState::JVMState(ciMethod* method, JVMState* caller) { assert(method != NULL, "must be valid call site"); _method = method; + _restart = false; debug_only(_bci = -99); // random garbage value debug_only(_map = (SafePointNode*)-1); _caller = caller; @@ -237,6 +238,7 @@ JVMState::JVMState(int stack_size) { _method = NULL; _bci = InvocationEntryBci; + _restart = false; debug_only(_map = (SafePointNode*)-1); _caller = NULL; _depth = 1; @@ -269,6 +271,7 @@ if (p->_method != q->_method) return false; if (p->_method == NULL) return true; // bci is irrelevant if (p->_bci != q->_bci) return false; + if (p->_restart != q->_restart) return false; p = p->caller(); q = q->caller(); if (p == q) return true; @@ -537,6 +540,7 @@ JVMState* JVMState::clone_shallow(Compile* C) const { JVMState* n = has_method() ? new (C) JVMState(_method, _caller) : new (C) JVMState(0); n->set_bci(_bci); + n->set_restart(_restart); n->set_locoff(_locoff); n->set_stkoff(_stkoff); n->set_monoff(_monoff); --- old/src/share/vm/opto/callnode.hpp Mon Jul 6 17:13:54 2009 +++ new/src/share/vm/opto/callnode.hpp Mon Jul 6 17:13:54 2009 @@ -188,6 +188,7 @@ uint _endoff; // Offset to end of input edge mapping uint _sp; // Jave Expression Stack Pointer for this state int _bci; // Byte Code Index of this JVM point + bool _restart; // whether this bytecode need to be re-executed ciMethod* _method; // Method Pointer SafePointNode* _map; // Map node associated with this scope public: @@ -224,6 +225,7 @@ uint sp() const { return _sp; } int bci() const { return _bci; } + bool is_restart() const { return _restart; } bool has_method() const { return _method != NULL; } ciMethod* method() const { assert(has_method(), ""); return _method; } JVMState* caller() const { return _caller; } @@ -267,7 +269,8 @@ } void set_map(SafePointNode *map) { _map = map; } void set_sp(uint sp) { _sp = sp; } - void set_bci(int bci) { _bci = bci; } + void set_bci(int bci) { assert(!_restart, ""); _bci = bci; } + void set_restart(bool restart) {_restart = restart;} // Miscellaneous utility functions JVMState* clone_deep(Compile* C) const; // recursively clones caller chain --- old/src/share/vm/opto/library_call.cpp Mon Jul 6 17:13:55 2009 +++ new/src/share/vm/opto/library_call.cpp Mon Jul 6 17:13:55 2009 @@ -3223,6 +3223,11 @@ } if (!stopped()) { + //set the original stack and the restart bit for deopt to restart + _sp += nargs; + assert(!jvms()->is_restart(), "restart should not have been set (?)"); + jvms()->set_restart(true); + // How many elements will we copy from the original? // The answer is MinI(orig_length - start, length). Node* orig_tail = _gvn.transform( new(C, 3) SubINode(orig_length, start) ); @@ -3229,7 +3234,7 @@ Node* moved = generate_min_max(vmIntrinsics::_min, orig_tail, length); const bool raw_mem_only = true; - Node* newcopy = new_array(klass_node, length, nargs, raw_mem_only); + Node* newcopy = new_array(klass_node, length, 0, raw_mem_only); // Generate a direct call to the right arraycopy function(s). // We know the copy is disjoint but we might not know if the @@ -3241,6 +3246,8 @@ generate_arraycopy(TypeAryPtr::OOPS, T_OBJECT, original, start, newcopy, intcon(0), moved, disjoint_bases, length_never_negative); + _sp -= nargs; + jvms()->set_restart(false); push(newcopy); } @@ -4025,6 +4032,11 @@ int raw_adr_idx = Compile::AliasIdxRaw; const bool raw_mem_only = true; + //set the original stack and the restart bit for deopt to restart + _sp += nargs; + assert(!jvms()->is_restart(), "restart should not have been set (?)"); + jvms()->set_restart(true); + Node* array_ctl = generate_array_guard(obj_klass, (RegionNode*)NULL); if (array_ctl != NULL) { // It's an array. @@ -4129,6 +4141,9 @@ result_mem ->set_req(_slow_path, reset_memory()); } + _sp -= nargs; + jvms()->set_restart(false); + // Return the combined state. set_control( _gvn.transform(result_reg) ); set_i_o( _gvn.transform(result_i_o) ); --- old/src/share/vm/opto/output.cpp Mon Jul 6 17:13:56 2009 +++ new/src/share/vm/opto/output.cpp Mon Jul 6 17:13:56 2009 @@ -905,7 +905,7 @@ // Describe the scope here assert(jvms->bci() >= InvocationEntryBci && jvms->bci() <= 0x10000, "must be a valid or entry BCI"); // Now we can describe the scope. - debug_info()->describe_scope(safepoint_pc_offset,scope_method,jvms->bci(),locvals,expvals,monvals); + debug_info()->describe_scope(safepoint_pc_offset,scope_method,jvms->bci(), jvms->is_restart(), locvals,expvals,monvals); } // End jvms loop // Mark the end of the scope set. @@ -987,7 +987,7 @@ for (int depth = 1; depth <= max_depth; depth++) { JVMState* jvms = youngest_jvms->of_depth(depth); ciMethod* method = jvms->has_method() ? jvms->method() : NULL; - debug_info->describe_scope(pc_offset, method, jvms->bci()); + debug_info->describe_scope(pc_offset, method, jvms->bci(), jvms->is_restart()); } // Mark the end of the scope set. --- old/src/share/vm/runtime/vframe.hpp Mon Jul 6 17:13:57 2009 +++ new/src/share/vm/runtime/vframe.hpp Mon Jul 6 17:13:56 2009 @@ -401,8 +401,9 @@ // Decode first part of scopeDesc DebugInfoReadStream buffer(nm(), decode_offset); _sender_decode_offset = buffer.read_int(); - _method = methodOop(buffer.read_oop()); - _bci = buffer.read_bci(); + _method = methodOop(buffer.read_oop()); + bool dummy_restart = false; //useless information + _bci = buffer.read_bci_and_restart(dummy_restart); assert(_method->is_method(), "checking type of decoded method"); } --- old/src/share/vm/runtime/vframeArray.cpp Mon Jul 6 17:13:57 2009 +++ new/src/share/vm/runtime/vframeArray.cpp Mon Jul 6 17:13:57 2009 @@ -44,6 +44,7 @@ _method = vf->method(); _bci = vf->raw_bci(); + _restart = vf->is_restart(); int index; @@ -155,8 +156,12 @@ bcp = method()->bcp_from(0); // first byte code pc = Interpreter::deopt_entry(vtos, 0); // step = 0 since we don't skip current bytecode use_next_mdp = false; - } else { + } else if (is_restart()) { // Must restart this instruction according to debuginfo bcp = method()->bcp_from(bci()); + pc = Interpreter::deopt_entry(vtos, 0); + use_next_mdp = false; + } else { //some of them may still restart according to Interpreter::continuation_for + bcp = method()->bcp_from(bci()); pc = Interpreter::continuation_for(method(), bcp, callee_parameters, is_top_frame, use_next_mdp); } assert(Bytecodes::is_defined(*bcp), "must be a valid bytecode"); --- old/src/share/vm/runtime/vframeArray.hpp Mon Jul 6 17:13:58 2009 +++ new/src/share/vm/runtime/vframeArray.hpp Mon Jul 6 17:13:58 2009 @@ -41,7 +41,8 @@ private: frame _frame; // the interpreter frame we will unpack into - int _bci; // raw bci for this vframe + int _bci; // raw bci for this vframe + bool _restart; // whether sould we restart methodOop _method; // the method for this vframe MonitorChunk* _monitors; // active monitors for this vframe StackValueCollection* _locals; @@ -54,6 +55,7 @@ int bci(void) const; int raw_bci(void) const { return _bci; } + bool is_restart(void) const { return _restart; } methodOop method(void) const { return _method; } --- old/src/share/vm/runtime/vframe_hp.cpp Mon Jul 6 17:13:59 2009 +++ new/src/share/vm/runtime/vframe_hp.cpp Mon Jul 6 17:13:59 2009 @@ -276,6 +276,15 @@ return scope()->bci(); } +bool compiledVFrame::is_restart() const { + if (scope() == NULL) { + // native nmethods have no scope the method/bci is implied + nmethod* nm = code(); + assert(nm->is_native_method(), "must be native"); + return false; + } + return scope()->is_restart(); +} vframe* compiledVFrame::sender() const { const frame f = fr(); --- old/src/share/vm/runtime/vframe_hp.hpp Mon Jul 6 17:14:00 2009 +++ new/src/share/vm/runtime/vframe_hp.hpp Mon Jul 6 17:14:00 2009 @@ -27,6 +27,7 @@ // JVM state methodOop method() const; int bci() const; + bool is_restart() const; StackValueCollection* locals() const; StackValueCollection* expressions() const; GrowableArray* monitors() const; --- /dev/null Mon Jul 6 17:14:01 2009 +++ new/test/compiler/6833129/Test.java Mon Jul 6 17:14:00 2009 @@ -0,0 +1,62 @@ +/* + * Copyright 2009 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 6833129 + * @summary Object.clone() and Arrays.copyOf ignore coping with -XX:DeoptimizeALot + * @run main/othervm -Xbatch -XX:+DeoptimizeALot Test + */ + +public class Test{ + public static void init(int src[]) { + for (int i =0; i