Merge
This commit is contained in:
commit
3f8d493b0d
@ -187,11 +187,10 @@ public final class BinaryContainer implements SymbolTable {
|
|||||||
{"StubRoutines::_arrayof_oop_disjoint_arraycopy", "_aot_stub_routines_arrayof_oop_disjoint_arraycopy"},
|
{"StubRoutines::_arrayof_oop_disjoint_arraycopy", "_aot_stub_routines_arrayof_oop_disjoint_arraycopy"},
|
||||||
{"StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit", "_aot_stub_routines_arrayof_oop_disjoint_arraycopy_uninit"},
|
{"StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit", "_aot_stub_routines_arrayof_oop_disjoint_arraycopy_uninit"},
|
||||||
|
|
||||||
|
{"StubRoutines::_unsafe_arraycopy", "_aot_stub_routines_unsafe_arraycopy"},
|
||||||
|
|
||||||
{"StubRoutines::_checkcast_arraycopy", "_aot_stub_routines_checkcast_arraycopy"},
|
{"StubRoutines::_checkcast_arraycopy", "_aot_stub_routines_checkcast_arraycopy"},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{"StubRoutines::_aescrypt_encryptBlock", "_aot_stub_routines_aescrypt_encryptBlock"},
|
{"StubRoutines::_aescrypt_encryptBlock", "_aot_stub_routines_aescrypt_encryptBlock"},
|
||||||
{"StubRoutines::_aescrypt_decryptBlock", "_aot_stub_routines_aescrypt_decryptBlock"},
|
{"StubRoutines::_aescrypt_decryptBlock", "_aot_stub_routines_aescrypt_decryptBlock"},
|
||||||
{"StubRoutines::_cipherBlockChaining_encryptAESCrypt", "_aot_stub_routines_cipherBlockChaining_encryptAESCrypt"},
|
{"StubRoutines::_cipherBlockChaining_encryptAESCrypt", "_aot_stub_routines_cipherBlockChaining_encryptAESCrypt"},
|
||||||
@ -478,8 +477,8 @@ public final class BinaryContainer implements SymbolTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a global symbol of the form {@code "A" + container name}.
|
* Creates a global symbol of the form {@code "A" + container name}. Note, linker on Windows
|
||||||
* Note, linker on Windows does not allow names which start with '.'
|
* does not allow names which start with '.'
|
||||||
*
|
*
|
||||||
* @param container container to create a symbol for
|
* @param container container to create a symbol for
|
||||||
*/
|
*/
|
||||||
@ -685,7 +684,8 @@ public final class BinaryContainer implements SymbolTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add oop symbol by as follows. Extend the oop.got section with another slot for the VM to patch.
|
* Add oop symbol by as follows. Extend the oop.got section with another slot for the VM to
|
||||||
|
* patch.
|
||||||
*
|
*
|
||||||
* @param oopName name of the oop symbol
|
* @param oopName name of the oop symbol
|
||||||
*/
|
*/
|
||||||
@ -728,10 +728,9 @@ public final class BinaryContainer implements SymbolTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add klass symbol by as follows.
|
* Add klass symbol by as follows. - Adding the symbol name to the metaspace.names section - Add
|
||||||
* - Adding the symbol name to the metaspace.names section
|
* the offset of the name in metaspace.names to metaspace.offsets - Extend the klasses.got
|
||||||
* - Add the offset of the name in metaspace.names to metaspace.offsets
|
* section with another slot for the VM to patch
|
||||||
* - Extend the klasses.got section with another slot for the VM to patch
|
|
||||||
*
|
*
|
||||||
* @param klassName name of the metaspace symbol
|
* @param klassName name of the metaspace symbol
|
||||||
* @return the got offset in the klasses.got of the metaspace symbol
|
* @return the got offset in the klasses.got of the metaspace symbol
|
||||||
|
@ -27,6 +27,8 @@ import java.util.ListIterator;
|
|||||||
|
|
||||||
import org.graalvm.compiler.code.CompilationResult;
|
import org.graalvm.compiler.code.CompilationResult;
|
||||||
import org.graalvm.compiler.core.GraalCompiler;
|
import org.graalvm.compiler.core.GraalCompiler;
|
||||||
|
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||||
|
import org.graalvm.compiler.core.common.CompilationIdentifier.Verbosity;
|
||||||
import org.graalvm.compiler.debug.DebugContext;
|
import org.graalvm.compiler.debug.DebugContext;
|
||||||
import org.graalvm.compiler.hotspot.HotSpotBackend;
|
import org.graalvm.compiler.hotspot.HotSpotBackend;
|
||||||
import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
|
import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
|
||||||
@ -127,7 +129,13 @@ final class AOTBackend {
|
|||||||
ProfilingInfo profilingInfo = DefaultProfilingInfo.get(TriState.FALSE);
|
ProfilingInfo profilingInfo = DefaultProfilingInfo.get(TriState.FALSE);
|
||||||
|
|
||||||
final boolean isImmutablePIC = true;
|
final boolean isImmutablePIC = true;
|
||||||
CompilationResult compilationResult = new CompilationResult(resolvedMethod.getName(), isImmutablePIC);
|
CompilationIdentifier id = new CompilationIdentifier() {
|
||||||
|
@Override
|
||||||
|
public String toString(Verbosity verbosity) {
|
||||||
|
return resolvedMethod.getName();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
CompilationResult compilationResult = new CompilationResult(id, isImmutablePIC);
|
||||||
|
|
||||||
return GraalCompiler.compileGraph(graph, resolvedMethod, providers, backend, graphBuilderSuite, OptimisticOptimizations.ALL, profilingInfo, getSuites(), getLirSuites(),
|
return GraalCompiler.compileGraph(graph, resolvedMethod, providers, backend, graphBuilderSuite, OptimisticOptimizations.ALL, profilingInfo, getSuites(), getLirSuites(),
|
||||||
compilationResult, CompilationResultBuilderFactory.Default);
|
compilationResult, CompilationResultBuilderFactory.Default);
|
||||||
|
@ -57,7 +57,9 @@ public @interface ClassSubstitution {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the substitutions are for classes that may not be part of the runtime.
|
* Determines if the substitutions are for classes that may not be part of the runtime.
|
||||||
* Substitutions for such classes are omitted if the original classes cannot be found.
|
* Substitutions for such classes are omitted if the original classes cannot be found. If
|
||||||
|
* multiple classes are specified using {@link #className()} and {@link #optional()} is false,
|
||||||
|
* then at least one of the classes is required to be reachable.
|
||||||
*/
|
*/
|
||||||
boolean optional() default false;
|
boolean optional() default false;
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ public abstract class AssemblerTest extends GraalTest {
|
|||||||
StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).compilationId(compilationId).build();
|
StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).compilationId(compilationId).build();
|
||||||
CallingConvention cc = backend.newLIRGenerationResult(compilationId, null, null, graph, null).getCallingConvention();
|
CallingConvention cc = backend.newLIRGenerationResult(compilationId, null, null, graph, null).getCallingConvention();
|
||||||
|
|
||||||
CompilationResult compResult = new CompilationResult();
|
CompilationResult compResult = new CompilationResult(graph.compilationId());
|
||||||
byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc);
|
byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc);
|
||||||
compResult.setTargetCode(targetCode, targetCode.length);
|
compResult.setTargetCode(targetCode, targetCode.length);
|
||||||
compResult.setTotalFrameSize(0);
|
compResult.setTotalFrameSize(0);
|
||||||
|
@ -33,6 +33,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||||
import org.graalvm.compiler.graph.NodeSourcePosition;
|
import org.graalvm.compiler.graph.NodeSourcePosition;
|
||||||
import org.graalvm.util.EconomicSet;
|
import org.graalvm.util.EconomicSet;
|
||||||
|
|
||||||
@ -190,6 +191,8 @@ public class CompilationResult {
|
|||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
private final CompilationIdentifier compilationId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The buffer containing the emitted machine code.
|
* The buffer containing the emitted machine code.
|
||||||
*/
|
*/
|
||||||
@ -222,21 +225,26 @@ public class CompilationResult {
|
|||||||
|
|
||||||
private boolean isImmutablePIC;
|
private boolean isImmutablePIC;
|
||||||
|
|
||||||
public CompilationResult() {
|
public CompilationResult(CompilationIdentifier compilationId) {
|
||||||
this(null, false);
|
this(compilationId, compilationId.toString(CompilationIdentifier.Verbosity.NAME), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompilationResult(CompilationIdentifier compilationId, String name) {
|
||||||
|
this(compilationId, name, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompilationResult(CompilationIdentifier compilationId, boolean isImmutablePIC) {
|
||||||
|
this(compilationId, null, isImmutablePIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompilationResult(CompilationIdentifier compilationId, String name, boolean isImmutablePIC) {
|
||||||
|
this.compilationId = compilationId;
|
||||||
|
this.name = name;
|
||||||
|
this.isImmutablePIC = isImmutablePIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompilationResult(String name) {
|
public CompilationResult(String name) {
|
||||||
this(name, false);
|
this(null, name);
|
||||||
}
|
|
||||||
|
|
||||||
public CompilationResult(boolean isImmutablePIC) {
|
|
||||||
this(null, isImmutablePIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompilationResult(String name, boolean isImmutablePIC) {
|
|
||||||
this.name = name;
|
|
||||||
this.isImmutablePIC = isImmutablePIC;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -266,6 +274,7 @@ public class CompilationResult {
|
|||||||
this.totalFrameSize == that.totalFrameSize &&
|
this.totalFrameSize == that.totalFrameSize &&
|
||||||
this.targetCodeSize == that.targetCodeSize &&
|
this.targetCodeSize == that.targetCodeSize &&
|
||||||
Objects.equals(this.name, that.name) &&
|
Objects.equals(this.name, that.name) &&
|
||||||
|
Objects.equals(this.compilationId, that.compilationId) &&
|
||||||
Objects.equals(this.annotations, that.annotations) &&
|
Objects.equals(this.annotations, that.annotations) &&
|
||||||
Objects.equals(this.dataSection, that.dataSection) &&
|
Objects.equals(this.dataSection, that.dataSection) &&
|
||||||
Objects.equals(this.exceptionHandlers, that.exceptionHandlers) &&
|
Objects.equals(this.exceptionHandlers, that.exceptionHandlers) &&
|
||||||
@ -670,6 +679,10 @@ public class CompilationResult {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CompilationIdentifier getCompilationId() {
|
||||||
|
return compilationId;
|
||||||
|
}
|
||||||
|
|
||||||
public void setHasUnsafeAccess(boolean hasUnsafeAccess) {
|
public void setHasUnsafeAccess(boolean hasUnsafeAccess) {
|
||||||
checkOpen();
|
checkOpen();
|
||||||
this.hasUnsafeAccess = hasUnsafeAccess;
|
this.hasUnsafeAccess = hasUnsafeAccess;
|
||||||
|
@ -949,7 +949,7 @@ public abstract class GraalCompilerTest extends GraalTest {
|
|||||||
|
|
||||||
try (AllocSpy spy = AllocSpy.open(installedCodeOwner); DebugContext.Scope ds = debug.scope("Compiling", new DebugDumpScope(id.toString(CompilationIdentifier.Verbosity.ID), true))) {
|
try (AllocSpy spy = AllocSpy.open(installedCodeOwner); DebugContext.Scope ds = debug.scope("Compiling", new DebugDumpScope(id.toString(CompilationIdentifier.Verbosity.ID), true))) {
|
||||||
CompilationPrinter printer = CompilationPrinter.begin(options, id, installedCodeOwner, INVOCATION_ENTRY_BCI);
|
CompilationPrinter printer = CompilationPrinter.begin(options, id, installedCodeOwner, INVOCATION_ENTRY_BCI);
|
||||||
CompilationResult compResult = compile(installedCodeOwner, graphToCompile, new CompilationResult(), id, options);
|
CompilationResult compResult = compile(installedCodeOwner, graphToCompile, new CompilationResult(graphToCompile.compilationId()), id, options);
|
||||||
printer.finish(compResult);
|
printer.finish(compResult);
|
||||||
|
|
||||||
try (DebugContext.Scope s = debug.scope("CodeInstall", getCodeCache(), installedCodeOwner, compResult);
|
try (DebugContext.Scope s = debug.scope("CodeInstall", getCodeCache(), installedCodeOwner, compResult);
|
||||||
@ -1019,17 +1019,19 @@ public abstract class GraalCompilerTest extends GraalTest {
|
|||||||
*/
|
*/
|
||||||
protected final CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph) {
|
protected final CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph) {
|
||||||
OptionValues options = graph == null ? getInitialOptions() : graph.getOptions();
|
OptionValues options = graph == null ? getInitialOptions() : graph.getOptions();
|
||||||
return compile(installedCodeOwner, graph, new CompilationResult(), getOrCreateCompilationId(installedCodeOwner, graph), options);
|
CompilationIdentifier compilationId = getOrCreateCompilationId(installedCodeOwner, graph);
|
||||||
|
return compile(installedCodeOwner, graph, new CompilationResult(compilationId), compilationId, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, CompilationIdentifier compilationId) {
|
protected final CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, CompilationIdentifier compilationId) {
|
||||||
OptionValues options = graph == null ? getInitialOptions() : graph.getOptions();
|
OptionValues options = graph == null ? getInitialOptions() : graph.getOptions();
|
||||||
return compile(installedCodeOwner, graph, new CompilationResult(), compilationId, options);
|
return compile(installedCodeOwner, graph, new CompilationResult(compilationId), compilationId, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, OptionValues options) {
|
protected final CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, OptionValues options) {
|
||||||
assert graph == null || graph.getOptions() == options;
|
assert graph == null || graph.getOptions() == options;
|
||||||
return compile(installedCodeOwner, graph, new CompilationResult(), getOrCreateCompilationId(installedCodeOwner, graph), options);
|
CompilationIdentifier compilationId = getOrCreateCompilationId(installedCodeOwner, graph);
|
||||||
|
return compile(installedCodeOwner, graph, new CompilationResult(compilationId), compilationId, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,7 +64,7 @@ public class InfopointReasonTest extends GraalCompilerTest {
|
|||||||
final ResolvedJavaMethod method = getResolvedJavaMethod("testMethod");
|
final ResolvedJavaMethod method = getResolvedJavaMethod("testMethod");
|
||||||
final StructuredGraph graph = parseEager(method, AllowAssumptions.YES);
|
final StructuredGraph graph = parseEager(method, AllowAssumptions.YES);
|
||||||
final CompilationResult cr = compileGraph(graph, graph.method(), getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, graph.getProfilingInfo(),
|
final CompilationResult cr = compileGraph(graph, graph.method(), getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, graph.getProfilingInfo(),
|
||||||
createSuites(graph.getOptions()), createLIRSuites(graph.getOptions()), new CompilationResult(), CompilationResultBuilderFactory.Default);
|
createSuites(graph.getOptions()), createLIRSuites(graph.getOptions()), new CompilationResult(graph.compilationId()), CompilationResultBuilderFactory.Default);
|
||||||
for (Infopoint sp : cr.getInfopoints()) {
|
for (Infopoint sp : cr.getInfopoints()) {
|
||||||
assertNotNull(sp.reason);
|
assertNotNull(sp.reason);
|
||||||
if (sp instanceof Call) {
|
if (sp instanceof Call) {
|
||||||
@ -86,7 +86,7 @@ public class InfopointReasonTest extends GraalCompilerTest {
|
|||||||
assertTrue(graphLineSPs > 0);
|
assertTrue(graphLineSPs > 0);
|
||||||
PhaseSuite<HighTierContext> graphBuilderSuite = getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true));
|
PhaseSuite<HighTierContext> graphBuilderSuite = getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true));
|
||||||
final CompilationResult cr = compileGraph(graph, graph.method(), getProviders(), getBackend(), graphBuilderSuite, OptimisticOptimizations.ALL, graph.getProfilingInfo(),
|
final CompilationResult cr = compileGraph(graph, graph.method(), getProviders(), getBackend(), graphBuilderSuite, OptimisticOptimizations.ALL, graph.getProfilingInfo(),
|
||||||
createSuites(graph.getOptions()), createLIRSuites(graph.getOptions()), new CompilationResult(), CompilationResultBuilderFactory.Default);
|
createSuites(graph.getOptions()), createLIRSuites(graph.getOptions()), new CompilationResult(graph.compilationId()), CompilationResultBuilderFactory.Default);
|
||||||
int lineSPs = 0;
|
int lineSPs = 0;
|
||||||
for (Infopoint sp : cr.getInfopoints()) {
|
for (Infopoint sp : cr.getInfopoints()) {
|
||||||
assertNotNull(sp.reason);
|
assertNotNull(sp.reason);
|
||||||
|
@ -123,7 +123,7 @@ public class InvokeGraal {
|
|||||||
ProfilingInfo profilingInfo = graph.getProfilingInfo(method);
|
ProfilingInfo profilingInfo = graph.getProfilingInfo(method);
|
||||||
|
|
||||||
/* The default class and configuration for compilation results. */
|
/* The default class and configuration for compilation results. */
|
||||||
CompilationResult compilationResult = new CompilationResult();
|
CompilationResult compilationResult = new CompilationResult(graph.compilationId());
|
||||||
CompilationResultBuilderFactory factory = CompilationResultBuilderFactory.Default;
|
CompilationResultBuilderFactory factory = CompilationResultBuilderFactory.Default;
|
||||||
|
|
||||||
/* Invoke the whole Graal compilation pipeline. */
|
/* Invoke the whole Graal compilation pipeline. */
|
||||||
|
@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, 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.graalvm.compiler.graph.test;
|
||||||
|
|
||||||
|
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED;
|
||||||
|
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED;
|
||||||
|
|
||||||
|
import java.util.ConcurrentModificationException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import org.graalvm.compiler.api.test.Graal;
|
||||||
|
import org.graalvm.compiler.graph.Graph;
|
||||||
|
import org.graalvm.compiler.graph.Node;
|
||||||
|
import org.graalvm.compiler.graph.NodeBitMap;
|
||||||
|
import org.graalvm.compiler.graph.NodeClass;
|
||||||
|
import org.graalvm.compiler.nodeinfo.NodeInfo;
|
||||||
|
import org.graalvm.compiler.options.OptionValues;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class NodeBitMapTest extends GraphTest {
|
||||||
|
|
||||||
|
@NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
|
||||||
|
static final class TestNode extends Node {
|
||||||
|
public static final NodeClass<TestNode> TYPE = NodeClass.create(TestNode.class);
|
||||||
|
|
||||||
|
protected TestNode() {
|
||||||
|
super(TYPE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Graph graph;
|
||||||
|
private TestNode[] nodes = new TestNode[100];
|
||||||
|
private NodeBitMap map;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() {
|
||||||
|
// Need to initialize HotSpotGraalRuntime before any Node class is initialized.
|
||||||
|
Graal.getRuntime();
|
||||||
|
|
||||||
|
OptionValues options = getOptions();
|
||||||
|
graph = new Graph(options, getDebug(options));
|
||||||
|
for (int i = 0; i < nodes.length; i++) {
|
||||||
|
nodes[i] = graph.add(new TestNode());
|
||||||
|
}
|
||||||
|
map = graph.createNodeBitMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void iterateEmpty() {
|
||||||
|
for (Node n : map) {
|
||||||
|
Assert.fail("no elements expected: " + n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void iterateMarkedNodes() {
|
||||||
|
map.mark(nodes[99]);
|
||||||
|
map.mark(nodes[0]);
|
||||||
|
map.mark(nodes[7]);
|
||||||
|
map.mark(nodes[1]);
|
||||||
|
map.mark(nodes[53]);
|
||||||
|
|
||||||
|
Iterator<Node> iter = map.iterator();
|
||||||
|
Assert.assertTrue(iter.hasNext());
|
||||||
|
Assert.assertEquals(nodes[0], iter.next());
|
||||||
|
Assert.assertTrue(iter.hasNext());
|
||||||
|
Assert.assertEquals(nodes[1], iter.next());
|
||||||
|
Assert.assertTrue(iter.hasNext());
|
||||||
|
Assert.assertEquals(nodes[7], iter.next());
|
||||||
|
Assert.assertTrue(iter.hasNext());
|
||||||
|
Assert.assertEquals(nodes[53], iter.next());
|
||||||
|
Assert.assertTrue(iter.hasNext());
|
||||||
|
Assert.assertEquals(nodes[99], iter.next());
|
||||||
|
Assert.assertFalse(iter.hasNext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void deleteNodeWhileIterating() {
|
||||||
|
map.mark(nodes[99]);
|
||||||
|
map.mark(nodes[0]);
|
||||||
|
map.mark(nodes[7]);
|
||||||
|
map.mark(nodes[1]);
|
||||||
|
map.mark(nodes[53]);
|
||||||
|
|
||||||
|
Iterator<Node> iter = map.iterator();
|
||||||
|
Assert.assertTrue(iter.hasNext());
|
||||||
|
Assert.assertEquals(nodes[0], iter.next());
|
||||||
|
Assert.assertTrue(iter.hasNext());
|
||||||
|
Assert.assertEquals(nodes[1], iter.next());
|
||||||
|
nodes[7].markDeleted();
|
||||||
|
nodes[53].markDeleted();
|
||||||
|
Assert.assertTrue(iter.hasNext());
|
||||||
|
Assert.assertEquals(nodes[99], iter.next());
|
||||||
|
Assert.assertFalse(iter.hasNext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void deleteAllNodesBeforeIterating() {
|
||||||
|
for (int i = 0; i < nodes.length; i++) {
|
||||||
|
map.mark(nodes[i]);
|
||||||
|
nodes[i].markDeleted();
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<Node> iter = map.iterator();
|
||||||
|
Assert.assertFalse(iter.hasNext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void multipleHasNextInvocations() {
|
||||||
|
map.mark(nodes[7]);
|
||||||
|
|
||||||
|
Iterator<Node> iter = map.iterator();
|
||||||
|
Assert.assertTrue(iter.hasNext());
|
||||||
|
Assert.assertTrue(iter.hasNext());
|
||||||
|
Assert.assertEquals(nodes[7], iter.next());
|
||||||
|
Assert.assertFalse(iter.hasNext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = NoSuchElementException.class)
|
||||||
|
public void noSuchElement() {
|
||||||
|
map.iterator().next();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = ConcurrentModificationException.class)
|
||||||
|
public void concurrentModification() {
|
||||||
|
map.mark(nodes[7]);
|
||||||
|
|
||||||
|
map.mark(nodes[99]);
|
||||||
|
map.mark(nodes[0]);
|
||||||
|
map.mark(nodes[7]);
|
||||||
|
map.mark(nodes[1]);
|
||||||
|
map.mark(nodes[53]);
|
||||||
|
|
||||||
|
Iterator<Node> iter = map.iterator();
|
||||||
|
Assert.assertTrue(iter.hasNext());
|
||||||
|
Assert.assertEquals(nodes[0], iter.next());
|
||||||
|
Assert.assertTrue(iter.hasNext());
|
||||||
|
Assert.assertEquals(nodes[1], iter.next());
|
||||||
|
Assert.assertTrue(iter.hasNext());
|
||||||
|
nodes[7].markDeleted();
|
||||||
|
iter.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void nextWithoutHasNext() {
|
||||||
|
map.mark(nodes[99]);
|
||||||
|
map.mark(nodes[0]);
|
||||||
|
map.mark(nodes[7]);
|
||||||
|
map.mark(nodes[1]);
|
||||||
|
map.mark(nodes[53]);
|
||||||
|
|
||||||
|
Iterator<Node> iter = map.iterator();
|
||||||
|
Assert.assertEquals(nodes[0], iter.next());
|
||||||
|
Assert.assertEquals(nodes[1], iter.next());
|
||||||
|
Assert.assertEquals(nodes[7], iter.next());
|
||||||
|
Assert.assertEquals(nodes[53], iter.next());
|
||||||
|
Assert.assertEquals(nodes[99], iter.next());
|
||||||
|
Assert.assertFalse(iter.hasNext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void markWhileIterating() {
|
||||||
|
map.mark(nodes[0]);
|
||||||
|
|
||||||
|
Iterator<Node> iter = map.iterator();
|
||||||
|
Assert.assertTrue(iter.hasNext());
|
||||||
|
Assert.assertEquals(nodes[0], iter.next());
|
||||||
|
map.mark(nodes[7]);
|
||||||
|
Assert.assertTrue(iter.hasNext());
|
||||||
|
map.mark(nodes[1]);
|
||||||
|
Assert.assertEquals(nodes[7], iter.next());
|
||||||
|
map.mark(nodes[99]);
|
||||||
|
map.mark(nodes[53]);
|
||||||
|
Assert.assertTrue(iter.hasNext());
|
||||||
|
Assert.assertEquals(nodes[53], iter.next());
|
||||||
|
Assert.assertTrue(iter.hasNext());
|
||||||
|
Assert.assertEquals(nodes[99], iter.next());
|
||||||
|
Assert.assertFalse(iter.hasNext());
|
||||||
|
}
|
||||||
|
}
|
@ -23,22 +23,23 @@
|
|||||||
package org.graalvm.compiler.graph;
|
package org.graalvm.compiler.graph;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.ConcurrentModificationException;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import org.graalvm.compiler.graph.iterators.NodeIterable;
|
import org.graalvm.compiler.graph.iterators.NodeIterable;
|
||||||
|
|
||||||
public final class NodeBitMap implements NodeIterable<Node> {
|
public final class NodeBitMap extends NodeIdAccessor implements NodeIterable<Node> {
|
||||||
private static final int SHIFT = 6;
|
private static final int SHIFT = 6;
|
||||||
|
|
||||||
private long[] bits;
|
private long[] bits;
|
||||||
private int nodeCount;
|
private int nodeCount;
|
||||||
private int counter;
|
private int counter;
|
||||||
private final Graph graph;
|
|
||||||
|
|
||||||
public NodeBitMap(Graph graph) {
|
public NodeBitMap(Graph graph) {
|
||||||
|
super(graph);
|
||||||
this.nodeCount = graph.nodeIdCount();
|
this.nodeCount = graph.nodeIdCount();
|
||||||
this.bits = new long[sizeForNodeCount(nodeCount)];
|
this.bits = new long[sizeForNodeCount(nodeCount)];
|
||||||
this.graph = graph;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int sizeForNodeCount(int nodeCount) {
|
private static int sizeForNodeCount(int nodeCount) {
|
||||||
@ -50,9 +51,9 @@ public final class NodeBitMap implements NodeIterable<Node> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private NodeBitMap(NodeBitMap other) {
|
private NodeBitMap(NodeBitMap other) {
|
||||||
|
super(other.graph);
|
||||||
this.bits = other.bits.clone();
|
this.bits = other.bits.clone();
|
||||||
this.nodeCount = other.nodeCount;
|
this.nodeCount = other.nodeCount;
|
||||||
this.graph = other.graph;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Graph graph() {
|
public Graph graph() {
|
||||||
@ -60,12 +61,12 @@ public final class NodeBitMap implements NodeIterable<Node> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNew(Node node) {
|
public boolean isNew(Node node) {
|
||||||
return node.id() >= nodeCount;
|
return getNodeId(node) >= nodeCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMarked(Node node) {
|
public boolean isMarked(Node node) {
|
||||||
assert check(node, false);
|
assert check(node, false);
|
||||||
return isMarked(node.id());
|
return isMarked(getNodeId(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean checkAndMarkInc(Node node) {
|
public boolean checkAndMarkInc(Node node) {
|
||||||
@ -84,33 +85,33 @@ public final class NodeBitMap implements NodeIterable<Node> {
|
|||||||
|
|
||||||
public boolean isMarkedAndGrow(Node node) {
|
public boolean isMarkedAndGrow(Node node) {
|
||||||
assert check(node, true);
|
assert check(node, true);
|
||||||
int id = node.id();
|
int id = getNodeId(node);
|
||||||
checkGrow(id);
|
checkGrow(id);
|
||||||
return isMarked(id);
|
return isMarked(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mark(Node node) {
|
public void mark(Node node) {
|
||||||
assert check(node, false);
|
assert check(node, false);
|
||||||
int id = node.id();
|
int id = getNodeId(node);
|
||||||
bits[id >> SHIFT] |= (1L << id);
|
bits[id >> SHIFT] |= (1L << id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void markAndGrow(Node node) {
|
public void markAndGrow(Node node) {
|
||||||
assert check(node, true);
|
assert check(node, true);
|
||||||
int id = node.id();
|
int id = getNodeId(node);
|
||||||
checkGrow(id);
|
checkGrow(id);
|
||||||
bits[id >> SHIFT] |= (1L << id);
|
bits[id >> SHIFT] |= (1L << id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear(Node node) {
|
public void clear(Node node) {
|
||||||
assert check(node, false);
|
assert check(node, false);
|
||||||
int id = node.id();
|
int id = getNodeId(node);
|
||||||
bits[id >> SHIFT] &= ~(1L << id);
|
bits[id >> SHIFT] &= ~(1L << id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearAndGrow(Node node) {
|
public void clearAndGrow(Node node) {
|
||||||
assert check(node, true);
|
assert check(node, true);
|
||||||
int id = node.id();
|
int id = getNodeId(node);
|
||||||
checkGrow(id);
|
checkGrow(id);
|
||||||
bits[id >> SHIFT] &= ~(1L << id);
|
bits[id >> SHIFT] &= ~(1L << id);
|
||||||
}
|
}
|
||||||
@ -181,15 +182,30 @@ public final class NodeBitMap implements NodeIterable<Node> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int nextMarkedNodeId(int fromNodeId) {
|
protected Node nextMarkedNode(int fromNodeId) {
|
||||||
assert fromNodeId >= 0;
|
assert fromNodeId >= 0;
|
||||||
int wordIndex = fromNodeId >> SHIFT;
|
int wordIndex = fromNodeId >> SHIFT;
|
||||||
int wordsInUse = bits.length;
|
int wordsInUse = bits.length;
|
||||||
if (wordIndex < wordsInUse) {
|
if (wordIndex < wordsInUse) {
|
||||||
long word = bits[wordIndex] & (0xFFFFFFFFFFFFFFFFL << fromNodeId);
|
long word = getPartOfWord(bits[wordIndex], fromNodeId);
|
||||||
while (true) {
|
while (true) {
|
||||||
if (word != 0) {
|
while (word != 0) {
|
||||||
return wordIndex * Long.SIZE + Long.numberOfTrailingZeros(word);
|
int bitIndex = Long.numberOfTrailingZeros(word);
|
||||||
|
int nodeId = wordIndex * Long.SIZE + bitIndex;
|
||||||
|
Node result = graph.getNode(nodeId);
|
||||||
|
if (result == null) {
|
||||||
|
// node was deleted -> clear the bit and continue searching
|
||||||
|
bits[wordIndex] = bits[wordIndex] & ~(1 << bitIndex);
|
||||||
|
int nextNodeId = nodeId + 1;
|
||||||
|
if ((nextNodeId & (Long.SIZE - 1)) == 0) {
|
||||||
|
// we reached the end of this word
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
word = getPartOfWord(word, nextNodeId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (++wordIndex == wordsInUse) {
|
if (++wordIndex == wordsInUse) {
|
||||||
break;
|
break;
|
||||||
@ -197,30 +213,56 @@ public final class NodeBitMap implements NodeIterable<Node> {
|
|||||||
word = bits[wordIndex];
|
word = bits[wordIndex];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -2;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static long getPartOfWord(long word, int firstNodeIdToInclude) {
|
||||||
|
return word & (0xFFFFFFFFFFFFFFFFL << firstNodeIdToInclude);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This iterator only returns nodes that are marked in the {@link NodeBitMap} and are alive in
|
||||||
|
* the corresponding {@link Graph}.
|
||||||
|
*/
|
||||||
private class MarkedNodeIterator implements Iterator<Node> {
|
private class MarkedNodeIterator implements Iterator<Node> {
|
||||||
private int nextNodeId;
|
private int currentNodeId;
|
||||||
|
private Node currentNode;
|
||||||
|
|
||||||
MarkedNodeIterator() {
|
MarkedNodeIterator() {
|
||||||
nextNodeId = -1;
|
currentNodeId = -1;
|
||||||
forward();
|
forward();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void forward() {
|
private void forward() {
|
||||||
nextNodeId = NodeBitMap.this.nextMarkedNodeId(nextNodeId + 1);
|
assert currentNode == null;
|
||||||
|
currentNode = NodeBitMap.this.nextMarkedNode(currentNodeId + 1);
|
||||||
|
if (currentNode != null) {
|
||||||
|
assert currentNode.isAlive();
|
||||||
|
currentNodeId = getNodeId(currentNode);
|
||||||
|
} else {
|
||||||
|
currentNodeId = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
return nextNodeId >= 0;
|
if (currentNode == null && currentNodeId >= 0) {
|
||||||
|
forward();
|
||||||
|
}
|
||||||
|
return currentNodeId >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node next() {
|
public Node next() {
|
||||||
Node result = graph.getNode(nextNodeId);
|
if (!hasNext()) {
|
||||||
forward();
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
if (!currentNode.isAlive()) {
|
||||||
|
throw new ConcurrentModificationException("NodeBitMap was modified between the calls to hasNext() and next()");
|
||||||
|
}
|
||||||
|
|
||||||
|
Node result = currentNode;
|
||||||
|
currentNode = null;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014, 2016, 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.graalvm.compiler.hotspot.aarch64;
|
|
||||||
|
|
||||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN;
|
|
||||||
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN;
|
|
||||||
|
|
||||||
import org.graalvm.compiler.core.aarch64.AArch64NodeLIRBuilder;
|
|
||||||
import org.graalvm.compiler.core.common.type.RawPointerStamp;
|
|
||||||
import org.graalvm.compiler.core.common.type.Stamp;
|
|
||||||
import org.graalvm.compiler.core.common.type.StampFactory;
|
|
||||||
import org.graalvm.compiler.graph.NodeClass;
|
|
||||||
import org.graalvm.compiler.graph.NodeInputList;
|
|
||||||
import org.graalvm.compiler.nodeinfo.NodeInfo;
|
|
||||||
import org.graalvm.compiler.nodes.FixedWithNextNode;
|
|
||||||
import org.graalvm.compiler.nodes.ValueNode;
|
|
||||||
import org.graalvm.compiler.nodes.spi.LIRLowerable;
|
|
||||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
|
||||||
|
|
||||||
import jdk.vm.ci.code.CallingConvention;
|
|
||||||
import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
|
|
||||||
import jdk.vm.ci.meta.JavaConstant;
|
|
||||||
import jdk.vm.ci.meta.JavaKind;
|
|
||||||
import jdk.vm.ci.meta.JavaType;
|
|
||||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
|
||||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
|
||||||
import jdk.vm.ci.meta.Value;
|
|
||||||
|
|
||||||
@NodeInfo(cycles = CYCLES_UNKNOWN, cyclesRationale = "Native call is a block hole", size = SIZE_UNKNOWN)
|
|
||||||
public final class AArch64RawNativeCallNode extends FixedWithNextNode implements LIRLowerable {
|
|
||||||
public static final NodeClass<AArch64RawNativeCallNode> TYPE = NodeClass.create(AArch64RawNativeCallNode.class);
|
|
||||||
|
|
||||||
protected final JavaConstant functionPointer;
|
|
||||||
@Input NodeInputList<ValueNode> args;
|
|
||||||
|
|
||||||
public AArch64RawNativeCallNode(JavaKind returnType, JavaConstant functionPointer, ValueNode[] args) {
|
|
||||||
super(TYPE, StampFactory.forKind(returnType));
|
|
||||||
this.functionPointer = functionPointer;
|
|
||||||
this.args = new NodeInputList<>(this, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class PointerType implements JavaType {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "void*";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JavaType getComponentType() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JavaType getArrayClass() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JavaKind getJavaKind() {
|
|
||||||
// native pointers and java objects use the same registers in the calling convention
|
|
||||||
return JavaKind.Object;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JavaType toJavaType(Stamp stamp, MetaAccessProvider metaAccess) {
|
|
||||||
if (stamp instanceof RawPointerStamp) {
|
|
||||||
return new PointerType();
|
|
||||||
} else {
|
|
||||||
return stamp.javaType(metaAccess);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generate(NodeLIRBuilderTool generator) {
|
|
||||||
AArch64NodeLIRBuilder gen = (AArch64NodeLIRBuilder) generator;
|
|
||||||
Value[] parameter = new Value[args.count()];
|
|
||||||
JavaType[] parameterTypes = new JavaType[args.count()];
|
|
||||||
for (int i = 0; i < args.count(); i++) {
|
|
||||||
parameter[i] = generator.operand(args.get(i));
|
|
||||||
parameterTypes[i] = toJavaType(args.get(i).stamp(), gen.getLIRGeneratorTool().getMetaAccess());
|
|
||||||
}
|
|
||||||
JavaType returnType = toJavaType(stamp(), gen.getLIRGeneratorTool().getMetaAccess());
|
|
||||||
CallingConvention cc = generator.getLIRGeneratorTool().getCodeCache().getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.NativeCall, returnType, parameterTypes,
|
|
||||||
generator.getLIRGeneratorTool());
|
|
||||||
gen.getLIRGeneratorTool().emitCCall(functionPointer.asLong(), cc, parameter);
|
|
||||||
if (this.getStackKind() != JavaKind.Void) {
|
|
||||||
generator.setResult(this, gen.getLIRGeneratorTool().emitMove(cc.getReturn()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,130 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014, 2016, 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.graalvm.compiler.hotspot.amd64;
|
|
||||||
|
|
||||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN;
|
|
||||||
|
|
||||||
import org.graalvm.compiler.core.amd64.AMD64NodeLIRBuilder;
|
|
||||||
import org.graalvm.compiler.core.common.type.RawPointerStamp;
|
|
||||||
import org.graalvm.compiler.core.common.type.Stamp;
|
|
||||||
import org.graalvm.compiler.core.common.type.StampFactory;
|
|
||||||
import org.graalvm.compiler.graph.NodeClass;
|
|
||||||
import org.graalvm.compiler.graph.NodeInputList;
|
|
||||||
import org.graalvm.compiler.nodeinfo.NodeInfo;
|
|
||||||
import org.graalvm.compiler.nodeinfo.NodeSize;
|
|
||||||
import org.graalvm.compiler.nodes.FixedWithNextNode;
|
|
||||||
import org.graalvm.compiler.nodes.ValueNode;
|
|
||||||
import org.graalvm.compiler.nodes.spi.LIRLowerable;
|
|
||||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
|
||||||
|
|
||||||
import jdk.vm.ci.code.CallingConvention;
|
|
||||||
import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
|
|
||||||
import jdk.vm.ci.meta.JavaConstant;
|
|
||||||
import jdk.vm.ci.meta.JavaKind;
|
|
||||||
import jdk.vm.ci.meta.JavaType;
|
|
||||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
|
||||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
|
||||||
import jdk.vm.ci.meta.Value;
|
|
||||||
|
|
||||||
@NodeInfo(cycles = CYCLES_UNKNOWN, cyclesRationale = "Native call is a block hole", size = NodeSize.SIZE_UNKNOWN)
|
|
||||||
public final class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRLowerable {
|
|
||||||
public static final NodeClass<AMD64RawNativeCallNode> TYPE = NodeClass.create(AMD64RawNativeCallNode.class);
|
|
||||||
|
|
||||||
protected final JavaConstant functionPointer;
|
|
||||||
@Input NodeInputList<ValueNode> args;
|
|
||||||
|
|
||||||
public AMD64RawNativeCallNode(JavaKind returnType, JavaConstant functionPointer, ValueNode[] args) {
|
|
||||||
super(TYPE, StampFactory.forKind(returnType));
|
|
||||||
this.functionPointer = functionPointer;
|
|
||||||
this.args = new NodeInputList<>(this, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class PointerType implements JavaType {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "void*";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JavaType getComponentType() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JavaType getArrayClass() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JavaKind getJavaKind() {
|
|
||||||
// native pointers and java objects use the same registers in the calling convention
|
|
||||||
return JavaKind.Object;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JavaType toJavaType(Stamp stamp, MetaAccessProvider metaAccess) {
|
|
||||||
if (stamp instanceof RawPointerStamp) {
|
|
||||||
return new PointerType();
|
|
||||||
} else {
|
|
||||||
return stamp.javaType(metaAccess);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generate(NodeLIRBuilderTool generator) {
|
|
||||||
AMD64NodeLIRBuilder gen = (AMD64NodeLIRBuilder) generator;
|
|
||||||
Value[] parameter = new Value[args.count()];
|
|
||||||
JavaType[] parameterTypes = new JavaType[args.count()];
|
|
||||||
for (int i = 0; i < args.count(); i++) {
|
|
||||||
parameter[i] = generator.operand(args.get(i));
|
|
||||||
parameterTypes[i] = toJavaType(args.get(i).stamp(), gen.getLIRGeneratorTool().getMetaAccess());
|
|
||||||
}
|
|
||||||
JavaType returnType = toJavaType(stamp(), gen.getLIRGeneratorTool().getMetaAccess());
|
|
||||||
CallingConvention cc = generator.getLIRGeneratorTool().getCodeCache().getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.NativeCall, returnType, parameterTypes,
|
|
||||||
generator.getLIRGeneratorTool());
|
|
||||||
gen.getLIRGeneratorTool().emitCCall(functionPointer.asLong(), cc, parameter, countFloatingTypeArguments(args));
|
|
||||||
if (this.getStackKind() != JavaKind.Void) {
|
|
||||||
generator.setResult(this, gen.getLIRGeneratorTool().emitMove(cc.getReturn()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int countFloatingTypeArguments(NodeInputList<ValueNode> args) {
|
|
||||||
int count = 0;
|
|
||||||
for (ValueNode n : args) {
|
|
||||||
if (n.getStackKind() == JavaKind.Double || n.getStackKind() == JavaKind.Float) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (count > 8) {
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -207,7 +207,6 @@ public class CheckGraalIntrinsics extends GraalTest {
|
|||||||
"oracle/jrockit/jfr/Timing.counterTime()J",
|
"oracle/jrockit/jfr/Timing.counterTime()J",
|
||||||
"oracle/jrockit/jfr/VMJFR.classID0(Ljava/lang/Class;)J",
|
"oracle/jrockit/jfr/VMJFR.classID0(Ljava/lang/Class;)J",
|
||||||
"oracle/jrockit/jfr/VMJFR.threadID()I",
|
"oracle/jrockit/jfr/VMJFR.threadID()I",
|
||||||
"sun/misc/Unsafe.copyMemory(Ljava/lang/Object;JLjava/lang/Object;JJ)V",
|
|
||||||
"sun/nio/cs/ISO_8859_1$Encoder.encodeISOArray([CI[BII)I",
|
"sun/nio/cs/ISO_8859_1$Encoder.encodeISOArray([CI[BII)I",
|
||||||
"sun/security/provider/DigestBase.implCompressMultiBlock([BII)I",
|
"sun/security/provider/DigestBase.implCompressMultiBlock([BII)I",
|
||||||
"sun/security/provider/SHA.implCompress([BI)V",
|
"sun/security/provider/SHA.implCompress([BI)V",
|
||||||
@ -273,7 +272,6 @@ public class CheckGraalIntrinsics extends GraalTest {
|
|||||||
"jdk/internal/misc/Unsafe.compareAndExchangeShortRelease(Ljava/lang/Object;JSS)S",
|
"jdk/internal/misc/Unsafe.compareAndExchangeShortRelease(Ljava/lang/Object;JSS)S",
|
||||||
"jdk/internal/misc/Unsafe.compareAndSetByte(Ljava/lang/Object;JBB)Z",
|
"jdk/internal/misc/Unsafe.compareAndSetByte(Ljava/lang/Object;JBB)Z",
|
||||||
"jdk/internal/misc/Unsafe.compareAndSetShort(Ljava/lang/Object;JSS)Z",
|
"jdk/internal/misc/Unsafe.compareAndSetShort(Ljava/lang/Object;JSS)Z",
|
||||||
"jdk/internal/misc/Unsafe.copyMemory0(Ljava/lang/Object;JLjava/lang/Object;JJ)V",
|
|
||||||
"jdk/internal/misc/Unsafe.getAndAddByte(Ljava/lang/Object;JB)B",
|
"jdk/internal/misc/Unsafe.getAndAddByte(Ljava/lang/Object;JB)B",
|
||||||
"jdk/internal/misc/Unsafe.getAndAddShort(Ljava/lang/Object;JS)S",
|
"jdk/internal/misc/Unsafe.getAndAddShort(Ljava/lang/Object;JS)S",
|
||||||
"jdk/internal/misc/Unsafe.getAndSetByte(Ljava/lang/Object;JB)B",
|
"jdk/internal/misc/Unsafe.getAndSetByte(Ljava/lang/Object;JB)B",
|
||||||
|
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, 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.graalvm.compiler.hotspot.test;
|
||||||
|
|
||||||
|
import org.graalvm.compiler.replacements.test.MethodSubstitutionTest;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import jdk.vm.ci.code.InstalledCode;
|
||||||
|
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||||
|
import sun.misc.Unsafe;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the VM independent intrinsification of {@link Unsafe} methods.
|
||||||
|
*/
|
||||||
|
public class HotSpotUnsafeSubstitutionTest extends MethodSubstitutionTest {
|
||||||
|
|
||||||
|
public void testSubstitution(String testMethodName, Class<?> holder, String methodName, Class<?>[] parameterTypes, Object receiver, Object[] args1, Object[] args2) {
|
||||||
|
ResolvedJavaMethod testMethod = getResolvedJavaMethod(testMethodName);
|
||||||
|
ResolvedJavaMethod originalMethod = getResolvedJavaMethod(holder, methodName, parameterTypes);
|
||||||
|
|
||||||
|
// Force compilation
|
||||||
|
InstalledCode code = getCode(testMethod);
|
||||||
|
assert code != null;
|
||||||
|
|
||||||
|
// Verify that the original method and the substitution produce the same value
|
||||||
|
Object expected = invokeSafe(originalMethod, receiver, args1);
|
||||||
|
Object actual = invokeSafe(testMethod, null, args2);
|
||||||
|
assertDeepEquals(expected, actual);
|
||||||
|
|
||||||
|
// Verify that the generated code and the original produce the same value
|
||||||
|
expected = invokeSafe(originalMethod, receiver, args1);
|
||||||
|
actual = executeVarargsSafe(code, args2);
|
||||||
|
assertDeepEquals(expected, actual);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnsafeSubstitutions() throws Exception {
|
||||||
|
testGraph("unsafeCopyMemory");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unsafeCopyMemory(Object srcBase, long srcOffset, Object dstBase, long dstOffset, long bytes) {
|
||||||
|
UNSAFE.copyMemory(srcBase, srcOffset, dstBase, dstOffset, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] testCopyMemorySnippet(long src, int bytes) {
|
||||||
|
byte[] result = new byte[bytes];
|
||||||
|
UNSAFE.copyMemory(null, src, result, Unsafe.ARRAY_BYTE_BASE_OFFSET, bytes);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCopyMemory() {
|
||||||
|
int size = 128;
|
||||||
|
long src = UNSAFE.allocateMemory(size);
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
UNSAFE.putByte(null, src + i, (byte) i);
|
||||||
|
}
|
||||||
|
test("testCopyMemorySnippet", src, size);
|
||||||
|
}
|
||||||
|
}
|
@ -64,9 +64,9 @@ import org.graalvm.compiler.options.OptionType;
|
|||||||
import org.graalvm.compiler.options.OptionValues;
|
import org.graalvm.compiler.options.OptionValues;
|
||||||
import org.graalvm.compiler.phases.tiers.SuitesProvider;
|
import org.graalvm.compiler.phases.tiers.SuitesProvider;
|
||||||
import org.graalvm.compiler.word.Word;
|
import org.graalvm.compiler.word.Word;
|
||||||
import org.graalvm.util.Equivalence;
|
|
||||||
import org.graalvm.util.EconomicMap;
|
import org.graalvm.util.EconomicMap;
|
||||||
import org.graalvm.util.EconomicSet;
|
import org.graalvm.util.EconomicSet;
|
||||||
|
import org.graalvm.util.Equivalence;
|
||||||
import org.graalvm.util.MapCursor;
|
import org.graalvm.util.MapCursor;
|
||||||
import org.graalvm.word.Pointer;
|
import org.graalvm.word.Pointer;
|
||||||
|
|
||||||
@ -257,6 +257,18 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen
|
|||||||
@NodeIntrinsic(ForeignCallNode.class)
|
@NodeIntrinsic(ForeignCallNode.class)
|
||||||
private static native void sha5ImplCompressStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state);
|
private static native void sha5ImplCompressStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.graalvm.compiler.hotspot.meta.HotSpotUnsafeSubstitutions#copyMemory
|
||||||
|
*/
|
||||||
|
public static final ForeignCallDescriptor UNSAFE_ARRAYCOPY = new ForeignCallDescriptor("unsafe_arraycopy", void.class, Word.class, Word.class, Word.class);
|
||||||
|
|
||||||
|
public static void unsafeArraycopy(Word srcAddr, Word dstAddr, Word size) {
|
||||||
|
unsafeArraycopyStub(HotSpotBackend.UNSAFE_ARRAYCOPY, srcAddr, dstAddr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NodeIntrinsic(ForeignCallNode.class)
|
||||||
|
private static native void unsafeArraycopyStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word srcAddr, Word dstAddr, Word size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see VMErrorNode
|
* @see VMErrorNode
|
||||||
*/
|
*/
|
||||||
|
@ -198,7 +198,7 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler {
|
|||||||
|
|
||||||
public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) {
|
public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) {
|
||||||
StructuredGraph graph = createGraph(method, entryBCI, useProfilingInfo, compilationId, options, debug);
|
StructuredGraph graph = createGraph(method, entryBCI, useProfilingInfo, compilationId, options, debug);
|
||||||
CompilationResult result = new CompilationResult();
|
CompilationResult result = new CompilationResult(compilationId);
|
||||||
return compileHelper(CompilationResultBuilderFactory.Default, result, graph, method, entryBCI, useProfilingInfo, options);
|
return compileHelper(CompilationResultBuilderFactory.Default, result, graph, method, entryBCI, useProfilingInfo, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +111,7 @@ import jdk.vm.ci.meta.JavaConstant;
|
|||||||
import jdk.vm.ci.meta.JavaKind;
|
import jdk.vm.ci.meta.JavaKind;
|
||||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||||
|
import sun.misc.Unsafe;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the {@link Plugins} used when running on HotSpot.
|
* Defines the {@link Plugins} used when running on HotSpot.
|
||||||
@ -202,6 +203,7 @@ public class HotSpotGraphBuilderPlugins {
|
|||||||
registerCRC32Plugins(invocationPlugins, config, replacementBytecodeProvider);
|
registerCRC32Plugins(invocationPlugins, config, replacementBytecodeProvider);
|
||||||
registerBigIntegerPlugins(invocationPlugins, config, replacementBytecodeProvider);
|
registerBigIntegerPlugins(invocationPlugins, config, replacementBytecodeProvider);
|
||||||
registerSHAPlugins(invocationPlugins, config, replacementBytecodeProvider);
|
registerSHAPlugins(invocationPlugins, config, replacementBytecodeProvider);
|
||||||
|
registerUnsafePlugins(invocationPlugins, replacementBytecodeProvider);
|
||||||
StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, snippetReflection, invocationPlugins, replacementBytecodeProvider, true);
|
StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, snippetReflection, invocationPlugins, replacementBytecodeProvider, true);
|
||||||
|
|
||||||
for (NodeIntrinsicPluginFactory factory : GraalServices.load(NodeIntrinsicPluginFactory.class)) {
|
for (NodeIntrinsicPluginFactory factory : GraalServices.load(NodeIntrinsicPluginFactory.class)) {
|
||||||
@ -313,6 +315,17 @@ public class HotSpotGraphBuilderPlugins {
|
|||||||
r.registerMethodSubstitution(ReflectionSubstitutions.class, "getClassAccessFlags", Class.class);
|
r.registerMethodSubstitution(ReflectionSubstitutions.class, "getClassAccessFlags", Class.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void registerUnsafePlugins(InvocationPlugins plugins, BytecodeProvider replacementBytecodeProvider) {
|
||||||
|
Registration r;
|
||||||
|
if (Java8OrEarlier) {
|
||||||
|
r = new Registration(plugins, Unsafe.class, replacementBytecodeProvider);
|
||||||
|
} else {
|
||||||
|
r = new Registration(plugins, "jdk.internal.misc.Unsafe", replacementBytecodeProvider);
|
||||||
|
}
|
||||||
|
r.registerMethodSubstitution(HotSpotUnsafeSubstitutions.class, HotSpotUnsafeSubstitutions.copyMemoryName, "copyMemory", Receiver.class, Object.class, long.class, Object.class, long.class,
|
||||||
|
long.class);
|
||||||
|
}
|
||||||
|
|
||||||
private static final LocationIdentity INSTANCE_KLASS_CONSTANTS = NamedLocationIdentity.immutable("InstanceKlass::_constants");
|
private static final LocationIdentity INSTANCE_KLASS_CONSTANTS = NamedLocationIdentity.immutable("InstanceKlass::_constants");
|
||||||
private static final LocationIdentity CONSTANT_POOL_LENGTH = NamedLocationIdentity.immutable("ConstantPool::_length");
|
private static final LocationIdentity CONSTANT_POOL_LENGTH = NamedLocationIdentity.immutable("ConstantPool::_length");
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA2_IMPL_COMPRESS;
|
|||||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA5_IMPL_COMPRESS;
|
import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA5_IMPL_COMPRESS;
|
||||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA_IMPL_COMPRESS;
|
import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA_IMPL_COMPRESS;
|
||||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.SQUARE_TO_LEN;
|
import static org.graalvm.compiler.hotspot.HotSpotBackend.SQUARE_TO_LEN;
|
||||||
|
import static org.graalvm.compiler.hotspot.HotSpotBackend.UNSAFE_ARRAYCOPY;
|
||||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER;
|
import static org.graalvm.compiler.hotspot.HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER;
|
||||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.VM_ERROR;
|
import static org.graalvm.compiler.hotspot.HotSpotBackend.VM_ERROR;
|
||||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.WRONG_METHOD_HANDLER;
|
import static org.graalvm.compiler.hotspot.HotSpotBackend.WRONG_METHOD_HANDLER;
|
||||||
@ -330,6 +331,8 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall
|
|||||||
registerCheckcastArraycopyDescriptor(true, c.checkcastArraycopyUninit);
|
registerCheckcastArraycopyDescriptor(true, c.checkcastArraycopyUninit);
|
||||||
registerCheckcastArraycopyDescriptor(false, c.checkcastArraycopy);
|
registerCheckcastArraycopyDescriptor(false, c.checkcastArraycopy);
|
||||||
|
|
||||||
|
registerForeignCall(UNSAFE_ARRAYCOPY, c.unsafeArraycopy, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.any());
|
||||||
|
|
||||||
if (c.useMultiplyToLenIntrinsic()) {
|
if (c.useMultiplyToLenIntrinsic()) {
|
||||||
registerForeignCall(MULTIPLY_TO_LEN, c.multiplyToLen, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Int));
|
registerForeignCall(MULTIPLY_TO_LEN, c.multiplyToLen, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Int));
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, 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.graalvm.compiler.hotspot.meta;
|
||||||
|
|
||||||
|
import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
|
||||||
|
|
||||||
|
import org.graalvm.compiler.api.replacements.ClassSubstitution;
|
||||||
|
import org.graalvm.compiler.api.replacements.MethodSubstitution;
|
||||||
|
import org.graalvm.compiler.hotspot.HotSpotBackend;
|
||||||
|
import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode;
|
||||||
|
import org.graalvm.compiler.word.Word;
|
||||||
|
import org.graalvm.word.WordFactory;
|
||||||
|
|
||||||
|
@ClassSubstitution(className = {"jdk.internal.misc.Unsafe", "sun.misc.Unsafe"})
|
||||||
|
public class HotSpotUnsafeSubstitutions {
|
||||||
|
|
||||||
|
public static final String copyMemoryName = Java8OrEarlier ? "copyMemory" : "copyMemory0";
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
@MethodSubstitution(isStatic = false)
|
||||||
|
static void copyMemory(Object receiver, Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes) {
|
||||||
|
Word srcAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(srcBase, srcOffset));
|
||||||
|
Word dstAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(destBase, destOffset));
|
||||||
|
Word size = Word.signed(bytes);
|
||||||
|
HotSpotBackend.unsafeArraycopy(srcAddr, dstAddr, size);
|
||||||
|
}
|
||||||
|
}
|
@ -216,8 +216,9 @@ public abstract class Stub {
|
|||||||
|
|
||||||
@SuppressWarnings("try")
|
@SuppressWarnings("try")
|
||||||
private CompilationResult buildCompilationResult(DebugContext debug, final Backend backend) {
|
private CompilationResult buildCompilationResult(DebugContext debug, final Backend backend) {
|
||||||
CompilationResult compResult = new CompilationResult(toString(), GeneratePIC.getValue(options));
|
CompilationIdentifier compilationId = getStubCompilationId();
|
||||||
final StructuredGraph graph = getGraph(debug, getStubCompilationId());
|
final StructuredGraph graph = getGraph(debug, compilationId);
|
||||||
|
CompilationResult compResult = new CompilationResult(compilationId, toString(), GeneratePIC.getValue(options));
|
||||||
|
|
||||||
// Stubs cannot be recompiled so they cannot be compiled with assumptions
|
// Stubs cannot be recompiled so they cannot be compiled with assumptions
|
||||||
assert graph.getAssumptions() == null;
|
assert graph.getAssumptions() == null;
|
||||||
|
@ -365,10 +365,6 @@ final class TraceInterval extends IntervalHint {
|
|||||||
return intTo;
|
return intTo;
|
||||||
}
|
}
|
||||||
|
|
||||||
int numUsePositions() {
|
|
||||||
return numUsePos();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLocationHint(IntervalHint interval) {
|
public void setLocationHint(IntervalHint interval) {
|
||||||
locationHint = interval;
|
locationHint = interval;
|
||||||
}
|
}
|
||||||
@ -452,6 +448,10 @@ final class TraceInterval extends IntervalHint {
|
|||||||
return spillSt == SpillState.StartInMemory || (spillSt == SpillState.SpillStore && opId > spillDefinitionPos() && !canMaterialize());
|
return spillSt == SpillState.StartInMemory || (spillSt == SpillState.SpillStore && opId > spillDefinitionPos() && !canMaterialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean preSpilledAllocated() {
|
||||||
|
return spillState() == SpillState.StartInMemory && numUsePos() == 0 && !hasHint();
|
||||||
|
}
|
||||||
|
|
||||||
// test intersection
|
// test intersection
|
||||||
boolean intersects(TraceInterval i) {
|
boolean intersects(TraceInterval i) {
|
||||||
return intersectsAt(i) != -1;
|
return intersectsAt(i) != -1;
|
||||||
|
@ -541,16 +541,23 @@ public final class TraceLinearScanLifetimeAnalysisPhase extends TraceLinearScanA
|
|||||||
assert instructionIndex == 0 : "not at start?" + instructionIndex;
|
assert instructionIndex == 0 : "not at start?" + instructionIndex;
|
||||||
handleTraceBegin(blocks[0]);
|
handleTraceBegin(blocks[0]);
|
||||||
|
|
||||||
// fix spill state for phi/incoming intervals
|
|
||||||
for (TraceInterval interval : allocator.intervals()) {
|
|
||||||
if (interval != null && interval.spillState().equals(SpillState.NoDefinitionFound) && interval.spillDefinitionPos() != -1) {
|
|
||||||
// there was a definition in a phi/incoming
|
|
||||||
interval.setSpillState(SpillState.NoSpillStore);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (TraceRAuseInterTraceHints.getValue(allocator.getLIR().getOptions())) {
|
if (TraceRAuseInterTraceHints.getValue(allocator.getLIR().getOptions())) {
|
||||||
addInterTraceHints();
|
addInterTraceHints();
|
||||||
}
|
}
|
||||||
|
// fix spill state for phi/incoming intervals
|
||||||
|
for (TraceInterval interval : allocator.intervals()) {
|
||||||
|
if (interval != null) {
|
||||||
|
if (interval.spillState().equals(SpillState.NoDefinitionFound) && interval.spillDefinitionPos() != -1) {
|
||||||
|
// there was a definition in a phi/incoming
|
||||||
|
interval.setSpillState(SpillState.NoSpillStore);
|
||||||
|
}
|
||||||
|
if (interval.preSpilledAllocated()) {
|
||||||
|
// pre-spill unused, start in memory intervals
|
||||||
|
allocator.assignSpillSlot(interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (FixedInterval interval1 : allocator.fixedIntervals()) {
|
for (FixedInterval interval1 : allocator.fixedIntervals()) {
|
||||||
if (interval1 != null) {
|
if (interval1 != null) {
|
||||||
/* We use [-1, 0] to avoid intersection with incoming values. */
|
/* We use [-1, 0] to avoid intersection with incoming values. */
|
||||||
|
@ -153,7 +153,7 @@ public final class TraceLinearScanPhase extends TraceAllocationPhase<TraceAlloca
|
|||||||
@Override
|
@Override
|
||||||
public boolean apply(TraceInterval i) {
|
public boolean apply(TraceInterval i) {
|
||||||
// all TraceIntervals are variable intervals
|
// all TraceIntervals are variable intervals
|
||||||
return true;
|
return !i.preSpilledAllocated();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private static final Comparator<TraceInterval> SORT_BY_FROM_COMP = new Comparator<TraceInterval>() {
|
private static final Comparator<TraceInterval> SORT_BY_FROM_COMP = new Comparator<TraceInterval>() {
|
||||||
|
@ -319,7 +319,7 @@ public abstract class GraalCompilerState {
|
|||||||
assert !graph.isFrozen();
|
assert !graph.isFrozen();
|
||||||
ResolvedJavaMethod installedCodeOwner = graph.method();
|
ResolvedJavaMethod installedCodeOwner = graph.method();
|
||||||
request = new Request<>(graph, installedCodeOwner, getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL,
|
request = new Request<>(graph, installedCodeOwner, getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL,
|
||||||
graph.getProfilingInfo(), createSuites(getOptions()), createLIRSuites(getOptions()), new CompilationResult(), CompilationResultBuilderFactory.Default);
|
graph.getProfilingInfo(), createSuites(getOptions()), createLIRSuites(getOptions()), new CompilationResult(graph.compilationId()), CompilationResultBuilderFactory.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -209,7 +209,6 @@ public class GraphEncoder {
|
|||||||
int nodeCount = nodeOrder.nextOrderId;
|
int nodeCount = nodeOrder.nextOrderId;
|
||||||
assert nodeOrder.orderIds.get(graph.start()) == START_NODE_ORDER_ID;
|
assert nodeOrder.orderIds.get(graph.start()) == START_NODE_ORDER_ID;
|
||||||
assert nodeOrder.orderIds.get(graph.start().next()) == FIRST_NODE_ORDER_ID;
|
assert nodeOrder.orderIds.get(graph.start().next()) == FIRST_NODE_ORDER_ID;
|
||||||
assert nodeCount == graph.getNodeCount() + 1;
|
|
||||||
|
|
||||||
long[] nodeStartOffsets = new long[nodeCount];
|
long[] nodeStartOffsets = new long[nodeCount];
|
||||||
UnmodifiableMapCursor<Node, Integer> cursor = nodeOrder.orderIds.getEntries();
|
UnmodifiableMapCursor<Node, Integer> cursor = nodeOrder.orderIds.getEntries();
|
||||||
@ -218,6 +217,7 @@ public class GraphEncoder {
|
|||||||
Integer orderId = cursor.getValue();
|
Integer orderId = cursor.getValue();
|
||||||
|
|
||||||
assert !(node instanceof AbstractBeginNode) || nodeOrder.orderIds.get(((AbstractBeginNode) node).next()) == orderId + BEGIN_NEXT_ORDER_ID_OFFSET;
|
assert !(node instanceof AbstractBeginNode) || nodeOrder.orderIds.get(((AbstractBeginNode) node).next()) == orderId + BEGIN_NEXT_ORDER_ID_OFFSET;
|
||||||
|
assert nodeStartOffsets[orderId] == 0;
|
||||||
nodeStartOffsets[orderId] = writer.getBytesWritten();
|
nodeStartOffsets[orderId] = writer.getBytesWritten();
|
||||||
|
|
||||||
/* Write out the type, properties, and edges. */
|
/* Write out the type, properties, and edges. */
|
||||||
@ -284,7 +284,6 @@ public class GraphEncoder {
|
|||||||
writer.putUV(nodeOrder.maxFixedNodeOrderId);
|
writer.putUV(nodeOrder.maxFixedNodeOrderId);
|
||||||
writer.putUV(nodeCount);
|
writer.putUV(nodeCount);
|
||||||
for (int i = 0; i < nodeCount; i++) {
|
for (int i = 0; i < nodeCount; i++) {
|
||||||
assert i == NULL_ORDER_ID || i == START_NODE_ORDER_ID || nodeStartOffsets[i] > 0;
|
|
||||||
writer.putUV(metadataStart - nodeStartOffsets[i]);
|
writer.putUV(metadataStart - nodeStartOffsets[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,8 +343,25 @@ public class GraphEncoder {
|
|||||||
} while (current != null);
|
} while (current != null);
|
||||||
|
|
||||||
maxFixedNodeOrderId = nextOrderId - 1;
|
maxFixedNodeOrderId = nextOrderId - 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emit all parameters consecutively at a known location (after all fixed nodes). This
|
||||||
|
* allows substituting parameters when inlining during decoding by pre-initializing the
|
||||||
|
* decoded node list.
|
||||||
|
*
|
||||||
|
* Note that not all parameters must be present (unused parameters are deleted after
|
||||||
|
* parsing). This leads to holes in the orderId, i.e., unused orderIds.
|
||||||
|
*/
|
||||||
|
int parameterCount = graph.method().getSignature().getParameterCount(!graph.method().isStatic());
|
||||||
|
for (ParameterNode node : graph.getNodes(ParameterNode.TYPE)) {
|
||||||
|
assert orderIds.get(node) == null : "Parameter node must not be ordered yet";
|
||||||
|
assert node.index() < parameterCount : "Parameter index out of range";
|
||||||
|
orderIds.set(node, nextOrderId + node.index());
|
||||||
|
}
|
||||||
|
nextOrderId += parameterCount;
|
||||||
|
|
||||||
for (Node node : graph.getNodes()) {
|
for (Node node : graph.getNodes()) {
|
||||||
assert (node instanceof FixedNode) == (orderIds.get(node) != null) : "all fixed nodes must be ordered: " + node;
|
assert (node instanceof FixedNode || node instanceof ParameterNode) == (orderIds.get(node) != null) : "all fixed nodes and ParameterNodes must be ordered: " + node;
|
||||||
add(node);
|
add(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ import java.util.List;
|
|||||||
import org.graalvm.compiler.bytecode.BytecodeDisassembler;
|
import org.graalvm.compiler.bytecode.BytecodeDisassembler;
|
||||||
import org.graalvm.compiler.code.CompilationResult;
|
import org.graalvm.compiler.code.CompilationResult;
|
||||||
import org.graalvm.compiler.code.DisassemblerProvider;
|
import org.graalvm.compiler.code.DisassemblerProvider;
|
||||||
|
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||||
import org.graalvm.compiler.core.common.alloc.Trace;
|
import org.graalvm.compiler.core.common.alloc.Trace;
|
||||||
import org.graalvm.compiler.core.common.alloc.TraceBuilderResult;
|
import org.graalvm.compiler.core.common.alloc.TraceBuilderResult;
|
||||||
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
|
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
|
||||||
@ -72,6 +73,7 @@ public class CFGPrinterObserver implements DebugDumpHandler {
|
|||||||
private CFGPrinter cfgPrinter;
|
private CFGPrinter cfgPrinter;
|
||||||
private File cfgFile;
|
private File cfgFile;
|
||||||
private JavaMethod curMethod;
|
private JavaMethod curMethod;
|
||||||
|
private CompilationIdentifier curCompilation;
|
||||||
private List<String> curDecorators = Collections.emptyList();
|
private List<String> curDecorators = Collections.emptyList();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -92,6 +94,7 @@ public class CFGPrinterObserver implements DebugDumpHandler {
|
|||||||
*/
|
*/
|
||||||
private boolean checkMethodScope(DebugContext debug) {
|
private boolean checkMethodScope(DebugContext debug) {
|
||||||
JavaMethod method = null;
|
JavaMethod method = null;
|
||||||
|
CompilationIdentifier compilation = null;
|
||||||
ArrayList<String> decorators = new ArrayList<>();
|
ArrayList<String> decorators = new ArrayList<>();
|
||||||
for (Object o : debug.context()) {
|
for (Object o : debug.context()) {
|
||||||
if (o instanceof JavaMethod) {
|
if (o instanceof JavaMethod) {
|
||||||
@ -102,22 +105,33 @@ public class CFGPrinterObserver implements DebugDumpHandler {
|
|||||||
if (graph.method() != null) {
|
if (graph.method() != null) {
|
||||||
method = graph.method();
|
method = graph.method();
|
||||||
decorators.clear();
|
decorators.clear();
|
||||||
|
compilation = graph.compilationId();
|
||||||
}
|
}
|
||||||
} else if (o instanceof DebugDumpScope) {
|
} else if (o instanceof DebugDumpScope) {
|
||||||
DebugDumpScope debugDumpScope = (DebugDumpScope) o;
|
DebugDumpScope debugDumpScope = (DebugDumpScope) o;
|
||||||
if (debugDumpScope.decorator) {
|
if (debugDumpScope.decorator) {
|
||||||
decorators.add(debugDumpScope.name);
|
decorators.add(debugDumpScope.name);
|
||||||
}
|
}
|
||||||
|
} else if (o instanceof CompilationResult) {
|
||||||
|
CompilationResult compilationResult = (CompilationResult) o;
|
||||||
|
compilation = compilationResult.getCompilationId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method == null) {
|
if (method == null && compilation == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!method.equals(curMethod) || !curDecorators.equals(decorators)) {
|
if (compilation != null) {
|
||||||
cfgPrinter.printCompilation(method);
|
if (!compilation.equals(curCompilation) || !curDecorators.equals(decorators)) {
|
||||||
|
cfgPrinter.printCompilation(compilation);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!method.equals(curMethod) || !curDecorators.equals(decorators)) {
|
||||||
|
cfgPrinter.printCompilation(method);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
curCompilation = compilation;
|
||||||
curMethod = method;
|
curMethod = method;
|
||||||
curDecorators = decorators;
|
curDecorators = decorators;
|
||||||
return true;
|
return true;
|
||||||
@ -277,6 +291,7 @@ public class CFGPrinterObserver implements DebugDumpHandler {
|
|||||||
cfgPrinter = null;
|
cfgPrinter = null;
|
||||||
curDecorators = Collections.emptyList();
|
curDecorators = Collections.emptyList();
|
||||||
curMethod = null;
|
curMethod = null;
|
||||||
|
curCompilation = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||||
import org.graalvm.compiler.debug.LogStream;
|
import org.graalvm.compiler.debug.LogStream;
|
||||||
import org.graalvm.compiler.debug.TTY;
|
import org.graalvm.compiler.debug.TTY;
|
||||||
import org.graalvm.compiler.lir.util.IndexedValueMap;
|
import org.graalvm.compiler.lir.util.IndexedValueMap;
|
||||||
@ -115,12 +116,25 @@ public class CompilationPrinter implements Closeable {
|
|||||||
/**
|
/**
|
||||||
* Prints a compilation timestamp for a given method.
|
* Prints a compilation timestamp for a given method.
|
||||||
*
|
*
|
||||||
* @param method the method for which a timestamp will be printed
|
* @param javaMethod the method for which a timestamp will be printed
|
||||||
*/
|
*/
|
||||||
public void printCompilation(JavaMethod method) {
|
public void printCompilation(JavaMethod javaMethod) {
|
||||||
|
printCompilation(javaMethod.format("%H::%n"), javaMethod.format("%f %r %H.%n(%p)"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints a compilation id.
|
||||||
|
*
|
||||||
|
* @param compilationId the compilation method for which an id will be printed
|
||||||
|
*/
|
||||||
|
public void printCompilation(CompilationIdentifier compilationId) {
|
||||||
|
printCompilation(compilationId.toString(CompilationIdentifier.Verbosity.DETAILED), compilationId.toString(CompilationIdentifier.Verbosity.DETAILED));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printCompilation(final String name, String method) {
|
||||||
begin("compilation");
|
begin("compilation");
|
||||||
out.print("name \" ").print(method.format("%H::%n")).println('"');
|
out.print("name \" ").print(name).println('"');
|
||||||
out.print("method \"").print(method.format("%f %r %H.%n(%p)")).println('"');
|
out.print("method \"").print(method).println('"');
|
||||||
out.print("date ").println(System.currentTimeMillis());
|
out.print("date ").println(System.currentTimeMillis());
|
||||||
end("compilation");
|
end("compilation");
|
||||||
}
|
}
|
||||||
|
@ -95,10 +95,13 @@ public final class ClassSubstitutionVerifier extends AbstractVerifier {
|
|||||||
TypeElement typeElement = null;
|
TypeElement typeElement = null;
|
||||||
for (String className : classNames) {
|
for (String className : classNames) {
|
||||||
typeElement = env.getElementUtils().getTypeElement(className);
|
typeElement = env.getElementUtils().getTypeElement(className);
|
||||||
if (typeElement == null && !optional) {
|
if (typeElement != null) {
|
||||||
env.getMessager().printMessage(Kind.ERROR, String.format("The class '%s' was not found on the classpath.", stringValue), sourceElement, classSubstition, stringValue);
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (typeElement == null && !optional) {
|
||||||
|
env.getMessager().printMessage(Kind.ERROR, String.format("The class '%s' was not found on the classpath.", stringValue), sourceElement, classSubstition, stringValue);
|
||||||
|
}
|
||||||
|
|
||||||
return typeElement;
|
return typeElement;
|
||||||
}
|
}
|
||||||
|
@ -707,10 +707,22 @@ public abstract class PEGraphDecoder extends SimplifyingGraphDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoopScope inlineLoopScope = createInitialLoopScope(inlineScope, predecessor);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The GraphEncoder assigns parameters a nodeId immediately after the fixed nodes.
|
||||||
|
* Initializing createdNodes here avoid decoding and immediately replacing the
|
||||||
|
* ParameterNodes.
|
||||||
|
*/
|
||||||
|
int firstArgumentNodeId = inlineScope.maxFixedNodeOrderId + 1;
|
||||||
|
for (int i = 0; i < arguments.length; i++) {
|
||||||
|
inlineLoopScope.createdNodes[firstArgumentNodeId + i] = arguments[i];
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do the actual inlining by returning the initial loop scope for the inlined method scope.
|
* Do the actual inlining by returning the initial loop scope for the inlined method scope.
|
||||||
*/
|
*/
|
||||||
return createInitialLoopScope(inlineScope, predecessor);
|
return inlineLoopScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1028,9 +1040,7 @@ public abstract class PEGraphDecoder extends SimplifyingGraphDecoder {
|
|||||||
if (node instanceof ParameterNode) {
|
if (node instanceof ParameterNode) {
|
||||||
ParameterNode param = (ParameterNode) node;
|
ParameterNode param = (ParameterNode) node;
|
||||||
if (methodScope.isInlinedMethod()) {
|
if (methodScope.isInlinedMethod()) {
|
||||||
Node result = methodScope.arguments[param.index()];
|
throw GraalError.shouldNotReachHere("Parameter nodes are already registered when the inlined scope is created");
|
||||||
assert result != null;
|
|
||||||
return result;
|
|
||||||
|
|
||||||
} else if (parameterPlugin != null) {
|
} else if (parameterPlugin != null) {
|
||||||
assert !methodScope.isInlinedMethod();
|
assert !methodScope.isInlinedMethod();
|
||||||
|
@ -478,6 +478,8 @@ void AOTCodeHeap::link_stub_routines_symbols() {
|
|||||||
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_arrayof_oop_disjoint_arraycopy", address, StubRoutines::_arrayof_oop_disjoint_arraycopy);
|
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_arrayof_oop_disjoint_arraycopy", address, StubRoutines::_arrayof_oop_disjoint_arraycopy);
|
||||||
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_arrayof_oop_disjoint_arraycopy_uninit", address, StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit);
|
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_arrayof_oop_disjoint_arraycopy_uninit", address, StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit);
|
||||||
|
|
||||||
|
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_unsafe_arraycopy", address, StubRoutines::_unsafe_arraycopy);
|
||||||
|
|
||||||
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_checkcast_arraycopy", address, StubRoutines::_checkcast_arraycopy);
|
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_checkcast_arraycopy", address, StubRoutines::_checkcast_arraycopy);
|
||||||
|
|
||||||
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_aescrypt_encryptBlock", address, StubRoutines::_aescrypt_encryptBlock);
|
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_aescrypt_encryptBlock", address, StubRoutines::_aescrypt_encryptBlock);
|
||||||
|
Loading…
Reference in New Issue
Block a user