--- a/src/hotspot/share/opto/memnode.cpp Thu Oct 17 20:27:44 2019 +0100
+++ b/src/hotspot/share/opto/memnode.cpp Thu Oct 17 20:53:35 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -44,13 +44,11 @@
#include "opto/narrowptrnode.hpp"
#include "opto/phaseX.hpp"
#include "opto/regmask.hpp"
+#include "opto/rootnode.hpp"
#include "utilities/align.hpp"
#include "utilities/copy.hpp"
#include "utilities/macros.hpp"
#include "utilities/vmError.hpp"
-#if INCLUDE_ZGC
-#include "gc/z/c2/zBarrierSetC2.hpp"
-#endif
// Portions of code courtesy of Clifford Click
@@ -328,6 +326,24 @@
const Type *t_adr = phase->type(address);
if (t_adr == Type::TOP) return NodeSentinel; // caller will return NULL
+ if (can_reshape && is_unsafe_access() && (t_adr == TypePtr::NULL_PTR)) {
+ // Unsafe off-heap access with zero address. Remove access and other control users
+ // to not confuse optimizations and add a HaltNode to fail if this is ever executed.
+ assert(ctl != NULL, "unsafe accesses should be control dependent");
+ for (DUIterator_Fast imax, i = ctl->fast_outs(imax); i < imax; i++) {
+ Node* u = ctl->fast_out(i);
+ if (u != ctl) {
+ igvn->rehash_node_delayed(u);
+ int nb = u->replace_edge(ctl, phase->C->top());
+ --i, imax -= nb;
+ }
+ }
+ Node* frame = igvn->transform(new ParmNode(phase->C->start(), TypeFunc::FramePtr));
+ Node* halt = igvn->transform(new HaltNode(ctl, frame, "unsafe off-heap access with zero address"));
+ phase->C->root()->add_req(halt);
+ return this;
+ }
+
if (can_reshape && igvn != NULL &&
(igvn->_worklist.member(address) ||
(igvn->_worklist.size() > 0 && t_adr != adr_type())) ) {
@@ -908,14 +924,6 @@
// a load node that reads from the source array so we may be able to
// optimize out the ArrayCopy node later.
Node* LoadNode::can_see_arraycopy_value(Node* st, PhaseGVN* phase) const {
-#if INCLUDE_ZGC
- if (UseZGC) {
- if (bottom_type()->make_oopptr() != NULL) {
- return NULL;
- }
- }
-#endif
-
Node* ld_adr = in(MemNode::Address);
intptr_t ld_off = 0;
AllocateNode* ld_alloc = AllocateNode::Ideal_allocation(ld_adr, phase, ld_off);
@@ -973,7 +981,7 @@
ld->set_req(0, ctl);
ld->set_req(MemNode::Memory, mem);
// load depends on the tests that validate the arraycopy
- ld->_control_dependency = Pinned;
+ ld->_control_dependency = UnknownControl;
return ld;
}
return NULL;
@@ -1424,8 +1432,6 @@
}
}
- bool load_boxed_phi = load_boxed_values && base_is_phi && (base->in(0) == mem->in(0));
-
// Split through Phi (see original code in loopopts.cpp).
assert(C->have_alias_type(t_oop), "instance should have alias type");
@@ -1546,6 +1552,22 @@
return phi;
}
+AllocateNode* LoadNode::is_new_object_mark_load(PhaseGVN *phase) const {
+ if (Opcode() == Op_LoadX) {
+ Node* address = in(MemNode::Address);
+ AllocateNode* alloc = AllocateNode::Ideal_allocation(address, phase);
+ Node* mem = in(MemNode::Memory);
+ if (alloc != NULL && mem->is_Proj() &&
+ mem->in(0) != NULL &&
+ mem->in(0) == alloc->initialization() &&
+ alloc->initialization()->proj_out_or_null(0) != NULL) {
+ return alloc;
+ }
+ }
+ return NULL;
+}
+
+
//------------------------------Ideal------------------------------------------
// If the load is from Field memory and the pointer is non-null, it might be possible to
// zero out the control input.
@@ -1566,7 +1588,8 @@
// pointer stores & cardmarks must stay on the same side of a SafePoint.
if( ctrl != NULL && ctrl->Opcode() == Op_SafePoint &&
phase->C->get_alias_index(phase->type(address)->is_ptr()) != Compile::AliasIdxRaw &&
- !addr_mark ) {
+ !addr_mark &&
+ (depends_only_on_test() || has_unknown_control_dependency())) {
ctrl = ctrl->in(0);
set_req(MemNode::Control,ctrl);
progress = true;
@@ -1673,6 +1696,13 @@
}
}
+ AllocateNode* alloc = is_new_object_mark_load(phase);
+ if (alloc != NULL && alloc->Opcode() == Op_Allocate && UseBiasedLocking) {
+ InitializeNode* init = alloc->initialization();
+ Node* control = init->proj_out(0);
+ return alloc->make_ideal_mark(phase, address, control, mem);
+ }
+
return progress ? this : NULL;
}
@@ -1931,6 +1961,12 @@
return Type::get_zero_type(_type->basic_type());
}
}
+
+ Node* alloc = is_new_object_mark_load(phase);
+ if (alloc != NULL && !(alloc->Opcode() == Op_Allocate && UseBiasedLocking)) {
+ return TypeX::make(markWord::prototype().value());
+ }
+
return _type;
}
@@ -2811,7 +2847,8 @@
LoadStoreNode::LoadStoreNode( Node *c, Node *mem, Node *adr, Node *val, const TypePtr* at, const Type* rt, uint required )
: Node(required),
_type(rt),
- _adr_type(at)
+ _adr_type(at),
+ _barrier(0)
{
init_req(MemNode::Control, c );
init_req(MemNode::Memory , mem);
@@ -3105,16 +3142,6 @@
return NULL;
}
-#if INCLUDE_ZGC
- if (UseZGC) {
- if (req() == (Precedent+1) && in(MemBarNode::Precedent)->in(0) != NULL && in(MemBarNode::Precedent)->in(0)->is_LoadBarrier()) {
- Node* load_node = in(MemBarNode::Precedent)->in(0)->in(LoadBarrierNode::Oop);
- set_req(MemBarNode::Precedent, load_node);
- return this;
- }
- }
-#endif
-
bool progress = false;
// Eliminate volatile MemBars for scalar replaced objects.
if (can_reshape && req() == (Precedent+1)) {