//
// Copyright (C) 2007 United States Government as represented by the
// Administrator of the National Aeronautics and Space Administration
// (NASA). All Rights Reserved.
//
// This software is distributed under the NASA Open Source Agreement
// (NOSA), version 1.3. The NOSA has been approved by the Open Source
// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
// directory tree for the complete NOSA document.
//
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
//
package gov.nasa.jpf.jvm.bytecode;
import java.util.List;
import cmu.conditional.Conditional;
import cmu.conditional.One;
import de.fosd.typechef.featureexpr.FeatureExpr;
import gov.nasa.jpf.jvm.JVMInstruction;
import gov.nasa.jpf.jvm.JVMInstructionFactory;
import gov.nasa.jpf.util.Invocation;
import gov.nasa.jpf.vm.Instruction;
import gov.nasa.jpf.vm.MethodInfo;
import gov.nasa.jpf.vm.ObjRef;
import gov.nasa.jpf.vm.StackFrame;
import gov.nasa.jpf.vm.ThreadInfo;
import gov.nasa.jpf.vm.Types;
import gov.nasa.jpf.vm.choice.InvocationCG;
/**
* a sytnthetic INVOKE instruction that gets it's parameters from an
* InvocationCG. Whoever uses this better makes sure the frame this
* executes in has enough operand space (e.g. a DirectCallStackFrame).
*
*/
public class INVOKECG extends JVMInstruction {
List<Invocation> invokes;
InvokeInstruction realInvoke;
public INVOKECG(List<Invocation> invokes){
this.invokes = invokes;
}
public void setInvokes(List<Invocation> invokes) {
this.invokes = invokes;
}
public Conditional<Instruction> execute (FeatureExpr ctx, ThreadInfo ti) {
if (!ti.isFirstStepInsn()) {
InvocationCG cg = new InvocationCG( "INVOKECG", invokes);
if (ti.getVM().setNextChoiceGenerator(cg)){
return new One<Instruction>(this);
}
} else {
InvocationCG cg = ti.getVM().getCurrentChoiceGenerator( "INVOKECG", InvocationCG.class);
assert (cg != null) : "no current InvocationCG";
Invocation call = cg.getNextChoice();
MethodInfo callee = call.getMethodInfo();
JVMInstructionFactory insnFactory = JVMInstructionFactory.getFactory();
String clsName = callee.getClassInfo().getName();
String mthName = callee.getName();
String signature = callee.getSignature();
Instruction realInvoke;
if (callee.isStatic()){
realInvoke = insnFactory.invokestatic(clsName, mthName, signature);
} else {
realInvoke = insnFactory.invokevirtual(clsName, mthName, signature);
}
pushArguments(ctx, ti, call.getArguments(), call.getAttrs());
return new One<>(realInvoke);
}
return new One<>(getNext());
}
private void pushArguments (FeatureExpr ctx, ThreadInfo ti, Object[] args, Object[] attrs){
StackFrame frame = ti.getModifiableTopFrame();
if (args != null){
for (int i=0; i<args.length; i++){
Object a = args[i];
boolean isLong = false;
if (a != null){
if (a instanceof ObjRef){
frame.pushRef(ctx, ((ObjRef)a).getReference());
} else if (a instanceof Boolean){
frame.push(ctx, (Boolean)a ? 1 : 0, false);
} else if (a instanceof Integer){
frame.push(ctx, (Integer)a, false);
} else if (a instanceof Long){
frame.push(ctx, new One<>((Long)a));
isLong = true;
} else if (a instanceof Double){
frame.push(ctx, new One<>(Types.doubleToLong((Double)a)));
isLong = true;
} else if (a instanceof Byte){
frame.push(ctx, (Byte)a, false);
} else if (a instanceof Short){
frame.push(ctx, (Short)a, false);
} else if (a instanceof Float){
frame.push(ctx, Types.floatToInt((Float)a), false);
}
}
if (attrs != null && attrs[i] != null){
if (isLong){
frame.setLongOperandAttr(attrs[i]);
} else {
frame.setOperandAttr(attrs[i]);
}
}
}
}
}
public boolean isExtendedInstruction() {
return true;
}
public static final int OPCODE = 258;
public int getByteCode () {
return OPCODE;
}
public void accept(InstructionVisitor insVisitor) {
insVisitor.visit(this);
}
}