Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8273594: [lworld] JITs need to properly handle static inline type field with unloaded type #551

Closed
wants to merge 9 commits into from
@@ -1649,7 +1649,7 @@ void LIRGenerator::do_StoreField(StoreField* x) {
}
#endif

if (!inline_type_field_access_prolog(x, info)) {
if (!inline_type_field_access_prolog(x)) {
// Field store will always deopt due to unloaded field or holder klass
return;
}
@@ -2034,7 +2034,7 @@ LIR_Opr LIRGenerator::access_atomic_add_at(DecoratorSet decorators, BasicType ty
}
}

bool LIRGenerator::inline_type_field_access_prolog(AccessField* x, CodeEmitInfo* info) {
bool LIRGenerator::inline_type_field_access_prolog(AccessField* x) {
ciField* field = x->field();
assert(!field->is_flattened(), "Flattened field access should have been expanded");
if (!field->is_null_free()) {
@@ -2047,9 +2047,8 @@ bool LIRGenerator::inline_type_field_access_prolog(AccessField* x, CodeEmitInfo*
// Deoptimize if we load from a static field with an unloaded type because we need
// the default value if the field is null.
bool could_be_null = x->is_static() && x->as_LoadField() != NULL && !field->type()->is_loaded();
assert(!could_be_null || !field->holder()->is_loaded(), "inline type field should be loaded");
if (could_be_flat || could_be_null) {
assert(x->needs_patching(), "no deopt required");
CodeEmitInfo* info = state_for(x, x->state_before());
CodeStub* stub = new DeoptimizeStub(new CodeEmitInfo(info),
Deoptimization::Reason_unloaded,
Deoptimization::Action_make_not_entrant);
@@ -2088,7 +2087,7 @@ void LIRGenerator::do_LoadField(LoadField* x) {
}
#endif

if (!inline_type_field_access_prolog(x, info)) {
if (!inline_type_field_access_prolog(x)) {
// Field load will always deopt due to unloaded field or holder klass
LIR_Opr result = rlock_result(x, field_type);
__ move(LIR_OprFact::oopConst(NULL), result);
@@ -271,7 +271,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure {
void do_vectorizedMismatch(Intrinsic* x);
void do_blackhole(Intrinsic* x);

bool inline_type_field_access_prolog(AccessField* x, CodeEmitInfo* info);
bool inline_type_field_access_prolog(AccessField* x);
void access_flattened_array(bool is_load, LIRItem& array, LIRItem& index, LIRItem& obj_item, ciField* field = NULL, int offset = 0);
void access_sub_element(LIRItem& array, LIRItem& index, LIR_Opr& result, ciField* field, int sub_offset);
LIR_Opr get_and_load_element_address(LIRItem& array, LIRItem& index);
@@ -670,6 +670,15 @@ void ciTypeFlow::StateVector::do_getstatic(ciBytecodeStream* str) {
} else {
ciType* field_type = field->type();
if (!field_type->is_loaded()) {
if (field->is_static() && field->is_null_free()) {
// Deoptimize if we load from a static field with an unloaded
// inline type because we need the default value if the field is null.
trap(str, field_type->as_klass(),
Deoptimization::make_trap_request
(Deoptimization::Reason_unloaded,
Deoptimization::Action_reinterpret));
return;
}
// Normally, we need the field's type to be loaded if we are to
// do anything interesting with its value.
// We used to do this: trap(str, str->get_field_signature_index());
@@ -240,8 +240,11 @@ private void start() {
}

private void setupTests() {
for (Class<?> clazz : testClass.getDeclaredClasses()) {
checkAnnotationsInClass(clazz, "inner");
// TODO remove this once JDK-8273591 is fixed
if (!IGNORE_COMPILER_CONTROLS) {
for (Class<?> clazz : testClass.getDeclaredClasses()) {
checkAnnotationsInClass(clazz, "inner");
}
}
if (DUMP_REPLAY) {
addReplay();
@@ -23,10 +23,7 @@

package compiler.valhalla.inlinetypes;

import compiler.lib.ir_framework.Run;
import compiler.lib.ir_framework.RunInfo;
import compiler.lib.ir_framework.Scenario;
import compiler.lib.ir_framework.Test;
import compiler.lib.ir_framework.*;
import jdk.test.lib.Asserts;

import static compiler.valhalla.inlinetypes.InlineTypes.rI;
@@ -52,17 +49,17 @@ public static void main(String[] args) {
final Scenario[] scenarios = {
new Scenario(0),
new Scenario(1, "-XX:InlineFieldMaxFlatSize=0"),
new Scenario(2, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-XX:+PatchALot"),
new Scenario(3,
"-XX:InlineFieldMaxFlatSize=0",
"-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+PatchALot")
new Scenario(2, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+PatchALot"),
new Scenario(3, "-XX:InlineFieldMaxFlatSize=0",
"-XX:+IgnoreUnrecognizedVMOptions", "-XX:+PatchALot")
};
final String[] CutoffFlags = {"-XX:PerMethodRecompilationCutoff=-1", "-XX:PerBytecodeRecompilationCutoff=-1"};
final String[] flags = {// Prevent IR Test Framework from loading classes
"-DIgnoreCompilerControls=true",
// Some tests trigger frequent re-compilation. Don't mark them as non-compilable.
"-XX:PerMethodRecompilationCutoff=-1", "-XX:PerBytecodeRecompilationCutoff=-1"};
for (Scenario s : scenarios) {
s.addFlags(CutoffFlags);
s.addFlags(flags);
}

InlineTypes.getFramework()
.addScenarios(scenarios)
.start();
@@ -883,4 +880,30 @@ public void test20_verifier() {
MyValue20 vt = test20();
Asserts.assertEQ(vt.obj, null);
}

static primitive class Test21ClassA {
static Test21ClassB b;
static Test21ClassC c;
}

static primitive class Test21ClassB {
static int x = Test21ClassA.c.x;
}

static primitive class Test21ClassC {
int x = 42;
}

// Test access to static inline type field with unloaded type
@Test
public Object test21() {
return new Test21ClassA();
}

@Run(test = "test21")
public void test21_verifier() {
Object ret = test21();
Asserts.assertEQ(Test21ClassA.b.x, 0);
Asserts.assertEQ(Test21ClassA.c.x, 0);
}
}