Skip to content

Commit f4a4dcf

Browse files
committed
[GR-67668] Implement PINNED_TO_INITIAL_LAYER and improve CompilationBehavior
PullRequest: graal/21652
2 parents 3560a55 + d8ace80 commit f4a4dcf

File tree

5 files changed

+119
-56
lines changed

5 files changed

+119
-56
lines changed

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/HostVM.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,10 @@ public boolean buildingImageLayer() {
438438
return false;
439439
}
440440

441+
public boolean buildingInitialLayer() {
442+
return false;
443+
}
444+
441445
public boolean buildingSharedLayer() {
442446
return false;
443447
}

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -313,10 +313,21 @@ protected AnalysisMethod(AnalysisMethod original, MultiMethodKey multiMethodKey)
313313
this.enableReachableInCurrentLayer = original.enableReachableInCurrentLayer;
314314
}
315315

316+
/**
317+
* This method should not be used directly, except to set the {@link CompilationBehavior} from a
318+
* previous layer. To set a new {@link CompilationBehavior}, please use the associated setter.
319+
*/
316320
public void setCompilationBehavior(CompilationBehavior compilationBehavior) {
321+
assert getUniverse().getBigbang().getHostVM().buildingImageLayer() : "The method compilation behavior can only be set in layered images";
317322
this.compilationBehavior = compilationBehavior;
318323
}
319324

325+
private void setNewCompilationBehavior(CompilationBehavior compilationBehavior) {
326+
assert (!isInBaseLayer && this.compilationBehavior == CompilationBehavior.DEFAULT) || this.compilationBehavior == compilationBehavior : "The method was already assigned " +
327+
this.compilationBehavior + ", but trying to assign " + compilationBehavior;
328+
setCompilationBehavior(compilationBehavior);
329+
}
330+
320331
public CompilationBehavior getCompilationBehavior() {
321332
return compilationBehavior;
322333
}
@@ -327,11 +338,11 @@ public CompilationBehavior getCompilationBehavior() {
327338
*/
328339
public void setFullyDelayedToApplicationLayer() {
329340
HostVM hostVM = getUniverse().getBigbang().getHostVM();
330-
AnalysisError.guarantee(hostVM.buildingImageLayer(), "Methods can only be delayed in layered images");
341+
AnalysisError.guarantee(hostVM.buildingImageLayer(), "Methods can only be delayed in layered images: %s", this);
331342
AnalysisError.guarantee(parsedGraphCacheState.get() == GraphCacheEntry.UNPARSED, "The method %s was marked as delayed to the application layer but was already parsed", this);
332343
AnalysisError.guarantee(!hostVM.hasAlwaysInlineDirective(this), "Method %s with an always inline directive cannot be delayed to the application layer as such methods cannot be inlined", this);
333344
AnalysisError.guarantee(isConcrete(), "Method %s is not concrete and cannot be delayed to the application layer", this);
334-
this.compilationBehavior = CompilationBehavior.FULLY_DELAYED_TO_APPLICATION_LAYER;
345+
setNewCompilationBehavior(CompilationBehavior.FULLY_DELAYED_TO_APPLICATION_LAYER);
335346
}
336347

337348
/**
@@ -342,6 +353,22 @@ public boolean isDelayed() {
342353
return compilationBehavior == CompilationBehavior.FULLY_DELAYED_TO_APPLICATION_LAYER && buildingSharedLayer;
343354
}
344355

356+
public void setPinnedToInitialLayer() {
357+
BigBang bigbang = getUniverse().getBigbang();
358+
AnalysisError.guarantee(bigbang.getHostVM().buildingInitialLayer(), "Methods can only be pinned to the initial layer: %s", this);
359+
boolean nonAbstractInstanceClass = !declaringClass.isArray() && declaringClass.isInstanceClass() && !declaringClass.isAbstract();
360+
AnalysisError.guarantee(nonAbstractInstanceClass, "Only methods from non abstract instance class can be delayed: %s", this);
361+
bigbang.forcedAddRootMethod(this, true, "Method is pinned to the initial layer");
362+
if (!isStatic()) {
363+
declaringClass.registerAsInstantiated(this + " is pinned to the initial layer");
364+
}
365+
setNewCompilationBehavior(CompilationBehavior.PINNED_TO_INITIAL_LAYER);
366+
}
367+
368+
public boolean isPinnedToInitialLayer() {
369+
return compilationBehavior == CompilationBehavior.PINNED_TO_INITIAL_LAYER;
370+
}
371+
345372
private static String createName(ResolvedJavaMethod wrapped, MultiMethodKey multiMethodKey) {
346373
String aName = wrapped.getName();
347374
if (multiMethodKey != ORIGINAL_METHOD) {
@@ -1429,9 +1456,9 @@ public enum CompilationBehavior {
14291456
DEFAULT,
14301457

14311458
/**
1432-
* Method is pinned to a specific shared layer, meaning it has to be analyzed and compiled
1433-
* in this specific layer. A method can only be pinned to a shared layer.
1459+
* Method is pinned to the initial layer, meaning it has to be analyzed and compiled in this
1460+
* specific layer.
14341461
*/
1435-
PINNED_TO_SHARED_LAYER,
1462+
PINNED_TO_INITIAL_LAYER,
14361463
}
14371464
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ public enum UsageKind {
215215

216216
private final int layerId;
217217
private final boolean buildingImageLayer = ImageLayerBuildingSupport.buildingImageLayer();
218+
private final boolean buildingInitialLayer = ImageLayerBuildingSupport.buildingInitialLayer();
218219
private final boolean buildingSharedLayer = ImageLayerBuildingSupport.buildingSharedLayer();
219220
private final boolean buildingExtensionLayer = ImageLayerBuildingSupport.buildingExtensionLayer();
220221

@@ -284,6 +285,11 @@ public boolean buildingImageLayer() {
284285
return buildingImageLayer;
285286
}
286287

288+
@Override
289+
public boolean buildingInitialLayer() {
290+
return buildingInitialLayer;
291+
}
292+
287293
@Override
288294
public boolean buildingSharedLayer() {
289295
return buildingSharedLayer;
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.hosted.imagelayer;
26+
27+
import com.oracle.graal.pointsto.BigBang;
28+
import com.oracle.graal.pointsto.meta.AnalysisMethod;
29+
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
30+
import com.oracle.svm.core.feature.InternalFeature;
31+
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
32+
import com.oracle.svm.core.util.VMError;
33+
import com.oracle.svm.hosted.FeatureImpl;
34+
import com.oracle.svm.hosted.meta.HostedMethod;
35+
36+
@AutomaticallyRegisteredFeature
37+
public class LayerCompilationBehaviorFeature implements InternalFeature {
38+
@Override
39+
public boolean isInConfiguration(IsInConfigurationAccess access) {
40+
return ImageLayerBuildingSupport.buildingImageLayer();
41+
}
42+
43+
@Override
44+
public void beforeAnalysis(BeforeAnalysisAccess a) {
45+
if (ImageLayerBuildingSupport.buildingApplicationLayer()) {
46+
/*
47+
* Methods fully delayed to the application layer that are referenced in a shared layer
48+
* need to be marked as root and compiled in the application layer to avoid any
49+
* undefined reference.
50+
*/
51+
SVMImageLayerLoader loader = HostedImageLayerBuildingSupport.singleton().getLoader();
52+
FeatureImpl.BeforeAnalysisAccessImpl access = (FeatureImpl.BeforeAnalysisAccessImpl) a;
53+
BigBang bigbang = access.getUniverse().getBigbang();
54+
for (int methodId : HostedDynamicLayerInfo.singleton().getPreviousLayerDelayedMethodIds()) {
55+
AnalysisMethod method = loader.getAnalysisMethodForBaseLayerId(methodId);
56+
bigbang.forcedAddRootMethod(method, method.isConstructor(), "Fully delayed to application layer");
57+
}
58+
}
59+
}
60+
61+
@Override
62+
public void afterHeapLayout(AfterHeapLayoutAccess a) {
63+
boolean buildingInitialLayer = ImageLayerBuildingSupport.buildingInitialLayer();
64+
/* Methods pinned to a shared layer need to be compiled in the corresponding layer. */
65+
FeatureImpl.AfterHeapLayoutAccessImpl access = (FeatureImpl.AfterHeapLayoutAccessImpl) a;
66+
for (HostedMethod method : access.getHeap().hUniverse.getMethods()) {
67+
if (method.wrapped.isPinnedToInitialLayer()) {
68+
String msg = "The method %s was pinned to the initial layer but was not compiled in the initial layer";
69+
if (buildingInitialLayer) {
70+
VMError.guarantee(method.isCompiled(), msg, method);
71+
} else {
72+
VMError.guarantee(method.isCompiledInPriorLayer(), msg, method);
73+
}
74+
}
75+
}
76+
}
77+
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayerDelayedMethodFeature.java

Lines changed: 0 additions & 51 deletions
This file was deleted.

0 commit comments

Comments
 (0)