--- old/src/hotspot/share/c1/c1_Canonicalizer.cpp 2019-07-12 08:14:36.050321099 -0700 +++ new/src/hotspot/share/c1/c1_Canonicalizer.cpp 2019-07-12 08:14:35.722309360 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. 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 @@ -648,6 +648,8 @@ void Canonicalizer::do_NewTypeArray (NewTypeArray* x) {} void Canonicalizer::do_NewObjectArray (NewObjectArray* x) {} void Canonicalizer::do_NewMultiArray (NewMultiArray* x) {} +void Canonicalizer::do_WithField (WithField* x) {} +void Canonicalizer::do_DefaultValue (DefaultValue* x) {} void Canonicalizer::do_CheckCast (CheckCast* x) { if (x->klass()->is_loaded() && !x->is_never_null()) { // Don't canonicalize for non-nullable types -- we need to throw NPE. --- old/src/hotspot/share/c1/c1_Canonicalizer.hpp 2019-07-12 08:14:36.774347009 -0700 +++ new/src/hotspot/share/c1/c1_Canonicalizer.hpp 2019-07-12 08:14:36.454335557 -0700 @@ -85,6 +85,8 @@ virtual void do_NewTypeArray (NewTypeArray* x); virtual void do_NewObjectArray (NewObjectArray* x); virtual void do_NewMultiArray (NewMultiArray* x); + virtual void do_WithField (WithField* x); + virtual void do_DefaultValue (DefaultValue* x); virtual void do_CheckCast (CheckCast* x); virtual void do_InstanceOf (InstanceOf* x); virtual void do_MonitorEnter (MonitorEnter* x); --- old/src/hotspot/share/c1/c1_GraphBuilder.cpp 2019-07-12 08:14:37.474372062 -0700 +++ new/src/hotspot/share/c1/c1_GraphBuilder.cpp 2019-07-12 08:14:37.154360609 -0700 @@ -1856,7 +1856,6 @@ bool will_link; ciField* field_modify = stream()->get_field(will_link); ciInstanceKlass* holder = field_modify->holder(); - assert(holder->is_valuetype(), "must be a value klass"); BasicType field_type = field_modify->type()->basic_type(); ValueType* type = as_ValueType(field_type); @@ -1870,11 +1869,20 @@ scope()->set_wrote_fields(); const int offset = !needs_patching ? field_modify->offset() : -1; - Value val = pop(type); - Value obj = apop(); + if (!holder->is_loaded()) { + ValueStack* state_before = copy_state_before(); + Value val = pop(type); + Value obj = apop(); + apush(append_split(new WithField(obj->type(), state_before))); + return; + } ValueStack* state_before = copy_state_for_exception(); + Value val = pop(type); + Value obj = apop(); + + assert(holder->is_valuetype(), "must be a value klass"); NewValueTypeInstance* new_instance = new NewValueTypeInstance(holder->as_value_klass(), state_before, false); _memory->new_instance(new_instance); apush(append_split(new_instance)); @@ -2301,14 +2309,19 @@ } void GraphBuilder::new_value_type_instance(int klass_index) { - ValueStack* state_before = copy_state_exhandling(); bool will_link; ciKlass* klass = stream()->get_klass(will_link); - assert(klass->is_valuetype(), "must be a value klass"); - NewValueTypeInstance* new_instance = new NewValueTypeInstance(klass->as_value_klass(), - state_before, stream()->is_unresolved_klass()); - _memory->new_instance(new_instance); - apush(append_split(new_instance)); + if (klass->is_loaded()) { + assert(klass->is_valuetype(), "must be a value klass"); + ValueStack* state_before = copy_state_exhandling(); + NewValueTypeInstance* new_instance = new NewValueTypeInstance(klass->as_value_klass(), + state_before, stream()->is_unresolved_klass()); + _memory->new_instance(new_instance); + apush(append_split(new_instance)); + } else { + ValueStack* state_before = copy_state_before(); + apush(append_split(new DefaultValue(objectType, state_before))); + } } void GraphBuilder::new_type_array() { --- old/src/hotspot/share/c1/c1_Instruction.hpp 2019-07-12 08:14:38.226398975 -0700 +++ new/src/hotspot/share/c1/c1_Instruction.hpp 2019-07-12 08:14:37.902387379 -0700 @@ -77,6 +77,8 @@ class NewTypeArray; class NewObjectArray; class NewMultiArray; +class WithField; +class DefaultValue; class TypeCheck; class CheckCast; class InstanceOf; @@ -182,6 +184,8 @@ virtual void do_NewTypeArray (NewTypeArray* x) = 0; virtual void do_NewObjectArray (NewObjectArray* x) = 0; virtual void do_NewMultiArray (NewMultiArray* x) = 0; + virtual void do_WithField (WithField* x) = 0; + virtual void do_DefaultValue (DefaultValue* x) = 0; virtual void do_CheckCast (CheckCast* x) = 0; virtual void do_InstanceOf (InstanceOf* x) = 0; virtual void do_MonitorEnter (MonitorEnter* x) = 0; @@ -565,6 +569,8 @@ virtual NewTypeArray* as_NewTypeArray() { return NULL; } virtual NewObjectArray* as_NewObjectArray() { return NULL; } virtual NewMultiArray* as_NewMultiArray() { return NULL; } + virtual WithField* as_WithField() { return NULL; } + virtual DefaultValue* as_DefaultValue() { return NULL; } virtual TypeCheck* as_TypeCheck() { return NULL; } virtual CheckCast* as_CheckCast() { return NULL; } virtual InstanceOf* as_InstanceOf() { return NULL; } @@ -1467,6 +1473,19 @@ ciType* exact_type() const; }; +LEAF(WithField, StateSplit) + public: + // creation + WithField(ValueType* type, ValueStack* state_before) + : StateSplit(type, state_before) {} +}; + +LEAF(DefaultValue, StateSplit) + public: + // creation + DefaultValue(ValueType* type, ValueStack* state_before) + : StateSplit(type, state_before) {} +}; BASE(TypeCheck, StateSplit) private: --- old/src/hotspot/share/c1/c1_InstructionPrinter.cpp 2019-07-12 08:14:38.954425029 -0700 +++ new/src/hotspot/share/c1/c1_InstructionPrinter.cpp 2019-07-12 08:14:38.634413577 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. 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 @@ -542,6 +542,14 @@ print_klass(x->klass()); } +void InstructionPrinter::do_WithField(WithField* x) { + output()->print("withfield"); +} + +void InstructionPrinter::do_DefaultValue(DefaultValue* x) { + output()->print("defaultvalue"); +} + void InstructionPrinter::do_MonitorEnter(MonitorEnter* x) { output()->print("enter "); --- old/src/hotspot/share/c1/c1_InstructionPrinter.hpp 2019-07-12 08:14:39.666450510 -0700 +++ new/src/hotspot/share/c1/c1_InstructionPrinter.hpp 2019-07-12 08:14:39.346439058 -0700 @@ -108,6 +108,8 @@ virtual void do_NewTypeArray (NewTypeArray* x); virtual void do_NewObjectArray (NewObjectArray* x); virtual void do_NewMultiArray (NewMultiArray* x); + virtual void do_WithField (WithField* x); + virtual void do_DefaultValue (DefaultValue* x); virtual void do_CheckCast (CheckCast* x); virtual void do_InstanceOf (InstanceOf* x); virtual void do_MonitorEnter (MonitorEnter* x); --- old/src/hotspot/share/c1/c1_LIRGenerator.cpp 2019-07-12 08:14:40.374475848 -0700 +++ new/src/hotspot/share/c1/c1_LIRGenerator.cpp 2019-07-12 08:14:40.050464253 -0700 @@ -2163,6 +2163,29 @@ } } +void LIRGenerator::do_WithField(WithField* x) { + // This happens only when a class X uses the withfield bytecode to refer to + // an inline class V, where V has not yet been loaded. This is not a common + // case. Let's just deoptimize. + CodeEmitInfo* info = state_for(x, x->state_before()); + CodeStub* stub = new DeoptimizeStub(new CodeEmitInfo(info), + Deoptimization::Reason_unloaded, + Deoptimization::Action_make_not_entrant); + __ branch(lir_cond_always, T_ILLEGAL, stub); + LIR_Opr reg = rlock_result(x, T_OBJECT); + __ move(LIR_OprFact::oopConst(NULL), reg); +} + +void LIRGenerator::do_DefaultValue(DefaultValue* x) { + // Same as withfield above. Let's deoptimize. + CodeEmitInfo* info = state_for(x, x->state_before()); + CodeStub* stub = new DeoptimizeStub(new CodeEmitInfo(info), + Deoptimization::Reason_unloaded, + Deoptimization::Action_make_not_entrant); + __ branch(lir_cond_always, T_ILLEGAL, stub); + LIR_Opr reg = rlock_result(x, T_OBJECT); + __ move(LIR_OprFact::oopConst(NULL), reg); +} void LIRGenerator::do_NullCheck(NullCheck* x) { if (x->can_trap()) { --- old/src/hotspot/share/c1/c1_LIRGenerator.hpp 2019-07-12 08:14:41.118502475 -0700 +++ new/src/hotspot/share/c1/c1_LIRGenerator.hpp 2019-07-12 08:14:40.794490880 -0700 @@ -581,6 +581,8 @@ virtual void do_NewTypeArray (NewTypeArray* x); virtual void do_NewObjectArray (NewObjectArray* x); virtual void do_NewMultiArray (NewMultiArray* x); + virtual void do_WithField (WithField* x); + virtual void do_DefaultValue (DefaultValue* x); virtual void do_CheckCast (CheckCast* x); virtual void do_InstanceOf (InstanceOf* x); virtual void do_MonitorEnter (MonitorEnter* x); --- old/src/hotspot/share/c1/c1_Optimizer.cpp 2019-07-12 08:14:41.838528243 -0700 +++ new/src/hotspot/share/c1/c1_Optimizer.cpp 2019-07-12 08:14:41.514516648 -0700 @@ -515,6 +515,8 @@ void do_NewTypeArray (NewTypeArray* x); void do_NewObjectArray (NewObjectArray* x); void do_NewMultiArray (NewMultiArray* x); + void do_WithField (WithField* x); + void do_DefaultValue (DefaultValue* x); void do_CheckCast (CheckCast* x); void do_InstanceOf (InstanceOf* x); void do_MonitorEnter (MonitorEnter* x); @@ -703,6 +705,8 @@ void NullCheckVisitor::do_NewTypeArray (NewTypeArray* x) { nce()->handle_NewArray(x); } void NullCheckVisitor::do_NewObjectArray (NewObjectArray* x) { nce()->handle_NewArray(x); } void NullCheckVisitor::do_NewMultiArray (NewMultiArray* x) { nce()->handle_NewArray(x); } +void NullCheckVisitor::do_WithField (WithField* x) {} +void NullCheckVisitor::do_DefaultValue (DefaultValue* x) {} void NullCheckVisitor::do_CheckCast (CheckCast* x) { nce()->clear_last_explicit_null_check(); } void NullCheckVisitor::do_InstanceOf (InstanceOf* x) {} void NullCheckVisitor::do_MonitorEnter (MonitorEnter* x) { nce()->handle_AccessMonitor(x); } --- old/src/hotspot/share/c1/c1_RangeCheckElimination.hpp 2019-07-12 08:14:42.554553868 -0700 +++ new/src/hotspot/share/c1/c1_RangeCheckElimination.hpp 2019-07-12 08:14:42.234542415 -0700 @@ -147,6 +147,8 @@ void do_NewTypeArray (NewTypeArray* x) { /* nothing to do */ }; void do_NewObjectArray (NewObjectArray* x) { /* nothing to do */ }; void do_NewMultiArray (NewMultiArray* x) { /* nothing to do */ }; + void do_WithField (WithField* x) { /* nothing to do */ }; + void do_DefaultValue (DefaultValue* x) { /* nothing to do */ }; void do_CheckCast (CheckCast* x) { /* nothing to do */ }; void do_InstanceOf (InstanceOf* x) { /* nothing to do */ }; void do_BlockBegin (BlockBegin* x) { /* nothing to do */ }; --- old/src/hotspot/share/c1/c1_ValueMap.hpp 2019-07-12 08:14:43.278579779 -0700 +++ new/src/hotspot/share/c1/c1_ValueMap.hpp 2019-07-12 08:14:42.938567611 -0700 @@ -190,6 +190,8 @@ void do_NewTypeArray (NewTypeArray* x) { /* nothing to do */ } void do_NewObjectArray (NewObjectArray* x) { /* nothing to do */ } void do_NewMultiArray (NewMultiArray* x) { /* nothing to do */ } + void do_WithField (WithField* x) { /* nothing to do */ } + void do_DefaultValue (DefaultValue* x) { /* nothing to do */ } void do_CheckCast (CheckCast* x) { /* nothing to do */ } void do_InstanceOf (InstanceOf* x) { /* nothing to do */ } void do_BlockBegin (BlockBegin* x) { /* nothing to do */ }