Skip to content

Commit 41c0587

Browse files
author
Vladimir Ivanov
committed
8255367: C2: Deoptimization during vector box construction is broken
Reviewed-by: thartmann, kvn
1 parent f79e9d4 commit 41c0587

File tree

4 files changed

+87
-92
lines changed

4 files changed

+87
-92
lines changed

src/hotspot/share/opto/graphKit.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,11 @@ class GraphKit : public Phase {
889889
void add_empty_predicate_impl(Deoptimization::DeoptReason reason, int nargs);
890890

891891
Node* make_constant_from_field(ciField* field, Node* obj);
892+
893+
// Vector API support (implemented in vectorIntrinsics.cpp)
894+
Node* box_vector(Node* in, const TypeInstPtr* vbox_type, BasicType elem_bt, int num_elem, bool deoptimize_on_exception = false);
895+
Node* unbox_vector(Node* in, const TypeInstPtr* vbox_type, BasicType elem_bt, int num_elem, bool shuffle_to_vector = false);
896+
Node* vector_shift_count(Node* cnt, int shift_op, BasicType bt, int num_elem);
892897
};
893898

894899
// Helper class to support building of control flow branches. Upon

src/hotspot/share/opto/library_call.hpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -324,9 +324,6 @@ class LibraryCallKit : public GraphKit {
324324
bool inline_vector_convert();
325325
bool inline_vector_extract();
326326
bool inline_vector_insert();
327-
Node* box_vector(Node* in, const TypeInstPtr* vbox_type, BasicType bt, int num_elem);
328-
Node* unbox_vector(Node* in, const TypeInstPtr* vbox_type, BasicType bt, int num_elem, bool shuffle_to_vector = false);
329-
Node* shift_count(Node* cnt, int shift_op, BasicType bt, int num_elem);
330327

331328
enum VectorMaskUseType {
332329
VecMaskUseLoad,

src/hotspot/share/opto/vector.cpp

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -192,22 +192,13 @@ void PhaseVector::scalarize_vbox_node(VectorBoxNode* vec_box) {
192192

193193
Node* new_vbox = NULL;
194194
{
195-
PreserveReexecuteState prs(&kit);
196-
197-
kit.jvms()->set_should_reexecute(true);
198-
199-
const TypeInstPtr* vbox_type = vec_box->box_type();
200-
const TypeVect* vect_type = vec_box->vec_type();
201195
Node* vect = vec_box->in(VectorBoxNode::Value);
196+
const TypeInstPtr* vbox_type = vec_box->box_type();
197+
const TypeVect* vt = vec_box->vec_type();
198+
BasicType elem_bt = vt->element_basic_type();
199+
int num_elem = vt->length();
202200

203-
VectorBoxAllocateNode* alloc = new VectorBoxAllocateNode(C, vbox_type);
204-
kit.set_edges_for_java_call(alloc, /*must_throw=*/false, /*separate_io_proj=*/true);
205-
kit.make_slow_call_ex(alloc, C->env()->Throwable_klass(), /*separate_io_proj=*/true, /*deoptimize=*/true);
206-
kit.set_i_o(gvn.transform( new ProjNode(alloc, TypeFunc::I_O) ));
207-
kit.set_all_memory(gvn.transform( new ProjNode(alloc, TypeFunc::Memory) ));
208-
Node* ret = gvn.transform(new ProjNode(alloc, TypeFunc::Parms));
209-
210-
new_vbox = gvn.transform(new VectorBoxNode(C, ret, vect, vbox_type, vect_type));
201+
new_vbox = kit.box_vector(vect, vbox_type, elem_bt, num_elem, /*deoptimize=*/true);
211202

212203
kit.replace_in_map(vec_box, new_vbox);
213204
}
@@ -367,12 +358,12 @@ Node* PhaseVector::expand_vbox_alloc_node(VectorBoxAllocateNode* vbox_alloc,
367358

368359
// The store should be captured by InitializeNode and turned into initialized store later.
369360
Node* field_store = gvn.transform(kit.access_store_at(vec_obj,
370-
vec_field,
371-
vec_adr_type,
372-
arr,
373-
TypeOopPtr::make_from_klass(field->type()->as_klass()),
374-
T_OBJECT,
375-
IN_HEAP));
361+
vec_field,
362+
vec_adr_type,
363+
arr,
364+
TypeOopPtr::make_from_klass(field->type()->as_klass()),
365+
T_OBJECT,
366+
IN_HEAP));
376367
kit.set_memory(field_store, vec_adr_type);
377368

378369
kit.replace_call(vbox_alloc, vec_obj, true);

src/hotspot/share/opto/vectorIntrinsics.cpp

Lines changed: 71 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,76 @@
2929
#include "opto/vectornode.hpp"
3030
#include "prims/vectorSupport.hpp"
3131

32+
#ifdef ASSERT
33+
static bool is_vector(ciKlass* klass) {
34+
return klass->is_subclass_of(ciEnv::current()->vector_VectorPayload_klass());
35+
}
36+
37+
static bool check_vbox(const TypeInstPtr* vbox_type) {
38+
assert(vbox_type->klass_is_exact(), "");
39+
40+
ciInstanceKlass* ik = vbox_type->klass()->as_instance_klass();
41+
assert(is_vector(ik), "not a vector");
42+
43+
ciField* fd1 = ik->get_field_by_name(ciSymbol::ETYPE_name(), ciSymbol::class_signature(), /* is_static */ true);
44+
assert(fd1 != NULL, "element type info is missing");
45+
46+
ciConstant val1 = fd1->constant_value();
47+
BasicType elem_bt = val1.as_object()->as_instance()->java_mirror_type()->basic_type();
48+
assert(is_java_primitive(elem_bt), "element type info is missing");
49+
50+
ciField* fd2 = ik->get_field_by_name(ciSymbol::VLENGTH_name(), ciSymbol::int_signature(), /* is_static */ true);
51+
assert(fd2 != NULL, "vector length info is missing");
52+
53+
ciConstant val2 = fd2->constant_value();
54+
assert(val2.as_int() > 0, "vector length info is missing");
55+
56+
return true;
57+
}
58+
#endif
59+
60+
Node* GraphKit::box_vector(Node* vector, const TypeInstPtr* vbox_type, BasicType elem_bt, int num_elem, bool deoptimize_on_exception) {
61+
assert(EnableVectorSupport, "");
62+
63+
PreserveReexecuteState preexecs(this);
64+
jvms()->set_should_reexecute(true);
65+
66+
VectorBoxAllocateNode* alloc = new VectorBoxAllocateNode(C, vbox_type);
67+
set_edges_for_java_call(alloc, /*must_throw=*/false, /*separate_io_proj=*/true);
68+
make_slow_call_ex(alloc, env()->Throwable_klass(), /*separate_io_proj=*/true, deoptimize_on_exception);
69+
set_i_o(gvn().transform( new ProjNode(alloc, TypeFunc::I_O) ));
70+
set_all_memory(gvn().transform( new ProjNode(alloc, TypeFunc::Memory) ));
71+
Node* ret = gvn().transform(new ProjNode(alloc, TypeFunc::Parms));
72+
73+
assert(check_vbox(vbox_type), "");
74+
const TypeVect* vt = TypeVect::make(elem_bt, num_elem);
75+
VectorBoxNode* vbox = new VectorBoxNode(C, ret, vector, vbox_type, vt);
76+
return gvn().transform(vbox);
77+
}
78+
79+
Node* GraphKit::unbox_vector(Node* v, const TypeInstPtr* vbox_type, BasicType elem_bt, int num_elem, bool shuffle_to_vector) {
80+
assert(EnableVectorSupport, "");
81+
const TypeInstPtr* vbox_type_v = gvn().type(v)->is_instptr();
82+
if (vbox_type->klass() != vbox_type_v->klass()) {
83+
return NULL; // arguments don't agree on vector shapes
84+
}
85+
if (vbox_type_v->maybe_null()) {
86+
return NULL; // no nulls are allowed
87+
}
88+
assert(check_vbox(vbox_type), "");
89+
const TypeVect* vt = TypeVect::make(elem_bt, num_elem);
90+
Node* unbox = gvn().transform(new VectorUnboxNode(C, vt, v, merged_memory(), shuffle_to_vector));
91+
return unbox;
92+
}
93+
94+
Node* GraphKit::vector_shift_count(Node* cnt, int shift_op, BasicType bt, int num_elem) {
95+
assert(bt == T_INT || bt == T_LONG || bt == T_SHORT || bt == T_BYTE, "byte, short, long and int are supported");
96+
juint mask = (type2aelembytes(bt) * BitsPerByte - 1);
97+
Node* nmask = gvn().transform(ConNode::make(TypeInt::make(mask)));
98+
Node* mcnt = gvn().transform(new AndINode(cnt, nmask));
99+
return gvn().transform(VectorNode::shift_count(shift_op, mcnt, num_elem, bt));
100+
}
101+
32102
bool LibraryCallKit::arch_supports_vector(int sopc, int num_elem, BasicType type, VectorMaskUseType mask_use_type, bool has_scalar_args) {
33103
// Check that the operation is valid.
34104
if (sopc <= 0) {
@@ -108,66 +178,6 @@ static bool is_klass_initialized(const TypeInstPtr* vec_klass) {
108178
return klass->is_initialized();
109179
}
110180

111-
#ifdef ASSERT
112-
static bool is_vector(ciKlass* klass) {
113-
return klass->is_subclass_of(ciEnv::current()->vector_VectorPayload_klass());
114-
}
115-
116-
static bool check_vbox(const TypeInstPtr* vbox_type) {
117-
assert(vbox_type->klass_is_exact(), "");
118-
119-
ciInstanceKlass* ik = vbox_type->klass()->as_instance_klass();
120-
assert(is_vector(ik), "not a vector");
121-
122-
ciField* fd1 = ik->get_field_by_name(ciSymbol::ETYPE_name(), ciSymbol::class_signature(), /* is_static */ true);
123-
assert(fd1 != NULL, "element type info is missing");
124-
125-
ciConstant val1 = fd1->constant_value();
126-
BasicType elem_bt = val1.as_object()->as_instance()->java_mirror_type()->basic_type();
127-
assert(is_java_primitive(elem_bt), "element type info is missing");
128-
129-
ciField* fd2 = ik->get_field_by_name(ciSymbol::VLENGTH_name(), ciSymbol::int_signature(), /* is_static */ true);
130-
assert(fd2 != NULL, "vector length info is missing");
131-
132-
ciConstant val2 = fd2->constant_value();
133-
assert(val2.as_int() > 0, "vector length info is missing");
134-
135-
return true;
136-
}
137-
#endif
138-
139-
Node* LibraryCallKit::box_vector(Node* vector, const TypeInstPtr* vbox_type,
140-
BasicType elem_bt, int num_elem) {
141-
assert(EnableVectorSupport, "");
142-
const TypeVect* vec_type = TypeVect::make(elem_bt, num_elem);
143-
144-
VectorBoxAllocateNode* alloc = new VectorBoxAllocateNode(C, vbox_type);
145-
set_edges_for_java_call(alloc, /*must_throw=*/false, /*separate_io_proj=*/true);
146-
make_slow_call_ex(alloc, env()->Throwable_klass(), /*separate_io_proj=*/true);
147-
set_i_o(gvn().transform( new ProjNode(alloc, TypeFunc::I_O) ));
148-
set_all_memory(gvn().transform( new ProjNode(alloc, TypeFunc::Memory) ));
149-
Node* ret = gvn().transform(new ProjNode(alloc, TypeFunc::Parms));
150-
151-
assert(check_vbox(vbox_type), "");
152-
VectorBoxNode* vbox = new VectorBoxNode(C, ret, vector, vbox_type, vec_type);
153-
return gvn().transform(vbox);
154-
}
155-
156-
Node* LibraryCallKit::unbox_vector(Node* v, const TypeInstPtr* vbox_type, BasicType elem_bt, int num_elem, bool shuffle_to_vector) {
157-
assert(EnableVectorSupport, "");
158-
const TypeInstPtr* vbox_type_v = gvn().type(v)->is_instptr();
159-
if (vbox_type->klass() != vbox_type_v->klass()) {
160-
return NULL; // arguments don't agree on vector shapes
161-
}
162-
if (vbox_type_v->maybe_null()) {
163-
return NULL; // no nulls are allowed
164-
}
165-
assert(check_vbox(vbox_type), "");
166-
const TypeVect* vec_type = TypeVect::make(elem_bt, num_elem);
167-
Node* unbox = gvn().transform(new VectorUnboxNode(C, vec_type, v, merged_memory(), shuffle_to_vector));
168-
return unbox;
169-
}
170-
171181
// public static
172182
// <VM>
173183
// VM unaryOp(int oprId, Class<? extends VM> vmClass, Class<?> elementType, int length,
@@ -1165,14 +1175,6 @@ bool LibraryCallKit::inline_vector_rearrange() {
11651175
return true;
11661176
}
11671177

1168-
Node* LibraryCallKit::shift_count(Node* cnt, int shift_op, BasicType bt, int num_elem) {
1169-
assert(bt == T_INT || bt == T_LONG || bt == T_SHORT || bt == T_BYTE, "byte, short, long and int are supported");
1170-
juint mask = (type2aelembytes(bt) * BitsPerByte - 1);
1171-
Node* nmask = gvn().transform(ConNode::make(TypeInt::make(mask)));
1172-
Node* mcnt = gvn().transform(new AndINode(cnt, nmask));
1173-
return gvn().transform(VectorNode::shift_count(shift_op, mcnt, num_elem, bt));
1174-
}
1175-
11761178
// public static
11771179
// <V extends Vector<?,?>>
11781180
// V broadcastInt(int opr, Class<V> vectorClass, Class<?> elementType, int vlen,
@@ -1223,7 +1225,7 @@ bool LibraryCallKit::inline_vector_broadcast_int() {
12231225
return false; // not supported
12241226
}
12251227
Node* opd1 = unbox_vector(argument(4), vbox_type, elem_bt, num_elem);
1226-
Node* opd2 = shift_count(argument(5), opc, elem_bt, num_elem);
1228+
Node* opd2 = vector_shift_count(argument(5), opc, elem_bt, num_elem);
12271229
if (opd1 == NULL || opd2 == NULL) {
12281230
return false;
12291231
}

0 commit comments

Comments
 (0)