mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-18 10:04:42 +02:00
8263125: During deoptimization vectors should reassign scalarized payload after all objects are reallocated.
Reviewed-by: vlivanov, rrich
This commit is contained in:
parent
65421faec3
commit
a6e056fd51
5 changed files with 55 additions and 28 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -50,6 +50,7 @@ void Location::print_on(outputStream* st) const {
|
||||||
case float_in_dbl: st->print(",float"); break;
|
case float_in_dbl: st->print(",float"); break;
|
||||||
case dbl: st->print(",double"); break;
|
case dbl: st->print(",double"); break;
|
||||||
case addr: st->print(",address"); break;
|
case addr: st->print(",address"); break;
|
||||||
|
case vector: st->print(",vector"); break;
|
||||||
default: st->print("Wrong location type %d", type());
|
default: st->print("Wrong location type %d", type());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,16 +153,27 @@ Handle VectorSupport::allocate_vector_payload_helper(InstanceKlass* ik, frame* f
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle VectorSupport::allocate_vector_payload(InstanceKlass* ik, frame* fr, RegisterMap* reg_map, ScopeValue* payload, TRAPS) {
|
Handle VectorSupport::allocate_vector_payload(InstanceKlass* ik, frame* fr, RegisterMap* reg_map, ScopeValue* payload, TRAPS) {
|
||||||
if (payload->is_location() &&
|
if (payload->is_location()) {
|
||||||
payload->as_LocationValue()->location().type() == Location::vector) {
|
|
||||||
// Vector value in an aligned adjacent tuple (1, 2, 4, 8, or 16 slots).
|
|
||||||
Location location = payload->as_LocationValue()->location();
|
Location location = payload->as_LocationValue()->location();
|
||||||
return allocate_vector_payload_helper(ik, fr, reg_map, location, THREAD); // safepoint
|
if (location.type() == Location::vector) {
|
||||||
} else {
|
// Vector value in an aligned adjacent tuple (1, 2, 4, 8, or 16 slots).
|
||||||
// Scalar-replaced boxed vector representation.
|
return allocate_vector_payload_helper(ik, fr, reg_map, location, THREAD); // safepoint
|
||||||
StackValue* value = StackValue::create_stack_value(fr, reg_map, payload);
|
}
|
||||||
return value->get_obj();
|
#ifdef ASSERT
|
||||||
|
// Other payload values are: 'oop' type location and Scalar-replaced boxed vector representation.
|
||||||
|
// They will be processed in Deoptimization::reassign_fields() after all objects are reallocated.
|
||||||
|
else {
|
||||||
|
Location::Type loc_type = location.type();
|
||||||
|
assert(loc_type == Location::oop || loc_type == Location::narrowoop,
|
||||||
|
"expected 'oop'(%d) or 'narrowoop'(%d) types location but got: %d", Location::oop, Location::narrowoop, loc_type);
|
||||||
|
}
|
||||||
|
} else if (!payload->is_object()) {
|
||||||
|
stringStream ss;
|
||||||
|
payload->print_on(&ss);
|
||||||
|
assert(payload->is_object(), "expected 'object' value for scalar-replaced boxed vector but got: %s", ss.as_string());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
return Handle(THREAD, (oop)nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceOop VectorSupport::allocate_vector(InstanceKlass* ik, frame* fr, RegisterMap* reg_map, ObjectValue* ov, TRAPS) {
|
instanceOop VectorSupport::allocate_vector(InstanceKlass* ik, frame* fr, RegisterMap* reg_map, ObjectValue* ov, TRAPS) {
|
||||||
|
|
|
@ -178,7 +178,7 @@ JRT_BLOCK_ENTRY(Deoptimization::UnrollBlock*, Deoptimization::fetch_unroll_info(
|
||||||
JRT_END
|
JRT_END
|
||||||
|
|
||||||
#if COMPILER2_OR_JVMCI
|
#if COMPILER2_OR_JVMCI
|
||||||
static bool eliminate_allocations(JavaThread* thread, int exec_mode, CompiledMethod* compiled_method,
|
static bool rematerialize_objects(JavaThread* thread, int exec_mode, CompiledMethod* compiled_method,
|
||||||
frame& deoptee, RegisterMap& map, GrowableArray<compiledVFrame*>* chunk,
|
frame& deoptee, RegisterMap& map, GrowableArray<compiledVFrame*>* chunk,
|
||||||
bool& deoptimized_objects) {
|
bool& deoptimized_objects) {
|
||||||
bool realloc_failures = false;
|
bool realloc_failures = false;
|
||||||
|
@ -242,8 +242,8 @@ static bool eliminate_allocations(JavaThread* thread, int exec_mode, CompiledMet
|
||||||
return realloc_failures;
|
return realloc_failures;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void eliminate_locks(JavaThread* thread, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures,
|
static void restore_eliminated_locks(JavaThread* thread, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures,
|
||||||
frame& deoptee, int exec_mode, bool& deoptimized_objects) {
|
frame& deoptee, int exec_mode, bool& deoptimized_objects) {
|
||||||
JavaThread* deoptee_thread = chunk->at(0)->thread();
|
JavaThread* deoptee_thread = chunk->at(0)->thread();
|
||||||
assert(!EscapeBarrier::objs_are_deoptimized(deoptee_thread, deoptee.id()), "must relock just once");
|
assert(!EscapeBarrier::objs_are_deoptimized(deoptee_thread, deoptee.id()), "must relock just once");
|
||||||
assert(thread == Thread::current(), "should be");
|
assert(thread == Thread::current(), "should be");
|
||||||
|
@ -303,8 +303,9 @@ bool Deoptimization::deoptimize_objects_internal(JavaThread* thread, GrowableArr
|
||||||
bool const jvmci_enabled = JVMCI_ONLY(UseJVMCICompiler) NOT_JVMCI(false);
|
bool const jvmci_enabled = JVMCI_ONLY(UseJVMCICompiler) NOT_JVMCI(false);
|
||||||
|
|
||||||
// Reallocate the non-escaping objects and restore their fields.
|
// Reallocate the non-escaping objects and restore their fields.
|
||||||
if (jvmci_enabled COMPILER2_PRESENT(|| (DoEscapeAnalysis && EliminateAllocations))) {
|
if (jvmci_enabled COMPILER2_PRESENT(|| (DoEscapeAnalysis && EliminateAllocations)
|
||||||
realloc_failures = eliminate_allocations(thread, Unpack_none, cm, deoptee, map, chunk, deoptimized_objects);
|
|| EliminateAutoBox || EnableVectorAggressiveReboxing)) {
|
||||||
|
realloc_failures = rematerialize_objects(thread, Unpack_none, cm, deoptee, map, chunk, deoptimized_objects);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Revoke biases of objects with eliminated locks in the given frame.
|
// Revoke biases of objects with eliminated locks in the given frame.
|
||||||
|
@ -315,7 +316,7 @@ bool Deoptimization::deoptimize_objects_internal(JavaThread* thread, GrowableArr
|
||||||
|
|
||||||
// Now relock objects if synchronization on them was eliminated.
|
// Now relock objects if synchronization on them was eliminated.
|
||||||
if (jvmci_enabled COMPILER2_PRESENT(|| ((DoEscapeAnalysis || EliminateNestedLocks) && EliminateLocks))) {
|
if (jvmci_enabled COMPILER2_PRESENT(|| ((DoEscapeAnalysis || EliminateNestedLocks) && EliminateLocks))) {
|
||||||
eliminate_locks(thread, chunk, realloc_failures, deoptee, Unpack_none, deoptimized_objects);
|
restore_eliminated_locks(thread, chunk, realloc_failures, deoptee, Unpack_none, deoptimized_objects);
|
||||||
}
|
}
|
||||||
return deoptimized_objects;
|
return deoptimized_objects;
|
||||||
}
|
}
|
||||||
|
@ -368,17 +369,14 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
|
||||||
bool realloc_failures = false;
|
bool realloc_failures = false;
|
||||||
|
|
||||||
#if COMPILER2_OR_JVMCI
|
#if COMPILER2_OR_JVMCI
|
||||||
#if INCLUDE_JVMCI
|
bool const jvmci_enabled = JVMCI_ONLY(EnableJVMCI) NOT_JVMCI(false);
|
||||||
bool jvmci_enabled = true;
|
|
||||||
#else
|
|
||||||
bool jvmci_enabled = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Reallocate the non-escaping objects and restore their fields. Then
|
// Reallocate the non-escaping objects and restore their fields. Then
|
||||||
// relock objects if synchronization on them was eliminated.
|
// relock objects if synchronization on them was eliminated.
|
||||||
if (jvmci_enabled COMPILER2_PRESENT( || (DoEscapeAnalysis && EliminateAllocations) )) {
|
if (jvmci_enabled COMPILER2_PRESENT( || (DoEscapeAnalysis && EliminateAllocations)
|
||||||
|
|| EliminateAutoBox || EnableVectorAggressiveReboxing )) {
|
||||||
bool unused;
|
bool unused;
|
||||||
realloc_failures = eliminate_allocations(thread, exec_mode, cm, deoptee, map, chunk, unused);
|
realloc_failures = rematerialize_objects(thread, exec_mode, cm, deoptee, map, chunk, unused);
|
||||||
}
|
}
|
||||||
#endif // COMPILER2_OR_JVMCI
|
#endif // COMPILER2_OR_JVMCI
|
||||||
|
|
||||||
|
@ -396,7 +394,7 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
|
||||||
if ((jvmci_enabled COMPILER2_PRESENT( || ((DoEscapeAnalysis || EliminateNestedLocks) && EliminateLocks) ))
|
if ((jvmci_enabled COMPILER2_PRESENT( || ((DoEscapeAnalysis || EliminateNestedLocks) && EliminateLocks) ))
|
||||||
&& !EscapeBarrier::objs_are_deoptimized(thread, deoptee.id())) {
|
&& !EscapeBarrier::objs_are_deoptimized(thread, deoptee.id())) {
|
||||||
bool unused;
|
bool unused;
|
||||||
eliminate_locks(thread, chunk, realloc_failures, deoptee, exec_mode, unused);
|
restore_eliminated_locks(thread, chunk, realloc_failures, deoptee, exec_mode, unused);
|
||||||
}
|
}
|
||||||
#endif // COMPILER2_OR_JVMCI
|
#endif // COMPILER2_OR_JVMCI
|
||||||
|
|
||||||
|
@ -1406,7 +1404,21 @@ void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableAr
|
||||||
#endif // INCLUDE_JVMCI || INCLUDE_AOT
|
#endif // INCLUDE_JVMCI || INCLUDE_AOT
|
||||||
#ifdef COMPILER2
|
#ifdef COMPILER2
|
||||||
if (EnableVectorSupport && VectorSupport::is_vector(k)) {
|
if (EnableVectorSupport && VectorSupport::is_vector(k)) {
|
||||||
continue; // skip field reassignment for vectors
|
assert(sv->field_size() == 1, "%s not a vector", k->name()->as_C_string());
|
||||||
|
ScopeValue* payload = sv->field_at(0);
|
||||||
|
if (payload->is_location() &&
|
||||||
|
payload->as_LocationValue()->location().type() == Location::vector) {
|
||||||
|
if (PrintDeoptimizationDetails) {
|
||||||
|
tty->print_cr("skip field reassignment for this vector - it should be assigned already");
|
||||||
|
if (Verbose) {
|
||||||
|
Handle obj = sv->value();
|
||||||
|
k->oop_print_on(obj(), tty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue; // Such vector's value was already restored in VectorSupport::allocate_vector().
|
||||||
|
}
|
||||||
|
// Else fall-through to do assignment for scalar-replaced boxed vector representation
|
||||||
|
// which could be restored after vector object allocation.
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (k->is_instance_klass()) {
|
if (k->is_instance_klass()) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -141,6 +141,7 @@ StackValue* StackValue::create_stack_value(const frame* fr, const RegisterMap* r
|
||||||
return new StackValue(h);
|
return new StackValue(h);
|
||||||
}
|
}
|
||||||
case Location::addr: {
|
case Location::addr: {
|
||||||
|
loc.print_on(tty);
|
||||||
ShouldNotReachHere(); // both C1 and C2 now inline jsrs
|
ShouldNotReachHere(); // both C1 and C2 now inline jsrs
|
||||||
}
|
}
|
||||||
case Location::normal: {
|
case Location::normal: {
|
||||||
|
@ -154,9 +155,11 @@ StackValue* StackValue::create_stack_value(const frame* fr, const RegisterMap* r
|
||||||
return new StackValue();
|
return new StackValue();
|
||||||
}
|
}
|
||||||
case Location::vector: {
|
case Location::vector: {
|
||||||
ShouldNotReachHere(); // should be handled by Deoptimization::realloc_objects()
|
loc.print_on(tty);
|
||||||
|
ShouldNotReachHere(); // should be handled by VectorSupport::allocate_vector()
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
loc.print_on(tty);
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -34,7 +34,7 @@ import java.util.function.IntFunction;
|
||||||
* @requires (os.arch != "ppc64") & (os.arch != "ppc64le")
|
* @requires (os.arch != "ppc64") & (os.arch != "ppc64le")
|
||||||
* @modules jdk.incubator.vector
|
* @modules jdk.incubator.vector
|
||||||
* @modules java.base/jdk.internal.vm.annotation
|
* @modules java.base/jdk.internal.vm.annotation
|
||||||
* @run testng/othervm -XX:-TieredCompilation --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED
|
* @run testng/othervm/timeout=300 -XX:-TieredCompilation --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED
|
||||||
* Vector64ConversionTests
|
* Vector64ConversionTests
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue