8276455: C2: iterative EA
Reviewed-by: iveresov, neliasso, roland
This commit is contained in:
parent
de65230d71
commit
a1dfe57249
src/hotspot/share/opto
test
hotspot/jtreg/compiler
micro/org/openjdk/bench/vm/compiler
@ -48,6 +48,9 @@ const char* C2Compiler::retry_no_escape_analysis() {
|
||||
const char* C2Compiler::retry_no_locks_coarsening() {
|
||||
return "retry without locks coarsening";
|
||||
}
|
||||
const char* C2Compiler::retry_no_iterative_escape_analysis() {
|
||||
return "retry without iterative escape analysis";
|
||||
}
|
||||
const char* C2Compiler::retry_class_loading_during_parsing() {
|
||||
return "retry class loading during parsing";
|
||||
}
|
||||
@ -99,12 +102,13 @@ void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, boo
|
||||
|
||||
bool subsume_loads = SubsumeLoads;
|
||||
bool do_escape_analysis = DoEscapeAnalysis;
|
||||
bool do_iterative_escape_analysis = DoEscapeAnalysis;
|
||||
bool eliminate_boxing = EliminateAutoBox;
|
||||
bool do_locks_coarsening = EliminateLocks;
|
||||
|
||||
while (!env->failing()) {
|
||||
// Attempt to compile while subsuming loads into machine instructions.
|
||||
Options options(subsume_loads, do_escape_analysis, eliminate_boxing, do_locks_coarsening, install_code);
|
||||
Options options(subsume_loads, do_escape_analysis, do_iterative_escape_analysis, eliminate_boxing, do_locks_coarsening, install_code);
|
||||
Compile C(env, target, entry_bci, options, directive);
|
||||
|
||||
// Check result and retry if appropriate.
|
||||
@ -125,6 +129,12 @@ void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, boo
|
||||
env->report_failure(C.failure_reason());
|
||||
continue; // retry
|
||||
}
|
||||
if (C.failure_reason_is(retry_no_iterative_escape_analysis())) {
|
||||
assert(do_iterative_escape_analysis, "must make progress");
|
||||
do_iterative_escape_analysis = false;
|
||||
env->report_failure(C.failure_reason());
|
||||
continue; // retry
|
||||
}
|
||||
if (C.failure_reason_is(retry_no_locks_coarsening())) {
|
||||
assert(do_locks_coarsening, "must make progress");
|
||||
do_locks_coarsening = false;
|
||||
|
@ -49,6 +49,7 @@ public:
|
||||
// sentinel value used to trigger backtracking in compile_method().
|
||||
static const char* retry_no_subsuming_loads();
|
||||
static const char* retry_no_escape_analysis();
|
||||
static const char* retry_no_iterative_escape_analysis();
|
||||
static const char* retry_no_locks_coarsening();
|
||||
static const char* retry_class_loading_during_parsing();
|
||||
|
||||
|
@ -499,6 +499,12 @@ void Compile::print_compile_messages() {
|
||||
tty->print_cr("** Bailout: Recompile without escape analysis **");
|
||||
tty->print_cr("*********************************************************");
|
||||
}
|
||||
if (do_iterative_escape_analysis() != DoEscapeAnalysis && PrintOpto) {
|
||||
// Recompiling without iterative escape analysis
|
||||
tty->print_cr("*********************************************************");
|
||||
tty->print_cr("** Bailout: Recompile without iterative escape analysis**");
|
||||
tty->print_cr("*********************************************************");
|
||||
}
|
||||
if ((eliminate_boxing() != EliminateAutoBox) && PrintOpto) {
|
||||
// Recompiling without boxing elimination
|
||||
tty->print_cr("*********************************************************");
|
||||
@ -2161,27 +2167,37 @@ void Compile::Optimize() {
|
||||
if (major_progress()) print_method(PHASE_PHASEIDEAL_BEFORE_EA, 2);
|
||||
if (failing()) return;
|
||||
}
|
||||
ConnectionGraph::do_analysis(this, &igvn);
|
||||
|
||||
if (failing()) return;
|
||||
|
||||
// Optimize out fields loads from scalar replaceable allocations.
|
||||
igvn.optimize();
|
||||
print_method(PHASE_ITER_GVN_AFTER_EA, 2);
|
||||
|
||||
if (failing()) return;
|
||||
|
||||
if (congraph() != NULL && macro_count() > 0) {
|
||||
TracePhase tp("macroEliminate", &timers[_t_macroEliminate]);
|
||||
PhaseMacroExpand mexp(igvn);
|
||||
mexp.eliminate_macro_nodes();
|
||||
igvn.set_delay_transform(false);
|
||||
|
||||
igvn.optimize();
|
||||
print_method(PHASE_ITER_GVN_AFTER_ELIMINATION, 2);
|
||||
bool progress;
|
||||
do {
|
||||
ConnectionGraph::do_analysis(this, &igvn);
|
||||
|
||||
if (failing()) return;
|
||||
}
|
||||
|
||||
int mcount = macro_count(); // Record number of allocations and locks before IGVN
|
||||
|
||||
// Optimize out fields loads from scalar replaceable allocations.
|
||||
igvn.optimize();
|
||||
print_method(PHASE_ITER_GVN_AFTER_EA, 2);
|
||||
|
||||
if (failing()) return;
|
||||
|
||||
if (congraph() != NULL && macro_count() > 0) {
|
||||
TracePhase tp("macroEliminate", &timers[_t_macroEliminate]);
|
||||
PhaseMacroExpand mexp(igvn);
|
||||
mexp.eliminate_macro_nodes();
|
||||
igvn.set_delay_transform(false);
|
||||
|
||||
igvn.optimize();
|
||||
print_method(PHASE_ITER_GVN_AFTER_ELIMINATION, 2);
|
||||
|
||||
if (failing()) return;
|
||||
}
|
||||
progress = do_iterative_escape_analysis() &&
|
||||
(macro_count() < mcount) &&
|
||||
ConnectionGraph::has_candidates(this);
|
||||
// Try again if candidates exist and made progress
|
||||
// by removing some allocations and/or locks.
|
||||
} while (progress);
|
||||
}
|
||||
|
||||
// Loop transforms on the ideal graph. Range Check Elimination,
|
||||
|
@ -168,15 +168,18 @@ class Options {
|
||||
private:
|
||||
const bool _subsume_loads; // Load can be matched as part of a larger op.
|
||||
const bool _do_escape_analysis; // Do escape analysis.
|
||||
const bool _do_iterative_escape_analysis; // Do iterative escape analysis.
|
||||
const bool _eliminate_boxing; // Do boxing elimination.
|
||||
const bool _do_locks_coarsening; // Do locks coarsening
|
||||
const bool _install_code; // Install the code that was compiled
|
||||
public:
|
||||
Options(bool subsume_loads, bool do_escape_analysis,
|
||||
bool do_iterative_escape_analysis,
|
||||
bool eliminate_boxing, bool do_locks_coarsening,
|
||||
bool install_code) :
|
||||
_subsume_loads(subsume_loads),
|
||||
_do_escape_analysis(do_escape_analysis),
|
||||
_do_iterative_escape_analysis(do_iterative_escape_analysis),
|
||||
_eliminate_boxing(eliminate_boxing),
|
||||
_do_locks_coarsening(do_locks_coarsening),
|
||||
_install_code(install_code) {
|
||||
@ -186,6 +189,7 @@ class Options {
|
||||
return Options(
|
||||
/* subsume_loads = */ true,
|
||||
/* do_escape_analysis = */ false,
|
||||
/* do_iterative_escape_analysis = */ false,
|
||||
/* eliminate_boxing = */ false,
|
||||
/* do_lock_coarsening = */ false,
|
||||
/* install_code = */ true
|
||||
@ -534,6 +538,7 @@ class Compile : public Phase {
|
||||
bool subsume_loads() const { return _options._subsume_loads; }
|
||||
/** Do escape analysis. */
|
||||
bool do_escape_analysis() const { return _options._do_escape_analysis; }
|
||||
bool do_iterative_escape_analysis() const { return _options._do_iterative_escape_analysis; }
|
||||
/** Do boxing elimination. */
|
||||
bool eliminate_boxing() const { return _options._eliminate_boxing; }
|
||||
/** Do aggressive boxing elimination. */
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include "opto/rootnode.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) :
|
||||
ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn, int invocation) :
|
||||
_nodes(C->comp_arena(), C->unique(), C->unique(), NULL),
|
||||
_in_worklist(C->comp_arena()),
|
||||
_next_pidx(0),
|
||||
@ -49,6 +49,9 @@ ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) :
|
||||
_verify(false),
|
||||
_compile(C),
|
||||
_igvn(igvn),
|
||||
_invocation(invocation),
|
||||
_build_iterations(0),
|
||||
_build_time(0.),
|
||||
_node_map(C->comp_arena()) {
|
||||
// Add unknown java object.
|
||||
add_java_object(C->top(), PointsToNode::GlobalEscape);
|
||||
@ -96,7 +99,11 @@ void ConnectionGraph::do_analysis(Compile *C, PhaseIterGVN *igvn) {
|
||||
// to create space for them in ConnectionGraph::_nodes[].
|
||||
Node* oop_null = igvn->zerocon(T_OBJECT);
|
||||
Node* noop_null = igvn->zerocon(T_NARROWOOP);
|
||||
ConnectionGraph* congraph = new(C->comp_arena()) ConnectionGraph(C, igvn);
|
||||
int invocation = 0;
|
||||
if (C->congraph() != NULL) {
|
||||
invocation = C->congraph()->_invocation + 1;
|
||||
}
|
||||
ConnectionGraph* congraph = new(C->comp_arena()) ConnectionGraph(C, igvn, invocation);
|
||||
// Perform escape analysis
|
||||
if (congraph->compute_escape()) {
|
||||
// There are non escaping objects.
|
||||
@ -1326,18 +1333,12 @@ bool ConnectionGraph::complete_connection_graph(
|
||||
C->log()->text("%s", timeout ? "time" : "iterations");
|
||||
C->log()->end_elem(" limit'");
|
||||
}
|
||||
assert(ExitEscapeAnalysisOnTimeout, "infinite EA connection graph build (%f sec, %d iterations) with %d nodes and worklist size %d",
|
||||
_build_time, _build_iterations, nodes_size(), ptnodes_worklist.length());
|
||||
assert(ExitEscapeAnalysisOnTimeout, "infinite EA connection graph build during invocation %d (%f sec, %d iterations) with %d nodes and worklist size %d",
|
||||
_invocation, _build_time, _build_iterations, nodes_size(), ptnodes_worklist.length());
|
||||
// Possible infinite build_connection_graph loop,
|
||||
// bailout (no changes to ideal graph were made).
|
||||
return false;
|
||||
}
|
||||
#ifdef ASSERT
|
||||
if (Verbose && PrintEscapeAnalysis) {
|
||||
tty->print_cr("EA: %d iterations and %f sec to build connection graph with %d nodes and worklist size %d",
|
||||
_build_iterations, _build_time, nodes_size(), ptnodes_worklist.length());
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef GRAPH_BUILD_ITER_LIMIT
|
||||
|
||||
@ -2645,7 +2646,7 @@ PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, Gro
|
||||
// Retry compilation without escape analysis.
|
||||
// If this is the first failure, the sentinel string will "stick"
|
||||
// to the Compile object, and the C2Compiler will see it and retry.
|
||||
C->record_failure(C2Compiler::retry_no_escape_analysis());
|
||||
C->record_failure(_invocation > 0 ? C2Compiler::retry_no_iterative_escape_analysis() : C2Compiler::retry_no_escape_analysis());
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -3216,7 +3217,7 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist,
|
||||
ptnode_adr(n->_idx)->dump();
|
||||
assert(jobj != NULL && jobj != phantom_obj, "escaped allocation");
|
||||
#endif
|
||||
_compile->record_failure(C2Compiler::retry_no_escape_analysis());
|
||||
_compile->record_failure(_invocation > 0 ? C2Compiler::retry_no_iterative_escape_analysis() : C2Compiler::retry_no_escape_analysis());
|
||||
return;
|
||||
}
|
||||
Node *base = get_map(jobj->idx()); // CheckCastPP node
|
||||
@ -3236,7 +3237,7 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist,
|
||||
ptnode_adr(n->_idx)->dump();
|
||||
assert(jobj != NULL && jobj != phantom_obj, "escaped allocation");
|
||||
#endif
|
||||
_compile->record_failure(C2Compiler::retry_no_escape_analysis());
|
||||
_compile->record_failure(_invocation > 0 ? C2Compiler::retry_no_iterative_escape_analysis() : C2Compiler::retry_no_escape_analysis());
|
||||
return;
|
||||
} else {
|
||||
Node *val = get_map(jobj->idx()); // CheckCastPP node
|
||||
@ -3692,6 +3693,9 @@ void ConnectionGraph::dump(GrowableArray<PointsToNode*>& ptnodes_worklist) {
|
||||
tty->print("======== Connection graph for ");
|
||||
_compile->method()->print_short_name();
|
||||
tty->cr();
|
||||
tty->print_cr("invocation #%d: %d iterations and %f sec to build connection graph with %d nodes and worklist size %d",
|
||||
_invocation, _build_iterations, _build_time, nodes_size(), ptnodes_worklist.length());
|
||||
tty->cr();
|
||||
first = false;
|
||||
}
|
||||
ptn->dump();
|
||||
|
@ -340,6 +340,7 @@ private:
|
||||
|
||||
Unique_Node_List ideal_nodes; // Used by CG construction and types splitting.
|
||||
|
||||
int _invocation; // Current number of analysis invocation
|
||||
int _build_iterations; // Number of iterations took to build graph
|
||||
double _build_time; // Time (sec) took to build graph
|
||||
|
||||
@ -569,7 +570,7 @@ private:
|
||||
bool compute_escape();
|
||||
|
||||
public:
|
||||
ConnectionGraph(Compile *C, PhaseIterGVN *igvn);
|
||||
ConnectionGraph(Compile *C, PhaseIterGVN *igvn, int iteration);
|
||||
|
||||
// Check for non-escaping candidates
|
||||
static bool has_candidates(Compile *C);
|
||||
|
128
test/hotspot/jtreg/compiler/c2/irTests/TestIterativeEA.java
Normal file
128
test/hotspot/jtreg/compiler/c2/irTests/TestIterativeEA.java
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package compiler.c2.irTests;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import jdk.test.lib.Asserts;
|
||||
import compiler.lib.ir_framework.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8276455
|
||||
* @summary Test C2 iterative Escape Analysis to remove all allocations in test
|
||||
* @library /test/lib /
|
||||
* @run driver compiler.c2.irTests.TestIterativeEA
|
||||
*/
|
||||
public class TestIterativeEA {
|
||||
|
||||
public static void main(String[] args) {
|
||||
TestFramework.run();
|
||||
}
|
||||
|
||||
static class MyClass {
|
||||
int val;
|
||||
public MyClass(int val) {
|
||||
this.val = val;
|
||||
}
|
||||
}
|
||||
|
||||
static class AbstractClass {
|
||||
final int unused;
|
||||
public AbstractClass() {
|
||||
unused = 42;
|
||||
}
|
||||
}
|
||||
|
||||
static class HolderWithSuper extends AbstractClass {
|
||||
final MyClass obj;
|
||||
public HolderWithSuper(MyClass obj) {
|
||||
this.obj = obj;
|
||||
}
|
||||
}
|
||||
|
||||
static class Holder {
|
||||
final MyClass obj;
|
||||
public Holder(MyClass obj) {
|
||||
this.obj = obj;
|
||||
}
|
||||
}
|
||||
|
||||
static class GenericHolder {
|
||||
final Object obj;
|
||||
public GenericHolder(Object obj) {
|
||||
this.obj = obj;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({ Argument.RANDOM_EACH })
|
||||
@IR(failOn = { IRNode.ALLOC })
|
||||
public static int testSlow(int val) {
|
||||
MyClass obj = new MyClass(val);
|
||||
HolderWithSuper h1 = new HolderWithSuper(obj);
|
||||
GenericHolder h2 = new GenericHolder(h1);
|
||||
return ((HolderWithSuper)h2.obj).obj.val;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({ Argument.RANDOM_EACH })
|
||||
@IR(failOn = { IRNode.ALLOC })
|
||||
public static int testFast(int val) {
|
||||
MyClass obj = new MyClass(val);
|
||||
Holder h1 = new Holder(obj);
|
||||
GenericHolder h2 = new GenericHolder(h1);
|
||||
return ((Holder)h2.obj).obj.val;
|
||||
}
|
||||
|
||||
static class A {
|
||||
int i;
|
||||
public A(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
}
|
||||
|
||||
static class B {
|
||||
A a;
|
||||
public B(A a) {
|
||||
this.a = a;
|
||||
}
|
||||
}
|
||||
|
||||
static class C {
|
||||
B b;
|
||||
public C(B b) {
|
||||
this.b = b;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({ Argument.RANDOM_EACH })
|
||||
@IR(failOn = { IRNode.ALLOC })
|
||||
static int testNested(int i) {
|
||||
C c = new C(new B(new A(i)));
|
||||
return c.b.a.i;
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* 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 8276455
|
||||
* @summary Test C2 iterative Escape Analysis
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @requires vm.flagless
|
||||
* @requires vm.compiler2.enabled & vm.debug == true
|
||||
*
|
||||
* @run driver TestIterativeEA
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
public class TestIterativeEA {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-server", "-XX:-TieredCompilation", "-Xbatch", "-XX:+PrintEliminateAllocations",
|
||||
Launcher.class.getName());
|
||||
|
||||
OutputAnalyzer analyzer = new OutputAnalyzer(pb.start());
|
||||
|
||||
System.out.println(analyzer.getOutput());
|
||||
|
||||
analyzer.shouldHaveExitValue(0);
|
||||
analyzer.shouldContain("++++ Eliminated: 26 Allocate");
|
||||
analyzer.shouldContain("++++ Eliminated: 48 Allocate");
|
||||
analyzer.shouldContain("++++ Eliminated: 78 Allocate");
|
||||
}
|
||||
|
||||
static class A {
|
||||
int i;
|
||||
|
||||
public A(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
}
|
||||
|
||||
static class B {
|
||||
A a;
|
||||
|
||||
public B(A a) {
|
||||
this.a = a;
|
||||
}
|
||||
}
|
||||
|
||||
static class C {
|
||||
B b;
|
||||
|
||||
public C(B b) {
|
||||
this.b = b;
|
||||
}
|
||||
}
|
||||
|
||||
static int test(int i) {
|
||||
C c = new C(new B(new A(i)));
|
||||
return c.b.a.i;
|
||||
}
|
||||
|
||||
static class Launcher {
|
||||
public static void main(String[] args) {
|
||||
for (int i = 0; i < 12000; ++i) {
|
||||
int j = test(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
105
test/micro/org/openjdk/bench/vm/compiler/IterativeEA.java
Normal file
105
test/micro/org/openjdk/bench/vm/compiler/IterativeEA.java
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.openjdk.bench.vm.compiler;
|
||||
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Fork;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
@State(Scope.Thread)
|
||||
@Fork(1)
|
||||
|
||||
public class IterativeEA {
|
||||
|
||||
public static int ii = 1;
|
||||
|
||||
static class A {
|
||||
int i;
|
||||
|
||||
public A(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
}
|
||||
|
||||
static class B {
|
||||
A a;
|
||||
|
||||
public B(A a) {
|
||||
this.a = a;
|
||||
}
|
||||
}
|
||||
|
||||
static class C {
|
||||
B b;
|
||||
|
||||
public C(B b) {
|
||||
this.b = b;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int test1() {
|
||||
C c = new C(new B(new A(ii)));
|
||||
return c.b.a.i;
|
||||
}
|
||||
|
||||
static class Point {
|
||||
int x;
|
||||
int y;
|
||||
int ax[];
|
||||
int ay[];
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int test2() {
|
||||
Point p = new Point();
|
||||
p.ax = new int[2];
|
||||
p.ay = new int[2];
|
||||
int x = 3;
|
||||
p.ax[0] = x;
|
||||
p.ay[1] = 3 * x + ii;
|
||||
return p.ax[0] * p.ay[1];
|
||||
}
|
||||
|
||||
public static final Double dbc = Double.valueOf(1.);
|
||||
|
||||
@Benchmark
|
||||
public double test3() {
|
||||
Double j1 = Double.valueOf(1.);
|
||||
Double j2 = Double.valueOf(1.);
|
||||
for (int i = 0; i< 1000; i++) {
|
||||
j1 = j1 + 1.;
|
||||
j2 = j2 + 2.;
|
||||
}
|
||||
return j1 + j2;
|
||||
}
|
||||
}
|
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.openjdk.bench.vm.compiler;
|
||||
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Fork;
|
||||
import org.openjdk.jmh.annotations.Measurement;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.Setup;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
import org.openjdk.jmh.annotations.Warmup;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Fork(value = 3)
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@Warmup(iterations = 3, time = 500, timeUnit = TimeUnit.MILLISECONDS)
|
||||
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
|
||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||
@State(Scope.Benchmark)
|
||||
public class PointerBenchmarkFlat {
|
||||
|
||||
static final int ELEM_SIZE = 1_000_000;
|
||||
|
||||
PointerImpl ptr_ptr;
|
||||
PointerImplFlat ptr_ptr_flat;
|
||||
|
||||
@Setup
|
||||
public void setup() {
|
||||
ptr_ptr = new PointerImpl(new FakeSegment(MemoryAddress.NULL, Long.MAX_VALUE));
|
||||
ptr_ptr_flat = new PointerImplFlat(new FakeSegmentFlat(MemoryAddress.NULL, Long.MAX_VALUE));
|
||||
}
|
||||
|
||||
static class MemoryAddress {
|
||||
private long addr;
|
||||
|
||||
public MemoryAddress(long addr) {
|
||||
this.addr = addr;
|
||||
}
|
||||
|
||||
long toRawLongValue() {
|
||||
return addr;
|
||||
}
|
||||
|
||||
private static final MemoryAddress NULL = new MemoryAddress(0);
|
||||
|
||||
static MemoryAddress ofLong(long val) {
|
||||
return new MemoryAddress(val);
|
||||
}
|
||||
}
|
||||
|
||||
static class PointerImpl {
|
||||
final FakeSegment segment;
|
||||
|
||||
public PointerImpl(FakeSegment segment) {
|
||||
this.segment = segment;
|
||||
}
|
||||
|
||||
MemoryAddress address() {
|
||||
return segment.address();
|
||||
}
|
||||
|
||||
PointerImpl get(long index) {
|
||||
MemoryAddress address = MemoryAddress.ofLong(index);
|
||||
FakeSegment holder = new FakeSegment(address, Long.MAX_VALUE);
|
||||
return new PointerImpl(holder);
|
||||
}
|
||||
}
|
||||
|
||||
static class PointerImplFlat {
|
||||
final FakeSegmentFlat segment;
|
||||
|
||||
public PointerImplFlat(FakeSegmentFlat segment) {
|
||||
this.segment = segment;
|
||||
}
|
||||
|
||||
MemoryAddress address() {
|
||||
return segment.address();
|
||||
}
|
||||
|
||||
PointerImplFlat get(long index) {
|
||||
MemoryAddress address = MemoryAddress.ofLong(index);
|
||||
FakeSegmentFlat holder = new FakeSegmentFlat(address, Long.MAX_VALUE);
|
||||
return new PointerImplFlat(holder);
|
||||
}
|
||||
}
|
||||
|
||||
static class AbstractFakeSegment {
|
||||
final long size;
|
||||
|
||||
public AbstractFakeSegment(long size) {
|
||||
this.size = size;
|
||||
}
|
||||
}
|
||||
|
||||
static class FakeSegment extends AbstractFakeSegment {
|
||||
final MemoryAddress address;
|
||||
|
||||
public FakeSegment(MemoryAddress address, long size) {
|
||||
super(size);
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
MemoryAddress address() {
|
||||
return address;
|
||||
}
|
||||
}
|
||||
|
||||
static class FakeSegmentFlat {
|
||||
final MemoryAddress address;
|
||||
final long size;
|
||||
|
||||
public FakeSegmentFlat(MemoryAddress address, long size) {
|
||||
this.size = size;
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
MemoryAddress address() {
|
||||
return address;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int test() {
|
||||
int sum = 0;
|
||||
for (int i = 0 ; i < ELEM_SIZE ; i++) {
|
||||
sum += ptr_ptr.get(i).address().toRawLongValue();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int testFlat() {
|
||||
int sum = 0;
|
||||
for (int i = 0 ; i < ELEM_SIZE ; i++) {
|
||||
sum += ptr_ptr_flat.get(i).address().toRawLongValue();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user