Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8264954: unified handling for VectorMask object re-materialization during de-optimization #3408

Closed
wants to merge 3 commits into from

Conversation

@jatin-bhateja
Copy link
Member

@jatin-bhateja jatin-bhateja commented Apr 9, 2021

Following flow describes object reconstruction for de-optimization:-

  1. PhaseVector::scalarize_vbox_node() creates SafePointScalarObjectNode to captures the box type information, also it connects to node holding the boxed value.
  2. During code emit phase (PhaseOutput) C2 process above information to dumps ObjectValue holding the box information and LocationValue to holding the value information into ScopeDescriptor corresponding to Safepoint PC.
  3. De-optimization blobs dump the value held in registers to the stack locations using RegisterSave::save_live_registers() and a mapping b/w register and its stack location is added to RegisterMap.
  4. During de-optimization, compiled frame objects are re-allocated using identity information held in ObjectValue and their fields are initialized using values held in the stack locations accessed through register-stack mappings.

By inserting a VectorStoreMaskNode before stitching the mask holding node to Safepoint we make sure that value held in opmask/vector register is transferred to a byte vector. Thus rest of the flow works as it is, stack location will hold the value in the form of a byte array irrespective of the box shape.

tier1-tier3 regressions are clean with UseAVX=2/3.


Progress

  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue
  • Change must be properly reviewed

Issue

  • JDK-8264954: unified handling for VectorMask object re-materialization during de-optimization

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/jdk pull/3408/head:pull/3408
$ git checkout pull/3408

Update a local copy of the PR:
$ git checkout pull/3408
$ git pull https://git.openjdk.java.net/jdk pull/3408/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 3408

View PR using the GUI difftool:
$ git pr show -t 3408

Using diff file

Download this PR as a diff file:
https://git.openjdk.java.net/jdk/pull/3408.diff

@bridgekeeper
Copy link

@bridgekeeper bridgekeeper bot commented Apr 9, 2021

👋 Welcome back jbhateja! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

Loading

@jatin-bhateja
Copy link
Member Author

@jatin-bhateja jatin-bhateja commented Apr 9, 2021

/label hotspot-compiler-dev

Loading

@openjdk
Copy link

@openjdk openjdk bot commented Apr 9, 2021

@jatin-bhateja
The hotspot-compiler label was successfully added.

Loading

@mlbridge
Copy link

@mlbridge mlbridge bot commented Apr 9, 2021

Webrevs

Loading

Copy link

@iwanowww iwanowww left a comment

Very nice! I like your idea to unify mask representation. It simplifies implementation a lot.
But it also means there'll be 2 representations kept alive for masks with debug usages and burns 2 registers (speaking of x86, either 1 predicate + 1 vector registers on AVX512 or 2 vector regsiters on pre-AVX512). Do you see any problems with that? (It can be improved later if it turns out to be a problem in practice.)

Loading

} else if (vec_value->Opcode() != Op_VectorStoreMask) {
const TypeVect* vt = vec_value->bottom_type()->is_vect();
BasicType bt = vt->element_basic_type();
vec_value = gvn.transform(VectorStoreMaskNode::make(gvn, vec_value, bt, vt->length()));
Copy link

@iwanowww iwanowww Apr 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VectorStoreMaskNode::Identity() already handles VectorStoreMask (VectorLoadMask bv) elem_size ==> bv transformation, doesn't it? So, you can just unconditionally instantiate VectorStoreMaskNode and let IGVN handle it.

Also, an observation on naming: VectorLoadMask and VectorStoreMask names are misleading. On the surface, they look like memory nodes, but in fact, are cast nodes (Vector <-> Mask). Please, file an RFE to address that eventually.

Loading

@@ -88,20 +88,13 @@ jint VectorSupport::klass2length(InstanceKlass* ik) {

void VectorSupport::init_payload_element(typeArrayOop arr, bool is_mask, BasicType elem_bt, int index, address addr) {
if (is_mask) {
// Masks require special handling: when boxed they are packed and stored in boolean
Copy link

@iwanowww iwanowww Apr 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is still valid. Please, keep it and update with latest details about mask support.

Loading

case T_INT:
case T_LONG:
case T_FLOAT:
case T_DOUBLE: arr->bool_at_put(index, (*(jbyte*)addr) != 0); break;
Copy link

@iwanowww iwanowww Apr 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No switch needed anymore. Just leave the arr->bool_at_put(index, (*(jbyte*)addr) != 0).
As an option, consider adding an assert (assert(is_java_type(bt) && bt != T_BOOLEAN).

Loading

Copy link

@iwanowww iwanowww Apr 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I think you can get rid of is_mask and just use elem_bt = T_BOOLEAN / bool_at_put(index, (*(jboolean*)addr)).

Loading

// to SafePointNode will ensure packing the mask into a
// byte array for masks present in both predicated register
// or vector registers.
int elem_size = is_mask ? 1 : type2aelembytes(elem_bt);
Copy link

@iwanowww iwanowww Apr 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If elem_bt == T_BOOLEAN for masks, you can get rid of is_mask usages in VectorSupport::allocate_vector_payload_helper() and just introduce a special case in VectorSupport::klass2bt (as already done for VectorShuffles).

Loading

@jatin-bhateja
Copy link
Member Author

@jatin-bhateja jatin-bhateja commented Apr 9, 2021

Thanks @iwanowww , your comments are resolved.

Loading

Copy link

@iwanowww iwanowww left a comment

Looks good.

Minor comments follow.

Loading

// During scalarization inserting a VectorStoreMask node between mask
// and safepoint node always ensures the existence of masks in a boolean array.
//
// TODO: revisit when predicate registers are fully supported.
Copy link

@iwanowww iwanowww Apr 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO line can be removed now.

Loading

// logic for both predicated and non-predicated targets.
bool is_mask = is_vector_mask(iklass);
if (is_mask) {
if (vec_value->Opcode() != Op_VectorStoreMask) {
Copy link

@iwanowww iwanowww Apr 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better to do the check against the type of vec_value: VectorStoreMask produces a vector of booleans and you can guard gvn.transform(VectorStoreMaskNode::make(...)) call with bt != T_BOOLEAN check instead.

Loading

Copy link
Member Author

@jatin-bhateja jatin-bhateja Apr 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to bt != T_BOOLEAN check, we also need to check if type is a vectormask (explicit type added for mask generating nodes on targets supporting predicate registers).

A similar check needs to be added at following location
https://github.com/openjdk/jdk/blob/master/src/hotspot/share/opto/vector.cpp#L329

Keeping this as it is i.e. an Opcode based check.

Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to bt != T_BOOLEAN check, we also need to check if type is a vectormask (explicit type added for mask generating nodes on targets supporting predicate registers).

You check here that the mask is in canonical representation (which is a vector of booleans) before applying the canonicalizing conversion. Alternatively, you could check that the mask is in "native"/platform-dependent representation (vec_value has TypeVectMask type).

So, my reading of your response is that bt != T_BOOLEAN check is not enough to reliably distinguish between the representations: a mask for vector of booleans (in native representation) will have the same type as the vector of booleans produced by the canonicalizing cast of a mask value. I agree with that.

But until TypeVectMask is used uniformly and independently of predicate register support, TypeVect vs TypeVectMask doesn't cut the problem as well. And adding bt != T_BOOLEAN doesn't help.

So, I'm fine with leaving the Opcode check for now.

In the longer term, we need to come up with a uniform representation in type system for masks in native format to be able to reliably distinguish between masks and vectors in cross-platform manner.

Loading

//
void VectorSupport::init_payload_element(typeArrayOop arr, BasicType elem_bt, int index, address addr) {
switch (elem_bt) {
case T_BOOLEAN:
Copy link

@iwanowww iwanowww Apr 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, use bool_at_put() accessor here (just for clarity):

case T_BOOLEAN: arr->bool_at_put(index, *(jboolean*)addr); break;

Loading

@openjdk
Copy link

@openjdk openjdk bot commented Apr 9, 2021

@jatin-bhateja This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

8264954: unified handling for VectorMask object re-materialization during de-optimization

Reviewed-by: vlivanov

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 28 new commits pushed to the master branch:

  • e604320: 8264783: G1 BOT verification should not verify beyond allocation threshold
  • cb2806d: 8265018: [AIX] FileDispatcherImpl.c:31:10: fatal error: 'sys/mount.h' file not found
  • ecef1fc: 8264972: Unused TypeFunc declared in OptoRuntime
  • 440c34a: 8264644: Add PrintClassLoaderDataGraphAtExit to print the detailed CLD graph
  • b1ebf82: 8264358: Don't create invalid oop in method handle tracing
  • 627ad9f: 8262328: Templatize JVMFlag boilerplate access methods
  • c15680e: 8264868: Reduce inclusion of registerMap.hpp and register.hpp
  • 5784f6b: 8264948: Check for TLS extensions total length
  • 42f4d70: 8264649: runtime/InternalApi/ThreadCpuTimesDeadlock.java crash in fastdebug C2 with -XX:-UseTLAB
  • 76bd313: 8264872: Dependencies: Migrate to PerfData counters
  • ... and 18 more: https://git.openjdk.java.net/jdk/compare/951f277a71bfa5bd3a3934a8ccd66dfc25bae004...master

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

➡️ To integrate this PR with the above commit message to the master branch, type /integrate in a new comment.

Loading

@openjdk openjdk bot added the ready label Apr 9, 2021
@jatin-bhateja
Copy link
Member Author

@jatin-bhateja jatin-bhateja commented Apr 12, 2021

/integrate

Loading

@openjdk openjdk bot closed this Apr 12, 2021
@openjdk openjdk bot added integrated and removed ready rfr labels Apr 12, 2021
@openjdk
Copy link

@openjdk openjdk bot commented Apr 12, 2021

@jatin-bhateja Since your change was applied there have been 29 commits pushed to the master branch:

  • 3c9858d: 8264827: Large mapped buffer/segment crash the VM when calling isLoaded
  • e604320: 8264783: G1 BOT verification should not verify beyond allocation threshold
  • cb2806d: 8265018: [AIX] FileDispatcherImpl.c:31:10: fatal error: 'sys/mount.h' file not found
  • ecef1fc: 8264972: Unused TypeFunc declared in OptoRuntime
  • 440c34a: 8264644: Add PrintClassLoaderDataGraphAtExit to print the detailed CLD graph
  • b1ebf82: 8264358: Don't create invalid oop in method handle tracing
  • 627ad9f: 8262328: Templatize JVMFlag boilerplate access methods
  • c15680e: 8264868: Reduce inclusion of registerMap.hpp and register.hpp
  • 5784f6b: 8264948: Check for TLS extensions total length
  • 42f4d70: 8264649: runtime/InternalApi/ThreadCpuTimesDeadlock.java crash in fastdebug C2 with -XX:-UseTLAB
  • ... and 19 more: https://git.openjdk.java.net/jdk/compare/951f277a71bfa5bd3a3934a8ccd66dfc25bae004...master

Your commit was automatically rebased without conflicts.

Pushed as commit f71be8b.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
3 participants