Skip to content
Permalink
Browse files
8258412: [lworld] TestArrays::test73 fails due to unexpected result
  • Loading branch information
TobiHartmann committed Dec 16, 2020
1 parent 34232ad commit 56ddef2afb77ba8eca0936565ac08e350045f9a4
@@ -1626,7 +1626,6 @@ Compile::AliasType* Compile::find_alias_type(const TypePtr* adr_type, bool no_cr
}
int field_offset = flat->is_aryptr()->field_offset().get();
if (elemtype->isa_inlinetype() &&
elemtype->inline_klass() != NULL &&
field_offset != Type::OffsetBot) {
ciInlineKlass* vk = elemtype->inline_klass();
field_offset += vk->first_field_offset();
@@ -323,6 +323,9 @@ void InlineTypeBaseNode::load(GraphKit* kit, Node* base, Node* ptr, ciInstanceKl
}

void InlineTypeBaseNode::store_flattened(GraphKit* kit, Node* base, Node* ptr, ciInstanceKlass* holder, int holder_offset, DecoratorSet decorators) const {
if (kit->gvn().type(base)->isa_aryptr()) {
kit->C->set_flattened_accesses();
}
// The inline type is embedded into the object without an oop header. Subtract the
// offset of the first field to account for the missing header when storing the values.
if (holder == NULL) {
@@ -593,6 +596,9 @@ InlineTypeNode* InlineTypeNode::make_from_oop(GraphKit* kit, Node* oop, ciInline

// GraphKit wrapper for the 'make_from_flattened' method
InlineTypeNode* InlineTypeNode::make_from_flattened(GraphKit* kit, ciInlineKlass* vk, Node* obj, Node* ptr, ciInstanceKlass* holder, int holder_offset, DecoratorSet decorators) {
if (kit->gvn().type(obj)->isa_aryptr()) {
kit->C->set_flattened_accesses();
}
// Create and initialize an InlineTypeNode by loading all field values from
// a flattened inline type field at 'holder_offset' or from an inline type array.
InlineTypeNode* vt = make_uninitialized(kit->gvn(), vk);
@@ -460,7 +460,7 @@ class Parse : public GraphKit {
void do_one_bytecode();

// helper function to generate array store check
Node* array_store_check();
Node* array_store_check(Node*& adr, const Type*& elemtype);
// Helper function to generate array load
void array_load(BasicType etype);
// Helper function to generate array store
@@ -82,7 +82,6 @@ void Parse::array_load(BasicType bt) {
const TypeOopPtr* elemptr = elemtype->make_oopptr();
const TypeAryPtr* ary_t = _gvn.type(ary)->is_aryptr();
if (ary_t->is_flat()) {
C->set_flattened_accesses();
// Load from flattened inline type array
Node* vt = InlineTypeNode::make_from_flattened(this, elemtype->inline_klass(), ary, adr);
push(vt);
@@ -231,7 +230,7 @@ void Parse::array_store(BasicType bt) {
if (stopped()) return; // guaranteed null or range check
Node* cast_val = NULL;
if (bt == T_OBJECT) {
cast_val = array_store_check();
cast_val = array_store_check(adr, elemtype);
if (stopped()) return;
}
Node* val = pop_node(bt); // Value to store
@@ -240,6 +239,7 @@ void Parse::array_store(BasicType bt) {

const TypeAryPtr* ary_t = _gvn.type(ary)->is_aryptr();
const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(bt);
assert(adr->as_AddP()->in(AddPNode::Base) == ary, "inconsistent address base");

if (elemtype == TypeInt::BOOL) {
bt = T_BOOLEAN;
@@ -273,7 +273,6 @@ void Parse::array_store(BasicType bt) {

if (ary_t->is_flat()) {
// Store to flattened inline type array
C->set_flattened_accesses();
if (!cast_val->is_InlineType()) {
inc_sp(3);
cast_val = null_check(cast_val);
@@ -541,7 +540,7 @@ Node* Parse::array_addressing(BasicType type, int vals, const Type*& elemtype) {
bool null_free_array = true;
method()->array_access_profiled_type(bci(), array_type, element_type, element_ptr, flat_array, null_free_array);
if (array_type != NULL) {
record_profile_for_speculation(ary, array_type, ProfileMaybeNull);
ary = record_profile_for_speculation(ary, array_type, ProfileMaybeNull);
}
}

@@ -141,7 +141,7 @@ void Parse::do_instanceof() {

//------------------------------array_store_check------------------------------
// pull array from stack and check that the store is valid
Node* Parse::array_store_check() {
Node* Parse::array_store_check(Node*& adr, const Type*& elemtype) {
// Shorthand access to array store elements without popping them.
Node *obj = peek(0);
Node *idx = peek(1);
@@ -158,40 +158,16 @@ Node* Parse::array_store_check() {
// Extract the array klass type
Node* array_klass = load_object_klass(ary);
// Get the array klass
const TypeKlassPtr *tak = _gvn.type(array_klass)->is_klassptr();
const TypeKlassPtr* tak = _gvn.type(array_klass)->is_klassptr();

// The type of array_klass is usually INexact array-of-oop. Heroically
// cast array_klass to EXACT array and uncommon-trap if the cast fails.
// Make constant out of the inexact array klass, but use it only if the cast
// succeeds.
bool always_see_exact_class = false;
if (MonomorphicArrayCheck
&& !tak->klass_is_exact()) {
// Regarding the fourth condition in the if-statement from above:
//
// If the compiler has determined that the type of array 'ary' (represented
// by 'array_klass') is java/lang/Object, the compiler must not assume that
// the array 'ary' is monomorphic.
//
// If 'ary' were of type java/lang/Object, this arraystore would have to fail,
// because it is not possible to perform a arraystore into an object that is not
// a "proper" array.
//
// Therefore, let's obtain at runtime the type of 'ary' and check if we can still
// successfully perform the store.
//
// The implementation reasons for the condition are the following:
//
// java/lang/Object is the superclass of all arrays, but it is represented by the VM
// as an InstanceKlass. The checks generated by gen_checkcast() (see below) expect
// 'array_klass' to be ObjArrayKlass, which can result in invalid memory accesses.
//
// See issue JDK-8057622 for details.

// (If no MDO at all, hope for the best, until a trap actually occurs.)

if (MonomorphicArrayCheck && !tak->klass_is_exact()) {
// Make a constant out of the inexact array klass
const TypeKlassPtr *extak = NULL;
const TypeKlassPtr* extak = NULL;
const TypeOopPtr* ary_t = _gvn.type(ary)->is_oopptr();
ciKlass* ary_spec = ary_t->speculative_type();
Deoptimization::DeoptReason reason = Deoptimization::Reason_none;
@@ -215,6 +191,24 @@ Node* Parse::array_store_check() {
}
}
} else if (!too_many_traps(Deoptimization::Reason_array_check) && tak != TypeKlassPtr::OBJECT) {
// If the compiler has determined that the type of array 'ary' (represented
// by 'array_klass') is java/lang/Object, the compiler must not assume that
// the array 'ary' is monomorphic.
//
// If 'ary' were of type java/lang/Object, this arraystore would have to fail,
// because it is not possible to perform a arraystore into an object that is not
// a "proper" array.
//
// Therefore, let's obtain at runtime the type of 'ary' and check if we can still
// successfully perform the store.
//
// The implementation reasons for the condition are the following:
//
// java/lang/Object is the superclass of all arrays, but it is represented by the VM
// as an InstanceKlass. The checks generated by gen_checkcast() (see below) expect
// 'array_klass' to be ObjArrayKlass, which can result in invalid memory accesses.
//
// See issue JDK-8057622 for details.
extak = tak->cast_to_exactness(true)->is_klassptr();
reason = Deoptimization::Reason_array_check;
}
@@ -231,17 +225,22 @@ Node* Parse::array_store_check() {
tak->klass());
}
// Cast array klass to exactness
replace_in_map(array_klass,con);
replace_in_map(array_klass, con);
array_klass = con;
Node* cast = _gvn.transform(new CheckCastPPNode(control(), ary, extak->as_instance_type()));
replace_in_map(ary, cast);
ary = cast;

// Recompute element type and address
const TypeAryPtr* arytype = _gvn.type(ary)->is_aryptr();
elemtype = arytype->elem();
adr = array_element_address(ary, idx, T_OBJECT, arytype->size(), control());

CompileLog* log = C->log();
if (log != NULL) {
log->elem("cast_up reason='monomorphic_array' from='%d' to='(exact)'",
log->identify(tak->klass()));
}
// Use cast value moving forward
array_klass = con;
}
}
}
@@ -259,8 +258,7 @@ Node* Parse::array_store_check() {
immutable_memory(), p2, tak));

// Handle inline type arrays
const Type* elemtype = _gvn.type(ary)->is_aryptr()->elem();
if (elemtype->isa_inlinetype() != NULL || elemtype->is_inlinetypeptr()) {
if (elemtype->isa_inlinetype() != NULL || (elemtype->is_inlinetypeptr() && !elemtype->maybe_null())) {
// We statically know that this is an inline type array, use precise klass ptr
a_e_klass = makecon(TypeKlassPtr::make(elemtype->inline_klass()));
}
@@ -144,6 +144,7 @@
private static final int OSR_TEST_TIMEOUT = Integer.parseInt(System.getProperty("OSRTestTimeOut", "5000"));
protected static final boolean STRESS_CC = Boolean.parseBoolean(System.getProperty("StressCC", "false"));
private static final boolean SHUFFLE_TESTS = Boolean.parseBoolean(System.getProperty("ShuffleTests", "true"));
private static final boolean PREFER_CL_FLAGS = Boolean.parseBoolean(System.getProperty("PreferCommandLineFlags", "false"));

// "jtreg -DXcomp=true" runs all the scenarios with -Xcomp. This is faster than "jtreg -javaoptions:-Xcomp".
protected static final boolean RUN_SCENARIOS_WITH_XCOMP = Boolean.parseBoolean(System.getProperty("Xcomp", "false"));
@@ -362,12 +363,19 @@ public static void main(String[] args) throws Throwable {
System.out.println("Scenario #" + i + " is skipped due to -Dscenarios=" + SCENARIOS);
} else {
System.out.println("Scenario #" + i + " -------- ");
String[] cmds = InputArguments.getVmInputArgs();
String[] cmds = new String[0];
if (!PREFER_CL_FLAGS) {
cmds = InputArguments.getVmInputArgs();
}
if (RUN_SCENARIOS_WITH_XCOMP) {
cmds = concat(cmds, "-Xcomp");
}
cmds = concat(cmds, test.getVMParameters(i));
cmds = concat(cmds, test.getExtraVMParameters(i));
if (PREFER_CL_FLAGS) {
// Prefer flags set via the command line over the ones set by the test scenarios
cmds = concat(cmds, InputArguments.getVmInputArgs());
}
cmds = concat(cmds, testMainClassName);

OutputAnalyzer oa = ProcessTools.executeTestJvm(cmds);

0 comments on commit 56ddef2

Please sign in to comment.