< prev index next >
src/hotspot/share/c1/c1_LIRGenerator.cpp
Print this page
@@ -1541,11 +1541,11 @@
#endif
if (x->needs_null_check() &&
(needs_patching ||
MacroAssembler::needs_explicit_null_check(x->offset()))) {
- if (needs_patching && x->field()->signature()->starts_with("Q", 1)) {
+ if (needs_patching && x->field()->is_never_null()) {
// We are storing a field of type "QT;", but T is not yet loaded, so we don't
// know whether this field is flattened or not. Let's deoptimize and recompile.
CodeStub* stub = new DeoptimizeStub(new CodeEmitInfo(info),
Deoptimization::Reason_unloaded,
Deoptimization::Action_make_not_entrant);
@@ -1866,10 +1866,83 @@
}
return _barrier_set->resolve(this, decorators, obj);
}
+Value LIRGenerator::non_nullable_load_field_prolog(LoadField* x, CodeEmitInfo* info) {
+ ciField* field = x->field();
+ ciInstanceKlass* holder = field->holder();
+ Value default_value = NULL;
+
+ // Unloaded "QV;" klasses are represented by a ciInstanceKlass
+ bool field_type_unloaded = field->type()->is_instance_klass() && !field->type()->as_instance_klass()->is_loaded();
+
+ // Check for edge cases (1), (2) and (3) for getstatic and getfield
+ bool deopt = false;
+ bool need_default = false;
+ if (field->is_static()) {
+ // (1) holder is unloaded -- no problem: it will be loaded by patching, and field offset will be determined.
+
+ if (field_type_unloaded) {
+ // (2) field type is unloaded -- problem: we don't know what the default value is. Let's deopt.
+ // FIXME: consider getting the default value in patching code.
+ deopt = true;
+ } else {
+ need_default = true;
+ }
+
+ // (3) field is not flattenable -- we don't care: static fields are never flattened.
+ } else {
+ if (!holder->is_loaded()) {
+ // (1) holder is unloaded -- problem: we needed the field offset back in GraphBuilder::access_field()
+ // FIXME: consider getting field offset in patching code (but only if the field
+ // type was loaded at compilation time).
+ deopt = true;
+ } else if (field_type_unloaded) {
+ // (2) field type is unloaded -- problem: we don't whether it's flattened or not. Let's deopt
+ deopt = true;
+ } else if (!field->is_flattened()) {
+ // (3) field is not flattenable -- need default value in cases of uninitialized field
+ need_default = true;
+ }
+ }
+
+ assert(!(deopt && need_default), "cannot both be true");
+
+ if (deopt) {
+ assert(x->needs_patching(), "must be");
+ assert(info != NULL, "must be");
+ CodeStub* stub = new DeoptimizeStub(new CodeEmitInfo(info),
+ Deoptimization::Reason_unloaded,
+ Deoptimization::Action_make_not_entrant);
+ __ branch(lir_cond_always, T_ILLEGAL, stub);
+ } else if (need_default) {
+ assert(!field_type_unloaded, "must be");
+ assert(field->type()->is_valuetype(), "must be");
+ ciValueKlass* value_klass = field->type()->as_value_klass();
+ assert(value_klass->is_loaded(), "must be");
+
+ if (field->is_static() && holder->is_loaded()) {
+ ciInstance* mirror = field->holder()->java_mirror();
+ ciObject* val = mirror->field_value(field).as_object();
+ if (val->is_null_object()) {
+ // This is a non-nullable static field, but it's not initialized.
+ // We need to do a null check, and replace it with the default value.
+ } else {
+ // No need to perform null check on this static field
+ need_default = false;
+ }
+ }
+
+ if (need_default) {
+ default_value = new Constant(new InstanceConstant(value_klass->default_value_instance()));
+ }
+ }
+
+ return default_value;
+}
+
void LIRGenerator::do_LoadField(LoadField* x) {
bool needs_patching = x->needs_patching();
bool is_volatile = x->field()->is_volatile();
BasicType field_type = x->field_type();
@@ -1895,42 +1968,30 @@
tty->print_cr(" ###class not loaded at load_%s bci %d",
x->is_static() ? "static" : "field", x->printable_bci());
}
#endif
+ Value default_value = NULL;
+ if (x->field()->is_never_null()) {
+ default_value = non_nullable_load_field_prolog(x, info);
+ }
+
bool stress_deopt = StressLoopInvariantCodeMotion && info && info->deoptimize_on_exception();
if (x->needs_null_check() &&
(needs_patching ||
MacroAssembler::needs_explicit_null_check(x->offset()) ||
stress_deopt)) {
- if (needs_patching && x->field()->signature()->starts_with("Q", 1)) {
- // We are loading a field of type "QT;", but class T is not yet loaded. We don't know
- // whether this field is flattened or not. Let's deoptimize and recompile.
- CodeStub* stub = new DeoptimizeStub(new CodeEmitInfo(info),
- Deoptimization::Reason_unloaded,
- Deoptimization::Action_make_not_entrant);
- __ branch(lir_cond_always, T_ILLEGAL, stub);
- } else {
LIR_Opr obj = object.result();
if (stress_deopt) {
obj = new_register(T_OBJECT);
__ move(LIR_OprFact::oopConst(NULL), obj);
}
// Emit an explicit null check because the offset is too large.
// If the class is not loaded and the object is NULL, we need to deoptimize to throw a
// NoClassDefFoundError in the interpreter instead of an implicit NPE from compiled code.
__ null_check(obj, new CodeEmitInfo(info), /* deoptimize */ needs_patching);
}
- } else if (x->value_klass() != NULL && x->default_value() == NULL) {
- assert(x->is_static() && !x->value_klass()->is_loaded(), "must be");
- assert(needs_patching, "must be");
- // The value klass was not loaded so we don't know what its default value should be
- CodeStub* stub = new DeoptimizeStub(new CodeEmitInfo(info),
- Deoptimization::Reason_unloaded,
- Deoptimization::Action_make_not_entrant);
- __ branch(lir_cond_always, T_ILLEGAL, stub);
- }
DecoratorSet decorators = IN_HEAP;
if (is_volatile) {
decorators |= MO_SEQ_CST;
}
@@ -1941,18 +2002,18 @@
LIR_Opr result = rlock_result(x, field_type);
access_load_at(decorators, field_type,
object, LIR_OprFact::intConst(x->offset()), result,
info ? new CodeEmitInfo(info) : NULL, info);
- if (x->value_klass() != NULL && x->default_value() != NULL) {
+ if (default_value != NULL) {
LabelObj* L_end = new LabelObj();
__ cmp(lir_cond_notEqual, result, LIR_OprFact::oopConst(NULL));
__ branch(lir_cond_notEqual, T_OBJECT, L_end->label());
- LIRItem default_value(x->default_value(), this);
- default_value.load_item();
- __ move(default_value.result(), result);
+ LIRItem dv(default_value, this);
+ dv.load_item();
+ __ move(dv.result(), result);
__ branch_destination(L_end->label());
}
}
< prev index next >