8323058: Revisit j.l.classfile.CodeBuilder API surface

Reviewed-by: briangoetz, psandoz
This commit is contained in:
Adam Sotona 2024-05-02 10:08:29 +00:00
parent 286cbf831c
commit ae82405ff7
53 changed files with 725 additions and 876 deletions

View file

@ -228,7 +228,7 @@
* instruction invoking {@code println} could have been generated with {@link
* java.lang.classfile.CodeBuilder#invokevirtual(java.lang.constant.ClassDesc,
* java.lang.String, java.lang.constant.MethodTypeDesc) CodeBuilder.invokevirtual}, {@link
* java.lang.classfile.CodeBuilder#invokeInstruction(java.lang.classfile.Opcode,
* java.lang.classfile.CodeBuilder#invoke(java.lang.classfile.Opcode,
* java.lang.constant.ClassDesc, java.lang.String, java.lang.constant.MethodTypeDesc,
* boolean) CodeBuilder.invokeInstruction}, or {@link
* java.lang.classfile.CodeBuilder#with(java.lang.classfile.ClassFileElement)

View file

@ -213,7 +213,7 @@ class PackageSnippets {
if (e instanceof InvokeInstruction i
&& i.owner().asInternalName().equals("Foo")
&& i.opcode() == Opcode.INVOKESTATIC)
b.invokeInstruction(i.opcode(), CD_Bar, i.name().stringValue(), i.typeSymbol(), i.isInterface());
b.invoke(i.opcode(), CD_Bar, i.name().stringValue(), i.typeSymbol(), i.isInterface());
else b.with(e);
};
// @end
@ -327,7 +327,7 @@ class PackageSnippets {
for (CodeElement e : xm) {
if (e instanceof InvokeInstruction i && i.owner().asInternalName().equals("Foo")
&& i.opcode() == Opcode.INVOKESTATIC)
codeBuilder.invokeInstruction(i.opcode(), CD_Bar,
codeBuilder.invoke(i.opcode(), CD_Bar,
i.name().stringValue(), i.typeSymbol(), i.isInterface());
else codeBuilder.with(e);
}});

View file

@ -382,7 +382,7 @@ public class MethodHandleProxies {
// <clinit>
clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, cob -> {
cob.constantInstruction(ifaceDesc);
cob.loadConstant(ifaceDesc);
cob.putstatic(proxyDesc, TYPE_NAME, CD_Class);
cob.return_();
});
@ -406,7 +406,7 @@ public class MethodHandleProxies {
// this.m<i> = callerBoundTarget.asType(xxType);
cob.aload(0);
cob.aload(3);
cob.constantInstruction(mi.desc);
cob.loadConstant(mi.desc);
cob.invokevirtual(CD_MethodHandle, "asType", MTD_MethodHandle_MethodType);
cob.putfield(proxyDesc, mi.fieldName, CD_MethodHandle);
}
@ -423,12 +423,12 @@ public class MethodHandleProxies {
// check lookupClass
cob.aload(0);
cob.invokevirtual(CD_MethodHandles_Lookup, "lookupClass", MTD_Class);
cob.constantInstruction(proxyDesc);
cob.loadConstant(proxyDesc);
cob.if_acmpne(failLabel);
// check original access
cob.aload(0);
cob.invokevirtual(CD_MethodHandles_Lookup, "lookupModes", MTD_int);
cob.constantInstruction(Lookup.ORIGINAL);
cob.loadConstant(Lookup.ORIGINAL);
cob.iand();
cob.ifeq(failLabel);
// success
@ -452,11 +452,11 @@ public class MethodHandleProxies {
bcb.aload(0);
bcb.getfield(proxyDesc, mi.fieldName, CD_MethodHandle);
for (int j = 0; j < mi.desc.parameterCount(); j++) {
bcb.loadInstruction(TypeKind.from(mi.desc.parameterType(j)),
bcb.loadLocal(TypeKind.from(mi.desc.parameterType(j)),
bcb.parameterSlot(j));
}
bcb.invokevirtual(CD_MethodHandle, "invokeExact", mi.desc);
bcb.returnInstruction(TypeKind.from(mi.desc.returnType()));
bcb.return_(TypeKind.from(mi.desc.returnType()));
}, ctb -> ctb
// catch (Error | RuntimeException | Declared ex) { throw ex; }
.catchingMulti(mi.thrown, CodeBuilder::athrow)

View file

@ -1124,7 +1124,7 @@ public final class StringConcatFactory {
}
}
len += args.parameterCount() * ARGUMENT_SIZE_FACTOR;
cb.constantInstruction(len);
cb.loadConstant(len);
cb.invokespecial(STRING_BUILDER, "<init>", INT_CONSTRUCTOR_TYPE);
// At this point, we have a blank StringBuilder on stack, fill it in with .append calls.
@ -1137,7 +1137,7 @@ public final class StringConcatFactory {
}
Class<?> cl = args.parameterType(c);
TypeKind kind = TypeKind.from(cl);
cb.loadInstruction(kind, off);
cb.loadLocal(kind, off);
off += kind.slotSize();
MethodTypeDesc desc = getSBAppendDesc(cl);
cb.invokevirtual(STRING_BUILDER, "append", desc);

View file

@ -689,7 +689,7 @@ final class ProxyGenerator {
.block(blockBuilder -> blockBuilder
.aload(cob.parameterSlot(0))
.invokevirtual(CD_MethodHandles_Lookup, "lookupClass", MTD_Class)
.constantInstruction(Opcode.LDC, CD_Proxy)
.ldc(CD_Proxy)
.if_acmpne(blockBuilder.breakLabel())
.aload(cob.parameterSlot(0))
.invokevirtual(CD_MethodHandles_Lookup, "hasFullPrivilegeAccess", MTD_boolean)
@ -763,11 +763,11 @@ final class ProxyGenerator {
if (parameterTypes.length > 0) {
// Create an array and fill with the parameters converting primitives to wrappers
cob.constantInstruction(parameterTypes.length)
cob.loadConstant(parameterTypes.length)
.anewarray(CE_Object);
for (int i = 0; i < parameterTypes.length; i++) {
cob.dup()
.constantInstruction(i);
.loadConstant(i);
codeWrapArgument(cob, parameterTypes[i], cob.parameterSlot(i));
cob.aastore();
}
@ -811,7 +811,7 @@ final class ProxyGenerator {
*/
private void codeWrapArgument(CodeBuilder cob, Class<?> type, int slot) {
if (type.isPrimitive()) {
cob.loadInstruction(TypeKind.from(type).asLoadable(), slot);
cob.loadLocal(TypeKind.from(type).asLoadable(), slot);
PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type);
cob.invokestatic(prim.wrapperMethodRef);
} else {
@ -830,7 +830,7 @@ final class ProxyGenerator {
cob.checkcast(prim.wrapperClass)
.invokevirtual(prim.unwrapMethodRef)
.returnInstruction(TypeKind.from(type).asLoadable());
.return_(TypeKind.from(type).asLoadable());
} else {
cob.checkcast(toClassDesc(type))
.areturn();
@ -847,13 +847,13 @@ final class ProxyGenerator {
codeClassForName(cob, fromClass);
cob.ldc(method.getName())
.constantInstruction(parameterTypes.length)
.loadConstant(parameterTypes.length)
.anewarray(CE_Class);
// Construct an array with the parameter types mapping primitives to Wrapper types
for (int i = 0; i < parameterTypes.length; i++) {
cob.dup()
.constantInstruction(i);
.loadConstant(i);
if (parameterTypes[i].isPrimitive()) {
PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(parameterTypes[i]);
cob.getstatic(prim.typeFieldRef);

View file

@ -414,7 +414,7 @@ public class SwitchBootstraps {
cb.ireturn();
cb.labelBinding(nonNullLabel);
if (labelConstants.length == 0) {
cb.constantInstruction(0)
cb.loadConstant(0)
.ireturn();
return;
}
@ -454,7 +454,7 @@ public class SwitchBootstraps {
// Object o = ...
// o instanceof Wrapped(float)
cb.aload(SELECTOR_OBJ);
cb.instanceof_(Wrapper.forBasicType(classLabel)
cb.instanceOf(Wrapper.forBasicType(classLabel)
.wrapperType()
.describeConstable()
.orElseThrow());
@ -464,7 +464,7 @@ public class SwitchBootstraps {
// o instanceof float
Label notNumber = cb.newLabel();
cb.aload(SELECTOR_OBJ);
cb.instanceof_(ConstantDescs.CD_Number);
cb.instanceOf(ConstantDescs.CD_Number);
if (selectorType == long.class || selectorType == float.class || selectorType == double.class ||
selectorType == Long.class || selectorType == Float.class || selectorType == Double.class) {
cb.ifeq(next);
@ -493,7 +493,7 @@ public class SwitchBootstraps {
cb.goto_(compare);
cb.labelBinding(notNumber);
cb.aload(SELECTOR_OBJ);
cb.instanceof_(ConstantDescs.CD_Character);
cb.instanceOf(ConstantDescs.CD_Character);
cb.ifeq(next);
cb.aload(SELECTOR_OBJ);
cb.checkcast(ConstantDescs.CD_Character);
@ -514,11 +514,11 @@ public class SwitchBootstraps {
Optional<ClassDesc> classLabelConstableOpt = classLabel.describeConstable();
if (classLabelConstableOpt.isPresent()) {
cb.aload(SELECTOR_OBJ);
cb.instanceof_(classLabelConstableOpt.orElseThrow());
cb.instanceOf(classLabelConstableOpt.orElseThrow());
cb.ifeq(next);
} else {
cb.aload(EXTRA_CLASS_LABELS);
cb.constantInstruction(extraClassLabels.size());
cb.loadConstant(extraClassLabels.size());
cb.invokeinterface(ConstantDescs.CD_List,
"get",
MethodTypeDesc.of(ConstantDescs.CD_Object,
@ -537,7 +537,7 @@ public class SwitchBootstraps {
int enumIdx = enumDescs.size();
enumDescs.add(enumLabel);
cb.aload(ENUM_CACHE);
cb.constantInstruction(enumIdx);
cb.loadConstant(enumIdx);
cb.invokestatic(ConstantDescs.CD_Integer,
"valueOf",
MethodTypeDesc.of(ConstantDescs.CD_Integer,
@ -561,7 +561,7 @@ public class SwitchBootstraps {
Label compare = cb.newLabel();
Label notNumber = cb.newLabel();
cb.aload(SELECTOR_OBJ);
cb.instanceof_(ConstantDescs.CD_Number);
cb.instanceOf(ConstantDescs.CD_Number);
cb.ifeq(notNumber);
cb.aload(SELECTOR_OBJ);
cb.checkcast(ConstantDescs.CD_Number);
@ -571,7 +571,7 @@ public class SwitchBootstraps {
cb.goto_(compare);
cb.labelBinding(notNumber);
cb.aload(SELECTOR_OBJ);
cb.instanceof_(ConstantDescs.CD_Character);
cb.instanceOf(ConstantDescs.CD_Character);
cb.ifeq(next);
cb.aload(SELECTOR_OBJ);
cb.checkcast(ConstantDescs.CD_Character);
@ -587,9 +587,9 @@ public class SwitchBootstraps {
element.caseLabel() instanceof Double ||
element.caseLabel() instanceof Boolean)) {
if (element.caseLabel() instanceof Boolean c) {
cb.constantInstruction(c ? 1 : 0);
cb.loadConstant(c ? 1 : 0);
} else {
cb.constantInstruction((ConstantDesc) element.caseLabel());
cb.loadConstant((ConstantDesc) element.caseLabel());
}
cb.invokestatic(element.caseLabel().getClass().describeConstable().orElseThrow(),
"valueOf",
@ -605,11 +605,11 @@ public class SwitchBootstraps {
throw new InternalError("Unsupported label type: " +
element.caseLabel().getClass());
}
cb.constantInstruction(idx);
cb.loadConstant(idx);
cb.ireturn();
}
cb.labelBinding(dflt);
cb.constantInstruction(cases.size());
cb.loadConstant(cases.size());
cb.ireturn();
};
}

View file

@ -62,7 +62,7 @@ public final class CatchBuilderImpl implements CodeBuilder.CatchBuilder {
if (catchBlock == null) {
if (tryBlock.reachable()) {
b.branchInstruction(Opcode.GOTO, tryCatchEnd);
b.branch(Opcode.GOTO, tryCatchEnd);
}
}
@ -76,7 +76,7 @@ public final class CatchBuilderImpl implements CodeBuilder.CatchBuilder {
if (catchBlock != null) {
catchBlock.end();
if (catchBlock.reachable()) {
b.branchInstruction(Opcode.GOTO, tryCatchEnd);
b.branch(Opcode.GOTO, tryCatchEnd);
}
}

View file

@ -231,25 +231,25 @@ public record ClassRemapperImpl(Function<ClassDesc, ClassDesc> mapFunction) impl
return (CodeBuilder cob, CodeElement coe) -> {
switch (coe) {
case FieldInstruction fai ->
cob.fieldInstruction(fai.opcode(), map(fai.owner().asSymbol()),
cob.fieldAccess(fai.opcode(), map(fai.owner().asSymbol()),
fai.name().stringValue(), map(fai.typeSymbol()));
case InvokeInstruction ii ->
cob.invokeInstruction(ii.opcode(), map(ii.owner().asSymbol()),
cob.invoke(ii.opcode(), map(ii.owner().asSymbol()),
ii.name().stringValue(), mapMethodDesc(ii.typeSymbol()),
ii.isInterface());
case InvokeDynamicInstruction idi ->
cob.invokeDynamicInstruction(DynamicCallSiteDesc.of(
cob.invokedynamic(DynamicCallSiteDesc.of(
idi.bootstrapMethod(), idi.name().stringValue(),
mapMethodDesc(idi.typeSymbol()),
idi.bootstrapArgs().stream().map(this::mapConstantValue).toArray(ConstantDesc[]::new)));
case NewObjectInstruction c ->
cob.newObjectInstruction(map(c.className().asSymbol()));
cob.new_(map(c.className().asSymbol()));
case NewReferenceArrayInstruction c ->
cob.anewarray(map(c.componentType().asSymbol()));
case NewMultiArrayInstruction c ->
cob.multianewarray(map(c.arrayType().asSymbol()), c.dimensions());
case TypeCheckInstruction c ->
cob.typeCheckInstruction(c.opcode(), map(c.type().asSymbol()));
cob.with(TypeCheckInstruction.of(c.opcode(), map(c.type().asSymbol())));
case ExceptionCatch c ->
cob.exceptionCatch(c.tryStart(), c.tryEnd(), c.handler(),c.catchType()
.map(d -> TemporaryConstantPool.INSTANCE.classEntry(map(d.asSymbol()))));
@ -260,7 +260,7 @@ public record ClassRemapperImpl(Function<ClassDesc, ClassDesc> mapFunction) impl
cob.localVariableType(c.slot(), c.name().stringValue(),
mapSignature(c.signatureSymbol()), c.startScope(), c.endScope());
case LoadConstantInstruction ldc ->
cob.constantInstruction(ldc.opcode(),
cob.loadConstant(ldc.opcode(),
mapConstantValue(ldc.constantValue()));
case RuntimeVisibleTypeAnnotationsAttribute aa ->
cob.with(RuntimeVisibleTypeAnnotationsAttribute.of(

View file

@ -50,15 +50,15 @@ public final class CodeLocalsShifterImpl implements CodeLocalsShifter {
public void accept(CodeBuilder cob, CodeElement coe) {
switch (coe) {
case LoadInstruction li ->
cob.loadInstruction(
cob.loadLocal(
li.typeKind(),
shift(cob, li.slot(), li.typeKind()));
case StoreInstruction si ->
cob.storeInstruction(
cob.storeLocal(
si.typeKind(),
shift(cob, si.slot(), si.typeKind()));
case IncrementInstruction ii ->
cob.incrementInstruction(
cob.iinc(
shift(cob, ii.slot(), TypeKind.IntType),
ii.constant());
case LocalVariable lv ->

View file

@ -51,18 +51,18 @@ public record CodeRelabelerImpl(BiFunction<Label, CodeBuilder, Label> mapFunctio
public void accept(CodeBuilder cob, CodeElement coe) {
switch (coe) {
case BranchInstruction bi ->
cob.branchInstruction(
cob.branch(
bi.opcode(),
relabel(bi.target(), cob));
case LookupSwitchInstruction lsi ->
cob.lookupSwitchInstruction(
cob.lookupswitch(
relabel(lsi.defaultTarget(), cob),
lsi.cases().stream().map(c ->
SwitchCase.of(
c.caseValue(),
relabel(c.target(), cob))).toList());
case TableSwitchInstruction tsi ->
cob.tableSwitchInstruction(
cob.tableswitch(
tsi.lowValue(),
tsi.highValue(),
relabel(tsi.defaultTarget(), cob),

View file

@ -274,8 +274,8 @@ public class BindingSpecializer {
if (shouldAcquire(i)) {
int scopeLocal = cb.allocateLocal(ReferenceType);
initialScopeSlots[numScopes++] = scopeLocal;
cb.constantInstruction(null);
cb.storeInstruction(ReferenceType, scopeLocal); // need to initialize all scope locals here in case an exception occurs
cb.loadConstant(null);
cb.storeLocal(ReferenceType, scopeLocal); // need to initialize all scope locals here in case an exception occurs
}
}
scopeSlots = Arrays.copyOf(initialScopeSlots, numScopes); // fit to size
@ -284,7 +284,7 @@ public class BindingSpecializer {
// create a Binding.Context for this call
if (callingSequence.allocationSize() != 0) {
cb.constantInstruction(callingSequence.allocationSize());
cb.loadConstant(callingSequence.allocationSize());
cb.invokestatic(CD_SharedUtils, "newBoundedArena", MTD_NEW_BOUNDED_ARENA);
} else if (callingSequence.forUpcall() && needsSession()) {
cb.invokestatic(CD_SharedUtils, "newEmptyArena", MTD_NEW_EMPTY_ARENA);
@ -292,7 +292,7 @@ public class BindingSpecializer {
cb.getstatic(CD_SharedUtils, "DUMMY_ARENA", CD_Arena);
}
contextIdx = cb.allocateLocal(ReferenceType);
cb.storeInstruction(ReferenceType, contextIdx);
cb.storeLocal(ReferenceType, contextIdx);
// in case the call needs a return buffer, allocate it here.
// for upcalls the VM wrapper stub allocates the buffer.
@ -300,7 +300,7 @@ public class BindingSpecializer {
emitLoadInternalAllocator();
emitAllocateCall(callingSequence.returnBufferSize(), 1);
returnBufferIdx = cb.allocateLocal(ReferenceType);
cb.storeInstruction(ReferenceType, returnBufferIdx);
cb.storeLocal(ReferenceType, returnBufferIdx);
}
Label tryStart = cb.newLabel();
@ -323,7 +323,7 @@ public class BindingSpecializer {
// for downcalls, recipes have an input value, which we set up here
if (callingSequence.needsReturnBuffer() && i == 0) {
assert returnBufferIdx != -1;
cb.loadInstruction(ReferenceType, returnBufferIdx);
cb.loadLocal(ReferenceType, returnBufferIdx);
pushType(MemorySegment.class);
} else {
emitGetInput();
@ -339,7 +339,7 @@ public class BindingSpecializer {
// return buffer ptr is wrapped in a MemorySegment above, but not passed to the leaf handle
popType(MemorySegment.class);
returnBufferIdx = cb.allocateLocal(ReferenceType);
cb.storeInstruction(ReferenceType, returnBufferIdx);
cb.storeLocal(ReferenceType, returnBufferIdx);
} else {
// for upcalls the recipe result is an argument to the leaf handle
emitSetOutput(typeStack.pop());
@ -352,14 +352,14 @@ public class BindingSpecializer {
// load the leaf MethodHandle
if (callingSequence.forDowncall()) {
cb.constantInstruction(CLASS_DATA_DESC);
cb.loadConstant(CLASS_DATA_DESC);
} else {
cb.loadInstruction(ReferenceType, 0); // load target arg
cb.loadLocal(ReferenceType, 0); // load target arg
}
cb.checkcast(CD_MethodHandle);
// load all the leaf args
for (int i = 0; i < leafArgSlots.length; i++) {
cb.loadInstruction(TypeKind.from(leafArgTypes.get(i)), leafArgSlots[i]);
cb.loadLocal(TypeKind.from(leafArgTypes.get(i)), leafArgSlots[i]);
}
// call leaf MH
cb.invokevirtual(CD_MethodHandle, "invokeExact", desc(leafType));
@ -396,7 +396,7 @@ public class BindingSpecializer {
} else {
popType(callerMethodType.returnType());
assert typeStack.isEmpty();
cb.returnInstruction(TypeKind.from(callerMethodType.returnType()));
cb.return_(TypeKind.from(callerMethodType.returnType()));
}
} else {
assert callerMethodType.returnType() == void.class;
@ -411,13 +411,13 @@ public class BindingSpecializer {
// finally
emitCleanup();
if (callingSequence.forDowncall()) {
cb.throwInstruction();
cb.athrow();
} else {
cb.invokestatic(CD_SharedUtils, "handleUncaughtException", MTD_HANDLE_UNCAUGHT_EXCEPTION);
if (callerMethodType.returnType() != void.class) {
TypeKind returnTypeKind = TypeKind.from(callerMethodType.returnType());
emitConstZero(returnTypeKind);
cb.returnInstruction(returnTypeKind);
cb.return_(returnTypeKind);
} else {
cb.return_();
}
@ -477,13 +477,13 @@ public class BindingSpecializer {
}
private void emitSetOutput(Class<?> storeType) {
cb.storeInstruction(TypeKind.from(storeType), leafArgSlots[leafArgTypes.size()]);
cb.storeLocal(TypeKind.from(storeType), leafArgSlots[leafArgTypes.size()]);
leafArgTypes.add(storeType);
}
private void emitGetInput() {
Class<?> highLevelType = callerMethodType.parameterType(paramIndex);
cb.loadInstruction(TypeKind.from(highLevelType), cb.parameterSlot(paramIndex));
cb.loadLocal(TypeKind.from(highLevelType), cb.parameterSlot(paramIndex));
if (shouldAcquire(paramIndex)) {
cb.dup();
@ -505,7 +505,7 @@ public class BindingSpecializer {
boolean hasOtherScopes = curScopeLocalIdx != 0;
for (int i = 0; i < curScopeLocalIdx; i++) {
cb.dup(); // dup for comparison
cb.loadInstruction(ReferenceType, scopeSlots[i]);
cb.loadLocal(ReferenceType, scopeSlots[i]);
cb.if_acmpeq(skipAcquire);
}
@ -514,7 +514,7 @@ public class BindingSpecializer {
int nextScopeLocal = scopeSlots[curScopeLocalIdx++];
// call acquire first here. So that if it fails, we don't call release
cb.invokevirtual(CD_MemorySessionImpl, "acquire0", MTD_ACQUIRE0); // call acquire on the other
cb.storeInstruction(ReferenceType, nextScopeLocal); // store off one to release later
cb.storeLocal(ReferenceType, nextScopeLocal); // store off one to release later
if (hasOtherScopes) { // avoid ASM generating a bunch of nops for the dead code
cb.goto_(end);
@ -528,9 +528,9 @@ public class BindingSpecializer {
private void emitReleaseScopes() {
for (int scopeLocal : scopeSlots) {
cb.loadInstruction(ReferenceType, scopeLocal);
cb.loadLocal(ReferenceType, scopeLocal);
cb.ifThen(Opcode.IFNONNULL, ifCb -> {
ifCb.loadInstruction(ReferenceType, scopeLocal);
ifCb.loadLocal(ReferenceType, scopeLocal);
ifCb.invokevirtual(CD_MemorySessionImpl, "release0", MTD_RELEASE0);
});
}
@ -539,18 +539,18 @@ public class BindingSpecializer {
private void emitSaveReturnValue(Class<?> storeType) {
TypeKind typeKind = TypeKind.from(storeType);
retValIdx = cb.allocateLocal(typeKind);
cb.storeInstruction(typeKind, retValIdx);
cb.storeLocal(typeKind, retValIdx);
}
private void emitRestoreReturnValue(Class<?> loadType) {
assert retValIdx != -1;
cb.loadInstruction(TypeKind.from(loadType), retValIdx);
cb.loadLocal(TypeKind.from(loadType), retValIdx);
pushType(loadType);
}
private void emitLoadInternalSession() {
assert contextIdx != -1;
cb.loadInstruction(ReferenceType, contextIdx);
cb.loadLocal(ReferenceType, contextIdx);
cb.checkcast(CD_Arena);
cb.invokeinterface(CD_Arena, "scope", MTD_SCOPE);
cb.checkcast(CD_MemorySessionImpl);
@ -558,20 +558,20 @@ public class BindingSpecializer {
private void emitLoadInternalAllocator() {
assert contextIdx != -1;
cb.loadInstruction(ReferenceType, contextIdx);
cb.loadLocal(ReferenceType, contextIdx);
}
private void emitCloseContext() {
assert contextIdx != -1;
cb.loadInstruction(ReferenceType, contextIdx);
cb.loadLocal(ReferenceType, contextIdx);
cb.checkcast(CD_Arena);
cb.invokeinterface(CD_Arena, "close", MTD_CLOSE);
}
private void emitBoxAddress(BoxAddress boxAddress) {
popType(long.class);
cb.constantInstruction(boxAddress.size());
cb.constantInstruction(boxAddress.align());
cb.loadConstant(boxAddress.size());
cb.loadConstant(boxAddress.align());
if (needsSession()) {
emitLoadInternalSession();
cb.invokestatic(CD_Utils, "longToAddress", MTD_LONG_TO_ADDRESS_SCOPE);
@ -584,7 +584,7 @@ public class BindingSpecializer {
private void emitAllocBuffer(Allocate binding) {
if (callingSequence.forDowncall()) {
assert returnAllocatorIdx != -1;
cb.loadInstruction(ReferenceType, returnAllocatorIdx);
cb.loadLocal(ReferenceType, returnAllocatorIdx);
} else {
emitLoadInternalAllocator();
}
@ -603,11 +603,11 @@ public class BindingSpecializer {
if (SharedUtils.isPowerOfTwo(byteWidth)) {
int valueIdx = cb.allocateLocal(storeTypeKind);
cb.storeInstruction(storeTypeKind, valueIdx);
cb.storeLocal(storeTypeKind, valueIdx);
ClassDesc valueLayoutType = emitLoadLayoutConstant(storeType);
cb.constantInstruction(offset);
cb.loadInstruction(storeTypeKind, valueIdx);
cb.loadConstant(offset);
cb.loadLocal(storeTypeKind, valueIdx);
MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, desc(storeType));
cb.invokeinterface(CD_MemorySegment, "set", descriptor);
} else {
@ -618,9 +618,9 @@ public class BindingSpecializer {
assert storeType == long.class; // chunking only for int and long
}
int longValueIdx = cb.allocateLocal(LongType);
cb.storeInstruction(LongType, longValueIdx);
cb.storeLocal(LongType, longValueIdx);
int writeAddrIdx = cb.allocateLocal(ReferenceType);
cb.storeInstruction(ReferenceType, writeAddrIdx);
cb.storeLocal(ReferenceType, writeAddrIdx);
int remaining = byteWidth;
int chunkOffset = 0;
@ -647,25 +647,25 @@ public class BindingSpecializer {
//int writeChunk = (int) (((0xFFFF_FFFFL << shiftAmount) & longValue) >>> shiftAmount);
int shiftAmount = chunkOffset * Byte.SIZE;
mask = mask << shiftAmount;
cb.loadInstruction(LongType, longValueIdx);
cb.constantInstruction(mask);
cb.loadLocal(LongType, longValueIdx);
cb.loadConstant(mask);
cb.land();
if (shiftAmount != 0) {
cb.constantInstruction(shiftAmount);
cb.loadConstant(shiftAmount);
cb.lushr();
}
cb.l2i();
TypeKind chunkStoreTypeKind = TypeKind.from(chunkStoreType);
int chunkIdx = cb.allocateLocal(chunkStoreTypeKind);
cb.storeInstruction(chunkStoreTypeKind, chunkIdx);
cb.storeLocal(chunkStoreTypeKind, chunkIdx);
// chunk done, now write it
//writeAddress.set(JAVA_SHORT_UNALIGNED, offset, writeChunk);
cb.loadInstruction(ReferenceType, writeAddrIdx);
cb.loadLocal(ReferenceType, writeAddrIdx);
ClassDesc valueLayoutType = emitLoadLayoutConstant(chunkStoreType);
long writeOffset = offset + SharedUtils.pickChunkOffset(chunkOffset, byteWidth, chunkSize);
cb.constantInstruction(writeOffset);
cb.loadInstruction(chunkStoreTypeKind, chunkIdx);
cb.loadConstant(writeOffset);
cb.loadLocal(chunkStoreTypeKind, chunkIdx);
MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, desc(chunkStoreType));
cb.invokeinterface(CD_MemorySegment, "set", descriptor);
@ -690,13 +690,13 @@ public class BindingSpecializer {
emitSaveReturnValue(storeType);
} else {
int valueIdx = cb.allocateLocal(storeTypeKind);
cb.storeInstruction(storeTypeKind, valueIdx); // store away the stored value, need it later
cb.storeLocal(storeTypeKind, valueIdx); // store away the stored value, need it later
assert returnBufferIdx != -1;
cb.loadInstruction(ReferenceType, returnBufferIdx);
cb.loadLocal(ReferenceType, returnBufferIdx);
ClassDesc valueLayoutType = emitLoadLayoutConstant(storeType);
cb.constantInstruction(retBufOffset);
cb.loadInstruction(storeTypeKind, valueIdx);
cb.loadConstant(retBufOffset);
cb.loadLocal(storeTypeKind, valueIdx);
MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, desc(storeType));
cb.invokeinterface(CD_MemorySegment, "set", descriptor);
retBufOffset += abi.arch.typeSize(vmStore.storage().type());
@ -713,9 +713,9 @@ public class BindingSpecializer {
emitRestoreReturnValue(loadType);
} else {
assert returnBufferIdx != -1;
cb.loadInstruction(ReferenceType, returnBufferIdx);
cb.loadLocal(ReferenceType, returnBufferIdx);
ClassDesc valueLayoutType = emitLoadLayoutConstant(loadType);
cb.constantInstruction(retBufOffset);
cb.loadConstant(retBufOffset);
MethodTypeDesc descriptor = MethodTypeDesc.of(desc(loadType), valueLayoutType, CD_long);
cb.invokeinterface(CD_MemorySegment, "get", descriptor);
retBufOffset += abi.arch.typeSize(vmLoad.storage().type());
@ -735,14 +735,14 @@ public class BindingSpecializer {
private void emitShiftLeft(ShiftLeft shiftLeft) {
popType(long.class);
cb.constantInstruction(shiftLeft.shiftAmount() * Byte.SIZE);
cb.loadConstant(shiftLeft.shiftAmount() * Byte.SIZE);
cb.lshl();
pushType(long.class);
}
private void emitShiftRight(ShiftRight shiftRight) {
popType(long.class);
cb.constantInstruction(shiftRight.shiftAmount() * Byte.SIZE);
cb.loadConstant(shiftRight.shiftAmount() * Byte.SIZE);
cb.lushr();
pushType(long.class);
}
@ -757,7 +757,7 @@ public class BindingSpecializer {
// implement least significant byte non-zero test
// select first byte
cb.constantInstruction(0xFF);
cb.loadConstant(0xFF);
cb.iand();
// convert to boolean
@ -808,17 +808,17 @@ public class BindingSpecializer {
if (SharedUtils.isPowerOfTwo(byteWidth)) {
ClassDesc valueLayoutType = emitLoadLayoutConstant(loadType);
cb.constantInstruction(offset);
cb.loadConstant(offset);
MethodTypeDesc descriptor = MethodTypeDesc.of(desc(loadType), valueLayoutType, CD_long);
cb.invokeinterface(CD_MemorySegment, "get", descriptor);
} else {
// chunked
int readAddrIdx = cb.allocateLocal(ReferenceType);
cb.storeInstruction(ReferenceType, readAddrIdx);
cb.storeLocal(ReferenceType, readAddrIdx);
cb.constantInstruction(0L); // result
cb.loadConstant(0L); // result
int resultIdx = cb.allocateLocal(LongType);
cb.storeInstruction(LongType, resultIdx);
cb.storeLocal(LongType, resultIdx);
int remaining = byteWidth;
int chunkOffset = 0;
@ -847,30 +847,30 @@ public class BindingSpecializer {
throw new IllegalStateException("Unexpected chunk size for chunked write: " + chunkSize);
}
// read from segment
cb.loadInstruction(ReferenceType, readAddrIdx);
cb.loadLocal(ReferenceType, readAddrIdx);
ClassDesc valueLayoutType = emitLoadLayoutConstant(chunkType);
MethodTypeDesc descriptor = MethodTypeDesc.of(desc(chunkType), valueLayoutType, CD_long);
long readOffset = offset + SharedUtils.pickChunkOffset(chunkOffset, byteWidth, chunkSize);
cb.constantInstruction(readOffset);
cb.loadConstant(readOffset);
cb.invokeinterface(CD_MemorySegment, "get", descriptor);
cb.invokestatic(toULongHolder, "toUnsignedLong", toULongDescriptor);
// shift to right offset
int shiftAmount = chunkOffset * Byte.SIZE;
if (shiftAmount != 0) {
cb.constantInstruction(shiftAmount);
cb.loadConstant(shiftAmount);
cb.lshl();
}
// add to result
cb.loadInstruction(LongType, resultIdx);
cb.loadLocal(LongType, resultIdx);
cb.lor();
cb.storeInstruction(LongType, resultIdx);
cb.storeLocal(LongType, resultIdx);
remaining -= chunkSize;
chunkOffset += chunkSize;
} while (remaining != 0);
cb.loadInstruction(LongType, resultIdx);
cb.loadLocal(LongType, resultIdx);
if (loadType == int.class) {
cb.l2i();
} else {
@ -890,25 +890,25 @@ public class BindingSpecializer {
// operand/srcSegment is on the stack
// generating a call to:
// MemorySegment::copy(MemorySegment srcSegment, long srcOffset, MemorySegment dstSegment, long dstOffset, long bytes)
cb.constantInstruction(0L);
cb.loadConstant(0L);
// create the dstSegment by allocating it. Similar to:
// context.allocator().allocate(size, alignment)
emitLoadInternalAllocator();
emitAllocateCall(size, alignment);
cb.dup();
int storeIdx = cb.allocateLocal(ReferenceType);
cb.storeInstruction(ReferenceType, storeIdx);
cb.constantInstruction(0L);
cb.constantInstruction(size);
cb.storeLocal(ReferenceType, storeIdx);
cb.loadConstant(0L);
cb.loadConstant(size);
cb.invokestatic(CD_MemorySegment, "copy", MTD_COPY, true);
cb.loadInstruction(ReferenceType, storeIdx);
cb.loadLocal(ReferenceType, storeIdx);
pushType(MemorySegment.class);
}
private void emitAllocateCall(long size, long alignment) {
cb.constantInstruction(size);
cb.constantInstruction(alignment);
cb.loadConstant(size);
cb.loadConstant(alignment);
cb.invokeinterface(CD_SegmentAllocator, "allocate", MTD_ALLOCATE);
}