4242 * Aggregates metadata derived from a {@code BytecodeInterpreterHandlerConfig} annotation which is
4343 * resolved against a concrete bytecode handler signature. The resulting model describes the stub
4444 * ABI: argument expansion, non-null guarantees, {@code returnValue}/copy-from-return slots, mutable
45- * expanded fields, scratch fields, and the maximum opcode for which a handler exists.
45+ * expanded fields and the maximum opcode for which a handler exists.
4646 */
4747public final class BytecodeHandlerConfig {
4848
@@ -184,11 +184,11 @@ private static int appendReceiver(List<ArgumentInfo> arguments, AnnotationValue
184184
185185 switch (expansionKind ) {
186186 case NONE -> {
187- arguments .add (new ArgumentInfo (declaringClass , nextIndex ++, originalIndex , false , false , false , null , null , false , true , nonNull , false , 0 ));
187+ arguments .add (new ArgumentInfo (declaringClass , nextIndex ++, originalIndex , false , false , false , null , null , false , true , nonNull , 0 ));
188188 }
189189 case VIRTUAL -> throw GraalError .shouldNotReachHere ("Receiver cannot be VIRTUAL" );
190190 case MATERIALIZED -> {
191- arguments .add (new ArgumentInfo (declaringClass , nextIndex ++, originalIndex , false , true , false , null , null , false , true , nonNull , false , 0 ));
191+ arguments .add (new ArgumentInfo (declaringClass , nextIndex ++, originalIndex , false , true , false , null , null , false , true , nonNull , 0 ));
192192 nextIndex = appendMaterializedFields (arguments , receiverConfig , declaringClass , declaringClass , originalIndex , nextIndex , templateModeEnabled );
193193 }
194194 default -> throw GraalError .shouldNotReachHere ("Unknown expansion kind " + expansionKind );
@@ -205,30 +205,28 @@ private static int appendParameter(List<ArgumentInfo> arguments, AnnotationValue
205205
206206 switch (expansionKind ) {
207207 case NONE -> {
208- arguments .add (new ArgumentInfo (parameterType , nextIndex ++, originalIndex , copyFromReturn , false , false , null , null , false , !copyFromReturn , nonNull , false , 0 ));
208+ arguments .add (new ArgumentInfo (parameterType , nextIndex ++, originalIndex , copyFromReturn , false , false , null , null , false , !copyFromReturn , nonNull , 0 ));
209209 }
210210 case VIRTUAL -> {
211211 List <AnnotationValue > fields = parameterConfig .getList ("fields" , AnnotationValue .class );
212212 for (ResolvedJavaField javaField : parameterType .getInstanceFields (true )) {
213213 ResolvedJavaType fieldType = javaField .getType ().resolve (declaringClass );
214214 boolean fieldNonNull = false ;
215215 AnnotationValue fieldConfig = findFieldConfig (fields , javaField .getName ());
216- boolean scratch = templateModeEnabled && fieldConfig != null && fieldConfig .getBoolean ("scratch" );
217216 int templateVariants = templateModeEnabled ? getTemplateVariants (fieldConfig , javaField ) : 0 ;
218- GraalError .guarantee (!scratch || templateVariants == 0 , "Scratch field %s cannot be a template variable" , javaField .format ("%H.%n" ));
219217 if (!fieldType .isPrimitive ()) {
220- fieldNonNull = ! scratch && fieldConfig != null && fieldConfig .getBoolean ("nonNull" );
218+ fieldNonNull = fieldConfig != null && fieldConfig .getBoolean ("nonNull" );
221219 GraalError .guarantee (templateVariants == 0 , "Field %s is marked as a template variable" , javaField .format ("%H.%n" ));
222220 } else if (templateVariants > 0 ) {
223221 GraalError .guarantee (fieldType .getJavaKind () == JavaKind .Int , "Template variable field %s must be int" , javaField .format ("%H.%n" ));
224222 }
225223 int abiIndex = templateVariants > 0 ? -1 : nextIndex ++;
226224 arguments .add (new ArgumentInfo (fieldType , abiIndex , originalIndex , false , false , true , parameterType , javaField , true , javaField .isFinal (),
227- fieldNonNull , scratch , templateVariants ));
225+ fieldNonNull , templateVariants ));
228226 }
229227 }
230228 case MATERIALIZED -> {
231- arguments .add (new ArgumentInfo (parameterType , nextIndex ++, originalIndex , copyFromReturn , true , false , null , null , false , true , nonNull , false , 0 ));
229+ arguments .add (new ArgumentInfo (parameterType , nextIndex ++, originalIndex , copyFromReturn , true , false , null , null , false , true , nonNull , 0 ));
232230 nextIndex = appendMaterializedFields (arguments , parameterConfig , parameterType , declaringClass , originalIndex , nextIndex , templateModeEnabled );
233231 }
234232 default -> throw GraalError .shouldNotReachHere ("Unknown expansion kind " + expansionKind );
@@ -243,16 +241,13 @@ private static int appendMaterializedFields(List<ArgumentInfo> arguments, Annota
243241 for (ResolvedJavaField javaField : expandedType .getInstanceFields (true )) {
244242 AnnotationValue fieldConfig = findFieldConfig (fields , javaField .getName ());
245243 if (fieldConfig != null ) {
246- if (templateModeEnabled ) {
247- GraalError .guarantee (!fieldConfig .getBoolean ("scratch" ), "Scratch field %s must belong to a VIRTUAL argument" , javaField .format ("%H.%n" ));
248- }
249244 ResolvedJavaType fieldType = javaField .getType ().resolve (declaringClass );
250245 boolean fieldNonNull = !fieldType .isPrimitive () && fieldConfig .getBoolean ("nonNull" );
251246 if (templateModeEnabled ) {
252247 GraalError .guarantee (getTemplateVariants (fieldConfig , javaField ) == 0 , "Field %s is marked as a template variable" , javaField .format ("%H.%n" ));
253248 }
254249 arguments .add (new ArgumentInfo (fieldType , nextIndex ++, originalIndex , false , false , true , declaringClass , javaField , false , javaField .isFinal (),
255- fieldNonNull , false , 0 ));
250+ fieldNonNull , 0 ));
256251 }
257252 }
258253 return nextIndex ;
@@ -336,6 +331,22 @@ public List<ResolvedJavaType> getStubAbiArgumentTypes() {
336331 return stubAbiArgumentTypes ;
337332 }
338333
334+ /**
335+ * Returns the number of thread-local slots required to preserve ordinary ABI arguments and
336+ * template variables when a handler chain returns to Java.
337+ */
338+ public int getPendingStateSlotCount () {
339+ return stubAbiArgumentInfos .size () + templateVariableArguments .size ();
340+ }
341+
342+ /**
343+ * Returns the thread-local slot assigned to a template variable. Template slots follow the
344+ * dense stub ABI slots and do not form part of the stub calling convention.
345+ */
346+ public int getTemplateVariablePendingStateSlot (int templateVariableIndex ) {
347+ return stubAbiArgumentInfos .size () + templateVariableIndex ;
348+ }
349+
339350 @ Override
340351 public boolean equals (Object obj ) {
341352 if (this == obj ) {
@@ -397,10 +408,6 @@ private enum ExpansionKind {
397408 * produce multiple {@link ArgumentInfo}s that share the same {@link #originalIndex()} but map to
398409 * different stub ABI {@link #index()} values. In template mode, template variables have index
399410 * {@code -1} and are excluded from the stub ABI.
400- * <p>
401- * When template mode is enabled, scratch fields are still ABI arguments so threaded handlers
402- * can pass them to each other, but they are initialized with default values at the Java caller
403- * boundary and are not written back to the original owner object.
404411 */
405412 public record ArgumentInfo (ResolvedJavaType type ,
406413 int index ,
@@ -413,7 +420,6 @@ public record ArgumentInfo(ResolvedJavaType type,
413420 boolean isOwnerVirtual ,
414421 boolean isImmutable ,
415422 boolean nonNull ,
416- boolean scratch ,
417423 int templateVariants ) {
418424 public boolean isTemplateVariable () {
419425 return templateVariants > 0 ;
@@ -424,7 +430,7 @@ public boolean isTemplateVariable() {
424430 * edge: the {@code copyFromReturn} value and mutable fields of virtual-expanded arguments.
425431 */
426432 public boolean needsPendingExceptionState () {
427- return copyFromReturn || (isExpanded && isOwnerVirtual && !isImmutable && ! scratch );
433+ return copyFromReturn || (isExpanded && isOwnerVirtual && !isImmutable );
428434 }
429435 }
430436}
0 commit comments