< prev index next >

src/hotspot/share/ci/ciTypeFlow.cpp

Print this page

        

*** 29,38 **** --- 29,39 ---- #include "ci/ciMethodData.hpp" #include "ci/ciObjArrayKlass.hpp" #include "ci/ciStreams.hpp" #include "ci/ciTypeArrayKlass.hpp" #include "ci/ciTypeFlow.hpp" + #include "ci/ciValueKlass.hpp" #include "compiler/compileLog.hpp" #include "interpreter/bytecode.hpp" #include "interpreter/bytecodes.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp"
*** 269,278 **** --- 270,280 ---- // interface, or array class. The meet of two types of the same // kind is their least common ancestor. The meet of two types of // different kinds is always java.lang.Object. ciType* ciTypeFlow::StateVector::type_meet_internal(ciType* t1, ciType* t2, ciTypeFlow* analyzer) { assert(t1 != t2, "checked in caller"); + if (t1->equals(top_type())) { return t2; } else if (t2->equals(top_type())) { return t1; } else if (t1->is_primitive_type() || t2->is_primitive_type()) {
*** 289,299 **** } // At least one of the two types is a non-top primitive type. // The other type is not equal to it. Fall to bottom. return bottom_type(); ! } else { // Both types are non-top non-primitive types. That is, // both types are either instanceKlasses or arrayKlasses. ciKlass* object_klass = analyzer->env()->Object_klass(); ciKlass* k1 = t1->as_klass(); ciKlass* k2 = t2->as_klass(); --- 291,308 ---- } // At least one of the two types is a non-top primitive type. // The other type is not equal to it. Fall to bottom. return bottom_type(); ! } ! ! // Unwrap the types after gathering nullness information ! bool never_null1 = t1->is_never_null(); ! bool never_null2 = t2->is_never_null(); ! t1 = t1->unwrap(); ! t2 = t2->unwrap(); ! // Both types are non-top non-primitive types. That is, // both types are either instanceKlasses or arrayKlasses. ciKlass* object_klass = analyzer->env()->Object_klass(); ciKlass* k1 = t1->as_klass(); ciKlass* k2 = t2->as_klass();
*** 324,342 **** assert(k2 == ciObjArrayKlass::make(elem), "shortcut is OK"); return k2; } else { return ciObjArrayKlass::make(elem); } } else { return object_klass; } } else { // Must be two plain old instance klasses. assert(k1->is_instance_klass(), "previous cases handle non-instances"); assert(k2->is_instance_klass(), "previous cases handle non-instances"); ! return k1->least_common_ancestor(k2); } } } // ------------------------------------------------------------------ --- 333,360 ---- assert(k2 == ciObjArrayKlass::make(elem), "shortcut is OK"); return k2; } else { return ciObjArrayKlass::make(elem); } + } else if (k1->is_value_array_klass() || k2->is_value_array_klass()) { + ciKlass* elem1 = k1->as_array_klass()->element_klass(); + ciKlass* elem2 = k2->as_array_klass()->element_klass(); + ciKlass* elem = type_meet_internal(elem1, elem2, analyzer)->as_klass(); + return ciArrayKlass::make(elem); } else { return object_klass; } } else { // Must be two plain old instance klasses. assert(k1->is_instance_klass(), "previous cases handle non-instances"); assert(k2->is_instance_klass(), "previous cases handle non-instances"); ! ciType* result = k1->least_common_ancestor(k2); ! if (never_null1 && never_null2 && result->is_valuetype()) { ! // Both value types are never null, mark the result as never null ! result = analyzer->mark_as_never_null(result); } + return result; } } // ------------------------------------------------------------------
*** 394,410 **** // even if it were possible for an OSR entry point to be at bci zero. } // "Push" the method signature into the first few locals. state->set_stack_size(-max_locals()); if (!method()->is_static()) { ! state->push(method()->holder()); assert(state->tos() == state->local(0), ""); } for (ciSignatureStream str(method()->signature()); !str.at_return_type(); str.next()) { ! state->push_translate(str.type()); } // Set the rest of the locals to bottom. Cell cell = state->next_cell(state->tos()); state->set_stack_size(0); int limit = state->limit_cell(); --- 412,437 ---- // even if it were possible for an OSR entry point to be at bci zero. } // "Push" the method signature into the first few locals. state->set_stack_size(-max_locals()); if (!method()->is_static()) { ! ciType* holder = method()->holder(); ! if (holder->is_valuetype()) { ! // The receiver is never null ! holder = mark_as_never_null(holder); ! } ! state->push(holder); assert(state->tos() == state->local(0), ""); } for (ciSignatureStream str(method()->signature()); !str.at_return_type(); str.next()) { ! ciType* arg = str.type(); ! if (str.is_never_null()) { ! arg = mark_as_never_null(arg); ! } ! state->push_translate(arg); } // Set the rest of the locals to bottom. Cell cell = state->next_cell(state->tos()); state->set_stack_size(0); int limit = state->limit_cell();
*** 546,561 **** } } } // ------------------------------------------------------------------ ! // ciTypeFlow::StateVector::do_aaload ! void ciTypeFlow::StateVector::do_aaload(ciBytecodeStream* str) { pop_int(); ! ciObjArrayKlass* array_klass = pop_objArray(); if (array_klass == NULL) { ! // Did aaload on a null reference; push a null and ignore the exception. // This instruction will never continue normally. All we have to do // is report a value that will meet correctly with any downstream // reference types on paths that will truly be executed. This null type // meets with any reference type to yield that same reference type. // (The compiler will generate an unconditional exception here.) --- 573,588 ---- } } } // ------------------------------------------------------------------ ! // ciTypeFlow::StateVector::do_aload ! void ciTypeFlow::StateVector::do_aload(ciBytecodeStream* str) { pop_int(); ! ciArrayKlass* array_klass = pop_objOrValueArray(); if (array_klass == NULL) { ! // Did aload on a null reference; push a null and ignore the exception. // This instruction will never continue normally. All we have to do // is report a value that will meet correctly with any downstream // reference types on paths that will truly be executed. This null type // meets with any reference type to yield that same reference type. // (The compiler will generate an unconditional exception here.)
*** 576,587 **** --- 603,619 ---- trap(str, element_klass, Deoptimization::make_trap_request (Deoptimization::Reason_unloaded, Deoptimization::Action_reinterpret)); } else { + if (element_klass->is_valuetype()) { + // Value type array elements are never null + push(outer()->mark_as_never_null(element_klass)); + } else { push_object(element_klass); } + } } // ------------------------------------------------------------------ // ciTypeFlow::StateVector::do_checkcast
*** 595,606 **** --- 627,644 ---- // 2) C2 does an OSR compile in a later block (see bug 4778368). pop_object(); do_null_assert(klass); } else { pop_object(); + if (str->is_klass_never_null()) { + // Casting to a Q-Type contains a NULL check + assert(klass->is_valuetype(), "must be a value type"); + push(outer()->mark_as_never_null(klass)); + } else { push_object(klass); } + } } // ------------------------------------------------------------------ // ciTypeFlow::StateVector::do_getfield void ciTypeFlow::StateVector::do_getfield(ciBytecodeStream* str) {
*** 637,646 **** --- 675,688 ---- // here can make an OSR entry point unreachable, triggering the // assert on non_osr_block in ciTypeFlow::get_start_state. // (See bug 4379915.) do_null_assert(field_type->as_klass()); } else { + if (field->is_flattenable()) { + // A flattenable field is never null + field_type = outer()->mark_as_never_null(field_type); + } push_translate(field_type); } } }
*** 704,713 **** --- 746,758 ---- // ever sees a non-null value, loading has occurred. // // See do_getstatic() for similar explanation, as well as bug 4684993. do_null_assert(return_type->as_klass()); } else { + if (sigstr.is_never_null()) { + return_type = outer()->mark_as_never_null(return_type); + } push_translate(return_type); } } } }
*** 727,743 **** // OutOfMemoryError in the CI while loading constant push_null(); outer()->record_failure("ldc did not link"); return; } ! if (basic_type == T_OBJECT || basic_type == T_ARRAY) { ciObject* obj = con.as_object(); if (obj->is_null_object()) { push_null(); } else { assert(obj->is_instance() || obj->is_array(), "must be java_mirror of klass"); ! push_object(obj->klass()); } } else { push_translate(ciType::make(basic_type)); } } --- 772,792 ---- // OutOfMemoryError in the CI while loading constant push_null(); outer()->record_failure("ldc did not link"); return; } ! if (basic_type == T_OBJECT || basic_type == T_VALUETYPE || basic_type == T_ARRAY) { ciObject* obj = con.as_object(); if (obj->is_null_object()) { push_null(); } else { assert(obj->is_instance() || obj->is_array(), "must be java_mirror of klass"); ! ciType* type = obj->klass(); ! if (type->is_valuetype()) { ! type = outer()->mark_as_never_null(type); ! } ! push(type); } } else { push_translate(ciType::make(basic_type)); } }
*** 769,778 **** --- 818,863 ---- push_object(klass); } } // ------------------------------------------------------------------ + // ciTypeFlow::StateVector::do_defaultvalue + void ciTypeFlow::StateVector::do_defaultvalue(ciBytecodeStream* str) { + bool will_link; + ciKlass* klass = str->get_klass(will_link); + if (!will_link) { + trap(str, klass, str->get_klass_index()); + } else { + // The default value type is never null + push(outer()->mark_as_never_null(klass)); + } + } + + // ------------------------------------------------------------------ + // ciTypeFlow::StateVector::do_withfield + void ciTypeFlow::StateVector::do_withfield(ciBytecodeStream* str) { + bool will_link; + ciField* field = str->get_field(will_link); + ciKlass* klass = field->holder(); + if (!will_link) { + trap(str, klass, str->get_field_holder_index()); + } else { + ciType* type = pop_value(); + ciType* field_type = field->type(); + assert(field_type->is_loaded(), "field type must be loaded"); + if (field_type->is_two_word()) { + ciType* type2 = pop_value(); + assert(type2->is_two_word(), "must be 2nd half"); + assert(type == half_type(type2), "must be 2nd half"); + } + pop_object(); + // The newly created value type can never be null + push(outer()->mark_as_never_null(klass)); + } + } + + // ------------------------------------------------------------------ // ciTypeFlow::StateVector::do_newarray void ciTypeFlow::StateVector::do_newarray(ciBytecodeStream* str) { pop_int(); ciKlass* klass = ciTypeArrayKlass::make((BasicType)str->get_index()); push_object(klass);
*** 873,889 **** tty->print_cr(">> Interpreting bytecode %d:%s", str->cur_bci(), Bytecodes::name(str->cur_bc())); } switch(str->cur_bc()) { ! case Bytecodes::_aaload: do_aaload(str); break; case Bytecodes::_aastore: { pop_object(); pop_int(); ! pop_objArray(); break; } case Bytecodes::_aconst_null: { push_null(); --- 958,974 ---- tty->print_cr(">> Interpreting bytecode %d:%s", str->cur_bci(), Bytecodes::name(str->cur_bc())); } switch(str->cur_bc()) { ! case Bytecodes::_aaload: do_aload(str); break; case Bytecodes::_aastore: { pop_object(); pop_int(); ! pop_objOrValueArray(); break; } case Bytecodes::_aconst_null: { push_null();
*** 901,911 **** bool will_link; ciKlass* element_klass = str->get_klass(will_link); if (!will_link) { trap(str, element_klass, str->get_klass_index()); } else { ! push_object(ciObjArrayKlass::make(element_klass)); } break; } case Bytecodes::_areturn: case Bytecodes::_ifnonnull: --- 986,996 ---- bool will_link; ciKlass* element_klass = str->get_klass(will_link); if (!will_link) { trap(str, element_klass, str->get_klass_index()); } else { ! push_object(ciArrayKlass::make(element_klass)); } break; } case Bytecodes::_areturn: case Bytecodes::_ifnonnull:
*** 1433,1442 **** --- 1518,1530 ---- case Bytecodes::_multianewarray: do_multianewarray(str); break; case Bytecodes::_new: do_new(str); break; + case Bytecodes::_defaultvalue: do_defaultvalue(str); break; + case Bytecodes::_withfield: do_withfield(str); break; + case Bytecodes::_newarray: do_newarray(str); break; case Bytecodes::_pop: { pop();
*** 1460,1469 **** --- 1548,1558 ---- ciType* value2 = pop_value(); push(value1); push(value2); break; } + case Bytecodes::_wide: default: { // The iterator should skip this. ShouldNotReachHere();
*** 1743,1755 **** _successors->append_if_missing(block); } break; } ! case Bytecodes::_athrow: case Bytecodes::_ireturn: ! case Bytecodes::_lreturn: case Bytecodes::_freturn: ! case Bytecodes::_dreturn: case Bytecodes::_areturn: case Bytecodes::_return: _successors = new (arena) GrowableArray<Block*>(arena, 1, 0, NULL); // No successors break; --- 1832,1847 ---- _successors->append_if_missing(block); } break; } ! case Bytecodes::_athrow: ! case Bytecodes::_ireturn: ! case Bytecodes::_lreturn: ! case Bytecodes::_freturn: ! case Bytecodes::_dreturn: ! case Bytecodes::_areturn: case Bytecodes::_return: _successors = new (arena) GrowableArray<Block*>(arena, 1, 0, NULL); // No successors break;
*** 2976,2985 **** --- 3068,3082 ---- // Record the first failure reason. _failure_reason = reason; } } + ciType* ciTypeFlow::mark_as_never_null(ciType* type) { + // Wrap the type to carry the information that it is never null + return env()->make_never_null_wrapper(type); + } + #ifndef PRODUCT // ------------------------------------------------------------------ // ciTypeFlow::print_on void ciTypeFlow::print_on(outputStream* st) const { // Walk through CI blocks
< prev index next >