8341548: More concise use of classfile API
Reviewed-by: liach
This commit is contained in:
parent
7312eea382
commit
62acc9c174
@ -394,10 +394,9 @@ import sun.invoke.util.Wrapper;
|
|||||||
.invokespecial(CD_Object, INIT_NAME, MTD_void);
|
.invokespecial(CD_Object, INIT_NAME, MTD_void);
|
||||||
int parameterCount = factoryType.parameterCount();
|
int parameterCount = factoryType.parameterCount();
|
||||||
for (int i = 0; i < parameterCount; i++) {
|
for (int i = 0; i < parameterCount; i++) {
|
||||||
cob.aload(0);
|
cob.aload(0)
|
||||||
Class<?> argType = factoryType.parameterType(i);
|
.loadLocal(TypeKind.from(factoryType.parameterType(i)), cob.parameterSlot(i))
|
||||||
cob.loadLocal(TypeKind.from(argType), cob.parameterSlot(i));
|
.putfield(pool.fieldRefEntry(lambdaClassEntry, pool.nameAndTypeEntry(argNames[i], argDescs[i])));
|
||||||
cob.putfield(pool.fieldRefEntry(lambdaClassEntry, pool.nameAndTypeEntry(argNames[i], argDescs[i])));
|
|
||||||
}
|
}
|
||||||
cob.return_();
|
cob.return_();
|
||||||
}
|
}
|
||||||
|
@ -891,10 +891,9 @@ class InvokerBytecodeGenerator {
|
|||||||
emitStaticInvoke(cob, invokeBasicName);
|
emitStaticInvoke(cob, invokeBasicName);
|
||||||
|
|
||||||
// goto L_done
|
// goto L_done
|
||||||
cob.goto_w(L_done);
|
cob.goto_w(L_done)
|
||||||
|
|
||||||
// L_fallback:
|
// L_fallback:
|
||||||
cob.labelBinding(L_fallback);
|
.labelBinding(L_fallback);
|
||||||
|
|
||||||
// invoke selectAlternativeName.arguments[2]
|
// invoke selectAlternativeName.arguments[2]
|
||||||
System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length);
|
System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length);
|
||||||
@ -945,26 +944,23 @@ class InvokerBytecodeGenerator {
|
|||||||
.dropParameterTypes(0,1)
|
.dropParameterTypes(0,1)
|
||||||
.changeReturnType(returnType);
|
.changeReturnType(returnType);
|
||||||
|
|
||||||
cob.exceptionCatch(L_startBlock, L_endBlock, L_handler, CD_Throwable);
|
cob.exceptionCatch(L_startBlock, L_endBlock, L_handler, CD_Throwable)
|
||||||
|
|
||||||
// Normal case
|
// Normal case
|
||||||
cob.labelBinding(L_startBlock);
|
.labelBinding(L_startBlock);
|
||||||
// load target
|
// load target
|
||||||
emitPushArgument(cob, invoker, 0);
|
emitPushArgument(cob, invoker, 0);
|
||||||
emitPushArguments(cob, args, 1); // skip 1st argument: method handle
|
emitPushArguments(cob, args, 1); // skip 1st argument: method handle
|
||||||
cob.invokevirtual(CD_MethodHandle, "invokeBasic", methodDesc(type.basicType()));
|
cob.invokevirtual(CD_MethodHandle, "invokeBasic", methodDesc(type.basicType()))
|
||||||
cob.labelBinding(L_endBlock);
|
.labelBinding(L_endBlock)
|
||||||
cob.goto_w(L_done);
|
.goto_w(L_done)
|
||||||
|
|
||||||
// Exceptional case
|
// Exceptional case
|
||||||
cob.labelBinding(L_handler);
|
.labelBinding(L_handler)
|
||||||
|
|
||||||
// Check exception's type
|
// Check exception's type
|
||||||
cob.dup();
|
.dup();
|
||||||
// load exception class
|
// load exception class
|
||||||
emitPushArgument(cob, invoker, 1);
|
emitPushArgument(cob, invoker, 1);
|
||||||
cob.swap();
|
cob.swap()
|
||||||
cob.invokevirtual(CD_Class, "isInstance", MTD_boolean_Object);
|
.invokevirtual(CD_Class, "isInstance", MTD_boolean_Object);
|
||||||
Label L_rethrow = cob.newLabel();
|
Label L_rethrow = cob.newLabel();
|
||||||
cob.ifeq(L_rethrow);
|
cob.ifeq(L_rethrow);
|
||||||
|
|
||||||
@ -974,13 +970,11 @@ class InvokerBytecodeGenerator {
|
|||||||
cob.swap();
|
cob.swap();
|
||||||
emitPushArguments(cob, args, 1); // skip 1st argument: method handle
|
emitPushArguments(cob, args, 1); // skip 1st argument: method handle
|
||||||
MethodType catcherType = type.insertParameterTypes(0, Throwable.class);
|
MethodType catcherType = type.insertParameterTypes(0, Throwable.class);
|
||||||
cob.invokevirtual(CD_MethodHandle, "invokeBasic", methodDesc(catcherType.basicType()));
|
cob.invokevirtual(CD_MethodHandle, "invokeBasic", methodDesc(catcherType.basicType()))
|
||||||
cob.goto_w(L_done);
|
.goto_w(L_done)
|
||||||
|
.labelBinding(L_rethrow)
|
||||||
cob.labelBinding(L_rethrow);
|
.athrow()
|
||||||
cob.athrow();
|
.labelBinding(L_done);
|
||||||
|
|
||||||
cob.labelBinding(L_done);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1075,8 +1069,8 @@ class InvokerBytecodeGenerator {
|
|||||||
cob.labelBinding(lFrom);
|
cob.labelBinding(lFrom);
|
||||||
emitPushArgument(cob, invoker, 0); // load target
|
emitPushArgument(cob, invoker, 0); // load target
|
||||||
emitPushArguments(cob, args, 1); // load args (skip 0: method handle)
|
emitPushArguments(cob, args, 1); // load args (skip 0: method handle)
|
||||||
cob.invokevirtual(CD_MethodHandle, "invokeBasic", methodDesc(type.basicType()));
|
cob.invokevirtual(CD_MethodHandle, "invokeBasic", methodDesc(type.basicType()))
|
||||||
cob.labelBinding(lTo);
|
.labelBinding(lTo);
|
||||||
|
|
||||||
// FINALLY_NORMAL:
|
// FINALLY_NORMAL:
|
||||||
int index = extendLocalsMap(new Class<?>[]{ returnType });
|
int index = extendLocalsMap(new Class<?>[]{ returnType });
|
||||||
@ -1084,17 +1078,16 @@ class InvokerBytecodeGenerator {
|
|||||||
emitStoreInsn(cob, basicReturnType.basicTypeKind(), index);
|
emitStoreInsn(cob, basicReturnType.basicTypeKind(), index);
|
||||||
}
|
}
|
||||||
emitPushArgument(cob, invoker, 1); // load cleanup
|
emitPushArgument(cob, invoker, 1); // load cleanup
|
||||||
cob.loadConstant(null);
|
cob.aconst_null();
|
||||||
if (isNonVoid) {
|
if (isNonVoid) {
|
||||||
emitLoadInsn(cob, basicReturnType.basicTypeKind(), index);
|
emitLoadInsn(cob, basicReturnType.basicTypeKind(), index);
|
||||||
}
|
}
|
||||||
emitPushArguments(cob, args, 1); // load args (skip 0: method handle)
|
emitPushArguments(cob, args, 1); // load args (skip 0: method handle)
|
||||||
cob.invokevirtual(CD_MethodHandle, "invokeBasic", cleanupDesc);
|
cob.invokevirtual(CD_MethodHandle, "invokeBasic", cleanupDesc)
|
||||||
cob.goto_w(lDone);
|
.goto_w(lDone)
|
||||||
|
|
||||||
// CATCH:
|
// CATCH:
|
||||||
cob.labelBinding(lCatch);
|
.labelBinding(lCatch)
|
||||||
cob.dup();
|
.dup();
|
||||||
|
|
||||||
// FINALLY_EXCEPTIONAL:
|
// FINALLY_EXCEPTIONAL:
|
||||||
emitPushArgument(cob, invoker, 1); // load cleanup
|
emitPushArgument(cob, invoker, 1); // load cleanup
|
||||||
@ -1107,10 +1100,9 @@ class InvokerBytecodeGenerator {
|
|||||||
if (isNonVoid) {
|
if (isNonVoid) {
|
||||||
emitPopInsn(cob, basicReturnType);
|
emitPopInsn(cob, basicReturnType);
|
||||||
}
|
}
|
||||||
cob.athrow();
|
cob.athrow()
|
||||||
|
|
||||||
// DONE:
|
// DONE:
|
||||||
cob.labelBinding(lDone);
|
.labelBinding(lDone);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1147,26 +1139,24 @@ class InvokerBytecodeGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
emitPushArgument(cob, invoker, 0); // push switch input
|
emitPushArgument(cob, invoker, 0); // push switch input
|
||||||
cob.tableswitch(0, numCases - 1, defaultLabel, cases);
|
cob.tableswitch(0, numCases - 1, defaultLabel, cases)
|
||||||
|
.labelBinding(defaultLabel);
|
||||||
cob.labelBinding(defaultLabel);
|
|
||||||
emitPushArgument(cob, invoker, 1); // push default handle
|
emitPushArgument(cob, invoker, 1); // push default handle
|
||||||
emitPushArguments(cob, args, 1); // again, skip collector
|
emitPushArguments(cob, args, 1); // again, skip collector
|
||||||
cob.invokevirtual(CD_MethodHandle, "invokeBasic", caseDescriptor);
|
cob.invokevirtual(CD_MethodHandle, "invokeBasic", caseDescriptor)
|
||||||
cob.goto_(endLabel);
|
.goto_(endLabel);
|
||||||
|
|
||||||
for (int i = 0; i < numCases; i++) {
|
for (int i = 0; i < numCases; i++) {
|
||||||
cob.labelBinding(cases.get(i).target());
|
cob.labelBinding(cases.get(i).target());
|
||||||
// Load the particular case:
|
// Load the particular case:
|
||||||
emitLoadInsn(cob, TypeKind.REFERENCE, casesLocal);
|
emitLoadInsn(cob, TypeKind.REFERENCE, casesLocal);
|
||||||
cob.loadConstant(i);
|
cob.loadConstant(i)
|
||||||
cob.aaload();
|
.aaload();
|
||||||
|
|
||||||
// invoke it:
|
// invoke it:
|
||||||
emitPushArguments(cob, args, 1); // again, skip collector
|
emitPushArguments(cob, args, 1); // again, skip collector
|
||||||
cob.invokevirtual(CD_MethodHandle, "invokeBasic", caseDescriptor);
|
cob.invokevirtual(CD_MethodHandle, "invokeBasic", caseDescriptor)
|
||||||
|
.goto_(endLabel);
|
||||||
cob.goto_(endLabel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cob.labelBinding(endLabel);
|
cob.labelBinding(endLabel);
|
||||||
@ -1335,16 +1325,14 @@ class InvokerBytecodeGenerator {
|
|||||||
// invoke fini
|
// invoke fini
|
||||||
emitLoopHandleInvoke(cob, invoker, finis, c, args, true, finiType, loopLocalStateTypes, clauseDataIndex,
|
emitLoopHandleInvoke(cob, invoker, finis, c, args, true, finiType, loopLocalStateTypes, clauseDataIndex,
|
||||||
firstLoopStateIndex);
|
firstLoopStateIndex);
|
||||||
cob.goto_w(lDone);
|
cob.goto_w(lDone)
|
||||||
|
|
||||||
// this is the beginning of the next loop clause
|
// this is the beginning of the next loop clause
|
||||||
cob.labelBinding(lNext);
|
.labelBinding(lNext);
|
||||||
}
|
}
|
||||||
|
|
||||||
cob.goto_w(lLoop);
|
cob.goto_w(lLoop)
|
||||||
|
|
||||||
// DONE:
|
// DONE:
|
||||||
cob.labelBinding(lDone);
|
.labelBinding(lDone);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1370,8 +1358,8 @@ class InvokerBytecodeGenerator {
|
|||||||
int firstLoopStateSlot) {
|
int firstLoopStateSlot) {
|
||||||
// load handle for clause
|
// load handle for clause
|
||||||
emitPushClauseArray(cob, clauseDataSlot, handles);
|
emitPushClauseArray(cob, clauseDataSlot, handles);
|
||||||
cob.loadConstant(clause);
|
cob.loadConstant(clause)
|
||||||
cob.aaload();
|
.aaload();
|
||||||
// load loop state (preceding the other arguments)
|
// load loop state (preceding the other arguments)
|
||||||
if (pushLocalState) {
|
if (pushLocalState) {
|
||||||
for (int s = 0; s < loopLocalStateTypes.length; ++s) {
|
for (int s = 0; s < loopLocalStateTypes.length; ++s) {
|
||||||
@ -1385,8 +1373,8 @@ class InvokerBytecodeGenerator {
|
|||||||
|
|
||||||
private void emitPushClauseArray(CodeBuilder cob, int clauseDataSlot, int which) {
|
private void emitPushClauseArray(CodeBuilder cob, int clauseDataSlot, int which) {
|
||||||
emitLoadInsn(cob, TypeKind.REFERENCE, clauseDataSlot);
|
emitLoadInsn(cob, TypeKind.REFERENCE, clauseDataSlot);
|
||||||
cob.loadConstant(which - 1);
|
cob.loadConstant(which - 1)
|
||||||
cob.aaload();
|
.aaload();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void emitZero(CodeBuilder cob, BasicType type) {
|
private void emitZero(CodeBuilder cob, BasicType type) {
|
||||||
@ -1519,14 +1507,14 @@ class InvokerBytecodeGenerator {
|
|||||||
@Override
|
@Override
|
||||||
public void accept(CodeBuilder cob) {
|
public void accept(CodeBuilder cob) {
|
||||||
// create parameter array
|
// create parameter array
|
||||||
cob.loadConstant(invokerType.parameterCount());
|
cob.loadConstant(invokerType.parameterCount())
|
||||||
cob.anewarray(CD_Object);
|
.anewarray(CD_Object);
|
||||||
|
|
||||||
// fill parameter array
|
// fill parameter array
|
||||||
for (int i = 0; i < invokerType.parameterCount(); i++) {
|
for (int i = 0; i < invokerType.parameterCount(); i++) {
|
||||||
Class<?> ptype = invokerType.parameterType(i);
|
Class<?> ptype = invokerType.parameterType(i);
|
||||||
cob.dup();
|
cob.dup()
|
||||||
cob.loadConstant(i);
|
.loadConstant(i);
|
||||||
emitLoadInsn(cob, basicType(ptype).basicTypeKind(), i);
|
emitLoadInsn(cob, basicType(ptype).basicTypeKind(), i);
|
||||||
// box if primitive type
|
// box if primitive type
|
||||||
if (ptype.isPrimitive()) {
|
if (ptype.isPrimitive()) {
|
||||||
@ -1535,10 +1523,10 @@ class InvokerBytecodeGenerator {
|
|||||||
cob.aastore();
|
cob.aastore();
|
||||||
}
|
}
|
||||||
// invoke
|
// invoke
|
||||||
cob.aload(0);
|
cob.aload(0)
|
||||||
cob.getfield(CD_MethodHandle, "form", CD_LambdaForm);
|
.getfield(CD_MethodHandle, "form", CD_LambdaForm)
|
||||||
cob.swap(); // swap form and array; avoid local variable
|
.swap() // swap form and array; avoid local variable
|
||||||
cob.invokevirtual(CD_LambdaForm, "interpretWithArguments", MethodTypeDescImpl.ofValidated(CD_Object, CD_Object_array));
|
.invokevirtual(CD_LambdaForm, "interpretWithArguments", MethodTypeDescImpl.ofValidated(CD_Object, CD_Object_array));
|
||||||
|
|
||||||
// maybe unbox
|
// maybe unbox
|
||||||
Class<?> rtype = invokerType.returnType();
|
Class<?> rtype = invokerType.returnType();
|
||||||
@ -1592,9 +1580,9 @@ class InvokerBytecodeGenerator {
|
|||||||
|
|
||||||
// Load arguments from array
|
// Load arguments from array
|
||||||
for (int i = 0; i < dstType.parameterCount(); i++) {
|
for (int i = 0; i < dstType.parameterCount(); i++) {
|
||||||
cob.aload(1);
|
cob.aload(1)
|
||||||
cob.loadConstant(i);
|
.loadConstant(i)
|
||||||
cob.aaload();
|
.aaload();
|
||||||
|
|
||||||
// Maybe unbox
|
// Maybe unbox
|
||||||
Class<?> dptype = dstType.parameterType(i);
|
Class<?> dptype = dstType.parameterType(i);
|
||||||
@ -1645,9 +1633,9 @@ class InvokerBytecodeGenerator {
|
|||||||
clb.withMethodBody("dummy", MTD_void, ACC_STATIC, new Consumer<>() {
|
clb.withMethodBody("dummy", MTD_void, ACC_STATIC, new Consumer<>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(CodeBuilder cob) {
|
public void accept(CodeBuilder cob) {
|
||||||
cob.ldc(os.toString());
|
cob.ldc(os.toString())
|
||||||
cob.pop();
|
.pop()
|
||||||
cob.return_();
|
.return_();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -373,46 +373,43 @@ public class MethodHandleProxies {
|
|||||||
String methodName, List<MethodInfo> methods) {
|
String methodName, List<MethodInfo> methods) {
|
||||||
return ClassFile.of(ClassHierarchyResolverOption.of(ClassHierarchyResolver.ofClassLoading(loader)))
|
return ClassFile.of(ClassHierarchyResolverOption.of(ClassHierarchyResolver.ofClassLoading(loader)))
|
||||||
.build(proxyDesc, clb -> {
|
.build(proxyDesc, clb -> {
|
||||||
clb.withSuperclass(CD_Object);
|
clb.withSuperclass(CD_Object)
|
||||||
clb.withFlags(ACC_FINAL | ACC_SYNTHETIC);
|
.withFlags(ACC_FINAL | ACC_SYNTHETIC)
|
||||||
clb.withInterfaceSymbols(ifaceDesc);
|
.withInterfaceSymbols(ifaceDesc)
|
||||||
|
|
||||||
// static and instance fields
|
// static and instance fields
|
||||||
clb.withField(TYPE_NAME, CD_Class, ACC_PRIVATE | ACC_STATIC | ACC_FINAL);
|
.withField(TYPE_NAME, CD_Class, ACC_PRIVATE | ACC_STATIC | ACC_FINAL)
|
||||||
clb.withField(TARGET_NAME, CD_MethodHandle, ACC_PRIVATE | ACC_FINAL);
|
.withField(TARGET_NAME, CD_MethodHandle, ACC_PRIVATE | ACC_FINAL);
|
||||||
for (var mi : methods) {
|
for (var mi : methods) {
|
||||||
clb.withField(mi.fieldName, CD_MethodHandle, ACC_PRIVATE | ACC_FINAL);
|
clb.withField(mi.fieldName, CD_MethodHandle, ACC_PRIVATE | ACC_FINAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// <clinit>
|
// <clinit>
|
||||||
clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, cob -> {
|
clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, cob -> {
|
||||||
cob.loadConstant(ifaceDesc);
|
cob.loadConstant(ifaceDesc)
|
||||||
cob.putstatic(proxyDesc, TYPE_NAME, CD_Class);
|
.putstatic(proxyDesc, TYPE_NAME, CD_Class)
|
||||||
cob.return_();
|
.return_();
|
||||||
});
|
});
|
||||||
|
|
||||||
// <init>(Lookup, MethodHandle target, MethodHandle callerBoundTarget)
|
// <init>(Lookup, MethodHandle target, MethodHandle callerBoundTarget)
|
||||||
clb.withMethodBody(INIT_NAME, MTD_void_Lookup_MethodHandle_MethodHandle, 0, cob -> {
|
clb.withMethodBody(INIT_NAME, MTD_void_Lookup_MethodHandle_MethodHandle, 0, cob -> {
|
||||||
cob.aload(0);
|
cob.aload(0)
|
||||||
cob.invokespecial(CD_Object, INIT_NAME, MTD_void);
|
.invokespecial(CD_Object, INIT_NAME, MTD_void)
|
||||||
|
|
||||||
// call ensureOriginalLookup to verify the given Lookup has access
|
// call ensureOriginalLookup to verify the given Lookup has access
|
||||||
cob.aload(1);
|
.aload(1)
|
||||||
cob.invokestatic(proxyDesc, "ensureOriginalLookup", MTD_void_Lookup);
|
.invokestatic(proxyDesc, ENSURE_ORIGINAL_LOOKUP, MTD_void_Lookup)
|
||||||
|
|
||||||
// this.target = target;
|
// this.target = target;
|
||||||
cob.aload(0);
|
.aload(0)
|
||||||
cob.aload(2);
|
.aload(2)
|
||||||
cob.putfield(proxyDesc, TARGET_NAME, CD_MethodHandle);
|
.putfield(proxyDesc, TARGET_NAME, CD_MethodHandle);
|
||||||
|
|
||||||
// method handles adjusted to the method type of each method
|
// method handles adjusted to the method type of each method
|
||||||
for (var mi : methods) {
|
for (var mi : methods) {
|
||||||
// this.m<i> = callerBoundTarget.asType(xxType);
|
// this.m<i> = callerBoundTarget.asType(xxType);
|
||||||
cob.aload(0);
|
cob.aload(0)
|
||||||
cob.aload(3);
|
.aload(3)
|
||||||
cob.loadConstant(mi.desc);
|
.loadConstant(mi.desc)
|
||||||
cob.invokevirtual(CD_MethodHandle, "asType", MTD_MethodHandle_MethodType);
|
.invokevirtual(CD_MethodHandle, "asType", MTD_MethodHandle_MethodType)
|
||||||
cob.putfield(proxyDesc, mi.fieldName, CD_MethodHandle);
|
.putfield(proxyDesc, mi.fieldName, CD_MethodHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// complete
|
// complete
|
||||||
@ -425,26 +422,26 @@ public class MethodHandleProxies {
|
|||||||
clb.withMethodBody(ENSURE_ORIGINAL_LOOKUP, MTD_void_Lookup, ACC_PRIVATE | ACC_STATIC, cob -> {
|
clb.withMethodBody(ENSURE_ORIGINAL_LOOKUP, MTD_void_Lookup, ACC_PRIVATE | ACC_STATIC, cob -> {
|
||||||
var failLabel = cob.newLabel();
|
var failLabel = cob.newLabel();
|
||||||
// check lookupClass
|
// check lookupClass
|
||||||
cob.aload(0);
|
cob.aload(0)
|
||||||
cob.invokevirtual(CD_MethodHandles_Lookup, "lookupClass", MTD_Class);
|
.invokevirtual(CD_MethodHandles_Lookup, "lookupClass", MTD_Class)
|
||||||
cob.loadConstant(proxyDesc);
|
.loadConstant(proxyDesc)
|
||||||
cob.if_acmpne(failLabel);
|
.if_acmpne(failLabel)
|
||||||
// check original access
|
// check original access
|
||||||
cob.aload(0);
|
.aload(0)
|
||||||
cob.invokevirtual(CD_MethodHandles_Lookup, "lookupModes", MTD_int);
|
.invokevirtual(CD_MethodHandles_Lookup, "lookupModes", MTD_int)
|
||||||
cob.loadConstant(Lookup.ORIGINAL);
|
.loadConstant(Lookup.ORIGINAL)
|
||||||
cob.iand();
|
.iand()
|
||||||
cob.ifeq(failLabel);
|
.ifeq(failLabel)
|
||||||
// success
|
// success
|
||||||
cob.return_();
|
.return_()
|
||||||
// throw exception
|
// throw exception
|
||||||
cob.labelBinding(failLabel);
|
.labelBinding(failLabel)
|
||||||
cob.new_(CD_IllegalAccessException);
|
.new_(CD_IllegalAccessException)
|
||||||
cob.dup();
|
.dup()
|
||||||
cob.aload(0); // lookup
|
.aload(0) // lookup
|
||||||
cob.invokevirtual(CD_Object, "toString", MTD_String);
|
.invokevirtual(CD_Object, "toString", MTD_String)
|
||||||
cob.invokespecial(CD_IllegalAccessException, INIT_NAME, MTD_void_String);
|
.invokespecial(CD_IllegalAccessException, INIT_NAME, MTD_void_String)
|
||||||
cob.athrow();
|
.athrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
// implementation methods
|
// implementation methods
|
||||||
@ -453,14 +450,14 @@ public class MethodHandleProxies {
|
|||||||
clb.withMethodBody(methodName, mi.desc, ACC_PUBLIC, cob -> cob
|
clb.withMethodBody(methodName, mi.desc, ACC_PUBLIC, cob -> cob
|
||||||
.trying(bcb -> {
|
.trying(bcb -> {
|
||||||
// return this.handleField.invokeExact(arguments...);
|
// return this.handleField.invokeExact(arguments...);
|
||||||
bcb.aload(0);
|
bcb.aload(0)
|
||||||
bcb.getfield(proxyDesc, mi.fieldName, CD_MethodHandle);
|
.getfield(proxyDesc, mi.fieldName, CD_MethodHandle);
|
||||||
for (int j = 0; j < mi.desc.parameterCount(); j++) {
|
for (int j = 0; j < mi.desc.parameterCount(); j++) {
|
||||||
bcb.loadLocal(TypeKind.from(mi.desc.parameterType(j)),
|
bcb.loadLocal(TypeKind.from(mi.desc.parameterType(j)),
|
||||||
bcb.parameterSlot(j));
|
bcb.parameterSlot(j));
|
||||||
}
|
}
|
||||||
bcb.invokevirtual(CD_MethodHandle, "invokeExact", mi.desc);
|
bcb.invokevirtual(CD_MethodHandle, "invokeExact", mi.desc)
|
||||||
bcb.return_(TypeKind.from(mi.desc.returnType()));
|
.return_(TypeKind.from(mi.desc.returnType()));
|
||||||
}, ctb -> ctb
|
}, ctb -> ctb
|
||||||
// catch (Error | RuntimeException | Declared ex) { throw ex; }
|
// catch (Error | RuntimeException | Declared ex) { throw ex; }
|
||||||
.catchingMulti(mi.thrown, CodeBuilder::athrow)
|
.catchingMulti(mi.thrown, CodeBuilder::athrow)
|
||||||
|
@ -29,7 +29,6 @@ import java.lang.Enum.EnumDesc;
|
|||||||
import java.lang.classfile.CodeBuilder;
|
import java.lang.classfile.CodeBuilder;
|
||||||
import java.lang.constant.ClassDesc;
|
import java.lang.constant.ClassDesc;
|
||||||
import java.lang.constant.ConstantDesc;
|
import java.lang.constant.ConstantDesc;
|
||||||
import java.lang.constant.ConstantDescs;
|
|
||||||
import java.lang.constant.MethodTypeDesc;
|
import java.lang.constant.MethodTypeDesc;
|
||||||
import java.lang.invoke.CallSite;
|
import java.lang.invoke.CallSite;
|
||||||
import java.lang.invoke.ConstantCallSite;
|
import java.lang.invoke.ConstantCallSite;
|
||||||
@ -55,6 +54,7 @@ import jdk.internal.constant.ReferenceClassDescImpl;
|
|||||||
import jdk.internal.misc.PreviewFeatures;
|
import jdk.internal.misc.PreviewFeatures;
|
||||||
import jdk.internal.vm.annotation.Stable;
|
import jdk.internal.vm.annotation.Stable;
|
||||||
|
|
||||||
|
import static java.lang.constant.ConstantDescs.*;
|
||||||
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE;
|
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE;
|
||||||
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.STRONG;
|
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.STRONG;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -86,15 +86,15 @@ public class SwitchBootstraps {
|
|||||||
private static final ClassDesc CD_Objects = ReferenceClassDescImpl.ofValidated("Ljava/util/Objects;");
|
private static final ClassDesc CD_Objects = ReferenceClassDescImpl.ofValidated("Ljava/util/Objects;");
|
||||||
|
|
||||||
private static final MethodTypeDesc CHECK_INDEX_DESCRIPTOR =
|
private static final MethodTypeDesc CHECK_INDEX_DESCRIPTOR =
|
||||||
MethodTypeDescImpl.ofValidated(ConstantDescs.CD_int, ConstantDescs.CD_int, ConstantDescs.CD_int);
|
MethodTypeDescImpl.ofValidated(CD_int, CD_int, CD_int);
|
||||||
private static final MethodTypeDesc MTD_TYPE_SWITCH = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_int,
|
private static final MethodTypeDesc MTD_TYPE_SWITCH = MethodTypeDescImpl.ofValidated(CD_int,
|
||||||
ConstantDescs.CD_Object,
|
CD_Object,
|
||||||
ConstantDescs.CD_int);
|
CD_int);
|
||||||
private static final MethodTypeDesc MTD_TYPE_SWITCH_EXTRA = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_int,
|
private static final MethodTypeDesc MTD_TYPE_SWITCH_EXTRA = MethodTypeDescImpl.ofValidated(CD_int,
|
||||||
ConstantDescs.CD_Object,
|
CD_Object,
|
||||||
ConstantDescs.CD_int,
|
CD_int,
|
||||||
CD_BiPredicate,
|
CD_BiPredicate,
|
||||||
ConstantDescs.CD_List);
|
CD_List);
|
||||||
private static final MethodType MT_TYPE_SWITCH_EXTRA = MethodType.methodType(int.class,
|
private static final MethodType MT_TYPE_SWITCH_EXTRA = MethodType.methodType(int.class,
|
||||||
Object.class,
|
Object.class,
|
||||||
int.class,
|
int.class,
|
||||||
@ -484,16 +484,16 @@ public class SwitchBootstraps {
|
|||||||
|
|
||||||
return cb -> {
|
return cb -> {
|
||||||
// Objects.checkIndex(RESTART_IDX, labelConstants + 1)
|
// Objects.checkIndex(RESTART_IDX, labelConstants + 1)
|
||||||
cb.iload(RESTART_IDX);
|
cb.iload(RESTART_IDX)
|
||||||
cb.loadConstant(labelConstants.length + 1);
|
.loadConstant(labelConstants.length + 1)
|
||||||
cb.invokestatic(CD_Objects, "checkIndex", CHECK_INDEX_DESCRIPTOR);
|
.invokestatic(CD_Objects, "checkIndex", CHECK_INDEX_DESCRIPTOR)
|
||||||
cb.pop();
|
.pop()
|
||||||
cb.aload(SELECTOR_OBJ);
|
.aload(SELECTOR_OBJ);
|
||||||
Label nonNullLabel = cb.newLabel();
|
Label nonNullLabel = cb.newLabel();
|
||||||
cb.ifnonnull(nonNullLabel);
|
cb.ifnonnull(nonNullLabel)
|
||||||
cb.iconst_m1();
|
.iconst_m1()
|
||||||
cb.ireturn();
|
.ireturn()
|
||||||
cb.labelBinding(nonNullLabel);
|
.labelBinding(nonNullLabel);
|
||||||
if (labelConstants.length == 0) {
|
if (labelConstants.length == 0) {
|
||||||
cb.loadConstant(0)
|
cb.loadConstant(0)
|
||||||
.ireturn();
|
.ireturn();
|
||||||
@ -535,132 +535,132 @@ public class SwitchBootstraps {
|
|||||||
if (!selectorType.isPrimitive() && !Wrapper.isWrapperNumericOrBooleanType(selectorType)) {
|
if (!selectorType.isPrimitive() && !Wrapper.isWrapperNumericOrBooleanType(selectorType)) {
|
||||||
// Object o = ...
|
// Object o = ...
|
||||||
// o instanceof Wrapped(float)
|
// o instanceof Wrapped(float)
|
||||||
cb.aload(SELECTOR_OBJ);
|
cb.aload(SELECTOR_OBJ)
|
||||||
cb.instanceOf(Wrapper.forBasicType(classLabel).wrapperClassDescriptor());
|
.instanceOf(Wrapper.forBasicType(classLabel).wrapperClassDescriptor())
|
||||||
cb.ifeq(next);
|
.ifeq(next);
|
||||||
} else if (!unconditionalExactnessCheck(Wrapper.asPrimitiveType(selectorType), classLabel)) {
|
} else if (!unconditionalExactnessCheck(Wrapper.asPrimitiveType(selectorType), classLabel)) {
|
||||||
// Integer i = ... or int i = ...
|
// Integer i = ... or int i = ...
|
||||||
// o instanceof float
|
// o instanceof float
|
||||||
Label notNumber = cb.newLabel();
|
Label notNumber = cb.newLabel();
|
||||||
cb.aload(SELECTOR_OBJ);
|
cb.aload(SELECTOR_OBJ)
|
||||||
cb.instanceOf(ConstantDescs.CD_Number);
|
.instanceOf(CD_Number);
|
||||||
if (selectorType == long.class || selectorType == float.class || selectorType == double.class ||
|
if (selectorType == long.class || selectorType == float.class || selectorType == double.class ||
|
||||||
selectorType == Long.class || selectorType == Float.class || selectorType == Double.class) {
|
selectorType == Long.class || selectorType == Float.class || selectorType == Double.class) {
|
||||||
cb.ifeq(next);
|
cb.ifeq(next);
|
||||||
} else {
|
} else {
|
||||||
cb.ifeq(notNumber);
|
cb.ifeq(notNumber);
|
||||||
}
|
}
|
||||||
cb.aload(SELECTOR_OBJ);
|
cb.aload(SELECTOR_OBJ)
|
||||||
cb.checkcast(ConstantDescs.CD_Number);
|
.checkcast(CD_Number);
|
||||||
if (selectorType == long.class || selectorType == Long.class) {
|
if (selectorType == long.class || selectorType == Long.class) {
|
||||||
cb.invokevirtual(ConstantDescs.CD_Number,
|
cb.invokevirtual(CD_Number,
|
||||||
"longValue",
|
"longValue",
|
||||||
MethodTypeDesc.of(ConstantDescs.CD_long));
|
MethodTypeDesc.of(CD_long));
|
||||||
} else if (selectorType == float.class || selectorType == Float.class) {
|
} else if (selectorType == float.class || selectorType == Float.class) {
|
||||||
cb.invokevirtual(ConstantDescs.CD_Number,
|
cb.invokevirtual(CD_Number,
|
||||||
"floatValue",
|
"floatValue",
|
||||||
MethodTypeDesc.of(ConstantDescs.CD_float));
|
MethodTypeDesc.of(CD_float));
|
||||||
} else if (selectorType == double.class || selectorType == Double.class) {
|
} else if (selectorType == double.class || selectorType == Double.class) {
|
||||||
cb.invokevirtual(ConstantDescs.CD_Number,
|
cb.invokevirtual(CD_Number,
|
||||||
"doubleValue",
|
"doubleValue",
|
||||||
MethodTypeDesc.of(ConstantDescs.CD_double));
|
MethodTypeDesc.of(CD_double));
|
||||||
} else {
|
} else {
|
||||||
Label compare = cb.newLabel();
|
Label compare = cb.newLabel();
|
||||||
cb.invokevirtual(ConstantDescs.CD_Number,
|
cb.invokevirtual(CD_Number,
|
||||||
"intValue",
|
"intValue",
|
||||||
MethodTypeDesc.of(ConstantDescs.CD_int));
|
MethodTypeDesc.of(CD_int))
|
||||||
cb.goto_(compare);
|
.goto_(compare)
|
||||||
cb.labelBinding(notNumber);
|
.labelBinding(notNumber)
|
||||||
cb.aload(SELECTOR_OBJ);
|
.aload(SELECTOR_OBJ)
|
||||||
cb.instanceOf(ConstantDescs.CD_Character);
|
.instanceOf(CD_Character)
|
||||||
cb.ifeq(next);
|
.ifeq(next)
|
||||||
cb.aload(SELECTOR_OBJ);
|
.aload(SELECTOR_OBJ)
|
||||||
cb.checkcast(ConstantDescs.CD_Character);
|
.checkcast(CD_Character)
|
||||||
cb.invokevirtual(ConstantDescs.CD_Character,
|
.invokevirtual(CD_Character,
|
||||||
"charValue",
|
"charValue",
|
||||||
MethodTypeDesc.of(ConstantDescs.CD_char));
|
MethodTypeDesc.of(CD_char))
|
||||||
cb.labelBinding(compare);
|
.labelBinding(compare);
|
||||||
}
|
}
|
||||||
|
|
||||||
TypePairs typePair = TypePairs.of(Wrapper.asPrimitiveType(selectorType), classLabel);
|
TypePairs typePair = TypePairs.of(Wrapper.asPrimitiveType(selectorType), classLabel);
|
||||||
String methodName = TypePairs.typePairToName.get(typePair);
|
String methodName = TypePairs.typePairToName.get(typePair);
|
||||||
cb.invokestatic(referenceClassDesc(ExactConversionsSupport.class),
|
cb.invokestatic(referenceClassDesc(ExactConversionsSupport.class),
|
||||||
methodName,
|
methodName,
|
||||||
MethodTypeDesc.of(ConstantDescs.CD_boolean, classDesc(typePair.from)));
|
MethodTypeDesc.of(CD_boolean, classDesc(typePair.from)))
|
||||||
cb.ifeq(next);
|
.ifeq(next);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Optional<ClassDesc> classLabelConstableOpt = classLabel.describeConstable();
|
Optional<ClassDesc> classLabelConstableOpt = classLabel.describeConstable();
|
||||||
if (classLabelConstableOpt.isPresent()) {
|
if (classLabelConstableOpt.isPresent()) {
|
||||||
cb.aload(SELECTOR_OBJ);
|
cb.aload(SELECTOR_OBJ)
|
||||||
cb.instanceOf(classLabelConstableOpt.orElseThrow());
|
.instanceOf(classLabelConstableOpt.orElseThrow())
|
||||||
cb.ifeq(next);
|
.ifeq(next);
|
||||||
} else {
|
} else {
|
||||||
cb.aload(EXTRA_CLASS_LABELS);
|
cb.aload(EXTRA_CLASS_LABELS)
|
||||||
cb.loadConstant(extraClassLabels.size());
|
.loadConstant(extraClassLabels.size())
|
||||||
cb.invokeinterface(ConstantDescs.CD_List,
|
.invokeinterface(CD_List,
|
||||||
"get",
|
"get",
|
||||||
MethodTypeDesc.of(ConstantDescs.CD_Object,
|
MethodTypeDesc.of(CD_Object,
|
||||||
ConstantDescs.CD_int));
|
CD_int))
|
||||||
cb.checkcast(ConstantDescs.CD_Class);
|
.checkcast(CD_Class)
|
||||||
cb.aload(SELECTOR_OBJ);
|
.aload(SELECTOR_OBJ)
|
||||||
cb.invokevirtual(ConstantDescs.CD_Class,
|
.invokevirtual(CD_Class,
|
||||||
"isInstance",
|
"isInstance",
|
||||||
MethodTypeDesc.of(ConstantDescs.CD_boolean,
|
MethodTypeDesc.of(CD_boolean,
|
||||||
ConstantDescs.CD_Object));
|
CD_Object))
|
||||||
cb.ifeq(next);
|
.ifeq(next);
|
||||||
extraClassLabels.add(classLabel);
|
extraClassLabels.add(classLabel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (caseLabel instanceof EnumDesc<?> enumLabel) {
|
} else if (caseLabel instanceof EnumDesc<?> enumLabel) {
|
||||||
int enumIdx = enumDescs.size();
|
int enumIdx = enumDescs.size();
|
||||||
enumDescs.add(enumLabel);
|
enumDescs.add(enumLabel);
|
||||||
cb.aload(ENUM_CACHE);
|
cb.aload(ENUM_CACHE)
|
||||||
cb.loadConstant(enumIdx);
|
.loadConstant(enumIdx)
|
||||||
cb.invokestatic(ConstantDescs.CD_Integer,
|
.invokestatic(CD_Integer,
|
||||||
"valueOf",
|
"valueOf",
|
||||||
MethodTypeDesc.of(ConstantDescs.CD_Integer,
|
MethodTypeDesc.of(CD_Integer,
|
||||||
ConstantDescs.CD_int));
|
CD_int))
|
||||||
cb.aload(SELECTOR_OBJ);
|
.aload(SELECTOR_OBJ)
|
||||||
cb.invokeinterface(CD_BiPredicate,
|
.invokeinterface(CD_BiPredicate,
|
||||||
"test",
|
"test",
|
||||||
MethodTypeDesc.of(ConstantDescs.CD_boolean,
|
MethodTypeDesc.of(CD_boolean,
|
||||||
ConstantDescs.CD_Object,
|
CD_Object,
|
||||||
ConstantDescs.CD_Object));
|
CD_Object))
|
||||||
cb.ifeq(next);
|
.ifeq(next);
|
||||||
} else if (caseLabel instanceof String stringLabel) {
|
} else if (caseLabel instanceof String stringLabel) {
|
||||||
cb.ldc(stringLabel);
|
cb.ldc(stringLabel)
|
||||||
cb.aload(SELECTOR_OBJ);
|
.aload(SELECTOR_OBJ)
|
||||||
cb.invokevirtual(ConstantDescs.CD_Object,
|
.invokevirtual(CD_Object,
|
||||||
"equals",
|
"equals",
|
||||||
MethodTypeDesc.of(ConstantDescs.CD_boolean,
|
MethodTypeDesc.of(CD_boolean,
|
||||||
ConstantDescs.CD_Object));
|
CD_Object))
|
||||||
cb.ifeq(next);
|
.ifeq(next);
|
||||||
} else if (caseLabel instanceof Integer integerLabel) {
|
} else if (caseLabel instanceof Integer integerLabel) {
|
||||||
Label compare = cb.newLabel();
|
Label compare = cb.newLabel();
|
||||||
Label notNumber = cb.newLabel();
|
Label notNumber = cb.newLabel();
|
||||||
cb.aload(SELECTOR_OBJ);
|
cb.aload(SELECTOR_OBJ)
|
||||||
cb.instanceOf(ConstantDescs.CD_Number);
|
.instanceOf(CD_Number)
|
||||||
cb.ifeq(notNumber);
|
.ifeq(notNumber)
|
||||||
cb.aload(SELECTOR_OBJ);
|
.aload(SELECTOR_OBJ)
|
||||||
cb.checkcast(ConstantDescs.CD_Number);
|
.checkcast(CD_Number)
|
||||||
cb.invokevirtual(ConstantDescs.CD_Number,
|
.invokevirtual(CD_Number,
|
||||||
"intValue",
|
"intValue",
|
||||||
MethodTypeDesc.of(ConstantDescs.CD_int));
|
MethodTypeDesc.of(CD_int))
|
||||||
cb.goto_(compare);
|
.goto_(compare)
|
||||||
cb.labelBinding(notNumber);
|
.labelBinding(notNumber)
|
||||||
cb.aload(SELECTOR_OBJ);
|
.aload(SELECTOR_OBJ)
|
||||||
cb.instanceOf(ConstantDescs.CD_Character);
|
.instanceOf(CD_Character)
|
||||||
cb.ifeq(next);
|
.ifeq(next)
|
||||||
cb.aload(SELECTOR_OBJ);
|
.aload(SELECTOR_OBJ)
|
||||||
cb.checkcast(ConstantDescs.CD_Character);
|
.checkcast(CD_Character)
|
||||||
cb.invokevirtual(ConstantDescs.CD_Character,
|
.invokevirtual(CD_Character,
|
||||||
"charValue",
|
"charValue",
|
||||||
MethodTypeDesc.of(ConstantDescs.CD_char));
|
MethodTypeDesc.of(CD_char))
|
||||||
cb.labelBinding(compare);
|
.labelBinding(compare)
|
||||||
|
|
||||||
cb.loadConstant(integerLabel);
|
.loadConstant(integerLabel)
|
||||||
cb.if_icmpne(next);
|
.if_icmpne(next);
|
||||||
} else if ((caseLabel instanceof Long ||
|
} else if ((caseLabel instanceof Long ||
|
||||||
caseLabel instanceof Float ||
|
caseLabel instanceof Float ||
|
||||||
caseLabel instanceof Double ||
|
caseLabel instanceof Double ||
|
||||||
@ -674,23 +674,23 @@ public class SwitchBootstraps {
|
|||||||
cb.invokestatic(caseLabelWrapper.wrapperClassDescriptor(),
|
cb.invokestatic(caseLabelWrapper.wrapperClassDescriptor(),
|
||||||
"valueOf",
|
"valueOf",
|
||||||
MethodTypeDesc.of(caseLabelWrapper.wrapperClassDescriptor(),
|
MethodTypeDesc.of(caseLabelWrapper.wrapperClassDescriptor(),
|
||||||
caseLabelWrapper.basicClassDescriptor()));
|
caseLabelWrapper.basicClassDescriptor()))
|
||||||
cb.aload(SELECTOR_OBJ);
|
.aload(SELECTOR_OBJ)
|
||||||
cb.invokevirtual(ConstantDescs.CD_Object,
|
.invokevirtual(CD_Object,
|
||||||
"equals",
|
"equals",
|
||||||
MethodTypeDesc.of(ConstantDescs.CD_boolean,
|
MethodTypeDesc.of(CD_boolean,
|
||||||
ConstantDescs.CD_Object));
|
CD_Object))
|
||||||
cb.ifeq(next);
|
.ifeq(next);
|
||||||
} else {
|
} else {
|
||||||
throw new InternalError("Unsupported label type: " +
|
throw new InternalError("Unsupported label type: " +
|
||||||
caseLabel.getClass());
|
caseLabel.getClass());
|
||||||
}
|
}
|
||||||
cb.loadConstant(idx);
|
cb.loadConstant(idx)
|
||||||
cb.ireturn();
|
.ireturn();
|
||||||
}
|
}
|
||||||
cb.labelBinding(dflt);
|
cb.labelBinding(dflt)
|
||||||
cb.loadConstant(labelConstants.length);
|
.loadConstant(labelConstants.length)
|
||||||
cb.ireturn();
|
.ireturn();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,11 +193,10 @@ public class BindingSpecializer {
|
|||||||
CallingSequence callingSequence, ABIDescriptor abi) {
|
CallingSequence callingSequence, ABIDescriptor abi) {
|
||||||
String className = callingSequence.forDowncall() ? CLASS_NAME_DOWNCALL : CLASS_NAME_UPCALL;
|
String className = callingSequence.forDowncall() ? CLASS_NAME_DOWNCALL : CLASS_NAME_UPCALL;
|
||||||
byte[] bytes = ClassFile.of().build(ClassDesc.ofInternalName(className), clb -> {
|
byte[] bytes = ClassFile.of().build(ClassDesc.ofInternalName(className), clb -> {
|
||||||
clb.withFlags(ACC_PUBLIC + ACC_FINAL + ACC_SUPER);
|
clb.withFlags(ACC_PUBLIC + ACC_FINAL + ACC_SUPER)
|
||||||
clb.withSuperclass(CD_Object);
|
.withSuperclass(CD_Object)
|
||||||
clb.withVersion(CLASSFILE_VERSION, 0);
|
.withVersion(CLASSFILE_VERSION, 0)
|
||||||
|
.withMethodBody(METHOD_NAME, methodTypeDesc(callerMethodType), ACC_PUBLIC | ACC_STATIC,
|
||||||
clb.withMethodBody(METHOD_NAME, methodTypeDesc(callerMethodType), ACC_PUBLIC | ACC_STATIC,
|
|
||||||
cb -> new BindingSpecializer(cb, callerMethodType, callingSequence, abi, leafType).specialize());
|
cb -> new BindingSpecializer(cb, callerMethodType, callingSequence, abi, leafType).specialize());
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -275,8 +274,8 @@ public class BindingSpecializer {
|
|||||||
if (shouldAcquire(i)) {
|
if (shouldAcquire(i)) {
|
||||||
int scopeLocal = cb.allocateLocal(REFERENCE);
|
int scopeLocal = cb.allocateLocal(REFERENCE);
|
||||||
initialScopeSlots[numScopes++] = scopeLocal;
|
initialScopeSlots[numScopes++] = scopeLocal;
|
||||||
cb.loadConstant(null);
|
cb.aconst_null()
|
||||||
cb.storeLocal(REFERENCE, scopeLocal); // need to initialize all scope locals here in case an exception occurs
|
.astore(scopeLocal); // need to initialize all scope locals here in case an exception occurs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scopeSlots = Arrays.copyOf(initialScopeSlots, numScopes); // fit to size
|
scopeSlots = Arrays.copyOf(initialScopeSlots, numScopes); // fit to size
|
||||||
@ -285,15 +284,15 @@ public class BindingSpecializer {
|
|||||||
|
|
||||||
// create a Binding.Context for this call
|
// create a Binding.Context for this call
|
||||||
if (callingSequence.allocationSize() != 0) {
|
if (callingSequence.allocationSize() != 0) {
|
||||||
cb.loadConstant(callingSequence.allocationSize());
|
cb.loadConstant(callingSequence.allocationSize())
|
||||||
cb.invokestatic(CD_SharedUtils, "newBoundedArena", MTD_NEW_BOUNDED_ARENA);
|
.invokestatic(CD_SharedUtils, "newBoundedArena", MTD_NEW_BOUNDED_ARENA);
|
||||||
} else if (callingSequence.forUpcall() && needsSession()) {
|
} else if (callingSequence.forUpcall() && needsSession()) {
|
||||||
cb.invokestatic(CD_SharedUtils, "newEmptyArena", MTD_NEW_EMPTY_ARENA);
|
cb.invokestatic(CD_SharedUtils, "newEmptyArena", MTD_NEW_EMPTY_ARENA);
|
||||||
} else {
|
} else {
|
||||||
cb.getstatic(CD_SharedUtils, "DUMMY_ARENA", CD_Arena);
|
cb.getstatic(CD_SharedUtils, "DUMMY_ARENA", CD_Arena);
|
||||||
}
|
}
|
||||||
contextIdx = cb.allocateLocal(REFERENCE);
|
contextIdx = cb.allocateLocal(REFERENCE);
|
||||||
cb.storeLocal(REFERENCE, contextIdx);
|
cb.astore(contextIdx);
|
||||||
|
|
||||||
// in case the call needs a return buffer, allocate it here.
|
// in case the call needs a return buffer, allocate it here.
|
||||||
// for upcalls the VM wrapper stub allocates the buffer.
|
// for upcalls the VM wrapper stub allocates the buffer.
|
||||||
@ -301,7 +300,7 @@ public class BindingSpecializer {
|
|||||||
emitLoadInternalAllocator();
|
emitLoadInternalAllocator();
|
||||||
emitAllocateCall(callingSequence.returnBufferSize(), 1);
|
emitAllocateCall(callingSequence.returnBufferSize(), 1);
|
||||||
returnBufferIdx = cb.allocateLocal(REFERENCE);
|
returnBufferIdx = cb.allocateLocal(REFERENCE);
|
||||||
cb.storeLocal(REFERENCE, returnBufferIdx);
|
cb.astore(returnBufferIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
Label tryStart = cb.newLabel();
|
Label tryStart = cb.newLabel();
|
||||||
@ -324,7 +323,7 @@ public class BindingSpecializer {
|
|||||||
// for downcalls, recipes have an input value, which we set up here
|
// for downcalls, recipes have an input value, which we set up here
|
||||||
if (callingSequence.needsReturnBuffer() && i == 0) {
|
if (callingSequence.needsReturnBuffer() && i == 0) {
|
||||||
assert returnBufferIdx != -1;
|
assert returnBufferIdx != -1;
|
||||||
cb.loadLocal(REFERENCE, returnBufferIdx);
|
cb.aload(returnBufferIdx);
|
||||||
pushType(MemorySegment.class);
|
pushType(MemorySegment.class);
|
||||||
} else {
|
} else {
|
||||||
emitGetInput();
|
emitGetInput();
|
||||||
@ -340,7 +339,7 @@ public class BindingSpecializer {
|
|||||||
// return buffer ptr is wrapped in a MemorySegment above, but not passed to the leaf handle
|
// return buffer ptr is wrapped in a MemorySegment above, but not passed to the leaf handle
|
||||||
popType(MemorySegment.class);
|
popType(MemorySegment.class);
|
||||||
returnBufferIdx = cb.allocateLocal(REFERENCE);
|
returnBufferIdx = cb.allocateLocal(REFERENCE);
|
||||||
cb.storeLocal(REFERENCE, returnBufferIdx);
|
cb.astore(returnBufferIdx);
|
||||||
} else {
|
} else {
|
||||||
// for upcalls the recipe result is an argument to the leaf handle
|
// for upcalls the recipe result is an argument to the leaf handle
|
||||||
emitSetOutput(typeStack.pop());
|
emitSetOutput(typeStack.pop());
|
||||||
@ -355,7 +354,7 @@ public class BindingSpecializer {
|
|||||||
if (callingSequence.forDowncall()) {
|
if (callingSequence.forDowncall()) {
|
||||||
cb.loadConstant(CLASS_DATA_DESC);
|
cb.loadConstant(CLASS_DATA_DESC);
|
||||||
} else {
|
} else {
|
||||||
cb.loadLocal(REFERENCE, 0); // load target arg
|
cb.aload(0); // load target arg
|
||||||
}
|
}
|
||||||
cb.checkcast(CD_MethodHandle);
|
cb.checkcast(CD_MethodHandle);
|
||||||
// load all the leaf args
|
// load all the leaf args
|
||||||
@ -496,8 +495,8 @@ public class BindingSpecializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void emitAcquireScope() {
|
private void emitAcquireScope() {
|
||||||
cb.checkcast(CD_AbstractMemorySegmentImpl);
|
cb.checkcast(CD_AbstractMemorySegmentImpl)
|
||||||
cb.invokevirtual(CD_AbstractMemorySegmentImpl, "sessionImpl", MTD_SESSION_IMPL);
|
.invokevirtual(CD_AbstractMemorySegmentImpl, "sessionImpl", MTD_SESSION_IMPL);
|
||||||
Label skipAcquire = cb.newLabel();
|
Label skipAcquire = cb.newLabel();
|
||||||
Label end = cb.newLabel();
|
Label end = cb.newLabel();
|
||||||
|
|
||||||
@ -505,23 +504,22 @@ public class BindingSpecializer {
|
|||||||
assert curScopeLocalIdx != -1;
|
assert curScopeLocalIdx != -1;
|
||||||
boolean hasOtherScopes = curScopeLocalIdx != 0;
|
boolean hasOtherScopes = curScopeLocalIdx != 0;
|
||||||
for (int i = 0; i < curScopeLocalIdx; i++) {
|
for (int i = 0; i < curScopeLocalIdx; i++) {
|
||||||
cb.dup(); // dup for comparison
|
cb.dup() // dup for comparison
|
||||||
cb.loadLocal(REFERENCE, scopeSlots[i]);
|
.aload(scopeSlots[i])
|
||||||
cb.if_acmpeq(skipAcquire);
|
.if_acmpeq(skipAcquire);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1 scope to acquire on the stack
|
// 1 scope to acquire on the stack
|
||||||
cb.dup();
|
cb.dup();
|
||||||
int nextScopeLocal = scopeSlots[curScopeLocalIdx++];
|
int nextScopeLocal = scopeSlots[curScopeLocalIdx++];
|
||||||
// call acquire first here. So that if it fails, we don't call release
|
// 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.invokevirtual(CD_MemorySessionImpl, "acquire0", MTD_ACQUIRE0) // call acquire on the other
|
||||||
cb.storeLocal(REFERENCE, nextScopeLocal); // store off one to release later
|
.astore(nextScopeLocal); // store off one to release later
|
||||||
|
|
||||||
if (hasOtherScopes) { // avoid ASM generating a bunch of nops for the dead code
|
if (hasOtherScopes) { // avoid ASM generating a bunch of nops for the dead code
|
||||||
cb.goto_(end);
|
cb.goto_(end)
|
||||||
|
.labelBinding(skipAcquire)
|
||||||
cb.labelBinding(skipAcquire);
|
.pop(); // drop scope
|
||||||
cb.pop(); // drop scope
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cb.labelBinding(end);
|
cb.labelBinding(end);
|
||||||
@ -529,10 +527,10 @@ public class BindingSpecializer {
|
|||||||
|
|
||||||
private void emitReleaseScopes() {
|
private void emitReleaseScopes() {
|
||||||
for (int scopeLocal : scopeSlots) {
|
for (int scopeLocal : scopeSlots) {
|
||||||
cb.loadLocal(REFERENCE, scopeLocal);
|
cb.aload(scopeLocal)
|
||||||
cb.ifThen(Opcode.IFNONNULL, ifCb -> {
|
.ifThen(Opcode.IFNONNULL, ifCb -> {
|
||||||
ifCb.loadLocal(REFERENCE, scopeLocal);
|
ifCb.aload(scopeLocal)
|
||||||
ifCb.invokevirtual(CD_MemorySessionImpl, "release0", MTD_RELEASE0);
|
.invokevirtual(CD_MemorySessionImpl, "release0", MTD_RELEASE0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -551,28 +549,28 @@ public class BindingSpecializer {
|
|||||||
|
|
||||||
private void emitLoadInternalSession() {
|
private void emitLoadInternalSession() {
|
||||||
assert contextIdx != -1;
|
assert contextIdx != -1;
|
||||||
cb.loadLocal(REFERENCE, contextIdx);
|
cb.aload(contextIdx)
|
||||||
cb.checkcast(CD_Arena);
|
.checkcast(CD_Arena)
|
||||||
cb.invokeinterface(CD_Arena, "scope", MTD_SCOPE);
|
.invokeinterface(CD_Arena, "scope", MTD_SCOPE)
|
||||||
cb.checkcast(CD_MemorySessionImpl);
|
.checkcast(CD_MemorySessionImpl);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void emitLoadInternalAllocator() {
|
private void emitLoadInternalAllocator() {
|
||||||
assert contextIdx != -1;
|
assert contextIdx != -1;
|
||||||
cb.loadLocal(REFERENCE, contextIdx);
|
cb.aload(contextIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void emitCloseContext() {
|
private void emitCloseContext() {
|
||||||
assert contextIdx != -1;
|
assert contextIdx != -1;
|
||||||
cb.loadLocal(REFERENCE, contextIdx);
|
cb.aload(contextIdx)
|
||||||
cb.checkcast(CD_Arena);
|
.checkcast(CD_Arena)
|
||||||
cb.invokeinterface(CD_Arena, "close", MTD_CLOSE);
|
.invokeinterface(CD_Arena, "close", MTD_CLOSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void emitBoxAddress(BoxAddress boxAddress) {
|
private void emitBoxAddress(BoxAddress boxAddress) {
|
||||||
popType(long.class);
|
popType(long.class);
|
||||||
cb.loadConstant(boxAddress.size());
|
cb.loadConstant(boxAddress.size())
|
||||||
cb.loadConstant(boxAddress.align());
|
.loadConstant(boxAddress.align());
|
||||||
if (needsSession()) {
|
if (needsSession()) {
|
||||||
emitLoadInternalSession();
|
emitLoadInternalSession();
|
||||||
cb.invokestatic(CD_Utils, "longToAddress", MTD_LONG_TO_ADDRESS_SCOPE);
|
cb.invokestatic(CD_Utils, "longToAddress", MTD_LONG_TO_ADDRESS_SCOPE);
|
||||||
@ -585,7 +583,7 @@ public class BindingSpecializer {
|
|||||||
private void emitAllocBuffer(Allocate binding) {
|
private void emitAllocBuffer(Allocate binding) {
|
||||||
if (callingSequence.forDowncall()) {
|
if (callingSequence.forDowncall()) {
|
||||||
assert returnAllocatorIdx != -1;
|
assert returnAllocatorIdx != -1;
|
||||||
cb.loadLocal(REFERENCE, returnAllocatorIdx);
|
cb.aload(returnAllocatorIdx);
|
||||||
} else {
|
} else {
|
||||||
emitLoadInternalAllocator();
|
emitLoadInternalAllocator();
|
||||||
}
|
}
|
||||||
@ -607,8 +605,8 @@ public class BindingSpecializer {
|
|||||||
cb.storeLocal(storeTypeKind, valueIdx);
|
cb.storeLocal(storeTypeKind, valueIdx);
|
||||||
|
|
||||||
ClassDesc valueLayoutType = emitLoadLayoutConstant(storeType);
|
ClassDesc valueLayoutType = emitLoadLayoutConstant(storeType);
|
||||||
cb.loadConstant(offset);
|
cb.loadConstant(offset)
|
||||||
cb.loadLocal(storeTypeKind, valueIdx);
|
.loadLocal(storeTypeKind, valueIdx);
|
||||||
MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, classDesc(storeType));
|
MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, classDesc(storeType));
|
||||||
cb.invokeinterface(CD_MemorySegment, "set", descriptor);
|
cb.invokeinterface(CD_MemorySegment, "set", descriptor);
|
||||||
} else {
|
} else {
|
||||||
@ -619,9 +617,9 @@ public class BindingSpecializer {
|
|||||||
assert storeType == long.class; // chunking only for int and long
|
assert storeType == long.class; // chunking only for int and long
|
||||||
}
|
}
|
||||||
int longValueIdx = cb.allocateLocal(LONG);
|
int longValueIdx = cb.allocateLocal(LONG);
|
||||||
cb.storeLocal(LONG, longValueIdx);
|
cb.lstore(longValueIdx);
|
||||||
int writeAddrIdx = cb.allocateLocal(REFERENCE);
|
int writeAddrIdx = cb.allocateLocal(REFERENCE);
|
||||||
cb.storeLocal(REFERENCE, writeAddrIdx);
|
cb.astore(writeAddrIdx);
|
||||||
|
|
||||||
int remaining = byteWidth;
|
int remaining = byteWidth;
|
||||||
int chunkOffset = 0;
|
int chunkOffset = 0;
|
||||||
@ -648,25 +646,25 @@ public class BindingSpecializer {
|
|||||||
//int writeChunk = (int) (((0xFFFF_FFFFL << shiftAmount) & longValue) >>> shiftAmount);
|
//int writeChunk = (int) (((0xFFFF_FFFFL << shiftAmount) & longValue) >>> shiftAmount);
|
||||||
int shiftAmount = chunkOffset * Byte.SIZE;
|
int shiftAmount = chunkOffset * Byte.SIZE;
|
||||||
mask = mask << shiftAmount;
|
mask = mask << shiftAmount;
|
||||||
cb.loadLocal(LONG, longValueIdx);
|
cb.lload(longValueIdx)
|
||||||
cb.loadConstant(mask);
|
.loadConstant(mask)
|
||||||
cb.land();
|
.land();
|
||||||
if (shiftAmount != 0) {
|
if (shiftAmount != 0) {
|
||||||
cb.loadConstant(shiftAmount);
|
cb.loadConstant(shiftAmount)
|
||||||
cb.lushr();
|
.lushr();
|
||||||
}
|
}
|
||||||
cb.l2i();
|
cb.l2i();
|
||||||
TypeKind chunkStoreTypeKind = TypeKind.from(chunkStoreType);
|
TypeKind chunkStoreTypeKind = TypeKind.from(chunkStoreType);
|
||||||
int chunkIdx = cb.allocateLocal(chunkStoreTypeKind);
|
int chunkIdx = cb.allocateLocal(chunkStoreTypeKind);
|
||||||
cb.storeLocal(chunkStoreTypeKind, chunkIdx);
|
cb.storeLocal(chunkStoreTypeKind, chunkIdx)
|
||||||
// chunk done, now write it
|
// chunk done, now write it
|
||||||
|
|
||||||
//writeAddress.set(JAVA_SHORT_UNALIGNED, offset, writeChunk);
|
//writeAddress.set(JAVA_SHORT_UNALIGNED, offset, writeChunk);
|
||||||
cb.loadLocal(REFERENCE, writeAddrIdx);
|
.aload(writeAddrIdx);
|
||||||
ClassDesc valueLayoutType = emitLoadLayoutConstant(chunkStoreType);
|
ClassDesc valueLayoutType = emitLoadLayoutConstant(chunkStoreType);
|
||||||
long writeOffset = offset + SharedUtils.pickChunkOffset(chunkOffset, byteWidth, chunkSize);
|
long writeOffset = offset + SharedUtils.pickChunkOffset(chunkOffset, byteWidth, chunkSize);
|
||||||
cb.loadConstant(writeOffset);
|
cb.loadConstant(writeOffset)
|
||||||
cb.loadLocal(chunkStoreTypeKind, chunkIdx);
|
.loadLocal(chunkStoreTypeKind, chunkIdx);
|
||||||
MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, classDesc(chunkStoreType));
|
MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, classDesc(chunkStoreType));
|
||||||
cb.invokeinterface(CD_MemorySegment, "set", descriptor);
|
cb.invokeinterface(CD_MemorySegment, "set", descriptor);
|
||||||
|
|
||||||
@ -690,16 +688,16 @@ public class BindingSpecializer {
|
|||||||
if (!callingSequence.needsReturnBuffer()) {
|
if (!callingSequence.needsReturnBuffer()) {
|
||||||
emitSaveReturnValue(storeType);
|
emitSaveReturnValue(storeType);
|
||||||
} else {
|
} else {
|
||||||
int valueIdx = cb.allocateLocal(storeTypeKind);
|
|
||||||
cb.storeLocal(storeTypeKind, valueIdx); // store away the stored value, need it later
|
|
||||||
|
|
||||||
assert returnBufferIdx != -1;
|
assert returnBufferIdx != -1;
|
||||||
cb.loadLocal(REFERENCE, returnBufferIdx);
|
int valueIdx = cb.allocateLocal(storeTypeKind);
|
||||||
|
cb.storeLocal(storeTypeKind, valueIdx) // store away the stored value, need it later
|
||||||
|
.aload(returnBufferIdx);
|
||||||
ClassDesc valueLayoutType = emitLoadLayoutConstant(storeType);
|
ClassDesc valueLayoutType = emitLoadLayoutConstant(storeType);
|
||||||
cb.loadConstant(retBufOffset);
|
cb.loadConstant(retBufOffset)
|
||||||
cb.loadLocal(storeTypeKind, valueIdx);
|
.loadLocal(storeTypeKind, valueIdx)
|
||||||
MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, classDesc(storeType));
|
.invokeinterface(CD_MemorySegment,
|
||||||
cb.invokeinterface(CD_MemorySegment, "set", descriptor);
|
"set",
|
||||||
|
MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, classDesc(storeType)));
|
||||||
retBufOffset += abi.arch.typeSize(vmStore.storage().type());
|
retBufOffset += abi.arch.typeSize(vmStore.storage().type());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -714,11 +712,12 @@ public class BindingSpecializer {
|
|||||||
emitRestoreReturnValue(loadType);
|
emitRestoreReturnValue(loadType);
|
||||||
} else {
|
} else {
|
||||||
assert returnBufferIdx != -1;
|
assert returnBufferIdx != -1;
|
||||||
cb.loadLocal(REFERENCE, returnBufferIdx);
|
cb.aload(returnBufferIdx);
|
||||||
ClassDesc valueLayoutType = emitLoadLayoutConstant(loadType);
|
ClassDesc valueLayoutType = emitLoadLayoutConstant(loadType);
|
||||||
cb.loadConstant(retBufOffset);
|
cb.loadConstant(retBufOffset)
|
||||||
MethodTypeDesc descriptor = MethodTypeDesc.of(classDesc(loadType), valueLayoutType, CD_long);
|
.invokeinterface(CD_MemorySegment,
|
||||||
cb.invokeinterface(CD_MemorySegment, "get", descriptor);
|
"get",
|
||||||
|
MethodTypeDesc.of(classDesc(loadType), valueLayoutType, CD_long));
|
||||||
retBufOffset += abi.arch.typeSize(vmLoad.storage().type());
|
retBufOffset += abi.arch.typeSize(vmLoad.storage().type());
|
||||||
pushType(loadType);
|
pushType(loadType);
|
||||||
}
|
}
|
||||||
@ -736,15 +735,15 @@ public class BindingSpecializer {
|
|||||||
|
|
||||||
private void emitShiftLeft(ShiftLeft shiftLeft) {
|
private void emitShiftLeft(ShiftLeft shiftLeft) {
|
||||||
popType(long.class);
|
popType(long.class);
|
||||||
cb.loadConstant(shiftLeft.shiftAmount() * Byte.SIZE);
|
cb.loadConstant(shiftLeft.shiftAmount() * Byte.SIZE)
|
||||||
cb.lshl();
|
.lshl();
|
||||||
pushType(long.class);
|
pushType(long.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void emitShiftRight(ShiftRight shiftRight) {
|
private void emitShiftRight(ShiftRight shiftRight) {
|
||||||
popType(long.class);
|
popType(long.class);
|
||||||
cb.loadConstant(shiftRight.shiftAmount() * Byte.SIZE);
|
cb.loadConstant(shiftRight.shiftAmount() * Byte.SIZE)
|
||||||
cb.lushr();
|
.lushr();
|
||||||
pushType(long.class);
|
pushType(long.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -758,11 +757,10 @@ public class BindingSpecializer {
|
|||||||
// implement least significant byte non-zero test
|
// implement least significant byte non-zero test
|
||||||
|
|
||||||
// select first byte
|
// select first byte
|
||||||
cb.loadConstant(0xFF);
|
cb.loadConstant(0xFF)
|
||||||
cb.iand();
|
.iand()
|
||||||
|
|
||||||
// convert to boolean
|
// convert to boolean
|
||||||
cb.invokestatic(CD_Utils, "byteToBoolean", MTD_BYTE_TO_BOOLEAN);
|
.invokestatic(CD_Utils, "byteToBoolean", MTD_BYTE_TO_BOOLEAN);
|
||||||
}
|
}
|
||||||
case INT_TO_BYTE -> cb.i2b();
|
case INT_TO_BYTE -> cb.i2b();
|
||||||
case INT_TO_CHAR -> cb.i2c();
|
case INT_TO_CHAR -> cb.i2c();
|
||||||
@ -782,8 +780,8 @@ public class BindingSpecializer {
|
|||||||
|
|
||||||
private void emitSegmentBase() {
|
private void emitSegmentBase() {
|
||||||
popType(MemorySegment.class);
|
popType(MemorySegment.class);
|
||||||
cb.checkcast(CD_AbstractMemorySegmentImpl);
|
cb.checkcast(CD_AbstractMemorySegmentImpl)
|
||||||
cb.invokevirtual(CD_AbstractMemorySegmentImpl, "unsafeGetBase", MTD_UNSAFE_GET_BASE);
|
.invokevirtual(CD_AbstractMemorySegmentImpl, "unsafeGetBase", MTD_UNSAFE_GET_BASE);
|
||||||
pushType(Object.class);
|
pushType(Object.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -791,11 +789,11 @@ public class BindingSpecializer {
|
|||||||
popType(MemorySegment.class);
|
popType(MemorySegment.class);
|
||||||
|
|
||||||
if (!segmentOffset.allowHeap()) {
|
if (!segmentOffset.allowHeap()) {
|
||||||
cb.dup();
|
cb.dup()
|
||||||
cb.invokestatic(CD_SharedUtils, "checkNative", MTD_CHECK_NATIVE);
|
.invokestatic(CD_SharedUtils, "checkNative", MTD_CHECK_NATIVE);
|
||||||
}
|
}
|
||||||
cb.checkcast(CD_AbstractMemorySegmentImpl);
|
cb.checkcast(CD_AbstractMemorySegmentImpl)
|
||||||
cb.invokevirtual(CD_AbstractMemorySegmentImpl, "unsafeGetOffset", MTD_UNSAFE_GET_OFFSET);
|
.invokevirtual(CD_AbstractMemorySegmentImpl, "unsafeGetOffset", MTD_UNSAFE_GET_OFFSET);
|
||||||
|
|
||||||
pushType(long.class);
|
pushType(long.class);
|
||||||
}
|
}
|
||||||
@ -809,17 +807,17 @@ public class BindingSpecializer {
|
|||||||
|
|
||||||
if (SharedUtils.isPowerOfTwo(byteWidth)) {
|
if (SharedUtils.isPowerOfTwo(byteWidth)) {
|
||||||
ClassDesc valueLayoutType = emitLoadLayoutConstant(loadType);
|
ClassDesc valueLayoutType = emitLoadLayoutConstant(loadType);
|
||||||
cb.loadConstant(offset);
|
cb.loadConstant(offset)
|
||||||
MethodTypeDesc descriptor = MethodTypeDesc.of(classDesc(loadType), valueLayoutType, CD_long);
|
.invokeinterface(CD_MemorySegment,
|
||||||
cb.invokeinterface(CD_MemorySegment, "get", descriptor);
|
"get",
|
||||||
|
MethodTypeDesc.of(classDesc(loadType), valueLayoutType, CD_long));
|
||||||
} else {
|
} else {
|
||||||
// chunked
|
// chunked
|
||||||
int readAddrIdx = cb.allocateLocal(REFERENCE);
|
int readAddrIdx = cb.allocateLocal(REFERENCE);
|
||||||
cb.storeLocal(REFERENCE, readAddrIdx);
|
cb.astore(readAddrIdx)
|
||||||
|
.loadConstant(0L); // result
|
||||||
cb.loadConstant(0L); // result
|
|
||||||
int resultIdx = cb.allocateLocal(LONG);
|
int resultIdx = cb.allocateLocal(LONG);
|
||||||
cb.storeLocal(LONG, resultIdx);
|
cb.lstore(resultIdx);
|
||||||
|
|
||||||
int remaining = byteWidth;
|
int remaining = byteWidth;
|
||||||
int chunkOffset = 0;
|
int chunkOffset = 0;
|
||||||
@ -848,30 +846,30 @@ public class BindingSpecializer {
|
|||||||
throw new IllegalStateException("Unexpected chunk size for chunked write: " + chunkSize);
|
throw new IllegalStateException("Unexpected chunk size for chunked write: " + chunkSize);
|
||||||
}
|
}
|
||||||
// read from segment
|
// read from segment
|
||||||
cb.loadLocal(REFERENCE, readAddrIdx);
|
cb.aload(readAddrIdx);
|
||||||
ClassDesc valueLayoutType = emitLoadLayoutConstant(chunkType);
|
ClassDesc valueLayoutType = emitLoadLayoutConstant(chunkType);
|
||||||
MethodTypeDesc descriptor = MethodTypeDesc.of(classDesc(chunkType), valueLayoutType, CD_long);
|
MethodTypeDesc descriptor = MethodTypeDesc.of(classDesc(chunkType), valueLayoutType, CD_long);
|
||||||
long readOffset = offset + SharedUtils.pickChunkOffset(chunkOffset, byteWidth, chunkSize);
|
long readOffset = offset + SharedUtils.pickChunkOffset(chunkOffset, byteWidth, chunkSize);
|
||||||
cb.loadConstant(readOffset);
|
cb.loadConstant(readOffset)
|
||||||
cb.invokeinterface(CD_MemorySegment, "get", descriptor);
|
.invokeinterface(CD_MemorySegment, "get", descriptor)
|
||||||
cb.invokestatic(toULongHolder, "toUnsignedLong", toULongDescriptor);
|
.invokestatic(toULongHolder, "toUnsignedLong", toULongDescriptor);
|
||||||
|
|
||||||
// shift to right offset
|
// shift to right offset
|
||||||
int shiftAmount = chunkOffset * Byte.SIZE;
|
int shiftAmount = chunkOffset * Byte.SIZE;
|
||||||
if (shiftAmount != 0) {
|
if (shiftAmount != 0) {
|
||||||
cb.loadConstant(shiftAmount);
|
cb.loadConstant(shiftAmount)
|
||||||
cb.lshl();
|
.lshl();
|
||||||
}
|
}
|
||||||
// add to result
|
// add to result
|
||||||
cb.loadLocal(LONG, resultIdx);
|
cb.lload(resultIdx)
|
||||||
cb.lor();
|
.lor()
|
||||||
cb.storeLocal(LONG, resultIdx);
|
.lstore(resultIdx);
|
||||||
|
|
||||||
remaining -= chunkSize;
|
remaining -= chunkSize;
|
||||||
chunkOffset += chunkSize;
|
chunkOffset += chunkSize;
|
||||||
} while (remaining != 0);
|
} while (remaining != 0);
|
||||||
|
|
||||||
cb.loadLocal(LONG, resultIdx);
|
cb.lload(resultIdx);
|
||||||
if (loadType == int.class) {
|
if (loadType == int.class) {
|
||||||
cb.l2i();
|
cb.l2i();
|
||||||
} else {
|
} else {
|
||||||
@ -898,19 +896,18 @@ public class BindingSpecializer {
|
|||||||
emitAllocateCall(size, alignment);
|
emitAllocateCall(size, alignment);
|
||||||
cb.dup();
|
cb.dup();
|
||||||
int storeIdx = cb.allocateLocal(REFERENCE);
|
int storeIdx = cb.allocateLocal(REFERENCE);
|
||||||
cb.storeLocal(REFERENCE, storeIdx);
|
cb.astore(storeIdx)
|
||||||
cb.loadConstant(0L);
|
.loadConstant(0L)
|
||||||
cb.loadConstant(size);
|
.loadConstant(size)
|
||||||
cb.invokestatic(CD_MemorySegment, "copy", MTD_COPY, true);
|
.invokestatic(CD_MemorySegment, "copy", MTD_COPY, true)
|
||||||
|
.aload(storeIdx);
|
||||||
cb.loadLocal(REFERENCE, storeIdx);
|
|
||||||
pushType(MemorySegment.class);
|
pushType(MemorySegment.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void emitAllocateCall(long size, long alignment) {
|
private void emitAllocateCall(long size, long alignment) {
|
||||||
cb.loadConstant(size);
|
cb.loadConstant(size)
|
||||||
cb.loadConstant(alignment);
|
.loadConstant(alignment)
|
||||||
cb.invokeinterface(CD_SegmentAllocator, "allocate", MTD_ALLOCATE);
|
.invokeinterface(CD_SegmentAllocator, "allocate", MTD_ALLOCATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClassDesc emitLoadLayoutConstant(Class<?> type) {
|
private ClassDesc emitLoadLayoutConstant(Class<?> type) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user