/**
* Copyright 2013, Landz and its contributors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package z.znr.invoke.linux.x64;
import z.znr.InlineAssembler;
import z.znr.invoke.types.ParameterType;
import z.znr.invoke.types.ResultType;
import z.znr.invoke.types.Signature;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Collection;
import java.util.List;
import static z.znr.invoke.linux.x64.CodegenUtils.params;
public class DirectCheckMethodHandleGenerator implements MethodHandleGenerator {
private final MethodHandleGenerator[] primitiveGenerators = {
new PrimitiveX86MethodHandleGenerator(),
new PrimitiveNumericMethodHandleGenerator(),
};
@Override
public MethodHandle createBoundHandle(Signature signature, InlineAssembler inlineAssembler) {
return MethodHandles.guardWithTest(createDirectCheckHandle(signature.parameterTypeArray()),
getPrimitiveHandle(signature, inlineAssembler),
new DefaultMethodHandleGenerator().createBoundHandle(signature, inlineAssembler));
}
@Override
public boolean isSupported(ResultType resultType, Collection<ParameterType> parameterTypes) {
boolean isSupported = false;
List<ParameterType> primitiveParameterTypes = Util.asPrimitiveTypes(parameterTypes);
for (MethodHandleGenerator g : primitiveGenerators) {
isSupported |= g.isSupported(resultType, primitiveParameterTypes);
}
return isSupported && parameterTypes.size() <= 6;
}
private MethodHandle getPrimitiveHandle(Signature signature, InlineAssembler inlineAssembler) {
Signature primitiveContext = signature.asPrimitiveContext();
MethodHandle primitiveHandle = createPrimitiveMethodHandle(primitiveGenerators, primitiveContext, inlineAssembler);
for (int i = 0; i < signature.getParameterCount(); i++) {
if (signature.getParameterType(i).getDirectAddressHandle() != null) {
primitiveHandle = MethodHandles.filterArguments(primitiveHandle, i, signature.getParameterType(i).getDirectAddressHandle());
}
}
return primitiveHandle;
}
private static MethodHandle createPrimitiveMethodHandle(MethodHandleGenerator[] generators, Signature signature, InlineAssembler inlineAssembler) {
for (MethodHandleGenerator g : generators) {
if (g.isSupported(signature.getResultType(), signature.parameterTypeList())) {
return g.createBoundHandle(signature, inlineAssembler);
}
}
throw new RuntimeException("internal error");
}
private static MethodHandle createDirectCheckHandle(ParameterType[] parameterTypes) {
MethodHandle isTrue = Util.findStatic(AsmRuntime.class, "isTrue", MethodType.methodType(boolean.class, params(boolean.class, Util.countObjects(parameterTypes))));
for (int i = 0; i < parameterTypes.length; i++) {
if (parameterTypes[i].getDirectCheckHandle() == null) {
isTrue = MethodHandles.dropArguments(isTrue, i, parameterTypes[i].javaType());
} else {
isTrue = MethodHandles.filterArguments(isTrue, i, parameterTypes[i].getDirectCheckHandle());
}
}
return isTrue;
}
}