RFR: 8263164: assert(_base >= VectorA && _base <= VectorZ) failed: Not a Vector while calling StoreVectorNode::memory_size()
Vladimir Kozlov
kvn at openjdk.java.net
Thu Mar 11 03:55:06 UTC 2021
On Wed, 10 Mar 2021 04:18:16 GMT, Jie Fu <jiefu at openjdk.org> wrote:
>> What I mean is IGVN should replace nodes which have TOP input with TOP and remove them from graph as dead nodes.
>> `Value()` methods do replacement after checking node's inputs for TOP. And `Ideal()` method should check for TOP and immediately return to avoid unneeded transformations (or guard transformation code with `!= TOP` check) and let `Value()` do replacement with TOP.
>>
>> In case of memory nodes `MemNode::Ideal_common()` do such checks (but only for ctrl, mem and adr inputs):
>> https://github.com/openjdk/jdk/blob/master/src/hotspot/share/opto/memnode.cpp#L286
>>
>> To my surprise `StoreNode::Ideal()` does not check `in(MemNode::ValueIn)` input for TOP at all. May be because in normal case we don't do much for `in(MemNode::ValueIn)` when processing Store nodes and eventually `StoreNode::Value()` will replace node with TOP.
>>
>> Yes, your fix works for `Vector` nodes. But as you saw normal `Store` nodes also can have TOP value input and we do useless transformations until StoreNode::Value() calls. I think the better fix is to check ` in(MemNode::ValueIn)` for TOP in `StoreNode::Ideal()`.
>>
>> And we need to test it hard because it is very old code.
>
> Hi @vnkozlov ,
>
> Unfortunately, it doesn't work to avoid store->in(MemNode::ValueIn)->bottom_type() == Type::TOP by just improving StoreNode::Ideal().
>
> TOP value seems hard to be avoided for store nodes during C2's optimization phase.
> So I think we should support StoreVectorNode::memory_size() for that case, which has already been supported by non-vector stores.
>
> And I suggest to keep StoreNode::Ideal() as it is to lower the risk.
>
> What do you think?
>
> Thanks.
> Best regards,
> Jie
>
> --------------------------------------
>
> To show you how this can happen, please run vmTestbase/nsk/jdi/StepEvent/_itself_/stepEvent004/stepEvent004.java several times with the following change:
>
> diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp
> index 440e29f..28debe1 100644
> --- a/src/hotspot/share/opto/memnode.cpp
> +++ b/src/hotspot/share/opto/memnode.cpp
> @@ -2617,6 +2617,9 @@ Node *StoreNode::Ideal(PhaseGVN *phase, bool can_reshape) {
> Node* mem = in(MemNode::Memory);
> Node* address = in(MemNode::Address);
> Node* value = in(MemNode::ValueIn);
> +
> + if (value && value->is_top()) return NULL;
> +
> // Back-to-back stores to same address? Fold em up. Generally
> // unsafe if I have intervening uses... Also disallowed for StoreCM
> // since they must follow each StoreP operation. Redundant StoreCMs
> diff --git a/src/hotspot/share/opto/memnode.hpp b/src/hotspot/share/opto/memnode.hpp
> index b9ee30f..ea878f9 100644
> --- a/src/hotspot/share/opto/memnode.hpp
> +++ b/src/hotspot/share/opto/memnode.hpp
> @@ -603,6 +603,19 @@ public:
> #endif
> }
>
> + virtual int memory_size() const {
> + if (in(MemNode::ValueIn)->bottom_type() == Type::TOP) {
> + tty->print_cr("jiefu catch it ...");
> + this->dump();
> + assert(false, "Find top in StoreNode");
> + }
> +#ifdef ASSERT
> + return type2aelembytes(memory_type(), true);
> +#else
> + return type2aelembytes(memory_type());
> +#endif
> + }
> +
> // Polymorphic factory method
> //
> // We must ensure that stores of object references will be visible
>
>
> In my experiment, I got the failure like this
>
> jiefu catch it ...
> 21550 StoreI === 15446 15451 21551 1 [[ 15454 ]]
>
> #
> # A fatal error has been detected by the Java Runtime Environment:
> #
> # Internal Error (/home/jvm/jdk/src/hotspot/share/opto/memnode.hpp:610), pid=20324, tid=20395
> # assert(false) failed: Find top in StoreNode
> #
>
> Current thread (0x00007f8900308b40): JavaThread "C2 CompilerThread1" daemon [_thread_in_native, id=20395, stack(0x00007f891a5ac000,0x00007f891a6ad000)]
>
>
> Current CompileTask:
> C2: 2238 1321 % 4 nsk.share.jdi.sde.SDEDebugger::compareLocations @ 66 (381 bytes)
>
> Stack: [0x00007f891a5ac000,0x00007f891a6ad000], sp=0x00007f891a6a8280, free space=1008k
> Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)
> V [libjvm.so+0x91a452] StoreNode::memory_size() const+0xe2
> V [libjvm.so+0x1282223] InitializeNode::stores_are_sane(PhaseTransform*) [clone .part.212]+0x123
> V [libjvm.so+0x128fef8] InitializeNode::capture_store(StoreNode*, long, PhaseGVN*, bool)+0x268
> V [libjvm.so+0x12988a3] StoreNode::Ideal(PhaseGVN*, bool)+0x533
> V [libjvm.so+0x144564a] PhaseIterGVN::transform_old(Node*)+0xba
> V [libjvm.so+0x143f72d] PhaseIterGVN::optimize()+0x7d
> V [libjvm.so+0x979834] Compile::Optimize()+0x204
> V [libjvm.so+0x97c134] Compile::Compile(ciEnv*, ciMethod*, int, bool, bool, bool, bool, DirectiveSet*)+0x1864
> V [libjvm.so+0x7e253a] C2Compiler::compile_method(ciEnv*, ciMethod*, int, bool, DirectiveSet*)+0x10a
> V [libjvm.so+0x98a4c6] CompileBroker::invoke_compiler_on_method(CompileTask*)+0xbf6
> V [libjvm.so+0x98b058] CompileBroker::compiler_thread_loop()+0x4b8
> V [libjvm.so+0x17d120a] JavaThread::thread_main_inner()+0x2fa
> V [libjvm.so+0x17d1527] JavaThread::run()+0x2b7
> V [libjvm.so+0x17d5fe8] Thread::call_run()+0xf8
> V [libjvm.so+0x13c5866] thread_native_entry(Thread*)+0x116
Would be nice to see where TOP value is coming from in stepEvent004.java test.
-------------
PR: https://git.openjdk.java.net/jdk/pull/2867
More information about the hotspot-compiler-dev
mailing list