//
// 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.AllocInstruction;
import gov.nasa.jpf.vm.ClassInfo;
import gov.nasa.jpf.vm.ElementInfo;
import gov.nasa.jpf.vm.Heap;
import gov.nasa.jpf.vm.Instruction;
import gov.nasa.jpf.vm.LoadOnJPFRequired;
import gov.nasa.jpf.vm.MJIEnv;
import gov.nasa.jpf.vm.StackFrame;
import gov.nasa.jpf.vm.ThreadInfo;
import gov.nasa.jpf.vm.Types;
/**
* Create new object
* ... => ..., objectref
*/
public class NEW extends JVMInstruction implements AllocInstruction {
protected String cname;
protected int newObjRef = MJIEnv.NULL;
public NEW (String clsDescriptor){
cname = Types.getClassNameFromTypeName(clsDescriptor);
}
public String getClassName(){ // Needed for Java Race Finder
return(cname);
}
@Override
public Conditional<Instruction> execute (FeatureExpr ctx, ThreadInfo ti) {
Heap heap = ti.getHeap();
ClassInfo ci;
// resolve the referenced class
try {
ci = ti.resolveReferencedClass(cname);
} catch(LoadOnJPFRequired lre) {
return ti.getPC();
}
if (!ci.isRegistered()){
ci.registerClass(ctx, ti);
}
// since this is a NEW, we also have to pushClinit
if (!ci.isInitialized()) {
if (ci.initializeClass(ctx, ti)) {
return ti.getPC(); // reexecute this instruction once we return from the clinits
}
}
if (heap.isOutOfMemory()) { // simulate OutOfMemoryError
return new One<>(ti.createAndThrowException(ctx,
"java.lang.OutOfMemoryError", "trying to allocate new " + cname));
}
ElementInfo ei = heap.newObject(ctx, ci, ti);
int objRef = ei.getObjectRef();
newObjRef = objRef;
// pushes the return value onto the stack
StackFrame frame = ti.getModifiableTopFrame();
frame.pushRef( ctx, objRef);
return getNext(ctx, ti);
}
public int getLength() {
return 3; // opcode, index1, index2
}
public int getByteCode () {
return 0xBB;
}
public void accept(InstructionVisitor insVisitor) {
insVisitor.visit(this);
}
public int getNewObjectRef() {
return newObjRef;
}
public String toString() {
if (newObjRef != MJIEnv.NULL){
return "new " + cname + '@' + Integer.toHexString(newObjRef);
} else {
return "new " + cname;
}
}
}