
com.ibm.wala.shrike.shrikeBT.InvokeDynamicInstruction Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com.ibm.wala.shrike Show documentation
Show all versions of com.ibm.wala.shrike Show documentation
T. J. Watson Libraries for Analysis
The newest version!
/*
* Copyright (c) 2002 - 2014 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*/
package com.ibm.wala.shrike.shrikeBT;
import com.ibm.wala.shrike.shrikeCT.BootstrapMethodsReader.BootstrapMethod;
import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class InvokeDynamicInstruction extends Instruction implements IInvokeInstruction {
protected BootstrapMethod bootstrap;
protected String methodName;
protected String methodType;
public InvokeDynamicInstruction(
short opcode, BootstrapMethod bootstrap, String methodName, String methodType) {
super(opcode);
this.bootstrap = bootstrap;
this.methodName = methodName;
this.methodType = methodType;
}
ConstantPoolReader getLazyConstantPool() {
return null;
}
@Override
public boolean isPEI() {
return true;
}
@Override
public Dispatch getInvocationCode() {
int invokeType = getBootstrap().invokeType();
switch (invokeType) {
case 5:
return Dispatch.VIRTUAL;
case 6:
return Dispatch.STATIC;
case 7:
return Dispatch.SPECIAL;
case 9:
return Dispatch.INTERFACE;
default:
throw new Error("unexpected dynamic invoke type " + invokeType);
}
}
@Override
public final int getPoppedCount() {
return (getInvocationCode().equals(Dispatch.STATIC) ? 0 : 1)
+ Util.getParamsCount(getMethodSignature());
}
@Override
public final String getPushedType(String[] types) {
String t = Util.getReturnType(getMethodSignature());
if (t.equals(Constants.TYPE_void)) {
return null;
} else {
return t;
}
}
@Override
public final byte getPushedWordSize() {
String t = getMethodSignature();
int index = t.lastIndexOf(')');
return Util.getWordSize(t, index + 1);
}
public BootstrapMethod getBootstrap() {
return bootstrap;
}
@Override
public String getMethodSignature() {
return methodType;
}
@Override
public String getMethodName() {
return methodName;
}
@Override
public String getClassType() {
return 'L' + getBootstrap().methodClass();
}
@Override
public void visit(Visitor v) {
v.visitInvoke(this);
}
@Override
public String toString() {
return "InvokeDynamic [" + getBootstrap() + "] " + getMethodName() + getMethodSignature();
}
static final class Lazy extends InvokeDynamicInstruction {
private final ConstantPoolReader cp;
private final int index;
Lazy(short opcode, ConstantPoolReader cp, int index) {
super(opcode, null, null, null);
this.index = index;
this.cp = cp;
}
int getCPIndex() {
return index;
}
@Override
public BootstrapMethod getBootstrap() {
if (bootstrap == null) {
bootstrap = cp.getConstantPoolDynamicBootstrap(index);
}
return bootstrap;
}
@Override
public String getMethodName() {
if (methodName == null) {
methodName = cp.getConstantPoolDynamicName(index);
}
return methodName;
}
@Override
public String getMethodSignature() {
if (methodType == null) {
methodType = cp.getConstantPoolDynamicType(index);
}
return methodType;
}
@Override
ConstantPoolReader getLazyConstantPool() {
return cp;
}
}
public CallSite bootstrap(Class> cl)
throws ClassNotFoundException,
NoSuchMethodException,
SecurityException,
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException,
NoSuchFieldException {
ClassLoader classLoader = cl.getClassLoader();
ClassLoader bootstrapCL = classLoader;
Class> bootstrapClass =
Class.forName(getBootstrap().methodClass().replace('/', '.'), false, bootstrapCL);
MethodType bt = makeMethodType(bootstrapCL, bootstrap.methodType());
Method bootstrap =
bootstrapClass.getMethod(
this.bootstrap.methodName(),
bt.parameterList().toArray(new Class[bt.parameterCount()]));
Object[] args = new Object[bt.parameterCount()];
Lookup myLookup = MethodHandles.lookup().in(cl);
Field impl_lookup =
Lookup.class.getDeclaredField("IMPL_LOOKUP"); // get the required field via reflections
impl_lookup.setAccessible(true); // set it accessible
Lookup lutrusted =
(Lookup)
impl_lookup.get(
myLookup); // get the value of IMPL_LOOKUP from the Lookup instance and save it in a
// new Lookup object
args[0] = lutrusted;
args[1] = getMethodName();
args[2] = makeMethodType(classLoader, getMethodSignature());
for (int i = 3; i < bt.parameterCount(); i++) {
args[i] = getBootstrap().callArgument(bootstrapCL, i - 3);
}
bootstrap.setAccessible(true);
System.err.println(cl + " : " + bootstrap);
return (CallSite) bootstrap.invoke(null, args);
}
public static MethodType makeMethodType(ClassLoader classLoader, String descriptor)
throws ClassNotFoundException {
String returnType = Util.makeClass(Util.getReturnType(descriptor));
Class> returnClass = Class.forName(returnType, false, classLoader);
String[] paramTypes = Util.getParamsTypes(null, descriptor);
Class>[] paramClasses = new Class[paramTypes.length];
for (int i = 0; i < paramTypes.length; i++) {
paramClasses[i] = Class.forName(Util.makeClass(paramTypes[i]), false, classLoader);
}
MethodType mt = MethodType.methodType(returnClass, paramClasses);
return mt;
}
static InvokeDynamicInstruction make(ConstantPoolReader cp, int index, int mode) {
if (mode != OP_invokedynamic) {
throw new IllegalArgumentException("Unknown mode: " + mode);
}
return new Lazy((short) mode, cp, index);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy