/** * 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 com.kenai.jffi.MemoryIO; import com.kenai.jffi.PageManager; import jnr.x86asm.Assembler; import jnr.x86asm.CPU; import z.znr.InlineAssembler; import z.znr.invoke.types.NativeType; import z.znr.invoke.types.ParameterType; import z.znr.invoke.types.SignatureType; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Collection; import java.util.List; /** */ public final class Util { public static boolean getBooleanProperty(String propertyName, boolean defaultValue) { try { return Boolean.valueOf(System.getProperty(propertyName, Boolean.valueOf(defaultValue).toString())); } catch (SecurityException se) { return defaultValue; } } public static int sizeof(NativeType nativeType) { return nativeType.size(); } public static Class[] javaTypeArray(SignatureType[] types) { Class[] javaTypes = new Class[types.length]; for (int i = 0; i < types.length; ++i) { javaTypes[i] = types[i].javaType(); } return javaTypes; } public static MethodHandle getNotNullHandle() { return findStatic(AsmRuntime.class, "notNull", MethodType.methodType(boolean.class, Object.class)); } public static MethodHandle getIsNullHandle() { return findStatic(AsmRuntime.class, "isNull", MethodType.methodType(boolean.class, Object.class)); } public static MethodHandle findVirtual(Class klass, String methodName, MethodType methodType) { try { return Native.LOOKUP.findVirtual(klass, methodName, methodType); } catch (NoSuchMethodException | IllegalAccessException e) { throw new RuntimeException(e); } } public static MethodHandle findStatic(Class klass, String methodName, MethodType methodType) { try { return Native.LOOKUP.findStatic(klass, methodName, methodType); } catch (NoSuchMethodException | IllegalAccessException e) { throw new RuntimeException(e); } } public static List<ParameterType> asPrimitiveTypes(Collection<ParameterType> parameterTypes) { return Arrays.asList(convertParameterTypesToPrimitive(parameterTypes)); } public static ParameterType[] asPrimitiveTypes(ParameterType[] parameterTypes) { return convertParameterTypesToPrimitive(Arrays.asList(parameterTypes)); } private static ParameterType[] convertParameterTypesToPrimitive(Collection<ParameterType> parameterTypes) { ParameterType[] primitiveParameterTypes = new ParameterType[parameterTypes.size()]; int i = 0; for (ParameterType p : parameterTypes) { primitiveParameterTypes[i++] = p.asPrimitiveType(); } return primitiveParameterTypes; } public static MethodHandle getDirectCheckHandle(MethodHandle strategyLookup) { return MethodHandles.filterArguments(getStrategyIsDirectHandle(), 0, strategyLookup); } public static MethodHandle getDirectAddressHandle(MethodHandle strategyLookup) { MethodHandle addressHandle = getStrategyAddressHandle() .asType(MethodType.methodType(long.class, ObjectParameterStrategy.class, strategyLookup.type().parameterType(0))); return MethodHandles.foldArguments(addressHandle, strategyLookup); } private static MethodHandle getStrategyIsDirectHandle() { return findVirtual(com.kenai.jffi.ObjectParameterStrategy.class, "isDirect", MethodType.methodType(boolean.class)) .asType(MethodType.methodType(boolean.class, ObjectParameterStrategy.class)); } private static MethodHandle getStrategyAddressHandle() { return findVirtual(com.kenai.jffi.ObjectParameterStrategy.class, "address", MethodType.methodType(long.class, Object.class)); } public static int countObjects(ParameterType... parameterTypes) { int objectCount = 0; for (ParameterType p : parameterTypes) { if (p.isObject()) { objectCount++; } } return objectCount; } public static CodeAddress inlineAssemblerToCodeAddress(InlineAssembler inlineAssembler) { Assembler asm = new Assembler(CPU.X86_64); inlineAssembler.assemble(asm); long page = PageManager.getInstance().allocatePages(1, PageManager.PROT_READ | PageManager.PROT_WRITE); ByteBuffer buf = ByteBuffer.allocate(asm.codeSize()); asm.relocCode(buf, page); buf.flip(); MemoryIO.getInstance().putByteArray(page, buf.array(), buf.arrayOffset(), buf.limit()); buf.rewind(); // if (X86Disassembler.isAvailable()) { // X86Disassembler dis = X86Disassembler.create(); // dis.setInputBuffer(page, asm.codeSize()); // dis.setMode(X86Disassembler.Mode.X86_64); // // System.out.println("Dump of asm:"); // while (dis.disassemble()) { // System.out.println("\t" + dis.insn()); // } // } // Make the page executable (and non-writable, since some OS require that) PageManager.getInstance().protectPages(page, 1, PageManager.PROT_READ | PageManager.PROT_EXEC); return new CodeAddress(page); } }