mirror of
https://github.com/openjdk/jdk19u.git
synced 2025-12-10 00:20:40 -06:00
Merge
This commit is contained in:
commit
1d3871afcd
@ -5105,7 +5105,7 @@ operand iRegP()
|
||||
match(iRegP_R0);
|
||||
//match(iRegP_R2);
|
||||
//match(iRegP_R4);
|
||||
//match(iRegP_R5);
|
||||
match(iRegP_R5);
|
||||
match(thread_RegP);
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
|
||||
@ -3208,6 +3208,7 @@ operand iRegP()
|
||||
match(RegP);
|
||||
match(iRegPNoSp);
|
||||
match(iRegP_R10);
|
||||
match(iRegP_R15);
|
||||
match(javaThread_RegP);
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
|
||||
@ -869,7 +869,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||
//
|
||||
/*
|
||||
* if (is_aligned) {
|
||||
* goto copy_8_bytes;
|
||||
* if (count >= 32)
|
||||
* goto copy32_loop;
|
||||
* if (count >= 8)
|
||||
* goto copy8_loop;
|
||||
* goto copy_small;
|
||||
* }
|
||||
* bool is_backwards = step < 0;
|
||||
* int granularity = uabs(step);
|
||||
@ -887,9 +891,12 @@ class StubGenerator: public StubCodeGenerator {
|
||||
*
|
||||
* if ((dst % 8) == (src % 8)) {
|
||||
* aligned;
|
||||
* goto copy8;
|
||||
* goto copy_big;
|
||||
* }
|
||||
*
|
||||
* copy_big:
|
||||
* if the amount to copy is more than (or equal to) 32 bytes goto copy32_loop
|
||||
* else goto copy8_loop
|
||||
* copy_small:
|
||||
* load element one by one;
|
||||
* done;
|
||||
@ -950,10 +957,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
bool is_backwards = step < 0;
|
||||
int granularity = uabs(step);
|
||||
|
||||
const Register src = x30, dst = x31, cnt = x15, tmp3 = x16, tmp4 = x17;
|
||||
const Register src = x30, dst = x31, cnt = x15, tmp3 = x16, tmp4 = x17, tmp5 = x14, tmp6 = x13;
|
||||
|
||||
Label same_aligned;
|
||||
Label copy8, copy_small, done;
|
||||
Label copy_big, copy32_loop, copy8_loop, copy_small, done;
|
||||
|
||||
copy_insn ld_arr = NULL, st_arr = NULL;
|
||||
switch (granularity) {
|
||||
@ -988,36 +995,69 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
|
||||
if (is_aligned) {
|
||||
__ addi(tmp, cnt, -32);
|
||||
__ bgez(tmp, copy32_loop);
|
||||
__ addi(tmp, cnt, -8);
|
||||
__ bgez(tmp, copy8);
|
||||
__ bgez(tmp, copy8_loop);
|
||||
__ j(copy_small);
|
||||
} else {
|
||||
__ mv(tmp, 16);
|
||||
__ blt(cnt, tmp, copy_small);
|
||||
|
||||
__ xorr(tmp, src, dst);
|
||||
__ andi(tmp, tmp, 0b111);
|
||||
__ bnez(tmp, copy_small);
|
||||
|
||||
__ bind(same_aligned);
|
||||
__ andi(tmp, src, 0b111);
|
||||
__ beqz(tmp, copy_big);
|
||||
if (is_backwards) {
|
||||
__ addi(src, src, step);
|
||||
__ addi(dst, dst, step);
|
||||
}
|
||||
(_masm->*ld_arr)(tmp3, Address(src), t0);
|
||||
(_masm->*st_arr)(tmp3, Address(dst), t0);
|
||||
if (!is_backwards) {
|
||||
__ addi(src, src, step);
|
||||
__ addi(dst, dst, step);
|
||||
}
|
||||
__ addi(cnt, cnt, -granularity);
|
||||
__ beqz(cnt, done);
|
||||
__ j(same_aligned);
|
||||
|
||||
__ bind(copy_big);
|
||||
__ mv(tmp, 32);
|
||||
__ blt(cnt, tmp, copy8_loop);
|
||||
}
|
||||
|
||||
__ mv(tmp, 16);
|
||||
__ blt(cnt, tmp, copy_small);
|
||||
|
||||
__ xorr(tmp, src, dst);
|
||||
__ andi(tmp, tmp, 0b111);
|
||||
__ bnez(tmp, copy_small);
|
||||
|
||||
__ bind(same_aligned);
|
||||
__ andi(tmp, src, 0b111);
|
||||
__ beqz(tmp, copy8);
|
||||
__ bind(copy32_loop);
|
||||
if (is_backwards) {
|
||||
__ addi(src, src, step);
|
||||
__ addi(dst, dst, step);
|
||||
__ addi(src, src, -wordSize * 4);
|
||||
__ addi(dst, dst, -wordSize * 4);
|
||||
}
|
||||
(_masm->*ld_arr)(tmp3, Address(src), t0);
|
||||
(_masm->*st_arr)(tmp3, Address(dst), t0);
|
||||
if (!is_backwards) {
|
||||
__ addi(src, src, step);
|
||||
__ addi(dst, dst, step);
|
||||
}
|
||||
__ addi(cnt, cnt, -granularity);
|
||||
__ beqz(cnt, done);
|
||||
__ j(same_aligned);
|
||||
// we first load 32 bytes, then write it, so the direction here doesn't matter
|
||||
__ ld(tmp3, Address(src));
|
||||
__ ld(tmp4, Address(src, 8));
|
||||
__ ld(tmp5, Address(src, 16));
|
||||
__ ld(tmp6, Address(src, 24));
|
||||
__ sd(tmp3, Address(dst));
|
||||
__ sd(tmp4, Address(dst, 8));
|
||||
__ sd(tmp5, Address(dst, 16));
|
||||
__ sd(tmp6, Address(dst, 24));
|
||||
|
||||
__ bind(copy8);
|
||||
if (!is_backwards) {
|
||||
__ addi(src, src, wordSize * 4);
|
||||
__ addi(dst, dst, wordSize * 4);
|
||||
}
|
||||
__ addi(tmp, cnt, -(32 + wordSize * 4));
|
||||
__ addi(cnt, cnt, -wordSize * 4);
|
||||
__ bgez(tmp, copy32_loop); // cnt >= 32, do next loop
|
||||
|
||||
__ beqz(cnt, done); // if that's all - done
|
||||
|
||||
__ addi(tmp, cnt, -8); // if not - copy the reminder
|
||||
__ bltz(tmp, copy_small); // cnt < 8, go to copy_small, else fall throught to copy8_loop
|
||||
|
||||
__ bind(copy8_loop);
|
||||
if (is_backwards) {
|
||||
__ addi(src, src, -wordSize);
|
||||
__ addi(dst, dst, -wordSize);
|
||||
@ -1028,11 +1068,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ addi(src, src, wordSize);
|
||||
__ addi(dst, dst, wordSize);
|
||||
}
|
||||
__ addi(tmp, cnt, -(8 + wordSize));
|
||||
__ addi(cnt, cnt, -wordSize);
|
||||
__ addi(tmp4, cnt, -8);
|
||||
__ bgez(tmp4, copy8); // cnt >= 8, do next loop
|
||||
__ bgez(tmp, copy8_loop); // cnt >= 8, do next loop
|
||||
|
||||
__ beqz(cnt, done);
|
||||
__ beqz(cnt, done); // if that's all - done
|
||||
|
||||
__ bind(copy_small);
|
||||
if (is_backwards) {
|
||||
|
||||
@ -4328,13 +4328,13 @@ static void check_pax(void) {
|
||||
#ifndef ZERO
|
||||
size_t size = os::Linux::page_size();
|
||||
|
||||
void* p = ::mmap(NULL, size, PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
void* p = ::mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
if (p == MAP_FAILED) {
|
||||
log_debug(os)("os_linux.cpp: check_pax: mmap failed (%s)" , os::strerror(errno));
|
||||
vm_exit_out_of_memory(size, OOM_MMAP_ERROR, "failed to allocate memory for PaX check.");
|
||||
}
|
||||
|
||||
int res = ::mprotect(p, size, PROT_WRITE|PROT_EXEC);
|
||||
int res = ::mprotect(p, size, PROT_READ|PROT_WRITE|PROT_EXEC);
|
||||
if (res == -1) {
|
||||
log_debug(os)("os_linux.cpp: check_pax: mprotect failed (%s)" , os::strerror(errno));
|
||||
vm_exit_during_initialization(
|
||||
|
||||
@ -404,13 +404,7 @@ void CompilerConfig::set_compilation_policy_flags() {
|
||||
if (CompilerConfig::is_tiered() && CompilerConfig::is_c2_enabled()) {
|
||||
#ifdef COMPILER2
|
||||
// Some inlining tuning
|
||||
#ifdef X86
|
||||
if (FLAG_IS_DEFAULT(InlineSmallCode)) {
|
||||
FLAG_SET_DEFAULT(InlineSmallCode, 2500);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined AARCH64
|
||||
#if defined(X86) || defined(AARCH64) || defined(RISCV64)
|
||||
if (FLAG_IS_DEFAULT(InlineSmallCode)) {
|
||||
FLAG_SET_DEFAULT(InlineSmallCode, 2500);
|
||||
}
|
||||
|
||||
@ -66,6 +66,10 @@ ShenandoahFullGC::ShenandoahFullGC() :
|
||||
_gc_timer(ShenandoahHeap::heap()->gc_timer()),
|
||||
_preserved_marks(new PreservedMarksSet(true)) {}
|
||||
|
||||
ShenandoahFullGC::~ShenandoahFullGC() {
|
||||
delete _preserved_marks;
|
||||
}
|
||||
|
||||
bool ShenandoahFullGC::collect(GCCause::Cause cause) {
|
||||
vmop_entry_full(cause);
|
||||
// Always success
|
||||
|
||||
@ -66,6 +66,7 @@ private:
|
||||
|
||||
public:
|
||||
ShenandoahFullGC();
|
||||
~ShenandoahFullGC();
|
||||
bool collect(GCCause::Cause cause);
|
||||
|
||||
private:
|
||||
|
||||
@ -1270,15 +1270,6 @@ void Method::restore_unshareable_info(TRAPS) {
|
||||
assert(is_method() && is_valid_method(this), "ensure C++ vtable is restored");
|
||||
}
|
||||
|
||||
address Method::from_compiled_entry_no_trampoline() const {
|
||||
CompiledMethod *code = Atomic::load_acquire(&_code);
|
||||
if (code) {
|
||||
return code->verified_entry_point();
|
||||
} else {
|
||||
return adapter()->get_c2i_entry();
|
||||
}
|
||||
}
|
||||
|
||||
// The verified_code_entry() must be called when a invoke is resolved
|
||||
// on this method.
|
||||
|
||||
|
||||
@ -145,7 +145,6 @@ class Method : public Metadata {
|
||||
|
||||
static address make_adapters(const methodHandle& mh, TRAPS);
|
||||
address from_compiled_entry() const;
|
||||
address from_compiled_entry_no_trampoline() const;
|
||||
address from_interpreted_entry() const;
|
||||
|
||||
// access flag
|
||||
|
||||
@ -402,7 +402,7 @@ void Compile::remove_useless_node(Node* dead) {
|
||||
}
|
||||
|
||||
// Disconnect all useless nodes by disconnecting those at the boundary.
|
||||
void Compile::remove_useless_nodes(Unique_Node_List &useful) {
|
||||
void Compile::disconnect_useless_nodes(Unique_Node_List &useful, Unique_Node_List* worklist) {
|
||||
uint next = 0;
|
||||
while (next < useful.size()) {
|
||||
Node *n = useful.at(next++);
|
||||
@ -425,7 +425,7 @@ void Compile::remove_useless_nodes(Unique_Node_List &useful) {
|
||||
}
|
||||
}
|
||||
if (n->outcnt() == 1 && n->has_special_unique_user()) {
|
||||
record_for_igvn(n->unique_out());
|
||||
worklist->push(n->unique_out());
|
||||
}
|
||||
}
|
||||
|
||||
@ -435,6 +435,11 @@ void Compile::remove_useless_nodes(Unique_Node_List &useful) {
|
||||
remove_useless_nodes(_expensive_nodes, useful); // remove useless expensive nodes
|
||||
remove_useless_nodes(_for_post_loop_igvn, useful); // remove useless node recorded for post loop opts IGVN pass
|
||||
remove_useless_coarsened_locks(useful); // remove useless coarsened locks nodes
|
||||
#ifdef ASSERT
|
||||
if (_modified_nodes != NULL) {
|
||||
_modified_nodes->remove_useless_nodes(useful.member_set());
|
||||
}
|
||||
#endif
|
||||
|
||||
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
|
||||
bs->eliminate_useless_gc_barriers(useful, this);
|
||||
|
||||
@ -945,7 +945,7 @@ class Compile : public Phase {
|
||||
|
||||
void identify_useful_nodes(Unique_Node_List &useful);
|
||||
void update_dead_node_list(Unique_Node_List &useful);
|
||||
void remove_useless_nodes (Unique_Node_List &useful);
|
||||
void disconnect_useless_nodes(Unique_Node_List &useful, Unique_Node_List* worklist);
|
||||
|
||||
void remove_useless_node(Node* dead);
|
||||
|
||||
|
||||
@ -281,7 +281,9 @@ bool ConnectionGraph::compute_escape() {
|
||||
// 3. Adjust scalar_replaceable state of nonescaping objects and push
|
||||
// scalar replaceable allocations on alloc_worklist for processing
|
||||
// in split_unique_types().
|
||||
GrowableArray<JavaObjectNode*> jobj_worklist;
|
||||
int non_escaped_length = non_escaped_allocs_worklist.length();
|
||||
bool found_nsr_alloc = false;
|
||||
for (int next = 0; next < non_escaped_length; next++) {
|
||||
JavaObjectNode* ptn = non_escaped_allocs_worklist.at(next);
|
||||
bool noescape = (ptn->escape_state() == PointsToNode::NoEscape);
|
||||
@ -292,11 +294,25 @@ bool ConnectionGraph::compute_escape() {
|
||||
if (noescape && ptn->scalar_replaceable()) {
|
||||
adjust_scalar_replaceable_state(ptn);
|
||||
if (ptn->scalar_replaceable()) {
|
||||
alloc_worklist.append(ptn->ideal_node());
|
||||
jobj_worklist.push(ptn);
|
||||
} else {
|
||||
found_nsr_alloc = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Propagate NSR (Not Scalar Replaceable) state.
|
||||
if (found_nsr_alloc) {
|
||||
find_scalar_replaceable_allocs(jobj_worklist);
|
||||
}
|
||||
|
||||
for (int next = 0; next < jobj_worklist.length(); ++next) {
|
||||
JavaObjectNode* jobj = jobj_worklist.at(next);
|
||||
if (jobj->scalar_replaceable()) {
|
||||
alloc_worklist.append(jobj->ideal_node());
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
if (VerifyConnectionGraph) {
|
||||
// Verify that graph is complete - no new edges could be added or needed.
|
||||
@ -1865,15 +1881,19 @@ void ConnectionGraph::adjust_scalar_replaceable_state(JavaObjectNode* jobj) {
|
||||
set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is stored at unknown offset"));
|
||||
return;
|
||||
}
|
||||
// 2. An object is not scalar replaceable if the field into which it is
|
||||
// stored has multiple bases one of which is null.
|
||||
if (field->base_count() > 1) {
|
||||
for (BaseIterator i(field); i.has_next(); i.next()) {
|
||||
PointsToNode* base = i.get();
|
||||
if (base == null_obj) {
|
||||
set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is stored into field with potentially null base"));
|
||||
return;
|
||||
}
|
||||
for (BaseIterator i(field); i.has_next(); i.next()) {
|
||||
PointsToNode* base = i.get();
|
||||
// 2. An object is not scalar replaceable if the field into which it is
|
||||
// stored has multiple bases one of which is null.
|
||||
if ((base == null_obj) && (field->base_count() > 1)) {
|
||||
set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is stored into field with potentially null base"));
|
||||
return;
|
||||
}
|
||||
// 2.5. An object is not scalar replaceable if the field into which it is
|
||||
// stored has NSR base.
|
||||
if (!base->scalar_replaceable()) {
|
||||
set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is stored into field with NSR base"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1963,6 +1983,36 @@ void ConnectionGraph::adjust_scalar_replaceable_state(JavaObjectNode* jobj) {
|
||||
}
|
||||
}
|
||||
|
||||
// Propagate NSR (Not scalar replaceable) state.
|
||||
void ConnectionGraph::find_scalar_replaceable_allocs(GrowableArray<JavaObjectNode*>& jobj_worklist) {
|
||||
int jobj_length = jobj_worklist.length();
|
||||
bool found_nsr_alloc = true;
|
||||
while (found_nsr_alloc) {
|
||||
found_nsr_alloc = false;
|
||||
for (int next = 0; next < jobj_length; ++next) {
|
||||
JavaObjectNode* jobj = jobj_worklist.at(next);
|
||||
for (UseIterator i(jobj); (jobj->scalar_replaceable() && i.has_next()); i.next()) {
|
||||
PointsToNode* use = i.get();
|
||||
if (use->is_Field()) {
|
||||
FieldNode* field = use->as_Field();
|
||||
assert(field->is_oop() && field->scalar_replaceable(), "sanity");
|
||||
assert(field->offset() != Type::OffsetBot, "sanity");
|
||||
for (BaseIterator i(field); i.has_next(); i.next()) {
|
||||
PointsToNode* base = i.get();
|
||||
// An object is not scalar replaceable if the field into which
|
||||
// it is stored has NSR base.
|
||||
if ((base != null_obj) && !base->scalar_replaceable()) {
|
||||
set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is stored into field with NSR base"));
|
||||
found_nsr_alloc = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
void ConnectionGraph::verify_connection_graph(
|
||||
GrowableArray<PointsToNode*>& ptnodes_worklist,
|
||||
|
||||
@ -463,6 +463,9 @@ private:
|
||||
// Adjust scalar_replaceable state after Connection Graph is built.
|
||||
void adjust_scalar_replaceable_state(JavaObjectNode* jobj);
|
||||
|
||||
// Propagate NSR (Not scalar replaceable) state.
|
||||
void find_scalar_replaceable_allocs(GrowableArray<JavaObjectNode*>& jobj_worklist);
|
||||
|
||||
// Optimize ideal graph.
|
||||
void optimize_ideal_graph(GrowableArray<Node*>& ptr_cmp_worklist,
|
||||
GrowableArray<MemBarStoreStoreNode*>& storestore_worklist);
|
||||
|
||||
@ -3653,29 +3653,21 @@ bool IdealLoopTree::do_remove_empty_loop(PhaseIdealLoop *phase) {
|
||||
}
|
||||
|
||||
// Replace the phi at loop head with the final value of the last
|
||||
// iteration. Then the CountedLoopEnd will collapse (backedge never
|
||||
// taken) and all loop-invariant uses of the exit values will be correct.
|
||||
Node *phi = cl->phi();
|
||||
Node *exact_limit = phase->exact_limit(this);
|
||||
if (exact_limit != cl->limit()) {
|
||||
// We also need to replace the original limit to collapse loop exit.
|
||||
Node* cmp = cl->loopexit()->cmp_node();
|
||||
assert(cl->limit() == cmp->in(2), "sanity");
|
||||
// Duplicate cmp node if it has other users
|
||||
if (cmp->outcnt() > 1) {
|
||||
cmp = cmp->clone();
|
||||
cmp = phase->_igvn.register_new_node_with_optimizer(cmp);
|
||||
BoolNode *bol = cl->loopexit()->in(CountedLoopEndNode::TestValue)->as_Bool();
|
||||
phase->_igvn.replace_input_of(bol, 1, cmp); // put bol on worklist
|
||||
}
|
||||
phase->_igvn._worklist.push(cmp->in(2)); // put limit on worklist
|
||||
phase->_igvn.replace_input_of(cmp, 2, exact_limit); // put cmp on worklist
|
||||
}
|
||||
// iteration (exact_limit - stride), to make sure the loop exit value
|
||||
// is correct, for any users after the loop.
|
||||
// Note: the final value after increment should not overflow since
|
||||
// counted loop has limit check predicate.
|
||||
Node *final = new SubINode(exact_limit, cl->stride());
|
||||
phase->register_new_node(final,cl->in(LoopNode::EntryControl));
|
||||
phase->_igvn.replace_node(phi,final);
|
||||
Node* phi = cl->phi();
|
||||
Node* exact_limit = phase->exact_limit(this);
|
||||
Node* final_iv = new SubINode(exact_limit, cl->stride());
|
||||
phase->register_new_node(final_iv, cl->in(LoopNode::EntryControl));
|
||||
phase->_igvn.replace_node(phi, final_iv);
|
||||
|
||||
// Set loop-exit condition to false. Then the CountedLoopEnd will collapse,
|
||||
// because the back edge is never taken.
|
||||
Node* zero = phase->_igvn.intcon(0);
|
||||
phase->_igvn.replace_input_of(cl->loopexit(), CountedLoopEndNode::TestValue, zero);
|
||||
|
||||
phase->C->set_major_progress();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3896,17 +3896,6 @@ uint IdealLoopTree::est_loop_flow_merge_sz() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
bool IdealLoopTree::has_reduction_nodes() const {
|
||||
for (uint i = 0; i < _body.size(); i++) {
|
||||
if (_body[i]->is_reduction()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif // ASSERT
|
||||
|
||||
#ifndef PRODUCT
|
||||
//------------------------------dump_head--------------------------------------
|
||||
// Dump 1 liner for loop header info
|
||||
|
||||
@ -778,11 +778,6 @@ public:
|
||||
|
||||
void remove_main_post_loops(CountedLoopNode *cl, PhaseIdealLoop *phase);
|
||||
|
||||
#ifdef ASSERT
|
||||
// Tell whether the body contains nodes marked as reductions.
|
||||
bool has_reduction_nodes() const;
|
||||
#endif // ASSERT
|
||||
|
||||
#ifndef PRODUCT
|
||||
void dump_head() const; // Dump loop head only
|
||||
void dump() const; // Dump this loop recursively
|
||||
|
||||
@ -1488,7 +1488,12 @@ static bool stable_phi(PhiNode* phi, PhaseGVN *phase) {
|
||||
}
|
||||
//------------------------------split_through_phi------------------------------
|
||||
// Split instance or boxed field load through Phi.
|
||||
Node *LoadNode::split_through_phi(PhaseGVN *phase) {
|
||||
Node* LoadNode::split_through_phi(PhaseGVN* phase) {
|
||||
if (req() > 3) {
|
||||
assert(is_LoadVector() && Opcode() != Op_LoadVector, "load has too many inputs");
|
||||
// LoadVector subclasses such as LoadVectorMasked have extra inputs that the logic below doesn't take into account
|
||||
return NULL;
|
||||
}
|
||||
Node* mem = in(Memory);
|
||||
Node* address = in(Address);
|
||||
const TypeOopPtr *t_oop = phase->type(address)->isa_oopptr();
|
||||
|
||||
@ -423,7 +423,7 @@ PhaseRemoveUseless::PhaseRemoveUseless(PhaseGVN* gvn, Unique_Node_List* worklist
|
||||
worklist->remove_useless_nodes(_useful.member_set());
|
||||
|
||||
// Disconnect 'useless' nodes that are adjacent to useful nodes
|
||||
C->remove_useless_nodes(_useful);
|
||||
C->disconnect_useless_nodes(_useful, worklist);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
@ -1764,6 +1764,9 @@ void PhaseCCP::analyze() {
|
||||
Unique_Node_List worklist;
|
||||
worklist.push(C->root());
|
||||
|
||||
assert(_root_and_safepoints.size() == 0, "must be empty (unused)");
|
||||
_root_and_safepoints.push(C->root());
|
||||
|
||||
// Pull from worklist; compute new value; push changes out.
|
||||
// This loop is the meat of CCP.
|
||||
while( worklist.size() ) {
|
||||
@ -1774,8 +1777,9 @@ void PhaseCCP::analyze() {
|
||||
n = worklist.pop();
|
||||
}
|
||||
if (n->is_SafePoint()) {
|
||||
// Keep track of SafePoint nodes for PhaseCCP::transform()
|
||||
_safepoints.push(n);
|
||||
// Make sure safepoints are processed by PhaseCCP::transform even if they are
|
||||
// not reachable from the bottom. Otherwise, infinite loops would be removed.
|
||||
_root_and_safepoints.push(n);
|
||||
}
|
||||
const Type *t = n->Value(this);
|
||||
if (t != type(n)) {
|
||||
@ -1904,14 +1908,15 @@ Node *PhaseCCP::transform( Node *n ) {
|
||||
Node *new_node = _nodes[n->_idx]; // Check for transformed node
|
||||
if( new_node != NULL )
|
||||
return new_node; // Been there, done that, return old answer
|
||||
new_node = transform_once(n); // Check for constant
|
||||
_nodes.map( n->_idx, new_node ); // Flag as having been cloned
|
||||
|
||||
assert(n->is_Root(), "traversal must start at root");
|
||||
assert(_root_and_safepoints.member(n), "root (n) must be in list");
|
||||
|
||||
// Allocate stack of size _nodes.Size()/2 to avoid frequent realloc
|
||||
GrowableArray <Node *> trstack(C->live_nodes() >> 1);
|
||||
|
||||
trstack.push(new_node); // Process children of cloned node
|
||||
GrowableArray <Node *> transform_stack(C->live_nodes() >> 1);
|
||||
Unique_Node_List useful; // track all visited nodes, so that we can remove the complement
|
||||
|
||||
// Initialize the traversal.
|
||||
// This CCP pass may prove that no exit test for a loop ever succeeds (i.e. the loop is infinite). In that case,
|
||||
// the logic below doesn't follow any path from Root to the loop body: there's at least one such path but it's proven
|
||||
// never taken (its type is TOP). As a consequence the node on the exit path that's input to Root (let's call it n) is
|
||||
@ -1919,17 +1924,18 @@ Node *PhaseCCP::transform( Node *n ) {
|
||||
// through the graph from Root, this causes the loop body to never be processed here even when it's not dead (that
|
||||
// is reachable from Root following its uses). To prevent that issue, transform() starts walking the graph from Root
|
||||
// and all safepoints.
|
||||
for (uint i = 0; i < _safepoints.size(); ++i) {
|
||||
Node* nn = _safepoints.at(i);
|
||||
for (uint i = 0; i < _root_and_safepoints.size(); ++i) {
|
||||
Node* nn = _root_and_safepoints.at(i);
|
||||
Node* new_node = _nodes[nn->_idx];
|
||||
assert(new_node == NULL, "");
|
||||
new_node = transform_once(nn);
|
||||
_nodes.map(nn->_idx, new_node);
|
||||
trstack.push(new_node);
|
||||
new_node = transform_once(nn); // Check for constant
|
||||
_nodes.map(nn->_idx, new_node); // Flag as having been cloned
|
||||
transform_stack.push(new_node); // Process children of cloned node
|
||||
useful.push(new_node);
|
||||
}
|
||||
|
||||
while ( trstack.is_nonempty() ) {
|
||||
Node *clone = trstack.pop();
|
||||
while (transform_stack.is_nonempty()) {
|
||||
Node* clone = transform_stack.pop();
|
||||
uint cnt = clone->req();
|
||||
for( uint i = 0; i < cnt; i++ ) { // For all inputs do
|
||||
Node *input = clone->in(i);
|
||||
@ -1938,13 +1944,33 @@ Node *PhaseCCP::transform( Node *n ) {
|
||||
if( new_input == NULL ) {
|
||||
new_input = transform_once(input); // Check for constant
|
||||
_nodes.map( input->_idx, new_input );// Flag as having been cloned
|
||||
trstack.push(new_input);
|
||||
transform_stack.push(new_input); // Process children of cloned node
|
||||
useful.push(new_input);
|
||||
}
|
||||
assert( new_input == clone->in(i), "insanity check");
|
||||
}
|
||||
}
|
||||
}
|
||||
return new_node;
|
||||
|
||||
// The above transformation might lead to subgraphs becoming unreachable from the
|
||||
// bottom while still being reachable from the top. As a result, nodes in that
|
||||
// subgraph are not transformed and their bottom types are not updated, leading to
|
||||
// an inconsistency between bottom_type() and type(). In rare cases, LoadNodes in
|
||||
// such a subgraph, might be re-enqueued for IGVN indefinitely by MemNode::Ideal_common
|
||||
// because their address type is inconsistent. Therefore, we aggressively remove
|
||||
// all useless nodes here even before PhaseIdealLoop::build_loop_late gets a chance
|
||||
// to remove them anyway.
|
||||
if (C->cached_top_node()) {
|
||||
useful.push(C->cached_top_node());
|
||||
}
|
||||
C->update_dead_node_list(useful);
|
||||
remove_useless_nodes(useful.member_set());
|
||||
_worklist.remove_useless_nodes(useful.member_set());
|
||||
C->disconnect_useless_nodes(useful, &_worklist);
|
||||
|
||||
Node* new_root = _nodes[n->_idx];
|
||||
assert(new_root->is_Root(), "transformed root node must be a root node");
|
||||
return new_root;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -565,7 +565,7 @@ protected:
|
||||
// Phase for performing global Conditional Constant Propagation.
|
||||
// Should be replaced with combined CCP & GVN someday.
|
||||
class PhaseCCP : public PhaseIterGVN {
|
||||
Unique_Node_List _safepoints;
|
||||
Unique_Node_List _root_and_safepoints;
|
||||
// Non-recursive. Use analysis to transform single Node.
|
||||
virtual Node *transform_once( Node *n );
|
||||
|
||||
|
||||
@ -2416,11 +2416,6 @@ bool SuperWord::output() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the loop to be vectorized does not have inconsistent reduction
|
||||
// information, which would likely lead to a miscompilation.
|
||||
assert(!lpt()->has_reduction_nodes() || cl->is_reduction_loop(),
|
||||
"non-reduction loop contains reduction nodes");
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (TraceLoopOpts) {
|
||||
tty->print("SuperWord::output ");
|
||||
|
||||
@ -1992,8 +1992,6 @@ JRT_LEAF(void, SharedRuntime::fixup_callers_callsite(Method* method, address cal
|
||||
|
||||
AARCH64_PORT_ONLY(assert(pauth_ptr_is_raw(caller_pc), "should be raw"));
|
||||
|
||||
address entry_point = moop->from_compiled_entry_no_trampoline();
|
||||
|
||||
// It's possible that deoptimization can occur at a call site which hasn't
|
||||
// been resolved yet, in which case this function will be called from
|
||||
// an nmethod that has been patched for deopt and we can ignore the
|
||||
@ -2004,8 +2002,16 @@ JRT_LEAF(void, SharedRuntime::fixup_callers_callsite(Method* method, address cal
|
||||
// "to interpreter" stub in order to load up the Method*. Don't
|
||||
// ask me how I know this...
|
||||
|
||||
// Result from nmethod::is_unloading is not stable across safepoints.
|
||||
NoSafepointVerifier nsv;
|
||||
|
||||
CompiledMethod* callee = moop->code();
|
||||
if (callee == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
CodeBlob* cb = CodeCache::find_blob(caller_pc);
|
||||
if (cb == NULL || !cb->is_compiled() || entry_point == moop->get_c2i_entry()) {
|
||||
if (cb == NULL || !cb->is_compiled() || callee->is_unloading()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2063,6 +2069,7 @@ JRT_LEAF(void, SharedRuntime::fixup_callers_callsite(Method* method, address cal
|
||||
}
|
||||
}
|
||||
address destination = call->destination();
|
||||
address entry_point = callee->verified_entry_point();
|
||||
if (should_fixup_call_destination(destination, entry_point, caller_pc, moop, cb)) {
|
||||
call->set_destination_mt_safe(entry_point);
|
||||
}
|
||||
|
||||
@ -1229,10 +1229,11 @@ JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) : JavaThread
|
||||
|
||||
JavaThread::~JavaThread() {
|
||||
|
||||
// Ask ServiceThread to release the threadObj OopHandle
|
||||
// Ask ServiceThread to release the OopHandles
|
||||
ServiceThread::add_oop_handle_release(_threadObj);
|
||||
ServiceThread::add_oop_handle_release(_vthread);
|
||||
ServiceThread::add_oop_handle_release(_jvmti_vthread);
|
||||
ServiceThread::add_oop_handle_release(_extentLocalCache);
|
||||
|
||||
// Return the sleep event to the free list
|
||||
ParkEvent::Release(_SleepEvent);
|
||||
|
||||
@ -100,7 +100,7 @@ final class ProcessHandleImpl implements ProcessHandle {
|
||||
ThreadFactory threadFactory = grimReaper -> {
|
||||
Thread t = InnocuousThread.newSystemThread("process reaper", grimReaper,
|
||||
stackSize, Thread.MAX_PRIORITY);
|
||||
t.setDaemon(true);
|
||||
privilegedThreadSetDaemon(t, true);
|
||||
return t;
|
||||
};
|
||||
|
||||
@ -115,6 +115,22 @@ final class ProcessHandleImpl implements ProcessHandle {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private static void privilegedThreadSetName(Thread thread, String name) {
|
||||
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
|
||||
thread.setName(name);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private static void privilegedThreadSetDaemon(Thread thread, boolean on) {
|
||||
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
|
||||
thread.setDaemon(on);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a CompletableFuture that completes with process exit status when
|
||||
* the process completes.
|
||||
@ -140,8 +156,9 @@ final class ProcessHandleImpl implements ProcessHandle {
|
||||
processReaperExecutor.execute(new Runnable() {
|
||||
// Use inner class to avoid lambda stack overhead
|
||||
public void run() {
|
||||
String threadName = Thread.currentThread().getName();
|
||||
Thread.currentThread().setName("process reaper (pid " + pid + ")");
|
||||
Thread t = Thread.currentThread();
|
||||
String threadName = t.getName();
|
||||
privilegedThreadSetName(t, "process reaper (pid " + pid + ")");
|
||||
try {
|
||||
int exitValue = waitForProcessExit0(pid, shouldReap);
|
||||
if (exitValue == NOT_A_CHILD) {
|
||||
@ -172,7 +189,7 @@ final class ProcessHandleImpl implements ProcessHandle {
|
||||
completions.remove(pid, newCompletion);
|
||||
} finally {
|
||||
// Restore thread name
|
||||
Thread.currentThread().setName(threadName);
|
||||
privilegedThreadSetName(t, threadName);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -91,7 +91,7 @@
|
||||
(IS_SAFE_SIZE_MUL(sizeof(type), (n)) ? (new type[(size_t)(n)]) : throw std::bad_alloc())
|
||||
|
||||
#define SAFE_SIZE_NEW_ARRAY2(type, n, m) \
|
||||
(IS_SAFE_SIZE_MUL((m), (n)) && IS_SAFE_SIZE_MUL(sizeof(type), (n) * (m)) ? \
|
||||
(IS_SAFE_SIZE_MUL((m), (n)) && IS_SAFE_SIZE_MUL(sizeof(type), (size_t)(n) * (size_t)(m)) ? \
|
||||
(new type[(size_t)(n) * (size_t)(m)]) : throw std::bad_alloc())
|
||||
|
||||
/*
|
||||
|
||||
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Red Hat, Inc. 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 JDK-8292780
|
||||
* @summary misc tests failed "assert(false) failed: graph should be schedulable"
|
||||
*
|
||||
* @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestArrayCopyPartialInliningLoadSplit
|
||||
*/
|
||||
|
||||
public class TestArrayCopyPartialInliningLoadSplit {
|
||||
public static void main(String[] args) {
|
||||
byte[] array = new byte[16];
|
||||
for (int i = 0; i < 20_0000; i++) {
|
||||
test(array, 16, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private static void test(byte[] array, int length, int srcPos, int dstPos) {
|
||||
byte[] nonEscaping = new byte[16];
|
||||
nonEscaping[0] = 0x42;
|
||||
System.arraycopy(array, srcPos, nonEscaping, 1, 8);
|
||||
System.arraycopy(nonEscaping, 0, array, 0, length);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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
|
||||
* 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 8287217
|
||||
* @summary CCP must remove nodes that are not traversed, else their type can be inconsistent
|
||||
* @run main/othervm -Xcomp -XX:CompileCommand=compileonly,TestRemoveUnreachableCCP::test
|
||||
* TestRemoveUnreachableCCP
|
||||
*/
|
||||
|
||||
public class TestRemoveUnreachableCCP {
|
||||
|
||||
static void test() {
|
||||
Byte x = 1;
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
if ((i & 1) == 0) {
|
||||
x = (byte)x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] strArr) {
|
||||
for (int i = 0; i < 11; i++) {
|
||||
test();
|
||||
}
|
||||
}
|
||||
}
|
||||
82
test/hotspot/jtreg/compiler/escapeAnalysis/TestBrokenEA.java
Normal file
82
test/hotspot/jtreg/compiler/escapeAnalysis/TestBrokenEA.java
Normal file
@ -0,0 +1,82 @@
|
||||
/* Copyright (c) 2022, 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
|
||||
* 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 8285835
|
||||
* @summary EA does not propagate NSR (not scalar replaceable) state.
|
||||
* @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestBrokenEA
|
||||
*/
|
||||
|
||||
public class TestBrokenEA {
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (int i = 0; i < 20_000; i++) {
|
||||
test1(true);
|
||||
test1(false);
|
||||
test2(true);
|
||||
test2(false);
|
||||
}
|
||||
}
|
||||
|
||||
private static void test1(boolean flag) {
|
||||
A[] array = new A[1];
|
||||
if (flag) {
|
||||
C c = new C();
|
||||
B b = new B();
|
||||
b.c = c;
|
||||
A a = new A();
|
||||
a.b = b;
|
||||
array[0] = a;
|
||||
}
|
||||
A a = array[0];
|
||||
if (a != null) {
|
||||
a.b.c.f = 0x42;
|
||||
}
|
||||
}
|
||||
|
||||
private static void test2(boolean flag) {
|
||||
A a = null;
|
||||
if (flag) {
|
||||
C c = new C();
|
||||
B b = new B();
|
||||
b.c = c;
|
||||
a = new A();
|
||||
a.b = b;
|
||||
}
|
||||
if (a != null) {
|
||||
a.b.c.f = 0x42;
|
||||
}
|
||||
}
|
||||
|
||||
private static class A {
|
||||
public B b;
|
||||
}
|
||||
|
||||
private static class B {
|
||||
public C c;
|
||||
}
|
||||
|
||||
private static class C {
|
||||
public int f;
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2022, 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
|
||||
@ -23,7 +24,7 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8231988
|
||||
* @bug 8231988 8293996
|
||||
* @summary Unexpected test result caused by C2 IdealLoopTree::do_remove_empty_loop
|
||||
*
|
||||
* @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation
|
||||
@ -34,9 +35,11 @@ package compiler.loopopts;
|
||||
|
||||
public class TestRemoveEmptyLoop {
|
||||
|
||||
public void test() {
|
||||
public void test_cmp_helper() {
|
||||
int i = 34;
|
||||
// The empty loop that collapses
|
||||
for (; i > 0; i -= 11);
|
||||
// If uses same Cmp node as the loop condition
|
||||
if (i < 0) {
|
||||
// do nothing
|
||||
} else {
|
||||
@ -44,12 +47,38 @@ public class TestRemoveEmptyLoop {
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
TestRemoveEmptyLoop _instance = new TestRemoveEmptyLoop();
|
||||
public void test_cmp() {
|
||||
// Loop is OSR compiled, and test_cmp_helper inlined
|
||||
for (int i = 0; i < 50000; i++) {
|
||||
_instance.test();
|
||||
test_cmp_helper();
|
||||
}
|
||||
System.out.println("Test passed.");
|
||||
}
|
||||
|
||||
void test_collapse_helper() {
|
||||
int o = 11;
|
||||
int e = 43542;
|
||||
for (int i = 524; i < 19325; i += 1) {
|
||||
// The empty loop that is supposed to collapse
|
||||
for (int j = 0; j < 32767; j++) {
|
||||
o++;
|
||||
}
|
||||
for (int k = 0; k < o; k++) {
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void test_collapse() {
|
||||
// Loop is OSR compiled, and test_collapse_helper inlined
|
||||
for (int i = 0; i < 50000; i++) {
|
||||
test_collapse_helper();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
TestRemoveEmptyLoop _instance = new TestRemoveEmptyLoop();
|
||||
_instance.test_cmp();
|
||||
_instance.test_collapse();
|
||||
System.out.println("Test passed.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,7 +130,7 @@ public abstract class TestConstantsInError implements OutputProcessor {
|
||||
results.shouldMatch("Test_C1/.*::test \\(3 bytes\\)$")
|
||||
.shouldMatch("Test_C2/.*::test \\(3 bytes\\)$");
|
||||
|
||||
if (isC1 && Platform.isAArch64()) { // no code patching
|
||||
if (isC1 && (Platform.isAArch64() || Platform.isRISCV64())) { // no code patching
|
||||
results.shouldMatch("Test_C1/.*::test \\(3 bytes\\) made not entrant")
|
||||
.shouldMatch("Test_C2/.*::test \\(3 bytes\\) made not entrant");
|
||||
} else {
|
||||
@ -168,7 +168,7 @@ public abstract class TestConstantsInError implements OutputProcessor {
|
||||
.shouldMatch("Test_MH3/.*::test \\(3 bytes\\)$")
|
||||
.shouldMatch("Test_MH4/.*::test \\(3 bytes\\)$");
|
||||
|
||||
if (isC1 && Platform.isAArch64()) { // no code patching
|
||||
if (isC1 && (Platform.isAArch64() || Platform.isRISCV64())) { // no code patching
|
||||
results.shouldMatch("Test_MH1/.*::test \\(3 bytes\\) made not entrant")
|
||||
.shouldMatch("Test_MH2/.*::test \\(3 bytes\\) made not entrant")
|
||||
.shouldMatch("Test_MH3/.*::test \\(3 bytes\\) made not entrant")
|
||||
@ -191,7 +191,7 @@ public abstract class TestConstantsInError implements OutputProcessor {
|
||||
results.shouldMatch("Test_MT1/.*::test \\(3 bytes\\)$")
|
||||
.shouldMatch("Test_MT2/.*::test \\(3 bytes\\)$");
|
||||
|
||||
if (isC1 && Platform.isAArch64()) { // no code patching
|
||||
if (isC1 && (Platform.isAArch64() || Platform.isRISCV64())) { // no code patching
|
||||
results.shouldMatch("Test_MT1/.*::test \\(3 bytes\\) made not entrant")
|
||||
.shouldMatch("Test_MT2/.*::test \\(3 bytes\\) made not entrant");
|
||||
} else {
|
||||
@ -235,7 +235,7 @@ public abstract class TestConstantsInError implements OutputProcessor {
|
||||
.shouldMatch("Test_CD3.*::test \\(3 bytes\\)$")
|
||||
.shouldMatch("Test_CD4.*::test \\(3 bytes\\)$");
|
||||
|
||||
if (isC1 && Platform.isAArch64()) { // no code patching
|
||||
if (isC1 && (Platform.isAArch64() || Platform.isRISCV64())) { // no code patching
|
||||
results.shouldMatch("Test_CD1.*::test \\(3 bytes\\) made not entrant")
|
||||
.shouldMatch("Test_CD2.*::test \\(3 bytes\\) made not entrant")
|
||||
.shouldMatch("Test_CD3.*::test \\(3 bytes\\) made not entrant")
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (c) 2022, 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
|
||||
@ -24,10 +25,15 @@
|
||||
/**
|
||||
* @test
|
||||
* @bug 8253566
|
||||
* @bug 8295414
|
||||
* @summary clazz.isAssignableFrom will return false for interface implementors
|
||||
* @requires vm.compiler2.enabled
|
||||
*
|
||||
* @run main/othervm -XX:-BackgroundCompilation TestSubTypeCheckMacroTrichotomy
|
||||
* @run main/othervm -XX:-BackgroundCompilation
|
||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+StressReflectiveCode
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+ExpandSubTypeCheckAtParseTime
|
||||
* -XX:-TieredCompilation -XX:CompileThreshold=100 TestSubTypeCheckMacroTrichotomy
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@ -227,7 +227,6 @@ java/awt/print/Headless/HeadlessPrinterJob.java 8196088 windows-all
|
||||
sun/awt/datatransfer/SuplementaryCharactersTransferTest.java 8011371 generic-all
|
||||
sun/awt/shell/ShellFolderMemoryLeak.java 8197794 windows-all
|
||||
sun/java2d/DirectX/MultiPaintEventTest/MultiPaintEventTest.java 8284825 windows-all
|
||||
sun/java2d/DirectX/OnScreenRenderingResizeTest/OnScreenRenderingResizeTest.java 8022403 generic-all
|
||||
sun/java2d/DirectX/OverriddenInsetsTest/OverriddenInsetsTest.java 8196102 generic-all
|
||||
sun/java2d/DirectX/RenderingToCachedGraphicsTest/RenderingToCachedGraphicsTest.java 8196180 windows-all,macosx-all
|
||||
sun/java2d/SunGraphics2D/EmptyClipRenderingTest.java 8144029 macosx-all,linux-all
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6980747
|
||||
* @bug 6980747 8297451
|
||||
* @summary Check that Process-related classes have the proper
|
||||
* doPrivileged blocks, and can be initialized with an adversarial
|
||||
* security manager.
|
||||
@ -52,6 +52,17 @@ public class SecurityManagerClinit {
|
||||
}
|
||||
}
|
||||
|
||||
// Security manager that unconditionally performs Thread Modify Access checks.
|
||||
@SuppressWarnings("removal")
|
||||
private static class TMACSecurityManager extends SecurityManager {
|
||||
static final RuntimePermission MODIFY_THREAD_PERMISSION =
|
||||
new RuntimePermission("modifyThread");
|
||||
@Override
|
||||
public void checkAccess(Thread thread) {
|
||||
checkPermission(MODIFY_THREAD_PERMISSION);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
String javaExe =
|
||||
System.getProperty("java.home") +
|
||||
@ -60,10 +71,11 @@ public class SecurityManagerClinit {
|
||||
final SimplePolicy policy =
|
||||
new SimplePolicy
|
||||
(new FilePermission("<<ALL FILES>>", "execute"),
|
||||
new RuntimePermission("setSecurityManager"));
|
||||
new RuntimePermission("setSecurityManager"),
|
||||
new RuntimePermission("modifyThread"));
|
||||
Policy.setPolicy(policy);
|
||||
|
||||
System.setSecurityManager(new SecurityManager());
|
||||
System.setSecurityManager(new TMACSecurityManager());
|
||||
|
||||
try {
|
||||
String[] cmd = { javaExe, "-version" };
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2022, 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
|
||||
@ -60,7 +60,7 @@ import static java.util.stream.Collectors.toMap;
|
||||
* @modules jdk.compiler
|
||||
* jdk.zipfs
|
||||
* @summary Nearly exhaustive test of Class.getMethod() and Class.getMethods()
|
||||
* @run main PublicMethodsTest
|
||||
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies PublicMethodsTest
|
||||
*/
|
||||
public class PublicMethodsTest {
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2022, 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
|
||||
@ -25,25 +25,21 @@
|
||||
* @key headful
|
||||
* @bug 6664068 6666931
|
||||
* @summary Tests that resizing a window to which a tight loop is rendering
|
||||
* doesn't produce artifacts or crashes
|
||||
* @author Dmitri.Trembovetski@sun.com: area=Graphics
|
||||
* doesn't produce artifacts or crashes
|
||||
* @run main/othervm OnScreenRenderingResizeTest
|
||||
* @run main/othervm -Dsun.java2d.d3d=false OnScreenRenderingResizeTest
|
||||
*/
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Color;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Robot;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.VolatileImage;
|
||||
import java.io.File;
|
||||
@ -52,19 +48,33 @@ import javax.imageio.ImageIO;
|
||||
|
||||
public class OnScreenRenderingResizeTest {
|
||||
|
||||
private static volatile boolean done = false;
|
||||
private static volatile boolean nocheck = false;
|
||||
|
||||
private static final int FRAME_W = 256;
|
||||
private static final int FRAME_H = 256;
|
||||
private static final int IMAGE_W = 128;
|
||||
private static final int IMAGE_H = 128;
|
||||
private static int FRAME_W;
|
||||
private static int FRAME_H;
|
||||
private static int IMAGE_W;
|
||||
private static int IMAGE_H;
|
||||
private static final int tolerance = 12;
|
||||
private static long RUN_TIME = 1000*20;
|
||||
|
||||
private static final Color renderColor = Color.green;
|
||||
private static final Color bgColor = Color.white;
|
||||
|
||||
public static void main(String[] args) {
|
||||
private static Frame frame;
|
||||
|
||||
private static void createAndShowGUI() {
|
||||
frame = new Frame() {
|
||||
public void paint(Graphics g) {}
|
||||
public void update(Graphics g) {}
|
||||
};
|
||||
frame.setBackground(bgColor);
|
||||
frame.setUndecorated(true);
|
||||
frame.setAlwaysOnTop(true);
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
for (String arg : args) {
|
||||
if ("-inf".equals(arg)) {
|
||||
@ -74,126 +84,138 @@ public class OnScreenRenderingResizeTest {
|
||||
System.err.println("Test will not check rendering results");
|
||||
nocheck = true;
|
||||
} else {
|
||||
System.err.println("Usage: OnScreenRenderingResizeTest [-inf][-nocheck]");
|
||||
System.err.println("Usage: OnScreenRenderingResizeTest" +
|
||||
" [-inf][-nocheck]");
|
||||
}
|
||||
}
|
||||
|
||||
BufferedImage output =
|
||||
new BufferedImage(IMAGE_W, IMAGE_H, BufferedImage.TYPE_INT_RGB);
|
||||
output.setAccelerationPriority(0.0f);
|
||||
Graphics g = output.getGraphics();
|
||||
g.setColor(renderColor);
|
||||
g.fillRect(0, 0, output.getWidth(), output.getHeight());
|
||||
|
||||
final Frame frame = new Frame("OnScreenRenderingResizeTest") {
|
||||
public void paint(Graphics g) {}
|
||||
public void update(Graphics g) {}
|
||||
};
|
||||
frame.setBackground(bgColor);
|
||||
frame.setUndecorated(true);
|
||||
frame.pack();
|
||||
|
||||
GraphicsConfiguration gc = frame.getGraphicsConfiguration();
|
||||
Rectangle gcBounds = gc.getBounds();
|
||||
frame.setBounds(gcBounds.width / 4, gcBounds.height / 4, FRAME_W, FRAME_H);
|
||||
|
||||
frame.addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
done = true;
|
||||
}
|
||||
});
|
||||
try {
|
||||
EventQueue.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
frame.setVisible(true);
|
||||
createAndShowGUI();
|
||||
}
|
||||
});
|
||||
// wait for Vista's effects to complete
|
||||
Thread.sleep(2000);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
int maxW = gcBounds.width /2;
|
||||
int maxH = gcBounds.height/2;
|
||||
int minW = frame.getWidth();
|
||||
int minH = frame.getHeight();
|
||||
int incW = 10, incH = 10, cnt = 0;
|
||||
Robot robot = null;
|
||||
if (!nocheck && gc.getColorModel().getPixelSize() > 8) {
|
||||
try {
|
||||
robot = new Robot();
|
||||
} catch (AWTException ex) {
|
||||
System.err.println("Robot creation failed, continuing.");
|
||||
}
|
||||
} else {
|
||||
System.err.println("No screen rendering checks.");
|
||||
}
|
||||
try {
|
||||
GraphicsConfiguration gc = frame.getGraphicsConfiguration();
|
||||
Rectangle gcBounds = gc.getBounds();
|
||||
FRAME_W = (gcBounds.width / 4);
|
||||
FRAME_H = (gcBounds.height / 4);
|
||||
IMAGE_W = (gcBounds.width / 8);
|
||||
IMAGE_H = (gcBounds.height / 8);
|
||||
frame.setBounds(gcBounds.width / 4, gcBounds.height / 4,
|
||||
FRAME_W, FRAME_H);
|
||||
|
||||
VolatileImage vi = gc.createCompatibleVolatileImage(512, 512);
|
||||
vi.validate(gc);
|
||||
BufferedImage output =
|
||||
new BufferedImage(IMAGE_W, IMAGE_H,
|
||||
BufferedImage.TYPE_INT_RGB);
|
||||
output.setAccelerationPriority(0.0f);
|
||||
Graphics g = output.getGraphics();
|
||||
g.setColor(renderColor);
|
||||
g.fillRect(0, 0, IMAGE_W, IMAGE_H);
|
||||
|
||||
long timeStarted = System.currentTimeMillis();
|
||||
while (!done && (System.currentTimeMillis() - timeStarted) < RUN_TIME) {
|
||||
|
||||
if (++cnt > 100) {
|
||||
int w = frame.getWidth() + incW;
|
||||
int h = frame.getHeight() + incH;
|
||||
if (w < minW || w > maxW ) {
|
||||
incW = -incW;
|
||||
int maxW = gcBounds.width / 2;
|
||||
int maxH = gcBounds.height / 2;
|
||||
int minW = FRAME_W;
|
||||
int minH = FRAME_H;
|
||||
int incW = 10, incH = 10, cnt = 0;
|
||||
Robot robot = null;
|
||||
if (!nocheck && gc.getColorModel().getPixelSize() > 8) {
|
||||
try {
|
||||
robot = new Robot();
|
||||
robot.setAutoDelay(100);
|
||||
robot.mouseMove(0,0);
|
||||
} catch (AWTException ex) {
|
||||
System.err.println("Robot creation failed, continuing.");
|
||||
}
|
||||
if (h < minH || h > maxH ) {
|
||||
incH = -incH;
|
||||
}
|
||||
frame.setSize(w, h);
|
||||
cnt = 0;
|
||||
} else {
|
||||
System.err.println("No screen rendering checks.");
|
||||
}
|
||||
|
||||
// try to put the device into non-default state, for example,
|
||||
// this operation below will set the transform
|
||||
VolatileImage vi = gc.
|
||||
createCompatibleVolatileImage(IMAGE_W, IMAGE_H);
|
||||
vi.validate(gc);
|
||||
Graphics2D vig = (Graphics2D)vi.getGraphics();
|
||||
vig.rotate(30.0f, vi.getWidth()/2, vi.getHeight()/2);
|
||||
vig.drawImage(output, 0, 0,
|
||||
vi.getWidth(), vi.getHeight(), null);
|
||||
long timeStarted = System.currentTimeMillis();
|
||||
while ((System.currentTimeMillis() - timeStarted) < RUN_TIME) {
|
||||
|
||||
Insets in = frame.getInsets();
|
||||
frame.getGraphics().drawImage(output, in.left, in.top, null);
|
||||
if (cnt == 90 && robot != null) {
|
||||
robot.waitForIdle();
|
||||
// area where we blitted to should be either white or green
|
||||
Point p = frame.getLocationOnScreen();
|
||||
p.translate(in.left+10, in.top+10);
|
||||
BufferedImage bi =
|
||||
robot.createScreenCapture(
|
||||
new Rectangle(p.x, p.y, IMAGE_W/2, IMAGE_H/2));
|
||||
int accepted1[] = { Color.white.getRGB(), Color.green.getRGB()};
|
||||
checkBI(bi, accepted1);
|
||||
if (++cnt > 100) {
|
||||
int w = frame.getWidth() + incW;
|
||||
int h = frame.getHeight() + incH;
|
||||
if (w < minW || w > maxW ) {
|
||||
incW = -incW;
|
||||
}
|
||||
if (h < minH || h > maxH ) {
|
||||
incH = -incH;
|
||||
}
|
||||
frame.setSize(w, h);
|
||||
if (robot != null) {
|
||||
robot.waitForIdle();
|
||||
}
|
||||
cnt = 0;
|
||||
}
|
||||
// try to put the device into non-default state, for example,
|
||||
// this operation below will set the transform
|
||||
vi.validate(gc);
|
||||
Graphics2D vig = (Graphics2D)vi.getGraphics();
|
||||
vig.rotate(30.0f, IMAGE_W/2, IMAGE_H/2);
|
||||
vig.drawImage(output, 0, 0,
|
||||
IMAGE_W, IMAGE_H, null);
|
||||
|
||||
// the are where we didn't render should stay white
|
||||
p = frame.getLocationOnScreen();
|
||||
p.translate(in.left, in.top+IMAGE_H+5);
|
||||
bi = robot.createScreenCapture(
|
||||
new Rectangle(p.x, p.y,
|
||||
frame.getWidth()-in.left-in.right,
|
||||
frame.getHeight()-in.top-in.bottom-5-IMAGE_H));
|
||||
int accepted2[] = { Color.white.getRGB() };
|
||||
checkBI(bi, accepted2);
|
||||
frame.getGraphics().
|
||||
drawImage(output, 0, 0, null);
|
||||
if (cnt == 90 && robot != null) {
|
||||
robot.waitForIdle();
|
||||
// area where we blit and should be either white or green
|
||||
Point p = frame.getLocationOnScreen();
|
||||
p.translate(10, 10);
|
||||
BufferedImage bi =
|
||||
robot.createScreenCapture(
|
||||
new Rectangle(p.x, p.y,
|
||||
(IMAGE_W / 2), (IMAGE_H / 2)));
|
||||
int accepted1[] = {Color.white.getRGB(),
|
||||
Color.green.getRGB()};
|
||||
checkBI(bi, accepted1);
|
||||
|
||||
// the area where we didn't render should stay white
|
||||
robot.waitForIdle();
|
||||
p = frame.getLocationOnScreen();
|
||||
p.translate(10, IMAGE_H + 10);
|
||||
bi = robot.createScreenCapture(
|
||||
new Rectangle(p.x, p.y,
|
||||
frame.getWidth() - 20,
|
||||
frame.getHeight() - 20 - (IMAGE_H)));
|
||||
int accepted2[] = { Color.white.getRGB() };
|
||||
checkBI(bi, accepted2);
|
||||
}
|
||||
Thread.yield();
|
||||
}
|
||||
|
||||
Thread.yield();
|
||||
} finally {
|
||||
frame.dispose();
|
||||
}
|
||||
frame.dispose();
|
||||
System.out.println("Test Passed");
|
||||
}
|
||||
|
||||
private static void checkBI(BufferedImage bi, int accepted[]) {
|
||||
for (int x = 0; x < bi.getWidth(); x++) {
|
||||
for (int y = 0; y < bi.getHeight(); y++) {
|
||||
int pix = bi.getRGB(x, y);
|
||||
int actual = bi.getRGB(x, y);
|
||||
int alpha = (actual >> 24) & 0xFF;
|
||||
int red = (actual >> 16) & 0xFF;
|
||||
int green = (actual >> 8) & 0xFF;
|
||||
int blue = (actual) & 0xFF;
|
||||
boolean found = false;
|
||||
for (int acc : accepted) {
|
||||
if (pix == acc) {
|
||||
int accAlpha = (acc >> 24) & 0xFF;
|
||||
int accRed = (acc >> 16) & 0xFF;
|
||||
int accGreen = (acc >> 8) & 0xFF;
|
||||
int accBlue = (acc) & 0xFF;
|
||||
if (!(Math.abs(alpha - accAlpha) > tolerance ||
|
||||
Math.abs(red - accRed) > tolerance ||
|
||||
Math.abs(green - accGreen) > tolerance ||
|
||||
Math.abs(blue - accBlue) > tolerance)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@ -204,10 +226,10 @@ public class OnScreenRenderingResizeTest {
|
||||
ImageIO.write(bi, "png", new File(name));
|
||||
System.out.println("Screen shot file: " + name);
|
||||
} catch (IOException ex) {}
|
||||
|
||||
throw new
|
||||
RuntimeException("Test failed at " + x + "-" + y +
|
||||
" rgb=0x" + Integer.toHexString(pix));
|
||||
" rgb=0x" + Integer.
|
||||
toHexString(actual));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,6 +44,7 @@ import static java.awt.image.BufferedImage.TYPE_USHORT_GRAY;
|
||||
* @test
|
||||
* @bug 8264666
|
||||
* @summary No exception or errors should occur in ColorConvertOp.filter().
|
||||
* @run main/othervm/timeout=600 UnexpectedSourceImageSize
|
||||
*/
|
||||
public final class UnexpectedSourceImageSize {
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user