void write(ClassEnv e, CodeAttr ce, DataOutputStream out) throws IOException, jasError { if (wide) { target.writeWideOffset(ce, source, out); } else { int offset = ce.getPc(target); if (source != null) offset -= ce.getPc(source); if (offset > 32767 || offset < -32768) throw new jasError("reference from line " + ref + " exceed size for short"); target.writeOffset(ce, source, out); } }
// Recursive helper function. private static void popParams( CodeAttr code, int paramNo, int count, int[] incValues, Declaration decl, Variable vars) { if (count > 0) { count--; popParams( code, paramNo + 1, count, incValues, decl.nextDecl(), decl.getVariable() == null ? vars : vars.nextVar()); if (!decl.ignorable()) { if (incValues != null && incValues[paramNo] != SetExp.BAD_SHORT) code.emitInc(vars, (short) incValues[paramNo]); else code.emitStore(vars); } } }
// // called by the .end method directive to end the definition for a method // void endMethod() throws jasError { if (cur_method == null) throw new jasError(".end method without .method"); if (cur_annotation != null) opened_annotation("method"); if (code != null) { plantLabel(END_METHOD); flushInsnBuffer(); if (catch_table != null) { code.setCatchtable(catch_table); } if (var_table != null) { code.setLocalVarTable(var_table); } if (vtype_table != null) { code.setLocalVarTypeTable(vtype_table); } if (line_table != null) { code.setLineTable(line_table); } if (stackmap != null) { code.setStackMap(stackmap); } } cur_method.setCode(code, except_attr); class_env.addMethod(cur_method); // clear method state variables cur_method = null; code = null; labels = null; catch_table = null; line_table = null; var_table = null; vtype_table = null; stackmap = null; verifyframe = null; }
int size(ClassEnv ce, CodeAttr code) throws jasError { int sz = 8; // 4 + 4 + padding + jumptable int source_pc = code.getPc(source); if (((source_pc + 1) % 4) != 0) { // need padding sz += (4 - ((source_pc + 1) % 4)); } if (jmp != null) { sz += 8 * (jmp.length); } return sz; }
public static void main(String argv[]) throws jasError, IOException { // CodeAttr's contain the body of // a method. CodeAttr init = new CodeAttr(); init.addInsn(new Insn(opc_aload_0)); init.addInsn(new Insn(opc_invokenonvirtual, new MethodCP("java/lang/Object", "<init>", "()V"))); init.addInsn(new Insn(opc_return)); // ClassEnv's are used as a container // to hold all information about a class. ClassEnv nclass = new ClassEnv(); nclass.setClass(new ClassCP("out")); nclass.setSuperClass(new ClassCP("java/lang/Object")); // Add the init code to the class. nclass.addMethod((short) ACC_PUBLIC, "<init>", "()V", init, null); // write it all out nclass.write(new DataOutputStream(new FileOutputStream("out.class"))); }
int size(ClassEnv ce, CodeAttr code) throws jasError // the *real* reason for making it a // method.. { int sz = 12; // 4+4+4+jmptable+padding... int source_pc = code.getPc(source); if (((source_pc + 1) % 4) != 0) { // need padding sz += (4 - ((source_pc + 1) % 4)); } if (jmp != null) { sz += 4 * (jmp.length); } return sz; }
// // called by the .attribute directive // void addGenericAttr(String name, String file) throws IOException, jasError { GenericAttr gattr = new GenericAttr(name, file); if (cur_method != null) { flushInsnBuffer(); if (code != null) code.addGenericAttr(gattr); else cur_method.addGenericAttr(gattr); } else if (cur_field != null) { cur_field.addGenericAttr(gattr); } else if (class_header) { class_env.addGenericAttr(gattr); } else { outside(".attribute"); } }
void write(ClassEnv e, CodeAttr ce, DataOutputStream out) throws IOException, jasError { int pad; int source_pc = ce.getPc(source); if (((source_pc + 1) % 4) != 0) { // need padding pad = (4 - ((source_pc + 1) % 4)); for (int x = 0; x < pad; x++) out.writeByte(0); } dflt.writeWideOffset(ce, source, out); out.writeInt(min); out.writeInt(max); int cnt = jmp.length; for (int x = 0; x < cnt; x++) { jmp[x].writeWideOffset(ce, source, out); } }
public void emitTestIf(Variable incoming, Declaration decl, Compilation comp) { CodeAttr code = comp.getCode(); if (incoming != null) code.emitLoad(incoming); if (decl != null) { code.emitDup(); decl.compileStore(comp); } comp.compileConstant(this); code.emitSwap(); code.emitInvokeVirtual(isInstanceMethod); code.emitIfIntNotZero(); }
void write(ClassEnv e, CodeAttr ce, DataOutputStream out) throws IOException, jasError { int pad; int source_pc = ce.getPc(source); if (((source_pc + 1) % 4) != 0) { // need padding pad = (4 - ((source_pc + 1) % 4)); for (int x = 0; x < pad; x++) out.writeByte(0); } // write offset to default // as a 4 byte signed value dflt.writeWideOffset(ce, source, out); if (jmp == null) { out.writeInt(0); } else { out.writeInt(jmp.length); for (int x = 0; x < jmp.length; x++) { out.writeInt(match[x]); jmp[x].writeWideOffset(ce, source, out); } } }
public static void compileToArray(Expression[] args, Compilation comp) { CodeAttr code = comp.getCode(); if (args.length == 0) { code.emitGetStatic(Compilation.noArgsField); return; } code.emitPushInt(args.length); code.emitNewArray(Type.pointer_type); for (int i = 0; i < args.length; ++i) { Expression arg = args[i]; if (comp.usingCPStyle() && !(arg instanceof QuoteExp) && !(arg instanceof ReferenceExp)) { // If the argument involves a CPStyle function call, we will // have to save and restore anything on the JVM stack into // fields in the CallFrame. This is expensive, so defer // pushing the duplicated argument array and the index // until *after* we've calculated the argument. The downside // is that we have to do some extra stack operations. // However, these are cheap (and get compiled away when // compiling to native code). arg.compileWithPosition(comp, Target.pushObject); code.emitSwap(); code.emitDup(1, 1); code.emitSwap(); code.emitPushInt(i); code.emitSwap(); } else { code.emitDup(Compilation.objArrayType); code.emitPushInt(i); arg.compileWithPosition(comp, Target.pushObject); } code.emitArrayStore(Type.pointer_type); } }