InstructionHandle insertDeleteSpawncounter(InstructionList il, InstructionHandle i, int maxLocals) { // In this case, jumps to the return must in fact jump to // the new instruction sequence! So, we change the instruction // at the handle. // First, save the return instruction. Instruction r = i.getInstruction(); i.setInstruction(new ALOAD(maxLocals)); i = il .append(i, ins_f.createInvoke( "ibis.cashmere.impl.spawnSync.SpawnCounter", "deleteSpawnCounter", Type.VOID, new Type[] { spawnCounterType }, Constants.INVOKESTATIC)); i = il.append(i, r); return i; }
InstructionHandle pushParams(InstructionList il, Method m) { Type[] params = mtab.typesOfParams(m); InstructionHandle pos = il.getStart(); for (int i = 0, param = 0; i < params.length; i++, param++) { if (params[i].equals(Type.BOOLEAN) || params[i].equals(Type.BYTE) || params[i].equals(Type.SHORT) || params[i].equals(Type.CHAR) || params[i].equals(Type.INT)) { il.insert(pos, new ILOAD(param)); } else if (params[i].equals(Type.FLOAT)) { il.insert(pos, new FLOAD(param)); } else if (params[i].equals(Type.LONG)) { il.insert(pos, new LLOAD(param)); param++; } else if (params[i].equals(Type.DOUBLE)) { il.insert(pos, new DLOAD(param)); param++; } else { il.insert(pos, new ALOAD(param)); } } return pos; }
InstructionHandle rewriteStore(MethodGen m, InstructionList il, InstructionHandle i, int maxLocals, String localClassName) { LocalVariableInstruction curr = (LocalVariableInstruction) (i .getInstruction()); Type type = mtab.getLocalType(m, curr, i.getPosition()); if (type == null) { return i; } String name = mtab.getLocalName(m, curr, i.getPosition()); String fieldName = MethodTable.generatedLocalName(type, name); i.setInstruction(new ALOAD(maxLocals)); i = i.getNext(); if (type.equals(Type.LONG) || type.equals(Type.DOUBLE)) { il.insert(i, new DUP_X2()); il.insert(i, new POP()); } else { il.insert(i, new SWAP()); } i = il.insert(i, ins_f.createFieldAccess(localClassName, fieldName, type, Constants.PUTFIELD)); return i; }
InstructionHandle rewriteLoad(MethodGen m, InstructionList il, InstructionHandle i, int maxLocals, String localClassName) { LocalVariableInstruction curr = (LocalVariableInstruction) (i .getInstruction()); Type type = mtab.getLocalType(m, curr, i.getPosition()); if (type == null) { return i; } String name = mtab.getLocalName(m, curr, i.getPosition()); String fieldName = MethodTable.generatedLocalName(type, name); i.setInstruction(new ALOAD(maxLocals)); i = i.getNext(); i = il.insert(i, ins_f.createFieldAccess(localClassName, fieldName, type, Constants.GETFIELD)); return i; }
public void storeLocal(int pc, int slot) { boolean isupval = pi.isUpvalueAssign(pc, slot); int index = findSlotIndex( slot, isupval ); if (isupval) { boolean isupcreate = pi.isUpvalueCreate(pc, slot); if ( isupcreate ) { append(factory.createInvoke(classname, "newupe", TYPE_LOCALUPVALUE, ARG_TYPES_NONE, Constants.INVOKESTATIC)); append(InstructionConstants.DUP); append(new ASTORE(index)); } else { append(new ALOAD(index)); } append(InstructionConstants.SWAP); append(new PUSH(cp, 0)); append(InstructionConstants.SWAP); append(InstructionConstants.AASTORE); } else { append(new ASTORE(index)); } }
/** * This method is used to track calls made on a specific object. For instance, this could be used to track if "setHttpOnly(true)" * was executed on a specific cookie object. * * This allows the detector to find interchanged calls like this * * Cookie cookie1 = new Cookie("f", "foo"); <- This cookie is unsafe * Cookie cookie2 = new Cookie("b", "bar"); <- This cookie is safe * cookie1.setHttpOnly(false); * cookie2.setHttpOnly(true); * * @param cpg ConstantPoolGen * @param startLocation The Location of the cookie initialization call. * @param objectStackLocation The index of the cookie on the stack. * @param invokeInstruction The instruction we want to detect.s * @return The location of the invoke instruction provided for the cookie at a specific index on the stack. */ private Location getCookieInstructionLocation(ConstantPoolGen cpg, Location startLocation, int objectStackLocation, String invokeInstruction) { Location location = startLocation; InstructionHandle handle = location.getHandle(); int loadedStackValue = 0; // Loop until we find the setSecure call for this cookie while (handle.getNext() != null) { handle = handle.getNext(); Instruction nextInst = handle.getInstruction(); // We check if the index of the cookie used for this invoke is the same as the one provided if (nextInst instanceof ALOAD) { ALOAD loadInst = (ALOAD)nextInst; loadedStackValue = loadInst.getIndex(); } if (nextInst instanceof INVOKEVIRTUAL && loadedStackValue == objectStackLocation) { INVOKEVIRTUAL invoke = (INVOKEVIRTUAL) nextInst; String methodNameWithSignature = invoke.getClassName(cpg) + "." + invoke.getMethodName(cpg); if (methodNameWithSignature.equals(invokeInstruction)) { Integer val = ByteCode.getConstantInt(handle.getPrev()); if (val != null && val == TRUE_INT_VALUE) { return new Location(handle, location.getBasicBlock()); } } } } return null; }
InstructionHandle insertDeleteLocalRecord(MethodGen m, InstructionList il, InstructionHandle i, int maxLocals) { String local_record_name = localRecordName(m); // Note: maxLocals has been recomputed at this point. il.insert(i, new ALOAD(maxLocals - 5)); il.insert(i, ins_f.createInvoke(local_record_name, "delete", Type.VOID, new Type[] { new ObjectType(local_record_name) }, Constants.INVOKESTATIC)); return i; }
void removeUnusedLocals(Method mOrig, MethodGen m) { InstructionList il = m.getInstructionList(); InstructionHandle[] ins = il.getInstructionHandles(); for (int i = 0; i < ins.length; i++) { Instruction in = ins[i].getInstruction(); if (in instanceof LocalVariableInstruction) { LocalVariableInstruction curr = (LocalVariableInstruction) in; if (mtab.getLocal(m, curr, ins[i].getPosition()) != null && curr.getIndex() < m.getMaxLocals() - 5 && !mtab.isLocalUsedInInlet(mOrig, curr.getIndex())) { if (curr instanceof IINC) { ins[i].setInstruction(new NOP()); } else if (curr instanceof LSTORE || curr instanceof DSTORE) { ins[i].setInstruction(new POP2()); } else if (curr instanceof StoreInstruction) { ins[i].setInstruction(new POP()); } else if (curr instanceof ALOAD) { ins[i].setInstruction(new ACONST_NULL()); } else if (curr instanceof FLOAD) { ins[i].setInstruction(new FCONST((float) 0.0)); } else if (curr instanceof ILOAD) { ins[i].setInstruction(new ICONST(0)); } else if (curr instanceof DLOAD) { ins[i].setInstruction(new DCONST(0.0)); } else if (curr instanceof LLOAD) { ins[i].setInstruction(new LCONST(0L)); } else { System.out.println("unhandled ins in " + "removeUnusedLocals: " + curr); System.exit(1); } } } } }
InstructionHandle insertTypecheckCode(MethodGen m, InstructionList il, InstructionHandle pos, int spawnId, int exceptionPos) { ArrayList<CodeExceptionGen> catches = mtab.getCatchTypes(m, spawnId); InstructionHandle[] jumpTargets = new InstructionHandle[catches.size() + 1]; BranchHandle[] jumps = new BranchHandle[catches.size()]; for (int i = 0; i < catches.size(); i++) { CodeExceptionGen e = catches.get(i); ObjectType type = e.getCatchType(); InstructionHandle catchTarget = e.getHandlerPC(); jumpTargets[i] = il.insert(pos, new ALOAD(exceptionPos)); il.insert(pos, new INSTANCEOF(cpg.addClass(type))); il.insert(pos, new BIPUSH((byte) 1)); jumps[i] = il.insert(pos, new IF_ICMPNE(null)); il.insert(pos, new ALOAD(exceptionPos)); il.insert(pos, ins_f.createCheckCast(type)); il.insert(pos, new GOTO(catchTarget)); } InstructionHandle t = il.insert(pos, new ALOAD(exceptionPos)); il.insert(pos, new ATHROW()); jumpTargets[catches.size()] = t; for (int i = 0; i < catches.size(); i++) { jumps[i].setTarget(jumpTargets[i + 1]); } return pos; }
/** Tests whether an object load instruction is used for computing an array length. * * @param loadInstruction the load instruction that loads the object * reference onto the stack. * @return true if the instruction is a load instruction of an object which * is used for computing an array length. */ public boolean isUsedForArrayLength(InstructionHandle loadInstruction) { if (loadInstruction.getInstruction() instanceof ALOAD) { InstructionHandle next = loadInstruction.getNext(); if (next != null && (next.getInstruction() instanceof ARRAYLENGTH)) { return true; } } return false; }
private ArrayList<InstructionHandle> getAllObjectLoadInstructions(InstructionList il) { ArrayList<InstructionHandle> objectLoadInstructions = new ArrayList<InstructionHandle>(); InstructionHandle current = il.getStart(); while(current != null) { Instruction instruction = current.getInstruction(); if (instruction instanceof ALOAD || instruction instanceof GETSTATIC) { objectLoadInstructions.add(current); } current = current.getNext(); } return objectLoadInstructions; }
private int indexToCheckForAlias(InstructionHandle ih, MethodGen mg) { if (mg.isArrayStore(ih.getInstruction()) || ih.getInstruction() instanceof PUTFIELD) { ih = mg.getObjectReferenceLoadInstruction(ih); ALOAD objectLoadInstruction = (ALOAD) ih.getInstruction(); // The 'not an ALOAD' case is already dealt with. return objectLoadInstruction.getIndex(); } return -1; }
public void initializeSlots() { int slot = 0; createUpvalues(-1, 0, p.maxstacksize); if ( superclassType == SUPERTYPE_VARARGS ) { for ( slot=0; slot<p.numparams; slot++ ) { if ( pi.isInitialValueUsed(slot) ) { append(new ALOAD(1)); append(new PUSH(cp, slot+1)); append(factory.createInvoke(STR_VARARGS, "arg", TYPE_LUAVALUE, ARG_TYPES_INT, Constants.INVOKEVIRTUAL)); storeLocal(-1, slot); } } append(new ALOAD(1)); append(new PUSH(cp, 1 + p.numparams)); append(factory.createInvoke(STR_VARARGS, "subargs", TYPE_VARARGS, ARG_TYPES_INT, Constants.INVOKEVIRTUAL)); append(new ASTORE(1)); } else { // fixed arg function between 0 and 3 arguments for ( slot=0; slot<p.numparams; slot++ ) { this.plainSlotVars.put( Integer.valueOf(slot), Integer.valueOf(1+slot) ); if ( pi.isUpvalueCreate(-1, slot) ) { append(new ALOAD(1+slot)); storeLocal(-1, slot); } } } // nil parameters // TODO: remove this for lua 5.2, not needed for ( ; slot<p.maxstacksize; slot++ ) { if ( pi.isInitialValueUsed(slot) ) { loadNil(); storeLocal(-1, slot); } } }
public void loadLocal(int pc, int slot) { boolean isupval = pi.isUpvalueRefer(pc, slot); int index = findSlotIndex( slot, isupval ); append(new ALOAD(index)); if (isupval) { append(new PUSH(cp, 0)); append(InstructionConstants.AALOAD); } }
public void convertToUpvalue(int pc, int slot) { boolean isupassign = pi.isUpvalueAssign(pc, slot); if ( isupassign ) { int index = findSlotIndex( slot, false ); append(new ALOAD(index)); append(factory.createInvoke(classname, "newupl", TYPE_LOCALUPVALUE, ARG_TYPES_LUAVALUE, Constants.INVOKESTATIC)); int upindex = findSlotIndex( slot, true ); append(new ASTORE(upindex)); } }
public void closureInitUpvalueFromLocal(String protoname, int newup, int pc, int srcslot) { boolean isrw = pi.isReadWriteUpvalue( pi.vars[srcslot][pc].upvalue ); Type uptype = isrw? (Type) TYPE_LOCALUPVALUE: (Type) TYPE_LUAVALUE; String destname = upvalueName(newup); int index = findSlotIndex( srcslot, isrw ); append(new ALOAD(index)); append(factory.createFieldAccess(protoname, destname, uptype, Constants.PUTFIELD)); }
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitALOAD(ALOAD o){ int idx = o.getIndex(); if (idx < 0){ constraintViolated(o, "Index '"+idx+"' must be non-negative."); } else{ int maxminus1 = max_locals()-1; if (idx > maxminus1){ constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'."); } } }
protected boolean loadLocalVariable(Variable variable, InstructionList il) { if ( currentMethod == null ) throw new IllegalStateException(); for (LocalVariableGen lvg : currentMethod.getLocalVariables()) { if (lvg.getName().equals( variable.getName()) ) { il.append(new ALOAD(lvg.getIndex())); return true; } } return false; }
private void createConstructor(GenScope scope, ClassGen closureClass) { InstructionList il = new InstructionList(); il.append(InstructionConstants.THIS); // Push `this' il.append(new INVOKESPECIAL(closureClass.getConstantPool().addMethodref(closureClass.getSuperclassName(), "<init>", "()V"))); il.append(InstructionConstants.THIS); // Push `this' il.append(scope.getInstructionFactory().createConstant(this.getFormalParameters().size())); il.append(scope.getInstructionFactory().createPutField(DefaultTypes.IClosure.getClassName(), "numParameters_", Type.INT)); il.append(InstructionConstants.THIS); // Push `this' il.append(new ALOAD(1)); // first parameter il.append(scope.getInstructionFactory().createPutField(DefaultTypes.IClosure.getClassName(), "transformation_", DefaultTypes.IdcTransformation)); il.append(InstructionConstants.THIS); // Push `this' il.append(new ALOAD(2)); // second parameter il.append(scope.getInstructionFactory().createPutField(DefaultTypes.IClosure.getClassName(), "modelManager_", DefaultTypes.ModelManager)); // TODO: It would be nice to have cross-checking between code being generated and framework code /* il.append(InstructionConstants.THIS); // Push `this' il.append(new ALOAD(1)); // first parameter il.append(scope.getInstructionFactory().createPutField(DefaultTypes.IClosure.getClassName(), "modelManager_", DefaultTypes.ModelManager)); */ il.append(InstructionConstants.RETURN); MethodGen mg = new MethodGen(Constants.ACC_PUBLIC, Type.VOID, new Type[] { DefaultTypes.IdcTransformation, DefaultTypes.ModelManager } , null, "<init>", closureClass.getClassName(), il, closureClass.getConstantPool()); // mg.setMaxStack(3); mg.setMaxStack(); closureClass.addMethod(mg.getMethod()); }
void generateMain(ClassGen clg, Method origMain) { InstructionList il = new InstructionList(); MethodGen new_main = new MethodGen(Constants.ACC_STATIC | Constants.ACC_PUBLIC, Type.VOID, new Type[] { new ArrayType( Type.STRING, 1) }, new String[] { "argv" }, "main", clg .getClassName(), il, clg.getConstantPool()); il.append(ins_f.createNew(cashmereType)); il.append(new DUP()); il.append(ins_f.createInvoke("ibis.cashmere.impl.Cashmere", "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); il.append(ins_f.createInvoke("ibis.cashmere.impl.Cashmere", "isMaster", Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); BranchHandle ifcmp = il.append(new IFEQ(null)); InstructionHandle origMain_handle = il.append(new ALOAD(0)); InstructionHandle try_start = il.append(ins_f.createInvoke(clg .getClassName(), origMain.getName(), Type.VOID, new Type[] { new ArrayType(Type.STRING, 1) }, Constants.INVOKESTATIC)); BranchHandle try_end = il.append(new GOTO(null)); InstructionHandle e_handler = il.append(getCashmere(ins_f)); il.append(new SWAP()); il.append(ins_f.createInvoke("ibis.cashmere.impl.Cashmere", "exit", Type.VOID, new Type[] { new ObjectType("java.lang.Throwable")}, Constants.INVOKEVIRTUAL)); BranchHandle gto2 = il.append(new GOTO(null)); InstructionHandle ifeq_target = il.append(getCashmere(ins_f)); ifcmp.setTarget(ifeq_target); il.append(ins_f.createInvoke("ibis.cashmere.impl.Cashmere", "client", Type.VOID, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); il.append(getCashmere(ins_f)); il.append(ins_f.createInvoke("ibis.cashmere.impl.Cashmere", "isMaster", Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); il.append(new IFNE(origMain_handle)); InstructionHandle gto_target = il.append(getCashmere(ins_f)); try_end.setTarget(gto_target); il.append(ins_f.createInvoke("ibis.cashmere.impl.Cashmere", "exit", Type.VOID, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); InstructionHandle gto2_target = il.append(new RETURN()); gto2.setTarget(gto2_target); new_main.addExceptionHandler(try_start, try_end, e_handler, new ObjectType("java.lang.Throwable")); new_main.setMaxStack(); new_main.setMaxLocals(); new_main.addLocalVariable("argv", new ArrayType(Type.STRING, 1), 0, origMain_handle, null); removeLocalTypeTables(new_main); Method main = new_main.getMethod(); gen_c.addMethod(main); }
void rewriteAbort(MethodGen m, InstructionList il, InstructionHandle i, int maxLocals) { // in a clone, we have to abort two lists: the outstanding spawns of // the parent, and the outstanding spawns of the clone. Instruction fa = getCashmere(ins_f); Instruction ab = ins_f.createInvoke("ibis.cashmere.impl.Cashmere", "abort", Type.VOID, new Type[] { irType, irType }, Constants.INVOKEVIRTUAL); if (mtab.isClone(m)) { int parentPos = 3; if (!m.isStatic()) { // we have an additional 'this' param parentPos++; } i.getPrev().getPrev().setInstruction(fa); // push outstanding spawns i.getPrev().setInstruction(new ALOAD(maxLocals - 3)); // push parent invocationrecord i.setInstruction(new ALOAD(parentPos)); i = i.getNext(); } else if (mtab.containsInlet(m)) { i.getPrev().getPrev().setInstruction(fa); // push outstanding spawns i.getPrev().setInstruction(new ALOAD(maxLocals - 3)); i.setInstruction(new ACONST_NULL()); i = i.getNext(); } else { i.getPrev().setInstruction(fa); // push outstanding spawns i.setInstruction(new ALOAD(maxLocals - 3)); i = i.getNext(); il.insert(i, new ACONST_NULL()); } // and call Cashmere.abort il.insert(i, ab); // all jobs were killed, set outstandingSpawns to null il.insert(i, new ACONST_NULL()); // push null il.insert(i, new ASTORE(maxLocals - 3)); // write }
void initSpawnTargets(InstructionList il) { for (int i = 0; i < idTable.size(); i++) { InstructionList storeIns = getStoreIns(i); if (storeIns == null) { continue; } if (isArrayStore(storeIns.getStart())) { continue; } Instruction store = storeIns.getStart().getInstruction(); if (store instanceof LSTORE) { il.insert(new LCONST(0)); il.append(il.getStart(), store); } else if (store instanceof ISTORE) { il.insert(new ICONST(0)); il.append(il.getStart(), store); } else if (store instanceof FSTORE) { il.insert(new FCONST((float) 0.0)); il.append(il.getStart(), store); } else if (store instanceof DSTORE) { il.insert(new DCONST(0.0)); il.append(il.getStart(), store); } else if (store instanceof ASTORE) { il.insert(new ACONST_NULL()); il.append(il.getStart(), store); } else if (store instanceof PUTFIELD) { // no need to init. } else if (store instanceof PUTSTATIC) { // no need to init. } else if (store instanceof ALOAD) { // no need to init. } else { System.err.println("WARNING: Unhandled store instruction in " + "initSpawnTargets, opcode = " + store.getOpcode() + " ins = " + store); // System.exit(1); } } }
boolean nonEscapingConstructor(JavaClass javaClass, String constructorSignature) { if (javaClass.getClassName().equals("java.lang.Object")) { return true; } JavaClass superClass; try { superClass = javaClass.getSuperClass(); } catch(ClassNotFoundException e) { throw new Error("Superclass of " + javaClass.getClassName() + " not found"); } Method[] methods = javaClass.getMethods(); for (Method method : methods) { if (method.getName().equals("<init>") && method.getSignature().equals(constructorSignature)) { if (nonEscapingConstructor(superClass, "()V")) { ClassGen cg = new ClassGen(javaClass); MethodGen mg = new MethodGen(method, javaClass.getClassName(), cg.getConstantPool()); // Now check all ALOAD 0 instructions. They may only be used for // PUTFIELD and for calling super(). InstructionHandle h = mg.getInstructionList().getStart(); while (h != null) { Instruction i = h.getInstruction(); if (i instanceof ALOAD && ((ALOAD) i).getIndex() == 0) { if (! mg.isUsedForPutField(h)) { // Find instructions that consume exactly this load (but not more, // otherwise it could be a parameter to another constructor). InstructionHandle[] users = mg.findExactInstructionConsumers(h); if (users.length != 1) { return false; } i = users[0].getInstruction(); if (i instanceof INVOKESPECIAL) { INVOKESPECIAL invoker = (INVOKESPECIAL) i; if (! invoker.getMethodName(mg.getConstantPool()).equals("<init>") || ! nonEscapingConstructor(superClass, invoker.getSignature(mg.getConstantPool()))) { return false; } } else { return false; } } } h = h.getNext(); } return true; } } } return false; }
byte[] counterAdaptClass(final InputStream is, final String name) throws Exception { JavaClass jc = new ClassParser(is, name + ".class").parse(); ClassGen cg = new ClassGen(jc); ConstantPoolGen cp = cg.getConstantPool(); if (!cg.isInterface()) { FieldGen fg = new FieldGen(ACC_PUBLIC, Type.getType("I"), "_counter", cp); cg.addField(fg.getField()); } Method[] ms = cg.getMethods(); for (int j = 0; j < ms.length; ++j) { MethodGen mg = new MethodGen(ms[j], cg.getClassName(), cp); if (!mg.getName().equals("<init>") && !mg.isStatic() && !mg.isAbstract() && !mg.isNative()) { if (mg.getInstructionList() != null) { InstructionList il = new InstructionList(); il.append(new ALOAD(0)); il.append(new ALOAD(0)); il.append(new GETFIELD(cp.addFieldref(name, "_counter", "I"))); il.append(new ICONST(1)); il.append(new IADD()); il.append(new PUTFIELD(cp.addFieldref(name, "_counter", "I"))); mg.getInstructionList().insert(il); mg.setMaxStack(Math.max(mg.getMaxStack(), 2)); boolean lv = ms[j].getLocalVariableTable() == null; boolean ln = ms[j].getLineNumberTable() == null; if (lv) { mg.removeLocalVariables(); } if (ln) { mg.removeLineNumbers(); } cg.replaceMethod(ms[j], mg.getMethod()); } } } return cg.getJavaClass().getBytes(); }
public void loadVarargs() { append(new ALOAD(1)); }
public void loadVarresult() { append(new ALOAD(getVarresultIndex())); }
private String generateObserverClass(ModelDefinition model, ObserverDescription observer, TransformationContext context) { final String className = context.getRuntimeClassName() + "$" + observer.getName(); final String transformationFieldName = "transformation_"; ClassGen cg = new ClassGen(className, observer.getObserverClass(), context.getFilename(), Constants.ACC_PUBLIC | Constants.ACC_SUPER, new String[] {}); cg.addField(new FieldGen(Constants.ACC_PUBLIC, DefaultTypes.QoolTransformation, transformationFieldName, cg.getConstantPool()).getField()); // constructor InstructionList constructorIl = new InstructionList(); InstructionFactory constructorIfact = new InstructionFactory(cg); MethodGen constructor = new MethodGen(Constants.ACC_PUBLIC, Type.VOID, new Type[] { DefaultTypes.QoolTransformation } , null, "<init>", cg.getClassName(), constructorIl, cg.getConstantPool()); constructorIl.append(InstructionConstants.THIS); // Push `this' constructorIl.append(new INVOKESPECIAL(cg.getConstantPool().addMethodref(cg.getSuperclassName(), "<init>", "()V"))); constructorIl.append(InstructionFactory.THIS); constructorIl.append(new ALOAD(1)); constructorIl.append( constructorIfact.createPutField(cg.getClassName(), transformationFieldName, DefaultTypes.QoolTransformation) ); constructorIl.append(InstructionFactory.RETURN); constructor.setMaxLocals(); constructor.setMaxStack(); cg.addMethod(constructor.getMethod()); // end-of constructor EList<UpdateMethod> methods = observer.getUpdateMethods(); for (UpdateMethod updateMethod : methods) { EList<String> ptypes = updateMethod.getParameterTypes(); InstructionList il = new InstructionList(); InstructionFactory ifact = new InstructionFactory(cg); // TODO: Assuming void return type // TODO: Assuming object types Type[] types = new Type[ptypes.size()]; int i = 0; for(String strType : ptypes) { types[i++] = new ObjectType(strType); } MethodGen mg = new MethodGen(Constants.ACC_PUBLIC, Type.VOID, types, null, updateMethod.getName(), cg.getClassName(), il, cg.getConstantPool()); // TODO: assuming only 1 interest parameter assert(updateMethod.getInterest().size() == 1); il.append(InstructionConstants.THIS); il.append(ifact.createGetField(className, transformationFieldName, DefaultTypes.QoolTransformation)); il.append(ifact.createConstant(model.getName())); il.append(new ALOAD(updateMethod.getInterest().get(0) + 1)); il.append(ifact.createInvoke(DefaultTypes.QoolTransformation.getClassName(), "addObjectToQueues", Type.VOID, new Type[] { Type.STRING, Type.OBJECT }, Constants.INVOKEVIRTUAL)); il.append(InstructionFactory.RETURN); mg.setMaxLocals(); mg.setMaxStack(); cg.addMethod(mg.getMethod()); } context.addExtraClass(cg.getJavaClass()); return className; }
private void generateMethodForMethods(GenScope scope, String methodName, ArrayList<MethodDefinitionJVMGen> value) { InstructionList il = new InstructionList(); InstructionFactory ifact = new InstructionFactory(scope.getConstantPool()); MethodDefinitionJVMGen methodDef = value.get(0); if ( value.size() > 1 ) { System.out.println("WARNING: Don't know why I assumed that several definition of the same method may appear, probably because overloading..."); System.out.println(" Not sure why this seems to work for e.g., UML2Java tao example..."); } Type[] paramTypes = new Type[methodDef.getFormalParameters().size() + 1]; String[] paramNames = new String[paramTypes.length]; paramTypes[0] = Type.OBJECT; // Receptor object paramNames[0] = "self"; for(int i = 0; i < methodDef.getFormalParameters().size(); i++) { paramTypes[i + 1] = Type.OBJECT; paramNames[i + 1] = methodDef.getFormalParameters().get(i).getName(); } MethodGen method = new MethodGen(Constants.ACC_PUBLIC, Type.OBJECT, paramTypes, paramNames, methodName, scope.getClassGen().getClassName(), il, scope.getConstantPool()); scope.processMethod(method); // todo: call pre?? /* il.append(InstructionConstants.THIS); il.append(ifact.createConstant( methodName ) ); il.append(new ALOAD(1)); il.append(ifact.createInvoke(MethodLibraryBase.class.getName(), "performInvocation", Type.OBJECT, new Type[] { Type.STRING, Type.OBJECT }, Constants.INVOKEVIRTUAL)); */ // I think that performInvocation does not actually work because class loader issues, so // it was replaced by getMethodHandler but I didn't change this piece of code, 8/Nov/2012, trying... il.append(InstructionConstants.THIS); il.append(ifact.createConstant( methodName ) ); il.append(new ALOAD(1)); il.append(ifact.createInvoke(MethodLibraryBase.class.getName(), "getMethodHandler", DefaultTypes.RunnableClosure, new Type[] { Type.STRING, Type.OBJECT }, Constants.INVOKEVIRTUAL)); for(int i = 0; i < paramTypes.length; i++) { il.append(new ALOAD(i + 1)); // parameters } String callMethod = "call_" + paramTypes.length; il.append(ifact.createInvoke(DefaultTypes.RunnableClosure.getClassName(), callMethod, Type.OBJECT, paramTypes, Constants.INVOKEVIRTUAL)); il.append(InstructionConstants.ARETURN); method.setMaxLocals(); method.setMaxStack(); scope.getClassGen().addMethod(method.getMethod()); }