From 73be94ce9b9076346a402c330e46231e7debab33 Mon Sep 17 00:00:00 2001 From: Wanghuang-Huawei Date: Thu, 4 Feb 2021 16:35:06 +0800 Subject: [PATCH 01/12] 8261137: Optimization of Box nodes in uncommon_trap --- src/hotspot/share/opto/callGenerator.cpp | 47 +++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index 59cbfe11c458f..5e03824f20498 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -603,6 +603,51 @@ void CallGenerator::do_late_inline_helper() { C->remove_macro_node(call); } + if (callprojs.resproj != NULL && call->is_CallStaticJava() && + call->as_CallStaticJava()->is_boxing_method()) { + GraphKit kit(call->jvms()); + PhaseGVN& gvn = kit.gvn(); + + Node_List delay_boxes; + bool no_use = true; + for (DUIterator_Fast imax, i = callprojs.resproj->fast_outs(imax); i < imax; i++) { + Node* m = callprojs.resproj->fast_out(i); + if (m->is_CallStaticJava() && + m->as_CallStaticJava()->uncommon_trap_request() != 0) { + delay_boxes.push(m); + } else { + no_use = false; + break; + } + } + + if (no_use) { + // delay box node in uncommon_trap runtime, treat box as a scalarized object + while (delay_boxes.size() > 0) { + ProjNode* res = callprojs.resproj->as_Proj(); + Node* uncommon_trap_node = delay_boxes.pop(); + int in_edge = uncommon_trap_node->find_edge(res); + assert(in_edge > 0, "sanity"); + + ciInstanceKlass* klass = call->as_CallStaticJava()->method()->holder(); + int n_fields = klass->nof_nonstatic_fields(); + assert(n_fields == 1, "sanity"); + + uint first_ind = (uncommon_trap_node->req() - uncommon_trap_node->jvms()->scloff()); + Node* sobj = new SafePointScalarObjectNode(gvn.type(res)->isa_oopptr(), +#ifdef ASSERT + NULL, +#endif // ASSERT + first_ind, n_fields); + sobj->init_req(0, C->root()); + uncommon_trap_node->add_req(call->in(res->_con)); + sobj = gvn.transform(sobj); + uncommon_trap_node->jvms()->set_endoff(uncommon_trap_node->req()); + uncommon_trap_node->set_req(in_edge, sobj); + } + } + } + bool result_not_used = (callprojs.resproj == NULL || callprojs.resproj->outcnt() == 0); if (is_pure_call() && result_not_used) { // The call is marked as pure (no important side effects), but result isn't used. From 4dfee52a6a0136eab47cd00c291a109895f948bd Mon Sep 17 00:00:00 2001 From: Wanghuang-Huawei Date: Fri, 5 Feb 2021 15:25:21 +0800 Subject: [PATCH 02/12] refactor codes --- src/hotspot/share/opto/callGenerator.cpp | 92 ++++++++++++------------ 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index 5e03824f20498..d8b4f5cd9d246 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -554,6 +554,53 @@ void LateInlineVirtualCallGenerator::do_late_inline() { CallGenerator::do_late_inline_helper(); } +static void delay_box_in_uncommon_trap(CallNode* call, Node* resproj) { + if (resproj != NULL && call->is_CallStaticJava() && + call->as_CallStaticJava()->is_boxing_method()) { + GraphKit kit(call->jvms()); + PhaseGVN& gvn = kit.gvn(); + + Node_List delay_boxes; + bool no_use = true; + for (DUIterator_Fast imax, i = resproj->fast_outs(imax); i < imax; i++) { + Node* m = resproj->fast_out(i); + if (m->is_CallStaticJava() && + m->as_CallStaticJava()->uncommon_trap_request() != 0) { + delay_boxes.push(m); + } else { + no_use = false; + break; + } + } + + if (no_use) { + // delay box node in uncommon_trap runtime, treat box as a scalarized object + while (delay_boxes.size() > 0) { + ProjNode* res = resproj->as_Proj(); + Node* uncommon_trap_node = delay_boxes.pop(); + int in_edge = uncommon_trap_node->find_edge(res); + assert(in_edge > 0, "sanity"); + + ciInstanceKlass* klass = call->as_CallStaticJava()->method()->holder(); + int n_fields = klass->nof_nonstatic_fields(); + assert(n_fields == 1, "sanity"); + + uint first_ind = (uncommon_trap_node->req() - uncommon_trap_node->jvms()->scloff()); + Node* sobj = new SafePointScalarObjectNode(gvn.type(res)->isa_oopptr(), +#ifdef ASSERT + NULL, +#endif // ASSERT + first_ind, n_fields); + sobj->init_req(0, kit.root()); + uncommon_trap_node->add_req(call->in(res->_con)); + sobj = gvn.transform(sobj); + uncommon_trap_node->jvms()->set_endoff(uncommon_trap_node->req()); + uncommon_trap_node->set_req(in_edge, sobj); + } + } + } +} + void CallGenerator::do_late_inline_helper() { assert(is_late_inline(), "only late inline allowed"); @@ -603,50 +650,7 @@ void CallGenerator::do_late_inline_helper() { C->remove_macro_node(call); } - if (callprojs.resproj != NULL && call->is_CallStaticJava() && - call->as_CallStaticJava()->is_boxing_method()) { - GraphKit kit(call->jvms()); - PhaseGVN& gvn = kit.gvn(); - - Node_List delay_boxes; - bool no_use = true; - for (DUIterator_Fast imax, i = callprojs.resproj->fast_outs(imax); i < imax; i++) { - Node* m = callprojs.resproj->fast_out(i); - if (m->is_CallStaticJava() && - m->as_CallStaticJava()->uncommon_trap_request() != 0) { - delay_boxes.push(m); - } else { - no_use = false; - break; - } - } - - if (no_use) { - // delay box node in uncommon_trap runtime, treat box as a scalarized object - while (delay_boxes.size() > 0) { - ProjNode* res = callprojs.resproj->as_Proj(); - Node* uncommon_trap_node = delay_boxes.pop(); - int in_edge = uncommon_trap_node->find_edge(res); - assert(in_edge > 0, "sanity"); - - ciInstanceKlass* klass = call->as_CallStaticJava()->method()->holder(); - int n_fields = klass->nof_nonstatic_fields(); - assert(n_fields == 1, "sanity"); - - uint first_ind = (uncommon_trap_node->req() - uncommon_trap_node->jvms()->scloff()); - Node* sobj = new SafePointScalarObjectNode(gvn.type(res)->isa_oopptr(), -#ifdef ASSERT - NULL, -#endif // ASSERT - first_ind, n_fields); - sobj->init_req(0, C->root()); - uncommon_trap_node->add_req(call->in(res->_con)); - sobj = gvn.transform(sobj); - uncommon_trap_node->jvms()->set_endoff(uncommon_trap_node->req()); - uncommon_trap_node->set_req(in_edge, sobj); - } - } - } + delay_box_in_uncommon_trap(call, callprojs.resproj); bool result_not_used = (callprojs.resproj == NULL || callprojs.resproj->outcnt() == 0); if (is_pure_call() && result_not_used) { From 4c62ec8d5ee4f3cae1ac907e475d62d8af0bade9 Mon Sep 17 00:00:00 2001 From: Wanghuang-Huawei Date: Wed, 10 Feb 2021 14:41:41 +0800 Subject: [PATCH 03/12] fix some bugs --- src/hotspot/share/opto/callGenerator.cpp | 29 ++++++++++++------------ 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index d8b4f5cd9d246..fcb1cfb19ebae 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -555,18 +555,15 @@ void LateInlineVirtualCallGenerator::do_late_inline() { } static void delay_box_in_uncommon_trap(CallNode* call, Node* resproj) { - if (resproj != NULL && call->is_CallStaticJava() && + if (resproj != nullptr && call->is_CallStaticJava() && call->as_CallStaticJava()->is_boxing_method()) { - GraphKit kit(call->jvms()); - PhaseGVN& gvn = kit.gvn(); - - Node_List delay_boxes; + Unique_Node_List uncommon_trap_list; bool no_use = true; for (DUIterator_Fast imax, i = resproj->fast_outs(imax); i < imax; i++) { Node* m = resproj->fast_out(i); if (m->is_CallStaticJava() && m->as_CallStaticJava()->uncommon_trap_request() != 0) { - delay_boxes.push(m); + uncommon_trap_list.push(m); } else { no_use = false; break; @@ -574,28 +571,32 @@ static void delay_box_in_uncommon_trap(CallNode* call, Node* resproj) { } if (no_use) { + GraphKit kit(call->jvms()); + PhaseGVN& gvn = kit.gvn(); + // delay box node in uncommon_trap runtime, treat box as a scalarized object - while (delay_boxes.size() > 0) { + while (uncommon_trap_list.size() > 0) { ProjNode* res = resproj->as_Proj(); - Node* uncommon_trap_node = delay_boxes.pop(); - int in_edge = uncommon_trap_node->find_edge(res); - assert(in_edge > 0, "sanity"); + Node* uncommon_trap_node = uncommon_trap_list.pop(); ciInstanceKlass* klass = call->as_CallStaticJava()->method()->holder(); int n_fields = klass->nof_nonstatic_fields(); - assert(n_fields == 1, "sanity"); + assert(n_fields == 1, "the klass must be an auto-boxing klass"); uint first_ind = (uncommon_trap_node->req() - uncommon_trap_node->jvms()->scloff()); Node* sobj = new SafePointScalarObjectNode(gvn.type(res)->isa_oopptr(), #ifdef ASSERT - NULL, + (AllocateNode*)call, #endif // ASSERT first_ind, n_fields); sobj->init_req(0, kit.root()); uncommon_trap_node->add_req(call->in(res->_con)); sobj = gvn.transform(sobj); - uncommon_trap_node->jvms()->set_endoff(uncommon_trap_node->req()); - uncommon_trap_node->set_req(in_edge, sobj); + JVMState* jvms = uncommon_trap_node->jvms(); + jvms->set_endoff(uncommon_trap_node->req()); + int start = jvms->debug_start(); + int end = jvms->debug_end(); + uncommon_trap_node->replace_edges_in_range(res, sobj, start, end); } } } From e80e49599ef26e71384ba5ee7a4180e6b5cb2e45 Mon Sep 17 00:00:00 2001 From: Wanghuang-Huawei Date: Wed, 10 Feb 2021 14:55:44 +0800 Subject: [PATCH 04/12] delete useless line --- src/hotspot/share/opto/callGenerator.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index fcb1cfb19ebae..214ec1a3a22bf 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -573,7 +573,6 @@ static void delay_box_in_uncommon_trap(CallNode* call, Node* resproj) { if (no_use) { GraphKit kit(call->jvms()); PhaseGVN& gvn = kit.gvn(); - // delay box node in uncommon_trap runtime, treat box as a scalarized object while (uncommon_trap_list.size() > 0) { ProjNode* res = resproj->as_Proj(); From 84290aeb40938caeceac85593e11f387c5c1c6b4 Mon Sep 17 00:00:00 2001 From: Wanghuang-Huawei Date: Tue, 23 Feb 2021 15:30:01 +0800 Subject: [PATCH 05/12] add debuginfo optimization --- src/hotspot/share/opto/callGenerator.cpp | 71 ++++++++++---------- src/hotspot/share/opto/callnode.cpp | 6 +- src/hotspot/share/opto/callnode.hpp | 4 +- src/hotspot/share/opto/output.cpp | 10 +-- src/hotspot/share/runtime/deoptimization.cpp | 15 ++--- src/hotspot/share/runtime/deoptimization.hpp | 3 +- 6 files changed, 59 insertions(+), 50 deletions(-) diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index 214ec1a3a22bf..8a0a1f648a804 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -554,49 +554,52 @@ void LateInlineVirtualCallGenerator::do_late_inline() { CallGenerator::do_late_inline_helper(); } -static void delay_box_in_uncommon_trap(CallNode* call, Node* resproj) { +// replace box node to scalar node only in case it is directly referenced by debug info +static void replace_box_to_scalar(CallNode* call, Node* resproj) { if (resproj != nullptr && call->is_CallStaticJava() && call->as_CallStaticJava()->is_boxing_method()) { - Unique_Node_List uncommon_trap_list; - bool no_use = true; + Unique_Node_List debuginfo_node_list; for (DUIterator_Fast imax, i = resproj->fast_outs(imax); i < imax; i++) { Node* m = resproj->fast_out(i); - if (m->is_CallStaticJava() && - m->as_CallStaticJava()->uncommon_trap_request() != 0) { - uncommon_trap_list.push(m); + if (m->is_SafePoint()) { + SafePointNode* sfpt = m->as_SafePoint(); + uint dbg_start = sfpt->is_Call() ? sfpt->as_Call()->tf()->domain()->cnt() : (uint)TypeFunc::Parms+1; + for (uint i = 0; i < dbg_start; i++) { + if (sfpt->in(i) == resproj) { + return; + } + } + debuginfo_node_list.push(m); } else { - no_use = false; - break; + return; } } - if (no_use) { - GraphKit kit(call->jvms()); - PhaseGVN& gvn = kit.gvn(); - // delay box node in uncommon_trap runtime, treat box as a scalarized object - while (uncommon_trap_list.size() > 0) { - ProjNode* res = resproj->as_Proj(); - Node* uncommon_trap_node = uncommon_trap_list.pop(); - - ciInstanceKlass* klass = call->as_CallStaticJava()->method()->holder(); - int n_fields = klass->nof_nonstatic_fields(); - assert(n_fields == 1, "the klass must be an auto-boxing klass"); - - uint first_ind = (uncommon_trap_node->req() - uncommon_trap_node->jvms()->scloff()); - Node* sobj = new SafePointScalarObjectNode(gvn.type(res)->isa_oopptr(), + GraphKit kit(call->jvms()); + PhaseGVN& gvn = kit.gvn(); + // delay box in runtime, treat box as a scalarized object + while (debuginfo_node_list.size() > 0) { + ProjNode* res = resproj->as_Proj(); + Node* debuginfo_node = debuginfo_node_list.pop(); + + ciInstanceKlass* klass = call->as_CallStaticJava()->method()->holder(); + int n_fields = klass->nof_nonstatic_fields(); + assert(n_fields == 1, "the klass must be an auto-boxing klass"); + + uint first_ind = (debuginfo_node->req() - debuginfo_node->jvms()->scloff()); + Node* sobj = new SafePointScalarObjectNode(gvn.type(res)->isa_oopptr(), #ifdef ASSERT - (AllocateNode*)call, + call->isa_Allocate(), #endif // ASSERT - first_ind, n_fields); - sobj->init_req(0, kit.root()); - uncommon_trap_node->add_req(call->in(res->_con)); - sobj = gvn.transform(sobj); - JVMState* jvms = uncommon_trap_node->jvms(); - jvms->set_endoff(uncommon_trap_node->req()); - int start = jvms->debug_start(); - int end = jvms->debug_end(); - uncommon_trap_node->replace_edges_in_range(res, sobj, start, end); - } + first_ind, n_fields, true); + sobj->init_req(0, kit.root()); + debuginfo_node->add_req(call->in(res->_con)); + sobj = gvn.transform(sobj); + JVMState* jvms = debuginfo_node->jvms(); + jvms->set_endoff(debuginfo_node->req()); + int start = jvms->debug_start(); + int end = jvms->debug_end(); + debuginfo_node->replace_edges_in_range(res, sobj, start, end); } } } @@ -650,7 +653,7 @@ void CallGenerator::do_late_inline_helper() { C->remove_macro_node(call); } - delay_box_in_uncommon_trap(call, callprojs.resproj); + replace_box_to_scalar(call, callprojs.resproj); bool result_not_used = (callprojs.resproj == NULL || callprojs.resproj->outcnt() == 0); if (is_pure_call() && result_not_used) { diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp index b471fc6044057..c5d70164b5732 100644 --- a/src/hotspot/share/opto/callnode.cpp +++ b/src/hotspot/share/opto/callnode.cpp @@ -1512,10 +1512,12 @@ SafePointScalarObjectNode::SafePointScalarObjectNode(const TypeOopPtr* tp, AllocateNode* alloc, #endif uint first_index, - uint n_fields) : + uint n_fields, + bool is_auto_box) : TypeNode(tp, 1), // 1 control input -- seems required. Get from root. _first_index(first_index), - _n_fields(n_fields) + _n_fields(n_fields), + _is_auto_box(is_auto_box) #ifdef ASSERT , _alloc(alloc) #endif diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp index 52ec71878cd3e..de9450e68a538 100644 --- a/src/hotspot/share/opto/callnode.hpp +++ b/src/hotspot/share/opto/callnode.hpp @@ -500,6 +500,7 @@ class SafePointScalarObjectNode: public TypeNode { // states of the scalarized object fields are collected. // It is relative to the last (youngest) jvms->_scloff. uint _n_fields; // Number of non-static fields of the scalarized object. + bool _is_auto_box; // is the scalarized object is auto box. DEBUG_ONLY(AllocateNode* _alloc;) virtual uint hash() const ; // { return NO_HASH; } @@ -512,7 +513,7 @@ class SafePointScalarObjectNode: public TypeNode { #ifdef ASSERT AllocateNode* alloc, #endif - uint first_index, uint n_fields); + uint first_index, uint n_fields, bool is_auto_box = false); virtual int Opcode() const; virtual uint ideal_reg() const; virtual const RegMask &in_RegMask(uint) const; @@ -525,6 +526,7 @@ class SafePointScalarObjectNode: public TypeNode { } uint n_fields() const { return _n_fields; } + bool is_auto_box() const { return _is_auto_box; } #ifdef ASSERT AllocateNode* alloc() const { return _alloc; } #endif diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp index daff5e72ca809..317c63ac6d550 100644 --- a/src/hotspot/share/opto/output.cpp +++ b/src/hotspot/share/opto/output.cpp @@ -826,8 +826,9 @@ void PhaseOutput::FillLocArray( int idx, MachSafePointNode* sfpt, Node *local, ciKlass* cik = t->is_oopptr()->klass(); assert(cik->is_instance_klass() || cik->is_array_klass(), "Not supported allocation."); - sv = new ObjectValue(spobj->_idx, - new ConstantOopWriteValue(cik->java_mirror()->constant_encoding())); + ScopeValue* klass_sv = new ConstantOopWriteValue(cik->java_mirror()->constant_encoding()); + sv = spobj->is_auto_box() ? new AutoBoxObjectValue(spobj->_idx, klass_sv) + : new ObjectValue(spobj->_idx, klass_sv); set_sv_for_object_node(objs, sv); uint first_ind = spobj->first_index(sfpt->jvms()); @@ -1099,8 +1100,9 @@ void PhaseOutput::Process_OopMap_Node(MachNode *mach, int current_offset) { ciKlass* cik = t->is_oopptr()->klass(); assert(cik->is_instance_klass() || cik->is_array_klass(), "Not supported allocation."); - ObjectValue* sv = new ObjectValue(spobj->_idx, - new ConstantOopWriteValue(cik->java_mirror()->constant_encoding())); + ScopeValue* klass_sv = new ConstantOopWriteValue(cik->java_mirror()->constant_encoding()); + ObjectValue* sv = spobj->is_auto_box() ? new AutoBoxObjectValue(spobj->_idx, klass_sv) + : new ObjectValue(spobj->_idx, klass_sv); PhaseOutput::set_sv_for_object_node(objs, sv); uint first_ind = spobj->first_index(youngest_jvms); diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 20a29459be796..6dc80fbd926dd 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -897,7 +897,7 @@ Deoptimization::DeoptAction Deoptimization::_unloaded_action -#if INCLUDE_JVMCI || INCLUDE_AOT +#if COMPILER2 || INCLUDE_JVMCI || INCLUDE_AOT template class BoxCacheBase : public CHeapObj { protected: @@ -1026,7 +1026,7 @@ oop Deoptimization::get_cached_box(AutoBoxObjectValue* bv, frame* fr, RegisterMa } return NULL; } -#endif // INCLUDE_JVMCI || INCLUDE_AOT +#endif // COMPILER2 || INCLUDE_JVMCI || INCLUDE_AOT #if COMPILER2_OR_JVMCI bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, RegisterMap* reg_map, GrowableArray* objects, TRAPS) { @@ -1045,9 +1045,8 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, RegisterMap* oop obj = NULL; if (k->is_instance_klass()) { -#if INCLUDE_JVMCI || INCLUDE_AOT - CompiledMethod* cm = fr->cb()->as_compiled_method_or_null(); - if (cm->is_compiled_by_jvmci() && sv->is_auto_box()) { +#if COMPILER2 || INCLUDE_JVMCI || INCLUDE_AOT + if (sv->is_auto_box()) { AutoBoxObjectValue* abv = (AutoBoxObjectValue*) sv; obj = get_cached_box(abv, fr, reg_map, THREAD); if (obj != NULL) { @@ -1055,7 +1054,7 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, RegisterMap* abv->set_cached(true); } } -#endif // INCLUDE_JVMCI || INCLUDE_AOT +#endif // COMPILER2 || INCLUDE_JVMCI || INCLUDE_AOT InstanceKlass* ik = InstanceKlass::cast(k); if (obj == NULL) { #ifdef COMPILER2 @@ -1397,12 +1396,12 @@ void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableAr if (obj.is_null()) { continue; } -#if INCLUDE_JVMCI || INCLUDE_AOT +#if COMPILER2 || INCLUDE_JVMCI || INCLUDE_AOT // Don't reassign fields of boxes that came from a cache. Caches may be in CDS. if (sv->is_auto_box() && ((AutoBoxObjectValue*) sv)->is_cached()) { continue; } -#endif // INCLUDE_JVMCI || INCLUDE_AOT +#endif // COMPILER2 || INCLUDE_JVMCI || INCLUDE_AOT #ifdef COMPILER2 if (EnableVectorSupport && VectorSupport::is_vector(k)) { continue; // skip field reassignment for vectors diff --git a/src/hotspot/share/runtime/deoptimization.hpp b/src/hotspot/share/runtime/deoptimization.hpp index bd116f5974bdd..b52f02d1e9d4b 100644 --- a/src/hotspot/share/runtime/deoptimization.hpp +++ b/src/hotspot/share/runtime/deoptimization.hpp @@ -163,9 +163,10 @@ class Deoptimization : AllStatic { #if INCLUDE_JVMCI static address deoptimize_for_missing_exception_handler(CompiledMethod* cm); - static oop get_cached_box(AutoBoxObjectValue* bv, frame* fr, RegisterMap* reg_map, TRAPS); #endif + static oop get_cached_box(AutoBoxObjectValue* bv, frame* fr, RegisterMap* reg_map, TRAPS); + private: // Does the actual work for deoptimizing a single frame static void deoptimize_single_frame(JavaThread* thread, frame fr, DeoptReason reason); From 203249328cf9cfd070c1c0fa8b801c023845d8d1 Mon Sep 17 00:00:00 2001 From: Wanghuang-Huawei Date: Sat, 27 Feb 2021 15:12:05 +0800 Subject: [PATCH 06/12] fix bugs --- src/hotspot/share/opto/callGenerator.cpp | 40 ++++--- src/hotspot/share/opto/callnode.hpp | 2 +- .../c2/TestEliminateBoxInDebugInfo.java | 87 ++++++++++++++ ...stIdentityWithEliminateBoxInDebugInfo.java | 113 ++++++++++++++++++ 4 files changed, 223 insertions(+), 19 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/TestEliminateBoxInDebugInfo.java create mode 100644 test/hotspot/jtreg/compiler/c2/TestIdentityWithEliminateBoxInDebugInfo.java diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index 8a0a1f648a804..ebb91cfb2cbbc 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -558,48 +558,50 @@ void LateInlineVirtualCallGenerator::do_late_inline() { static void replace_box_to_scalar(CallNode* call, Node* resproj) { if (resproj != nullptr && call->is_CallStaticJava() && call->as_CallStaticJava()->is_boxing_method()) { - Unique_Node_List debuginfo_node_list; + Unique_Node_List safepoints; for (DUIterator_Fast imax, i = resproj->fast_outs(imax); i < imax; i++) { Node* m = resproj->fast_out(i); - if (m->is_SafePoint()) { - SafePointNode* sfpt = m->as_SafePoint(); - uint dbg_start = sfpt->is_Call() ? sfpt->as_Call()->tf()->domain()->cnt() : (uint)TypeFunc::Parms+1; - for (uint i = 0; i < dbg_start; i++) { - if (sfpt->in(i) == resproj) { - return; - } - } - debuginfo_node_list.push(m); + if (m->is_SafePoint() + && (!m->is_Call() || !m->as_Call()->has_non_debug_use(resproj))) { + safepoints.push(m); } else { return; } } +#ifndef PRODUCT + if (PrintEliminateAllocations && safepoints.size() > 0) { + tty->print("++++ Eliminated: %d ", call->_idx); + call->as_CallStaticJava()->method()->print_short_name(tty); + tty->cr(); + } +#endif + GraphKit kit(call->jvms()); PhaseGVN& gvn = kit.gvn(); // delay box in runtime, treat box as a scalarized object - while (debuginfo_node_list.size() > 0) { + while (safepoints.size() > 0) { ProjNode* res = resproj->as_Proj(); - Node* debuginfo_node = debuginfo_node_list.pop(); + Node* sfpt = safepoints.pop(); ciInstanceKlass* klass = call->as_CallStaticJava()->method()->holder(); int n_fields = klass->nof_nonstatic_fields(); assert(n_fields == 1, "the klass must be an auto-boxing klass"); - uint first_ind = (debuginfo_node->req() - debuginfo_node->jvms()->scloff()); + uint first_ind = sfpt->req() - sfpt->jvms()->scloff(); Node* sobj = new SafePointScalarObjectNode(gvn.type(res)->isa_oopptr(), #ifdef ASSERT call->isa_Allocate(), #endif // ASSERT first_ind, n_fields, true); sobj->init_req(0, kit.root()); - debuginfo_node->add_req(call->in(res->_con)); + sfpt->add_req(call->in(TypeFunc::Parms)); sobj = gvn.transform(sobj); - JVMState* jvms = debuginfo_node->jvms(); - jvms->set_endoff(debuginfo_node->req()); + JVMState* jvms = sfpt->jvms(); + jvms->set_endoff(sfpt->req()); int start = jvms->debug_start(); int end = jvms->debug_end(); - debuginfo_node->replace_edges_in_range(res, sobj, start, end); + sfpt->replace_edges_in_range(res, sobj, start, end); } } } @@ -653,7 +655,9 @@ void CallGenerator::do_late_inline_helper() { C->remove_macro_node(call); } - replace_box_to_scalar(call, callprojs.resproj); + if (C->eliminate_boxing()) { + replace_box_to_scalar(call, callprojs.resproj); + } bool result_not_used = (callprojs.resproj == NULL || callprojs.resproj->outcnt() == 0); if (is_pure_call() && result_not_used) { diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp index de9450e68a538..04490eeb64468 100644 --- a/src/hotspot/share/opto/callnode.hpp +++ b/src/hotspot/share/opto/callnode.hpp @@ -500,7 +500,7 @@ class SafePointScalarObjectNode: public TypeNode { // states of the scalarized object fields are collected. // It is relative to the last (youngest) jvms->_scloff. uint _n_fields; // Number of non-static fields of the scalarized object. - bool _is_auto_box; // is the scalarized object is auto box. + bool _is_auto_box; // True if the scalarized object is an auto box. DEBUG_ONLY(AllocateNode* _alloc;) virtual uint hash() const ; // { return NO_HASH; } diff --git a/test/hotspot/jtreg/compiler/c2/TestEliminateBoxInDebugInfo.java b/test/hotspot/jtreg/compiler/c2/TestEliminateBoxInDebugInfo.java new file mode 100644 index 0000000000000..1a0a64bef2bb9 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestEliminateBoxInDebugInfo.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021, Huawei and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8261137 + * @requires vm.debug == true & vm.flavor == "server" + * @summary Verify that box object is scalarized in case it is directly referenced by debug info. + * @library /test/lib + * + * @run main/othervm compiler.c2.TestEliminateBoxInDebugInfo + */ +package compiler.c2; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import jdk.test.lib.Asserts; + +public class TestEliminateBoxInDebugInfo { + public static void runTest() throws Exception { + final String[] arguments = { + "-XX:CompileCommand=compileonly,compiler/c2/TestEliminateBoxInDebugInfo$Test.foo", + "-XX:CompileCommand=dontinline,compiler/c2/TestEliminateBoxInDebugInfo$Test.black", + "-XX:+PrintEliminateAllocations", + Test.class.getName() + }; + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(arguments); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + System.out.println(output.getStdout()); + String pattern = ".*Eliminated.*"; + Pattern r = Pattern.compile(pattern); + Matcher m = r.matcher(output.getStdout()); + if (!m.find()) { + throw new RuntimeException("Could not find Elimination output"); + } + } + + public static void main(String[] args) throws Exception { + runTest(); + } + + static class Test { + public static void main(String[] args) throws Exception { + // warmup + for(int i = 0; i < 100000; i++) { + foo(1000 + (i % 1000)); + } + } + + public static int foo(int value) { + Integer ii = Integer.valueOf(value); + int sum = 0; + if (value > 999) { + sum += ii.intValue(); + } + black(); + return sum; + } + + public static void black() {} + } +} diff --git a/test/hotspot/jtreg/compiler/c2/TestIdentityWithEliminateBoxInDebugInfo.java b/test/hotspot/jtreg/compiler/c2/TestIdentityWithEliminateBoxInDebugInfo.java new file mode 100644 index 0000000000000..a19d638c77267 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestIdentityWithEliminateBoxInDebugInfo.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2021, Huawei and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8261137 + * @requires vm.flavor == "server" + * @summary Verify that box object identity matches after deoptimization When it is eliminated. + * @library /test/lib + * + * @run main/othervm compiler.c2.TestIdentityWithEliminateBoxInDebugInfo + */ +package compiler.c2; + +import jdk.test.lib.Asserts; + +public class TestIdentityWithEliminateBoxInDebugInfo { + interface TestF { + void apply(boolean condition); + } + + public static void helper(TestF f) { + // warmup + for(int i = 0; i < 100000; i++) { + f.apply(true); + } + // deoptimize + f.apply(false); + } + + public static void runTest() throws Exception { + helper((c) -> { + Integer a = Integer.valueOf(42); + Integer b = Integer.valueOf(-42); + if (!c) { + Asserts.assertTrue(a == Integer.valueOf(42)); + Asserts.assertTrue(b == Integer.valueOf(-42)); + } + }); + + helper((c) -> { + long highBitsOnly = 2L << 40; + Long a = Long.valueOf(42L); + Long b = Long.valueOf(-42L); + Long h = Long.valueOf(highBitsOnly); + if (!c) { + Asserts.assertTrue(a == Long.valueOf(42L)); + Asserts.assertTrue(b == Long.valueOf(-42L)); + Asserts.assertFalse(h == Long.valueOf(highBitsOnly)); + } + }); + + helper((c) -> { + Character a = Character.valueOf('a'); + Character b = Character.valueOf('Z'); + if (!c) { + Asserts.assertTrue(a == Character.valueOf('a')); + Asserts.assertTrue(b == Character.valueOf('Z')); + } + }); + + helper((c) -> { + Short a = Short.valueOf((short)42); + Short b = Short.valueOf((short)-42); + if (!c) { + Asserts.assertTrue(a == Short.valueOf((short)42)); + Asserts.assertTrue(b == Short.valueOf((short)-42)); + } + }); + + helper((c) -> { + Byte a = Byte.valueOf((byte)42); + Byte b = Byte.valueOf((byte)-42); + if (!c) { + Asserts.assertTrue(a == Byte.valueOf((byte)42)); + Asserts.assertTrue(b == Byte.valueOf((byte)-42)); + } + }); + + helper((c) -> { + Boolean a = Boolean.valueOf(true); + Boolean b = Boolean.valueOf(false); + if (!c) { + Asserts.assertTrue(a == Boolean.valueOf(true)); + Asserts.assertTrue(b == Boolean.valueOf(false)); + } + }); + } + + public static void main(String[] args) throws Exception { + runTest(); + } +} From a82410c78debcf01b0864c66cc3c7409cebfc8c0 Mon Sep 17 00:00:00 2001 From: Wanghuang-Huawei Date: Wed, 10 Mar 2021 19:55:33 +0800 Subject: [PATCH 07/12] refactor some codes --- src/hotspot/share/opto/callGenerator.cpp | 114 ++++++++++-------- src/hotspot/share/opto/callGenerator.hpp | 5 +- .../c2/TestEliminateBoxInDebugInfo.java | 1 + ...stIdentityWithEliminateBoxInDebugInfo.java | 2 +- 4 files changed, 70 insertions(+), 52 deletions(-) diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index ebb91cfb2cbbc..70c775f0bbfd4 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -318,16 +318,21 @@ class LateInlineCallGenerator : public DirectCallGenerator { private: jlong _unique_id; // unique id for log compilation bool _is_pure_call; // a hint that the call doesn't have important side effects to care about + bool _is_boxing_call; protected: CallGenerator* _inline_cg; virtual bool do_late_inline_check(Compile* C, JVMState* jvms) { return true; } virtual CallGenerator* inline_cg() const { return _inline_cg; } virtual bool is_pure_call() const { return _is_pure_call; } + virtual bool is_boxing_call() const { return _is_boxing_call; } public: - LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg, bool is_pure_call = false) : - DirectCallGenerator(method, true), _unique_id(0), _is_pure_call(is_pure_call), _inline_cg(inline_cg) {} + LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg, bool is_pure_call = false, bool is_boxing_call = false) : + DirectCallGenerator(method, true), _unique_id(0), + _is_pure_call(is_pure_call), + _is_boxing_call(is_boxing_call), + _inline_cg(inline_cg) {} virtual bool is_late_inline() const { return true; } @@ -448,17 +453,22 @@ class LateInlineVirtualCallGenerator : public VirtualCallGenerator { CallGenerator* _inline_cg; ciMethod* _callee; bool _is_pure_call; + bool _is_boxing_call; float _prof_factor; protected: virtual bool do_late_inline_check(Compile* C, JVMState* jvms); virtual CallGenerator* inline_cg() const { return _inline_cg; } virtual bool is_pure_call() const { return _is_pure_call; } + virtual bool is_boxing_call() const { return _is_boxing_call; } public: LateInlineVirtualCallGenerator(ciMethod* method, int vtable_index, float prof_factor) : VirtualCallGenerator(method, vtable_index, true /*separate_io_projs*/), - _unique_id(0), _inline_cg(NULL), _callee(NULL), _is_pure_call(false), _prof_factor(prof_factor) {} + _unique_id(0), _inline_cg(NULL), _callee(NULL), + _is_pure_call(false), + _is_boxing_call(false), + _prof_factor(prof_factor) {} virtual bool is_late_inline() const { return true; } @@ -556,54 +566,55 @@ void LateInlineVirtualCallGenerator::do_late_inline() { // replace box node to scalar node only in case it is directly referenced by debug info static void replace_box_to_scalar(CallNode* call, Node* resproj) { - if (resproj != nullptr && call->is_CallStaticJava() && - call->as_CallStaticJava()->is_boxing_method()) { - Unique_Node_List safepoints; - for (DUIterator_Fast imax, i = resproj->fast_outs(imax); i < imax; i++) { - Node* m = resproj->fast_out(i); - if (m->is_SafePoint() - && (!m->is_Call() || !m->as_Call()->has_non_debug_use(resproj))) { - safepoints.push(m); - } else { - return; - } + assert(call->as_CallStaticJava()->is_boxing_method(), "sanity"); + + Unique_Node_List safepoints; + for (DUIterator_Fast imax, i = resproj->fast_outs(imax); i < imax; i++) { + Node* m = resproj->fast_out(i); + if (m->is_SafePoint() + && (!m->is_Call() || !m->as_Call()->has_non_debug_use(resproj))) { + safepoints.push(m); + } else { + return; } + } #ifndef PRODUCT - if (PrintEliminateAllocations && safepoints.size() > 0) { - tty->print("++++ Eliminated: %d ", call->_idx); - call->as_CallStaticJava()->method()->print_short_name(tty); - tty->cr(); - } + if (PrintEliminateAllocations && safepoints.size() > 0) { + tty->print("++++ Eliminated: %d ", call->_idx); + call->as_CallStaticJava()->method()->print_short_name(tty); + tty->cr(); + } #endif - GraphKit kit(call->jvms()); - PhaseGVN& gvn = kit.gvn(); - // delay box in runtime, treat box as a scalarized object - while (safepoints.size() > 0) { - ProjNode* res = resproj->as_Proj(); - Node* sfpt = safepoints.pop(); - - ciInstanceKlass* klass = call->as_CallStaticJava()->method()->holder(); - int n_fields = klass->nof_nonstatic_fields(); - assert(n_fields == 1, "the klass must be an auto-boxing klass"); - - uint first_ind = sfpt->req() - sfpt->jvms()->scloff(); - Node* sobj = new SafePointScalarObjectNode(gvn.type(res)->isa_oopptr(), + GraphKit kit(call->jvms()); + PhaseGVN& gvn = kit.gvn(); + // delay box in runtime, treat box as a scalarized object + while (safepoints.size() > 0) { + ProjNode* res = resproj->as_Proj(); + Node* sfpt = safepoints.pop(); + + ciInstanceKlass* klass = call->as_CallStaticJava()->method()->holder(); + int n_fields = klass->nof_nonstatic_fields(); + assert(n_fields == 1, "the klass must be an auto-boxing klass"); + + uint first_ind = sfpt->req() - sfpt->jvms()->scloff(); + Node* sobj = new SafePointScalarObjectNode(gvn.type(res)->isa_oopptr(), #ifdef ASSERT call->isa_Allocate(), #endif // ASSERT - first_ind, n_fields, true); - sobj->init_req(0, kit.root()); - sfpt->add_req(call->in(TypeFunc::Parms)); - sobj = gvn.transform(sobj); - JVMState* jvms = sfpt->jvms(); - jvms->set_endoff(sfpt->req()); - int start = jvms->debug_start(); - int end = jvms->debug_end(); - sfpt->replace_edges_in_range(res, sobj, start, end); - } - } + first_ind, n_fields, true); + sobj->init_req(0, kit.root()); + sfpt->add_req(call->in(TypeFunc::Parms)); + sobj = gvn.transform(sobj); + JVMState* jvms = sfpt->jvms(); + jvms->set_endoff(sfpt->req()); + int start = jvms->debug_start(); + int end = jvms->debug_end(); + sfpt->replace_edges_in_range(res, sobj, start, end); + } + + assert(resproj->outcnt() == 0, "the box must have no use after replace"); } void CallGenerator::do_late_inline_helper() { @@ -655,14 +666,19 @@ void CallGenerator::do_late_inline_helper() { C->remove_macro_node(call); } - if (C->eliminate_boxing()) { - replace_box_to_scalar(call, callprojs.resproj); - } + bool call_can_eliminate = false; + + if (is_pure_call()) { + if (is_boxing_call() && callprojs.resproj != nullptr) { + replace_box_to_scalar(call, callprojs.resproj); + } - bool result_not_used = (callprojs.resproj == NULL || callprojs.resproj->outcnt() == 0); - if (is_pure_call() && result_not_used) { // The call is marked as pure (no important side effects), but result isn't used. // It's safe to remove the call. + call_can_eliminate = (callprojs.resproj == NULL || callprojs.resproj->outcnt() == 0); + } + + if (call_can_eliminate) { GraphKit kit(call->jvms()); kit.replace_call(call, C->top(), true); } else { @@ -784,7 +800,7 @@ class LateInlineBoxingCallGenerator : public LateInlineCallGenerator { public: LateInlineBoxingCallGenerator(ciMethod* method, CallGenerator* inline_cg) : - LateInlineCallGenerator(method, inline_cg, /*is_pure=*/true) {} + LateInlineCallGenerator(method, inline_cg, /*is_pure=*/true, /*is_boxing*/true) {} virtual JVMState* generate(JVMState* jvms) { Compile *C = Compile::current(); diff --git a/src/hotspot/share/opto/callGenerator.hpp b/src/hotspot/share/opto/callGenerator.hpp index 27b11b37a2e28..7385ea4053d58 100644 --- a/src/hotspot/share/opto/callGenerator.hpp +++ b/src/hotspot/share/opto/callGenerator.hpp @@ -45,8 +45,9 @@ class CallGenerator : public ResourceObj { void do_late_inline_helper(); virtual bool do_late_inline_check(Compile* C, JVMState* jvms) { ShouldNotReachHere(); return false; } - virtual CallGenerator* inline_cg() const { ShouldNotReachHere(); return NULL; } - virtual bool is_pure_call() const { ShouldNotReachHere(); return false; } + virtual CallGenerator* inline_cg() const { ShouldNotReachHere(); return NULL; } + virtual bool is_pure_call() const { ShouldNotReachHere(); return false; } + virtual bool is_boxing_call() const { ShouldNotReachHere(); return false; } public: // Accessors diff --git a/test/hotspot/jtreg/compiler/c2/TestEliminateBoxInDebugInfo.java b/test/hotspot/jtreg/compiler/c2/TestEliminateBoxInDebugInfo.java index 1a0a64bef2bb9..396c0072c9d00 100644 --- a/test/hotspot/jtreg/compiler/c2/TestEliminateBoxInDebugInfo.java +++ b/test/hotspot/jtreg/compiler/c2/TestEliminateBoxInDebugInfo.java @@ -46,6 +46,7 @@ public static void runTest() throws Exception { final String[] arguments = { "-XX:CompileCommand=compileonly,compiler/c2/TestEliminateBoxInDebugInfo$Test.foo", "-XX:CompileCommand=dontinline,compiler/c2/TestEliminateBoxInDebugInfo$Test.black", + "-Xbatch", "-XX:+PrintEliminateAllocations", Test.class.getName() }; diff --git a/test/hotspot/jtreg/compiler/c2/TestIdentityWithEliminateBoxInDebugInfo.java b/test/hotspot/jtreg/compiler/c2/TestIdentityWithEliminateBoxInDebugInfo.java index a19d638c77267..120dae6bcb1b3 100644 --- a/test/hotspot/jtreg/compiler/c2/TestIdentityWithEliminateBoxInDebugInfo.java +++ b/test/hotspot/jtreg/compiler/c2/TestIdentityWithEliminateBoxInDebugInfo.java @@ -28,7 +28,7 @@ * @summary Verify that box object identity matches after deoptimization When it is eliminated. * @library /test/lib * - * @run main/othervm compiler.c2.TestIdentityWithEliminateBoxInDebugInfo + * @run main/othervm -Xbatch compiler.c2.TestIdentityWithEliminateBoxInDebugInfo */ package compiler.c2; From 3934fd9a924d28b524b7108299a3ab17bcfb414e Mon Sep 17 00:00:00 2001 From: Wanghuang-Huawei Date: Fri, 19 Mar 2021 09:58:17 +0800 Subject: [PATCH 08/12] refactor --- src/hotspot/share/opto/callGenerator.cpp | 55 +++++++++---------- src/hotspot/share/opto/callGenerator.hpp | 6 +- .../c2/TestEliminateBoxInDebugInfo.java | 2 +- ...stIdentityWithEliminateBoxInDebugInfo.java | 2 +- 4 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index 70c775f0bbfd4..e315d86eb753e 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -318,21 +318,16 @@ class LateInlineCallGenerator : public DirectCallGenerator { private: jlong _unique_id; // unique id for log compilation bool _is_pure_call; // a hint that the call doesn't have important side effects to care about - bool _is_boxing_call; protected: CallGenerator* _inline_cg; virtual bool do_late_inline_check(Compile* C, JVMState* jvms) { return true; } virtual CallGenerator* inline_cg() const { return _inline_cg; } virtual bool is_pure_call() const { return _is_pure_call; } - virtual bool is_boxing_call() const { return _is_boxing_call; } public: - LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg, bool is_pure_call = false, bool is_boxing_call = false) : - DirectCallGenerator(method, true), _unique_id(0), - _is_pure_call(is_pure_call), - _is_boxing_call(is_boxing_call), - _inline_cg(inline_cg) {} + LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg, bool is_pure_call = false) : + DirectCallGenerator(method, true), _unique_id(0), _is_pure_call(is_pure_call), _inline_cg(inline_cg) {} virtual bool is_late_inline() const { return true; } @@ -453,22 +448,17 @@ class LateInlineVirtualCallGenerator : public VirtualCallGenerator { CallGenerator* _inline_cg; ciMethod* _callee; bool _is_pure_call; - bool _is_boxing_call; float _prof_factor; protected: virtual bool do_late_inline_check(Compile* C, JVMState* jvms); virtual CallGenerator* inline_cg() const { return _inline_cg; } virtual bool is_pure_call() const { return _is_pure_call; } - virtual bool is_boxing_call() const { return _is_boxing_call; } public: LateInlineVirtualCallGenerator(ciMethod* method, int vtable_index, float prof_factor) : VirtualCallGenerator(method, vtable_index, true /*separate_io_projs*/), - _unique_id(0), _inline_cg(NULL), _callee(NULL), - _is_pure_call(false), - _is_boxing_call(false), - _prof_factor(prof_factor) {} + _unique_id(0), _inline_cg(NULL), _callee(NULL), _is_pure_call(false), _prof_factor(prof_factor) {} virtual bool is_late_inline() const { return true; } @@ -564,19 +554,22 @@ void LateInlineVirtualCallGenerator::do_late_inline() { CallGenerator::do_late_inline_helper(); } -// replace box node to scalar node only in case it is directly referenced by debug info -static void replace_box_to_scalar(CallNode* call, Node* resproj) { - assert(call->as_CallStaticJava()->is_boxing_method(), "sanity"); +static bool has_non_debug_usages(Node* n) { + for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { + Node* m = n->fast_out(i); + if (!m->is_SafePoint() + || (m->is_Call() && m->as_Call()->has_non_debug_use(n))) { + return true; + } + } + return false; +} +static void scalarize_debug_usages(CallNode* call, Node* resproj) { Unique_Node_List safepoints; for (DUIterator_Fast imax, i = resproj->fast_outs(imax); i < imax; i++) { Node* m = resproj->fast_out(i); - if (m->is_SafePoint() - && (!m->is_Call() || !m->as_Call()->has_non_debug_use(resproj))) { - safepoints.push(m); - } else { - return; - } + safepoints.push(m); } #ifndef PRODUCT @@ -666,19 +659,23 @@ void CallGenerator::do_late_inline_helper() { C->remove_macro_node(call); } - bool call_can_eliminate = false; + bool result_not_used = false; if (is_pure_call()) { - if (is_boxing_call() && callprojs.resproj != nullptr) { - replace_box_to_scalar(call, callprojs.resproj); + if (is_boxing_late_inline() && callprojs.resproj != nullptr) { + // replace box node to scalar node only in case it is directly referenced by debug info + assert(call->as_CallStaticJava()->is_boxing_method(), "sanity"); + if (!has_non_debug_usages(callprojs.resproj)) { + scalarize_debug_usages(call, callprojs.resproj); + } } // The call is marked as pure (no important side effects), but result isn't used. // It's safe to remove the call. - call_can_eliminate = (callprojs.resproj == NULL || callprojs.resproj->outcnt() == 0); + result_not_used = (callprojs.resproj == NULL || callprojs.resproj->outcnt() == 0); } - if (call_can_eliminate) { + if (result_not_used) { GraphKit kit(call->jvms()); kit.replace_call(call, C->top(), true); } else { @@ -800,7 +797,7 @@ class LateInlineBoxingCallGenerator : public LateInlineCallGenerator { public: LateInlineBoxingCallGenerator(ciMethod* method, CallGenerator* inline_cg) : - LateInlineCallGenerator(method, inline_cg, /*is_pure=*/true, /*is_boxing*/true) {} + LateInlineCallGenerator(method, inline_cg, /*is_pure=*/true) {} virtual JVMState* generate(JVMState* jvms) { Compile *C = Compile::current(); @@ -813,6 +810,8 @@ class LateInlineBoxingCallGenerator : public LateInlineCallGenerator { return new_jvms; } + virtual bool is_boxing_late_inline() const { return true; } + virtual CallGenerator* with_call_node(CallNode* call) { LateInlineBoxingCallGenerator* cg = new LateInlineBoxingCallGenerator(method(), _inline_cg); cg->set_call_node(call->as_CallStaticJava()); diff --git a/src/hotspot/share/opto/callGenerator.hpp b/src/hotspot/share/opto/callGenerator.hpp index 7385ea4053d58..29bfc7b5df772 100644 --- a/src/hotspot/share/opto/callGenerator.hpp +++ b/src/hotspot/share/opto/callGenerator.hpp @@ -45,9 +45,8 @@ class CallGenerator : public ResourceObj { void do_late_inline_helper(); virtual bool do_late_inline_check(Compile* C, JVMState* jvms) { ShouldNotReachHere(); return false; } - virtual CallGenerator* inline_cg() const { ShouldNotReachHere(); return NULL; } - virtual bool is_pure_call() const { ShouldNotReachHere(); return false; } - virtual bool is_boxing_call() const { ShouldNotReachHere(); return false; } + virtual CallGenerator* inline_cg() const { ShouldNotReachHere(); return NULL; } + virtual bool is_pure_call() const { ShouldNotReachHere(); return false; } public: // Accessors @@ -75,6 +74,7 @@ class CallGenerator : public ResourceObj { virtual bool is_late_inline() const { return false; } // same but for method handle calls virtual bool is_mh_late_inline() const { return false; } + virtual bool is_boxing_late_inline() const { return false; } virtual bool is_string_late_inline() const { return false; } virtual bool is_virtual_late_inline() const { return false; } diff --git a/test/hotspot/jtreg/compiler/c2/TestEliminateBoxInDebugInfo.java b/test/hotspot/jtreg/compiler/c2/TestEliminateBoxInDebugInfo.java index 396c0072c9d00..07340bc0adc6a 100644 --- a/test/hotspot/jtreg/compiler/c2/TestEliminateBoxInDebugInfo.java +++ b/test/hotspot/jtreg/compiler/c2/TestEliminateBoxInDebugInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Huawei and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/c2/TestIdentityWithEliminateBoxInDebugInfo.java b/test/hotspot/jtreg/compiler/c2/TestIdentityWithEliminateBoxInDebugInfo.java index 120dae6bcb1b3..ecdf625d64d36 100644 --- a/test/hotspot/jtreg/compiler/c2/TestIdentityWithEliminateBoxInDebugInfo.java +++ b/test/hotspot/jtreg/compiler/c2/TestIdentityWithEliminateBoxInDebugInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Huawei and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it From 2f0276cd123abfca2ae92ac8b5cd6906a2b3edcb Mon Sep 17 00:00:00 2001 From: Wanghuang-Huawei Date: Wed, 24 Mar 2021 10:43:22 +0800 Subject: [PATCH 09/12] refactor --- src/hotspot/share/opto/callGenerator.cpp | 43 +++++++++----------- src/hotspot/share/runtime/deoptimization.cpp | 12 +++--- 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index e315d86eb753e..235706cfb616b 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -565,36 +565,22 @@ static bool has_non_debug_usages(Node* n) { return false; } +// delay box in runtime, treat box as a scalarized object static void scalarize_debug_usages(CallNode* call, Node* resproj) { - Unique_Node_List safepoints; - for (DUIterator_Fast imax, i = resproj->fast_outs(imax); i < imax; i++) { - Node* m = resproj->fast_out(i); - safepoints.push(m); - } - -#ifndef PRODUCT - if (PrintEliminateAllocations && safepoints.size() > 0) { - tty->print("++++ Eliminated: %d ", call->_idx); - call->as_CallStaticJava()->method()->print_short_name(tty); - tty->cr(); - } -#endif - GraphKit kit(call->jvms()); PhaseGVN& gvn = kit.gvn(); - // delay box in runtime, treat box as a scalarized object - while (safepoints.size() > 0) { - ProjNode* res = resproj->as_Proj(); - Node* sfpt = safepoints.pop(); - ciInstanceKlass* klass = call->as_CallStaticJava()->method()->holder(); - int n_fields = klass->nof_nonstatic_fields(); - assert(n_fields == 1, "the klass must be an auto-boxing klass"); + ProjNode* res = resproj->as_Proj(); + ciInstanceKlass* klass = call->as_CallStaticJava()->method()->holder(); + int n_fields = klass->nof_nonstatic_fields(); + assert(n_fields == 1, "the klass must be an auto-boxing klass"); + for (DUIterator_Last imin, i = res->last_outs(imin); i >= imin;) { + SafePointNode* sfpt = res->last_out(i)->as_SafePoint(); uint first_ind = sfpt->req() - sfpt->jvms()->scloff(); Node* sobj = new SafePointScalarObjectNode(gvn.type(res)->isa_oopptr(), #ifdef ASSERT - call->isa_Allocate(), + nullptr, #endif // ASSERT first_ind, n_fields, true); sobj->init_req(0, kit.root()); @@ -604,10 +590,19 @@ static void scalarize_debug_usages(CallNode* call, Node* resproj) { jvms->set_endoff(sfpt->req()); int start = jvms->debug_start(); int end = jvms->debug_end(); - sfpt->replace_edges_in_range(res, sobj, start, end); + int num_edges = sfpt->replace_edges_in_range(res, sobj, start, end, &gvn); + i -= num_edges; } - assert(resproj->outcnt() == 0, "the box must have no use after replace"); + assert(res->outcnt() == 0, "the box must have no use after replace"); + +#ifndef PRODUCT + if (PrintEliminateAllocations) { + tty->print("++++ Eliminated: %d ", call->_idx); + call->as_CallStaticJava()->method()->print_short_name(tty); + tty->cr(); + } +#endif } void CallGenerator::do_late_inline_helper() { diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 19c8281fddc10..44a81c5b5eae3 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -897,7 +897,7 @@ Deoptimization::DeoptAction Deoptimization::_unloaded_action -#if COMPILER2 || INCLUDE_JVMCI || INCLUDE_AOT +#if COMPILER2_OR_JVMCI || INCLUDE_AOT template class BoxCacheBase : public CHeapObj { protected: @@ -1025,7 +1025,7 @@ oop Deoptimization::get_cached_box(AutoBoxObjectValue* bv, frame* fr, RegisterMa } return NULL; } -#endif // COMPILER2 || INCLUDE_JVMCI || INCLUDE_AOT +#endif // COMPILER2_OR_JVMCI || INCLUDE_AOT #if COMPILER2_OR_JVMCI bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, RegisterMap* reg_map, GrowableArray* objects, TRAPS) { @@ -1044,7 +1044,7 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, RegisterMap* oop obj = NULL; if (k->is_instance_klass()) { -#if COMPILER2 || INCLUDE_JVMCI || INCLUDE_AOT +#if COMPILER2_OR_JVMCI || INCLUDE_AOT if (sv->is_auto_box()) { AutoBoxObjectValue* abv = (AutoBoxObjectValue*) sv; obj = get_cached_box(abv, fr, reg_map, THREAD); @@ -1053,7 +1053,7 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, RegisterMap* abv->set_cached(true); } } -#endif // COMPILER2 || INCLUDE_JVMCI || INCLUDE_AOT +#endif // COMPILER2_OR_JVMCI || INCLUDE_AOT InstanceKlass* ik = InstanceKlass::cast(k); if (obj == NULL) { #ifdef COMPILER2 @@ -1395,12 +1395,12 @@ void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableAr if (obj.is_null()) { continue; } -#if COMPILER2 || INCLUDE_JVMCI || INCLUDE_AOT +#if COMPILER2_OR_JVMCI || INCLUDE_AOT // Don't reassign fields of boxes that came from a cache. Caches may be in CDS. if (sv->is_auto_box() && ((AutoBoxObjectValue*) sv)->is_cached()) { continue; } -#endif // COMPILER2 || INCLUDE_JVMCI || INCLUDE_AOT +#endif // COMPILER2_OR_JVMCI || INCLUDE_AOT #ifdef COMPILER2 if (EnableVectorSupport && VectorSupport::is_vector(k)) { assert(sv->field_size() == 1, "%s not a vector", k->name()->as_C_string()); From fee961bb1baf1caf1d109bc6d92e43955e8c9d6d Mon Sep 17 00:00:00 2001 From: Wanghuang-Huawei Date: Wed, 24 Mar 2021 15:06:45 +0800 Subject: [PATCH 10/12] refact SafePointScalarObjectNode constructor --- src/hotspot/share/opto/callGenerator.cpp | 2 +- src/hotspot/share/opto/callnode.cpp | 7 ++++++- src/hotspot/share/opto/callnode.hpp | 6 +++--- .../TestEliminateBoxInDebugInfo.java | 2 +- .../TestIdentityWithEliminateBoxInDebugInfo.java | 0 5 files changed, 11 insertions(+), 6 deletions(-) rename test/hotspot/jtreg/compiler/{c2 => eliminateAutobox}/TestEliminateBoxInDebugInfo.java (98%) rename test/hotspot/jtreg/compiler/{c2 => eliminateAutobox}/TestIdentityWithEliminateBoxInDebugInfo.java (100%) diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index 235706cfb616b..1d3622060e36c 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -580,7 +580,7 @@ static void scalarize_debug_usages(CallNode* call, Node* resproj) { uint first_ind = sfpt->req() - sfpt->jvms()->scloff(); Node* sobj = new SafePointScalarObjectNode(gvn.type(res)->isa_oopptr(), #ifdef ASSERT - nullptr, + call, #endif // ASSERT first_ind, n_fields, true); sobj->init_req(0, kit.root()); diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp index 974249bf95cf1..491c6cb1d9a3d 100644 --- a/src/hotspot/share/opto/callnode.cpp +++ b/src/hotspot/share/opto/callnode.cpp @@ -1515,7 +1515,7 @@ void SafePointNode::disconnect_from_root(PhaseIterGVN *igvn) { SafePointScalarObjectNode::SafePointScalarObjectNode(const TypeOopPtr* tp, #ifdef ASSERT - AllocateNode* alloc, + CallNode* alloc, #endif uint first_index, uint n_fields, @@ -1528,6 +1528,11 @@ SafePointScalarObjectNode::SafePointScalarObjectNode(const TypeOopPtr* tp, , _alloc(alloc) #endif { +#ifdef ASSERT + if (alloc != nullptr) { + assert(alloc->is_Allocate() || alloc->as_CallStaticJava()->is_boxing_method(), "unexpected alloc"); + } +#endif init_class_id(Class_SafePointScalarObject); } diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp index aee6440187d8c..8f1e91e7e43de 100644 --- a/src/hotspot/share/opto/callnode.hpp +++ b/src/hotspot/share/opto/callnode.hpp @@ -502,7 +502,7 @@ class SafePointScalarObjectNode: public TypeNode { // It is relative to the last (youngest) jvms->_scloff. uint _n_fields; // Number of non-static fields of the scalarized object. bool _is_auto_box; // True if the scalarized object is an auto box. - DEBUG_ONLY(AllocateNode* _alloc;) + DEBUG_ONLY(CallNode* _alloc;) virtual uint hash() const ; // { return NO_HASH; } virtual bool cmp( const Node &n ) const; @@ -512,7 +512,7 @@ class SafePointScalarObjectNode: public TypeNode { public: SafePointScalarObjectNode(const TypeOopPtr* tp, #ifdef ASSERT - AllocateNode* alloc, + CallNode* alloc, #endif uint first_index, uint n_fields, bool is_auto_box = false); virtual int Opcode() const; @@ -529,7 +529,7 @@ class SafePointScalarObjectNode: public TypeNode { bool is_auto_box() const { return _is_auto_box; } #ifdef ASSERT - AllocateNode* alloc() const { return _alloc; } + CallNode* alloc() const { return _alloc; } #endif virtual uint size_of() const { return sizeof(*this); } diff --git a/test/hotspot/jtreg/compiler/c2/TestEliminateBoxInDebugInfo.java b/test/hotspot/jtreg/compiler/eliminateAutobox/TestEliminateBoxInDebugInfo.java similarity index 98% rename from test/hotspot/jtreg/compiler/c2/TestEliminateBoxInDebugInfo.java rename to test/hotspot/jtreg/compiler/eliminateAutobox/TestEliminateBoxInDebugInfo.java index 07340bc0adc6a..0de30dc1de9a1 100644 --- a/test/hotspot/jtreg/compiler/c2/TestEliminateBoxInDebugInfo.java +++ b/test/hotspot/jtreg/compiler/eliminateAutobox/TestEliminateBoxInDebugInfo.java @@ -24,7 +24,7 @@ /* * @test * @bug 8261137 - * @requires vm.debug == true & vm.flavor == "server" + * @requires vm.debug == true & vm.compiler2.enabled * @summary Verify that box object is scalarized in case it is directly referenced by debug info. * @library /test/lib * diff --git a/test/hotspot/jtreg/compiler/c2/TestIdentityWithEliminateBoxInDebugInfo.java b/test/hotspot/jtreg/compiler/eliminateAutobox/TestIdentityWithEliminateBoxInDebugInfo.java similarity index 100% rename from test/hotspot/jtreg/compiler/c2/TestIdentityWithEliminateBoxInDebugInfo.java rename to test/hotspot/jtreg/compiler/eliminateAutobox/TestIdentityWithEliminateBoxInDebugInfo.java From 9fe85cff32c14ae2f75016579ff80cbc142abeee Mon Sep 17 00:00:00 2001 From: Wanghuang-Huawei Date: Tue, 30 Mar 2021 09:24:26 +0800 Subject: [PATCH 11/12] refact SafePointScalarObjectNode constructor --- src/hotspot/share/opto/callnode.cpp | 8 +++++--- src/hotspot/share/opto/callnode.hpp | 6 +++--- src/hotspot/share/opto/node.hpp | 3 +++ src/hotspot/share/opto/vector.cpp | 2 +- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp index 491c6cb1d9a3d..9a525e75a663a 100644 --- a/src/hotspot/share/opto/callnode.cpp +++ b/src/hotspot/share/opto/callnode.cpp @@ -1515,7 +1515,7 @@ void SafePointNode::disconnect_from_root(PhaseIterGVN *igvn) { SafePointScalarObjectNode::SafePointScalarObjectNode(const TypeOopPtr* tp, #ifdef ASSERT - CallNode* alloc, + Node* alloc, #endif uint first_index, uint n_fields, @@ -1529,8 +1529,10 @@ SafePointScalarObjectNode::SafePointScalarObjectNode(const TypeOopPtr* tp, #endif { #ifdef ASSERT - if (alloc != nullptr) { - assert(alloc->is_Allocate() || alloc->as_CallStaticJava()->is_boxing_method(), "unexpected alloc"); + if (!alloc->is_Allocate() && !alloc->is_VectorBox() + && (!alloc->is_CallStaticJava() || !alloc->as_CallStaticJava()->is_boxing_method())) { + alloc->dump(); + assert(false, "unexpected call node"); } #endif init_class_id(Class_SafePointScalarObject); diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp index 8f1e91e7e43de..ffb03c7aae03b 100644 --- a/src/hotspot/share/opto/callnode.hpp +++ b/src/hotspot/share/opto/callnode.hpp @@ -502,7 +502,7 @@ class SafePointScalarObjectNode: public TypeNode { // It is relative to the last (youngest) jvms->_scloff. uint _n_fields; // Number of non-static fields of the scalarized object. bool _is_auto_box; // True if the scalarized object is an auto box. - DEBUG_ONLY(CallNode* _alloc;) + DEBUG_ONLY(Node* _alloc;) virtual uint hash() const ; // { return NO_HASH; } virtual bool cmp( const Node &n ) const; @@ -512,7 +512,7 @@ class SafePointScalarObjectNode: public TypeNode { public: SafePointScalarObjectNode(const TypeOopPtr* tp, #ifdef ASSERT - CallNode* alloc, + Node* alloc, #endif uint first_index, uint n_fields, bool is_auto_box = false); virtual int Opcode() const; @@ -529,7 +529,7 @@ class SafePointScalarObjectNode: public TypeNode { bool is_auto_box() const { return _is_auto_box; } #ifdef ASSERT - CallNode* alloc() const { return _alloc; } + Node* alloc() const { return _alloc; } #endif virtual uint size_of() const { return sizeof(*this); } diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index b5957802a5ea1..ac28cf77df1ee 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -161,6 +161,7 @@ class Type; class TypeNode; class UnlockNode; class VectorNode; +class VectorBoxNode; class LoadVectorNode; class LoadVectorMaskedNode; class StoreVectorMaskedNode; @@ -743,6 +744,7 @@ class Node { DEFINE_CLASS_ID(Halt, Node, 15) DEFINE_CLASS_ID(Opaque1, Node, 16) DEFINE_CLASS_ID(Move, Node, 17) + DEFINE_CLASS_ID(VectorBox, Node, 18) _max_classes = ClassMask_Move }; @@ -919,6 +921,7 @@ class Node { DEFINE_CLASS_QUERY(SubTypeCheck) DEFINE_CLASS_QUERY(Type) DEFINE_CLASS_QUERY(Vector) + DEFINE_CLASS_QUERY(VectorBox) DEFINE_CLASS_QUERY(LoadVector) DEFINE_CLASS_QUERY(LoadVectorGather) DEFINE_CLASS_QUERY(StoreVector) diff --git a/src/hotspot/share/opto/vector.cpp b/src/hotspot/share/opto/vector.cpp index 49293c4a26b8c..21d721c2c26fd 100644 --- a/src/hotspot/share/opto/vector.cpp +++ b/src/hotspot/share/opto/vector.cpp @@ -248,7 +248,7 @@ void PhaseVector::scalarize_vbox_node(VectorBoxNode* vec_box) { uint first_ind = (sfpt->req() - sfpt->jvms()->scloff()); Node* sobj = new SafePointScalarObjectNode(vec_box->box_type(), #ifdef ASSERT - NULL, + vec_box, #endif // ASSERT first_ind, n_fields); sobj->init_req(0, C->root()); From 31f215b4dc8b480314574f4f9920cc6594386d16 Mon Sep 17 00:00:00 2001 From: Wanghuang-Huawei Date: Tue, 30 Mar 2021 09:47:45 +0800 Subject: [PATCH 12/12] trivial fix --- src/hotspot/share/opto/callnode.cpp | 5 +++-- src/hotspot/share/opto/node.hpp | 3 --- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp index 9a525e75a663a..935ade005a381 100644 --- a/src/hotspot/share/opto/callnode.cpp +++ b/src/hotspot/share/opto/callnode.cpp @@ -1529,8 +1529,9 @@ SafePointScalarObjectNode::SafePointScalarObjectNode(const TypeOopPtr* tp, #endif { #ifdef ASSERT - if (!alloc->is_Allocate() && !alloc->is_VectorBox() - && (!alloc->is_CallStaticJava() || !alloc->as_CallStaticJava()->is_boxing_method())) { + if (!alloc->is_Allocate() + && !(alloc->Opcode() == Op_VectorBox) + && (!alloc->is_CallStaticJava() || !alloc->as_CallStaticJava()->is_boxing_method())) { alloc->dump(); assert(false, "unexpected call node"); } diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index ac28cf77df1ee..b5957802a5ea1 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -161,7 +161,6 @@ class Type; class TypeNode; class UnlockNode; class VectorNode; -class VectorBoxNode; class LoadVectorNode; class LoadVectorMaskedNode; class StoreVectorMaskedNode; @@ -744,7 +743,6 @@ class Node { DEFINE_CLASS_ID(Halt, Node, 15) DEFINE_CLASS_ID(Opaque1, Node, 16) DEFINE_CLASS_ID(Move, Node, 17) - DEFINE_CLASS_ID(VectorBox, Node, 18) _max_classes = ClassMask_Move }; @@ -921,7 +919,6 @@ class Node { DEFINE_CLASS_QUERY(SubTypeCheck) DEFINE_CLASS_QUERY(Type) DEFINE_CLASS_QUERY(Vector) - DEFINE_CLASS_QUERY(VectorBox) DEFINE_CLASS_QUERY(LoadVector) DEFINE_CLASS_QUERY(LoadVectorGather) DEFINE_CLASS_QUERY(StoreVector)