//
// Copyright (C) 2006 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 cmu.conditional.Conditional;
import cmu.conditional.One;
import de.fosd.typechef.featureexpr.FeatureExpr;
import gov.nasa.jpf.jvm.JVMInstruction;
import gov.nasa.jpf.vm.ClassInfo;
import gov.nasa.jpf.vm.ElementInfo;
import gov.nasa.jpf.vm.Instruction;
import gov.nasa.jpf.vm.LoadOnJPFRequired;
import gov.nasa.jpf.vm.StackFrame;
import gov.nasa.jpf.vm.ThreadInfo;
import gov.nasa.jpf.vm.Types;
/**
* Push item from runtime constant pool
* ... => ..., value
*/
public class LDC extends JVMInstruction {
public enum Type {STRING, CLASS, INT, FLOAT};
Type type;
protected String string; // the string value if Type.STRING, classname if Type.CLASS
protected int value;
public LDC() {}
public LDC (String s, boolean isClass){
if (isClass){
string = Types.getClassNameFromTypeName(s);
type = Type.CLASS;
} else {
string = s;
type = Type.STRING;
}
}
public LDC (int v){
value = v;
type = Type.INT;
}
public LDC (float f){
value = Float.floatToIntBits(f);
type = Type.FLOAT;
}
@Override
public Conditional<Instruction> execute (FeatureExpr ctx, ThreadInfo ti) {
StackFrame frame = ti.getModifiableTopFrame();
switch (type){
case STRING:
// too bad we can't cache it, since location might change between different paths
ElementInfo eiValue = ti.getHeap().newInternString(ctx, string, ti);
value = eiValue.getObjectRef();
frame.pushRef(ctx, value);
break;
case INT:
case FLOAT:
frame.push(ctx, new One<>(value));
break;
case CLASS:
ClassInfo ci;
// resolve the referenced class
try {
ci = ti.resolveReferencedClass(string);
} catch(LoadOnJPFRequired lre) {
return frame.getPC();
}
// LDC doesn't cause a <clinit> - we only register all required classes
// to make sure we have class objects. <clinit>s are called prior to
// GET/PUT or INVOKE
if (!ci.isRegistered()) {
ci.registerClass(ctx, ti);
}
frame.pushRef( ctx, ci.getClassObjectRef());
break;
}
return getNext(ctx, ti);
}
public int getLength() {
return 2; // opcode, index
}
public int getByteCode () {
return 0x12;
}
public int getValue() {
return value;
}
public Type getType() {
return type;
}
public boolean isString() {
return (type == Type.STRING);
}
public float getFloatValue(){
if(type!=Type.FLOAT){
throw new IllegalStateException();
}
return Float.intBitsToFloat(value);
}
public String getStringValue() { // if it is a String (not acquired from the class const pool)
if (type == Type.STRING) {
return string;
} else {
return null;
}
}
public String getClassValue() { // if it is the name of a Class (acquired from the class const pool)
if (type == Type.CLASS) {
return string;
} else {
return null;
}
}
public void accept(InstructionVisitor insVisitor) {
insVisitor.visit(this);
}
}