# HG changeset patch # User cfang # Date 1249446728 25200 # Node ID fc2281ddce3cb9dff917a0a7aeafcb1a739e6245 # Parent 2b9164d13ce9c44d268601e2a7133677de01403a 6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation Summary: Improvement on reexecute implementation to fix the assertion failure Reviewed-by: kvn, never diff -r 2b9164d13ce9 -r fc2281ddce3c src/share/vm/opto/library_call.cpp --- a/src/share/vm/opto/library_call.cpp Tue Aug 04 17:11:17 2009 -0700 +++ b/src/share/vm/opto/library_call.cpp Tue Aug 04 21:32:08 2009 -0700 @@ -3169,65 +3169,62 @@ Node* end = is_copyOfRange? argument(2): argument(1); Node* array_type_mirror = is_copyOfRange? argument(3): argument(2); - _sp += nargs; // set original stack for use by uncommon_trap - array_type_mirror = do_null_check(array_type_mirror, T_OBJECT); - original = do_null_check(original, T_OBJECT); - _sp -= nargs; - - // Check if a null path was taken unconditionally. - if (stopped()) return true; - - Node* orig_length = load_array_length(original); - - Node* klass_node = load_klass_from_mirror(array_type_mirror, false, nargs, - NULL, 0); - _sp += nargs; // set original stack for use by uncommon_trap - klass_node = do_null_check(klass_node, T_OBJECT); - _sp -= nargs; - - RegionNode* bailout = new (C, 1) RegionNode(1); - record_for_igvn(bailout); - - // Despite the generic type of Arrays.copyOf, the mirror might be int, int[], etc. - // Bail out if that is so. - Node* not_objArray = generate_non_objArray_guard(klass_node, bailout); - if (not_objArray != NULL) { - // Improve the klass node's type from the new optimistic assumption: - ciKlass* ak = ciArrayKlass::make(env()->Object_klass()); - const Type* akls = TypeKlassPtr::make(TypePtr::NotNull, ak, 0/*offset*/); - Node* cast = new (C, 2) CastPPNode(klass_node, akls); - cast->init_req(0, control()); - klass_node = _gvn.transform(cast); - } - - // Bail out if either start or end is negative. - generate_negative_guard(start, bailout, &start); - generate_negative_guard(end, bailout, &end); - - Node* length = end; - if (_gvn.type(start) != TypeInt::ZERO) { - length = _gvn.transform( new (C, 3) SubINode(end, start) ); - } - - // Bail out if length is negative. - // ...Not needed, since the new_array will throw the right exception. - //generate_negative_guard(length, bailout, &length); - - if (bailout->req() > 1) { - PreserveJVMState pjvms(this); - set_control( _gvn.transform(bailout) ); - _sp += nargs; // push the arguments back on the stack - uncommon_trap(Deoptimization::Reason_intrinsic, - Deoptimization::Action_maybe_recompile); - } - - if (!stopped()) { - Node *newcopy; - //set the original stack and the reexecute bit for the interpreter to reexecute - //the bytecode that invokes Arrays.copyOf if deoptimization happens - { PreserveReexecuteState preexecs(this); - _sp += nargs; - jvms()->set_should_reexecute(true); + Node* newcopy; + + //set the original stack and the reexecute bit for the interpreter to reexecute + //the bytecode that invokes Arrays.copyOf if deoptimization happens + { PreserveReexecuteState preexecs(this); + _sp += nargs; + jvms()->set_should_reexecute(true); + + array_type_mirror = do_null_check(array_type_mirror, T_OBJECT); + original = do_null_check(original, T_OBJECT); + + // Check if a null path was taken unconditionally. + if (stopped()) return true; + + Node* orig_length = load_array_length(original); + + Node* klass_node = load_klass_from_mirror(array_type_mirror, false, 0, + NULL, 0); + klass_node = do_null_check(klass_node, T_OBJECT); + + RegionNode* bailout = new (C, 1) RegionNode(1); + record_for_igvn(bailout); + + // Despite the generic type of Arrays.copyOf, the mirror might be int, int[], etc. + // Bail out if that is so. + Node* not_objArray = generate_non_objArray_guard(klass_node, bailout); + if (not_objArray != NULL) { + // Improve the klass node's type from the new optimistic assumption: + ciKlass* ak = ciArrayKlass::make(env()->Object_klass()); + const Type* akls = TypeKlassPtr::make(TypePtr::NotNull, ak, 0/*offset*/); + Node* cast = new (C, 2) CastPPNode(klass_node, akls); + cast->init_req(0, control()); + klass_node = _gvn.transform(cast); + } + + // Bail out if either start or end is negative. + generate_negative_guard(start, bailout, &start); + generate_negative_guard(end, bailout, &end); + + Node* length = end; + if (_gvn.type(start) != TypeInt::ZERO) { + length = _gvn.transform( new (C, 3) SubINode(end, start) ); + } + + // Bail out if length is negative. + // ...Not needed, since the new_array will throw the right exception. + //generate_negative_guard(length, bailout, &length); + + if (bailout->req() > 1) { + PreserveJVMState pjvms(this); + set_control( _gvn.transform(bailout) ); + uncommon_trap(Deoptimization::Reason_intrinsic, + Deoptimization::Action_maybe_recompile); + } + + if (!stopped()) { // How many elements will we copy from the original? // The answer is MinI(orig_length - start, length). @@ -3247,8 +3244,10 @@ generate_arraycopy(TypeAryPtr::OOPS, T_OBJECT, original, start, newcopy, intcon(0), moved, disjoint_bases, length_never_negative); - } //original reexecute and sp are set back here - + } + } //original reexecute and sp are set back here + + if(!stopped()) { push(newcopy); } @@ -4000,43 +3999,49 @@ // bool LibraryCallKit::inline_native_clone(bool is_virtual) { int nargs = 1; - Node* obj = null_check_receiver(callee()); - if (stopped()) return true; - Node* obj_klass = load_object_klass(obj); - const TypeKlassPtr* tklass = _gvn.type(obj_klass)->isa_klassptr(); - const TypeOopPtr* toop = ((tklass != NULL) - ? tklass->as_instance_type() - : TypeInstPtr::NOTNULL); - - // Conservatively insert a memory barrier on all memory slices. - // Do not let writes into the original float below the clone. - insert_mem_bar(Op_MemBarCPUOrder); - - // paths into result_reg: - enum { - _slow_path = 1, // out-of-line call to clone method (virtual or not) - _objArray_path, // plain array allocation, plus arrayof_oop_arraycopy - _array_path, // plain array allocation, plus arrayof_long_arraycopy - _instance_path, // plain instance allocation, plus arrayof_long_arraycopy - PATH_LIMIT - }; - RegionNode* result_reg = new(C, PATH_LIMIT) RegionNode(PATH_LIMIT); - PhiNode* result_val = new(C, PATH_LIMIT) PhiNode(result_reg, - TypeInstPtr::NOTNULL); - PhiNode* result_i_o = new(C, PATH_LIMIT) PhiNode(result_reg, Type::ABIO); - PhiNode* result_mem = new(C, PATH_LIMIT) PhiNode(result_reg, Type::MEMORY, - TypePtr::BOTTOM); - record_for_igvn(result_reg); - - const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM; - int raw_adr_idx = Compile::AliasIdxRaw; - const bool raw_mem_only = true; + PhiNode* result_val; //set the original stack and the reexecute bit for the interpreter to reexecute //the bytecode that invokes Object.clone if deoptimization happens { PreserveReexecuteState preexecs(this); + jvms()->set_should_reexecute(true); + + //null_check_receiver will adjust _sp (push and pop) + Node* obj = null_check_receiver(callee()); + if (stopped()) return true; + _sp += nargs; - jvms()->set_should_reexecute(true); + + Node* obj_klass = load_object_klass(obj); + const TypeKlassPtr* tklass = _gvn.type(obj_klass)->isa_klassptr(); + const TypeOopPtr* toop = ((tklass != NULL) + ? tklass->as_instance_type() + : TypeInstPtr::NOTNULL); + + // Conservatively insert a memory barrier on all memory slices. + // Do not let writes into the original float below the clone. + insert_mem_bar(Op_MemBarCPUOrder); + + // paths into result_reg: + enum { + _slow_path = 1, // out-of-line call to clone method (virtual or not) + _objArray_path, // plain array allocation, plus arrayof_oop_arraycopy + _array_path, // plain array allocation, plus arrayof_long_arraycopy + _instance_path, // plain instance allocation, plus arrayof_long_arraycopy + PATH_LIMIT + }; + RegionNode* result_reg = new(C, PATH_LIMIT) RegionNode(PATH_LIMIT); + result_val = new(C, PATH_LIMIT) PhiNode(result_reg, + TypeInstPtr::NOTNULL); + PhiNode* result_i_o = new(C, PATH_LIMIT) PhiNode(result_reg, Type::ABIO); + PhiNode* result_mem = new(C, PATH_LIMIT) PhiNode(result_reg, Type::MEMORY, + TypePtr::BOTTOM); + record_for_igvn(result_reg); + + const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM; + int raw_adr_idx = Compile::AliasIdxRaw; + const bool raw_mem_only = true; + Node* array_ctl = generate_array_guard(obj_klass, (RegionNode*)NULL); if (array_ctl != NULL) { @@ -4141,13 +4146,13 @@ result_i_o ->set_req(_slow_path, i_o()); result_mem ->set_req(_slow_path, reset_memory()); } + + // Return the combined state. + set_control( _gvn.transform(result_reg) ); + set_i_o( _gvn.transform(result_i_o) ); + set_all_memory( _gvn.transform(result_mem) ); } //original reexecute and sp are set back here - // Return the combined state. - set_control( _gvn.transform(result_reg) ); - set_i_o( _gvn.transform(result_i_o) ); - set_all_memory( _gvn.transform(result_mem) ); - push(_gvn.transform(result_val)); return true;