8261158: JVMState should not be shared between SafePointNodes
Reviewed-by: vlivanov, kvn
This commit is contained in:
parent
476994aa37
commit
06d7602833
@ -147,7 +147,7 @@ ArchDesc::ArchDesc()
|
|||||||
_internalMatch(cmpstr,hashstr, Form::arena),
|
_internalMatch(cmpstr,hashstr, Form::arena),
|
||||||
_chainRules(cmpstr,hashstr, Form::arena),
|
_chainRules(cmpstr,hashstr, Form::arena),
|
||||||
_cisc_spill_operand(NULL),
|
_cisc_spill_operand(NULL),
|
||||||
_needs_clone_jvms(false) {
|
_needs_deep_clone_jvms(false) {
|
||||||
|
|
||||||
// Initialize the opcode to MatchList table with NULLs
|
// Initialize the opcode to MatchList table with NULLs
|
||||||
for( int i=0; i<_last_opcode; ++i ) {
|
for( int i=0; i<_last_opcode; ++i ) {
|
||||||
|
@ -123,9 +123,9 @@ private:
|
|||||||
|
|
||||||
// If a Call node uses $constanttablebase, it gets MachConstantBaseNode
|
// If a Call node uses $constanttablebase, it gets MachConstantBaseNode
|
||||||
// by the matcher and the matcher will modify the jvms. If so, jvm states
|
// by the matcher and the matcher will modify the jvms. If so, jvm states
|
||||||
// always have to be cloned when a node is cloned. Adlc generates
|
// always have to be deep cloned when a node is cloned. Adlc generates
|
||||||
// Compile::needs_clone_jvms() accordingly.
|
// Compile::needs_deep_clone_jvms() accordingly.
|
||||||
bool _needs_clone_jvms;
|
bool _needs_deep_clone_jvms;
|
||||||
|
|
||||||
// Methods for outputting the DFA
|
// Methods for outputting the DFA
|
||||||
void gen_match(FILE *fp, MatchList &mlist, ProductionState &status, Dict &operands_chained_from);
|
void gen_match(FILE *fp, MatchList &mlist, ProductionState &status, Dict &operands_chained_from);
|
||||||
@ -295,7 +295,7 @@ public:
|
|||||||
void addPreHeaderBlocks(FILE *fp_hpp);
|
void addPreHeaderBlocks(FILE *fp_hpp);
|
||||||
void addHeaderBlocks(FILE *fp_hpp);
|
void addHeaderBlocks(FILE *fp_hpp);
|
||||||
void addSourceBlocks(FILE *fp_cpp);
|
void addSourceBlocks(FILE *fp_cpp);
|
||||||
void generate_needs_clone_jvms(FILE *fp_cpp);
|
void generate_needs_deep_clone_jvms(FILE *fp_cpp);
|
||||||
void generate_adlc_verification(FILE *fp_cpp);
|
void generate_adlc_verification(FILE *fp_cpp);
|
||||||
|
|
||||||
// output declaration of class State
|
// output declaration of class State
|
||||||
|
@ -305,7 +305,7 @@ int main(int argc, char *argv[])
|
|||||||
AD.buildInstructMatchCheck(AD._CPP_file._fp); // .cpp
|
AD.buildInstructMatchCheck(AD._CPP_file._fp); // .cpp
|
||||||
// define methods for machine dependent frame management
|
// define methods for machine dependent frame management
|
||||||
AD.buildFrameMethods(AD._CPP_file._fp); // .cpp
|
AD.buildFrameMethods(AD._CPP_file._fp); // .cpp
|
||||||
AD.generate_needs_clone_jvms(AD._CPP_file._fp);
|
AD.generate_needs_deep_clone_jvms(AD._CPP_file._fp);
|
||||||
|
|
||||||
// do this last:
|
// do this last:
|
||||||
AD.addPreprocessorChecks(AD._CPP_file._fp); // .cpp
|
AD.addPreprocessorChecks(AD._CPP_file._fp); // .cpp
|
||||||
|
@ -1792,7 +1792,7 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
|
|||||||
if (node->is_ideal_call() != Form::invalid_type &&
|
if (node->is_ideal_call() != Form::invalid_type &&
|
||||||
node->is_ideal_call() != Form::JAVA_LEAF) {
|
node->is_ideal_call() != Form::JAVA_LEAF) {
|
||||||
fprintf(fp, " // MachConstantBaseNode added in matcher.\n");
|
fprintf(fp, " // MachConstantBaseNode added in matcher.\n");
|
||||||
_needs_clone_jvms = true;
|
_needs_deep_clone_jvms = true;
|
||||||
} else {
|
} else {
|
||||||
fprintf(fp, " add_req(C->mach_constant_base_node());\n");
|
fprintf(fp, " add_req(C->mach_constant_base_node());\n");
|
||||||
}
|
}
|
||||||
@ -3603,9 +3603,9 @@ char reg_save_policy(const char *calling_convention) {
|
|||||||
return callconv;
|
return callconv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchDesc::generate_needs_clone_jvms(FILE *fp_cpp) {
|
void ArchDesc::generate_needs_deep_clone_jvms(FILE *fp_cpp) {
|
||||||
fprintf(fp_cpp, "bool Compile::needs_clone_jvms() { return %s; }\n\n",
|
fprintf(fp_cpp, "bool Compile::needs_deep_clone_jvms() { return %s; }\n\n",
|
||||||
_needs_clone_jvms ? "true" : "false");
|
_needs_deep_clone_jvms ? "true" : "false");
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------generate_assertion_checks-------------------
|
//---------------------------generate_assertion_checks-------------------
|
||||||
|
@ -1362,6 +1362,7 @@ SafePointNode* SafePointNode::next_exception() const {
|
|||||||
//------------------------------Ideal------------------------------------------
|
//------------------------------Ideal------------------------------------------
|
||||||
// Skip over any collapsed Regions
|
// Skip over any collapsed Regions
|
||||||
Node *SafePointNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
Node *SafePointNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||||
|
assert(_jvms == NULL || ((uintptr_t)_jvms->map() & 1) || _jvms->map() == this, "inconsistent JVMState");
|
||||||
return remove_dead_region(phase, can_reshape) ? this : NULL;
|
return remove_dead_region(phase, can_reshape) ? this : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,6 +352,18 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
JVMState* jvms() const { return _jvms; }
|
JVMState* jvms() const { return _jvms; }
|
||||||
|
virtual bool needs_deep_clone_jvms(Compile* C) { return false; }
|
||||||
|
void clone_jvms(Compile* C) {
|
||||||
|
if (jvms() != NULL) {
|
||||||
|
if (needs_deep_clone_jvms(C)) {
|
||||||
|
set_jvms(jvms()->clone_deep(C));
|
||||||
|
jvms()->set_map_deep(this);
|
||||||
|
} else {
|
||||||
|
jvms()->clone_shallow(C)->bind_map(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void verify_input(JVMState* jvms, uint idx) const {
|
void verify_input(JVMState* jvms, uint idx) const {
|
||||||
assert(verify_jvms(jvms), "jvms must match");
|
assert(verify_jvms(jvms), "jvms must match");
|
||||||
@ -615,14 +627,8 @@ public:
|
|||||||
virtual bool guaranteed_safepoint() { return true; }
|
virtual bool guaranteed_safepoint() { return true; }
|
||||||
// For macro nodes, the JVMState gets modified during expansion. If calls
|
// For macro nodes, the JVMState gets modified during expansion. If calls
|
||||||
// use MachConstantBase, it gets modified during matching. So when cloning
|
// use MachConstantBase, it gets modified during matching. So when cloning
|
||||||
// the node the JVMState must be cloned. Default is not to clone.
|
// the node the JVMState must be deep cloned. Default is to shallow clone.
|
||||||
virtual bool needs_clone_jvms(Compile* C) { return C->needs_clone_jvms(); }
|
virtual bool needs_deep_clone_jvms(Compile* C) { return C->needs_deep_clone_jvms(); }
|
||||||
void clone_jvms(Compile* C) {
|
|
||||||
if ((jvms() != NULL) && needs_clone_jvms(C)) {
|
|
||||||
set_jvms(jvms()->clone_deep(C));
|
|
||||||
jvms()->set_map_deep(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true if the call may modify n
|
// Returns true if the call may modify n
|
||||||
virtual bool may_modify(const TypeOopPtr* t_oop, PhaseTransform* phase);
|
virtual bool may_modify(const TypeOopPtr* t_oop, PhaseTransform* phase);
|
||||||
@ -736,10 +742,10 @@ public:
|
|||||||
bool is_boxing_method() const {
|
bool is_boxing_method() const {
|
||||||
return is_macro() && (method() != NULL) && method()->is_boxing_method();
|
return is_macro() && (method() != NULL) && method()->is_boxing_method();
|
||||||
}
|
}
|
||||||
// Late inlining modifies the JVMState, so we need to clone it
|
// Late inlining modifies the JVMState, so we need to deep clone it
|
||||||
// when the call node is cloned (because it is macro node).
|
// when the call node is cloned (because it is macro node).
|
||||||
virtual bool needs_clone_jvms(Compile* C) {
|
virtual bool needs_deep_clone_jvms(Compile* C) {
|
||||||
return is_boxing_method() || CallNode::needs_clone_jvms(C);
|
return is_boxing_method() || CallNode::needs_deep_clone_jvms(C);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int Opcode() const;
|
virtual int Opcode() const;
|
||||||
@ -762,10 +768,10 @@ public:
|
|||||||
init_class_id(Class_CallDynamicJava);
|
init_class_id(Class_CallDynamicJava);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Late inlining modifies the JVMState, so we need to clone it
|
// Late inlining modifies the JVMState, so we need to deep clone it
|
||||||
// when the call node is cloned.
|
// when the call node is cloned.
|
||||||
virtual bool needs_clone_jvms(Compile* C) {
|
virtual bool needs_deep_clone_jvms(Compile* C) {
|
||||||
return IncrementalInlineVirtual || CallNode::needs_clone_jvms(C);
|
return IncrementalInlineVirtual || CallNode::needs_deep_clone_jvms(C);
|
||||||
}
|
}
|
||||||
|
|
||||||
int _vtable_index;
|
int _vtable_index;
|
||||||
@ -917,8 +923,8 @@ public:
|
|||||||
virtual uint size_of() const; // Size is bigger
|
virtual uint size_of() const; // Size is bigger
|
||||||
AllocateNode(Compile* C, const TypeFunc *atype, Node *ctrl, Node *mem, Node *abio,
|
AllocateNode(Compile* C, const TypeFunc *atype, Node *ctrl, Node *mem, Node *abio,
|
||||||
Node *size, Node *klass_node, Node *initial_test);
|
Node *size, Node *klass_node, Node *initial_test);
|
||||||
// Expansion modifies the JVMState, so we need to clone it
|
// Expansion modifies the JVMState, so we need to deep clone it
|
||||||
virtual bool needs_clone_jvms(Compile* C) { return true; }
|
virtual bool needs_deep_clone_jvms(Compile* C) { return true; }
|
||||||
virtual int Opcode() const;
|
virtual int Opcode() const;
|
||||||
virtual uint ideal_reg() const { return Op_RegP; }
|
virtual uint ideal_reg() const { return Op_RegP; }
|
||||||
virtual bool guaranteed_safepoint() { return false; }
|
virtual bool guaranteed_safepoint() { return false; }
|
||||||
@ -1131,8 +1137,8 @@ public:
|
|||||||
virtual bool guaranteed_safepoint() { return false; }
|
virtual bool guaranteed_safepoint() { return false; }
|
||||||
|
|
||||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||||
// Expansion modifies the JVMState, so we need to clone it
|
// Expansion modifies the JVMState, so we need to deep clone it
|
||||||
virtual bool needs_clone_jvms(Compile* C) { return true; }
|
virtual bool needs_deep_clone_jvms(Compile* C) { return true; }
|
||||||
|
|
||||||
bool is_nested_lock_region(); // Is this Lock nested?
|
bool is_nested_lock_region(); // Is this Lock nested?
|
||||||
bool is_nested_lock_region(Compile * c); // Why isn't this Lock nested?
|
bool is_nested_lock_region(Compile * c); // Why isn't this Lock nested?
|
||||||
|
@ -792,7 +792,7 @@ class Compile : public Phase {
|
|||||||
MachConstantBaseNode* mach_constant_base_node();
|
MachConstantBaseNode* mach_constant_base_node();
|
||||||
bool has_mach_constant_base_node() const { return _mach_constant_base_node != NULL; }
|
bool has_mach_constant_base_node() const { return _mach_constant_base_node != NULL; }
|
||||||
// Generated by adlc, true if CallNode requires MachConstantBase.
|
// Generated by adlc, true if CallNode requires MachConstantBase.
|
||||||
bool needs_clone_jvms();
|
bool needs_deep_clone_jvms();
|
||||||
|
|
||||||
// Handy undefined Node
|
// Handy undefined Node
|
||||||
Node* top() const { return _top; }
|
Node* top() const { return _top; }
|
||||||
|
@ -558,8 +558,6 @@ Node *Node::clone() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (n->is_Call()) {
|
if (n->is_Call()) {
|
||||||
// cloning CallNode may need to clone JVMState
|
|
||||||
n->as_Call()->clone_jvms(C);
|
|
||||||
// CallGenerator is linked to the original node.
|
// CallGenerator is linked to the original node.
|
||||||
CallGenerator* cg = n->as_Call()->generator();
|
CallGenerator* cg = n->as_Call()->generator();
|
||||||
if (cg != NULL) {
|
if (cg != NULL) {
|
||||||
@ -572,6 +570,9 @@ Node *Node::clone() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (n->is_SafePoint()) {
|
if (n->is_SafePoint()) {
|
||||||
|
// Scalar replacement and macro expansion might modify the JVMState.
|
||||||
|
// Clone it to make sure it's not shared between SafePointNodes.
|
||||||
|
n->as_SafePoint()->clone_jvms(C);
|
||||||
n->as_SafePoint()->clone_replaced_nodes();
|
n->as_SafePoint()->clone_replaced_nodes();
|
||||||
}
|
}
|
||||||
return n; // Return the clone
|
return n; // Return the clone
|
||||||
|
Loading…
Reference in New Issue
Block a user