List of usage examples for org.objectweb.asm Opcodes DUP
int DUP
To view the source code for org.objectweb.asm Opcodes DUP.
Click Source Link
From source file:org.eclipse.objectteams.otredyn.bytecode.asm.AddGlobalTeamActivationAdapter.java
License:Open Source License
@Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { synchronized (AddGlobalTeamActivationAdapter.class) { if (!done && isMainMethod(name, desc, access)) { done = true;//from w ww . j ava2s . c om final MethodVisitor methodVisitor = cv.visitMethod(access, name, desc, null, null); return new AdviceAdapter(this.api, methodVisitor, access, name, desc) { @Override protected void onMethodEnter() { List<String> teams = getTeamsFromConfigFile(); for (String aTeam : teams) { Label start, end, typeHandler, ctorHandler, after; String aTeamSlash = aTeam.replace('.', '/'); // new SomeTeam(): methodVisitor.visitLabel(start = new Label()); methodVisitor.visitTypeInsn(Opcodes.NEW, aTeamSlash); // .activate(Team.ALL_THREADS): methodVisitor.visitInsn(Opcodes.DUP); methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, aTeamSlash, "<init>", "()V", false); methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, ClassNames.TEAM_SLASH, "ALL_THREADS", "Ljava/lang/Thread;"); methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, aTeamSlash, "activate", "(Ljava/lang/Thread;)V", false); methodVisitor.visitLabel(end = new Label()); methodVisitor.visitJumpInsn(Opcodes.GOTO, after = new Label()); // catch (ClassNotFoundException, NoClassDefFoundError): // System.err.println(...) methodVisitor.visitLabel(typeHandler = new Label()); methodVisitor.visitInsn(Opcodes.POP); // discard the exception methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "err", "Ljava/io/PrintStream;"); methodVisitor.visitLdcInsn("Config error: Team class '" + aTeam + "' in config file '" + TEAM_CONFIG_FILE + "' can not be found!"); methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); methodVisitor.visitJumpInsn(Opcodes.GOTO, after); methodVisitor.visitTryCatchBlock(start, end, typeHandler, "java/lang/ClassNotFoundException"); // dup to avoid stackmap errors (ASM bug at 1.8) methodVisitor.visitLabel(typeHandler = new Label()); methodVisitor.visitInsn(Opcodes.POP); // discard the exception methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "err", "Ljava/io/PrintStream;"); methodVisitor.visitLdcInsn("Config error: Team class '" + aTeam + "' in config file '" + TEAM_CONFIG_FILE + "' can not be found!"); methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); methodVisitor.visitJumpInsn(Opcodes.GOTO, after); // methodVisitor.visitTryCatchBlock(start, end, typeHandler, "java/lang/NoClassDefFoundError"); // catch (NoSuchMethodError): // System.err.println(...) methodVisitor.visitLabel(ctorHandler = new Label()); methodVisitor.visitInsn(Opcodes.POP); // discard the exception methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "err", "Ljava/io/PrintStream;"); methodVisitor.visitLdcInsn( "Activation failed: Team class '" + aTeam + "' has no default constuctor!"); methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); methodVisitor.visitTryCatchBlock(start, end, ctorHandler, "java/lang/NoSuchMethodError"); methodVisitor.visitLabel(after); } } @Override public void visitMaxs(int maxStack, int maxLocals) { super.visitMaxs(Math.max(maxStack, 3), maxLocals); } }; } return null; } }
From source file:org.eclipse.objectteams.otredyn.bytecode.asm.CreateAddRemoveRoleMethod.java
License:Open Source License
void genGetInitializedRoleSet(InsnList instructions, int targetLocal) { // x = this._OT$roleSet instructions.add(new IntInsnNode(Opcodes.ALOAD, 0)); instructions.add(new FieldInsnNode(Opcodes.GETFIELD, name, ConstantMembers.OT_ROLE_SET, ConstantMembers.HASH_SET_FIELD_TYPE)); instructions.add(new IntInsnNode(Opcodes.ASTORE, targetLocal)); instructions.add(new IntInsnNode(Opcodes.ALOAD, targetLocal)); // if (x == null) { LabelNode skipInstantiation = new LabelNode(); instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, skipInstantiation)); // this._OT$roleSet = new HashSet(); instructions.add(new IntInsnNode(Opcodes.ALOAD, 0)); instructions.add(new TypeInsnNode(Opcodes.NEW, ClassNames.HASH_SET_SLASH)); instructions.add(new InsnNode(Opcodes.DUP)); instructions//from ww w . jav a2s . c om .add(new MethodInsnNode(Opcodes.INVOKESPECIAL, ClassNames.HASH_SET_SLASH, "<init>", "()V", false)); instructions.add(new IntInsnNode(Opcodes.ASTORE, targetLocal)); instructions.add(new IntInsnNode(Opcodes.ALOAD, targetLocal)); instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, name, ConstantMembers.OT_ROLE_SET, ConstantMembers.HASH_SET_FIELD_TYPE)); instructions.add(skipInstantiation); // } }
From source file:org.eclipse.objectteams.otredyn.bytecode.asm.CreateDispatchCodeInOrgMethodAdapter.java
License:Open Source License
@Override protected InsnList createInstructionsToCheackTeams(MethodNode method) { InsnList instructions = new InsnList(); instructions.add(new InsnNode(Opcodes.DUP)); LabelNode label = new LabelNode(); //if (teams == null) { instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, label)); instructions.add(new InsnNode(Opcodes.POP)); //put the boundMethodId on the stack instructions.add(createLoadIntConstant(boundMethodId)); Type[] args = Type.getArgumentTypes(method.desc); // box the arguments instructions.add(getBoxingInstructions(args, (method.access & Opcodes.ACC_STATIC) != 0)); //callOrigStatic(boundMethodId, args); instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, name, ConstantMembers.callOrigStatic.getName(), ConstantMembers.callOrigStatic.getSignature())); Type returnType = Type.getReturnType(method.desc); instructions.add(getUnboxingInstructionsForReturnValue(returnType)); instructions.add(label);/*from w ww .j ava2s. c o m*/ return instructions; }
From source file:org.eclipse.objectteams.otredyn.bytecode.asm.CreateMethodAccessAdapter.java
License:Open Source License
@Override public boolean transform() { MethodNode methodNode = getMethod(method); InsnList instructions = new InsnList(); if (isConstructor) { // create empty object for constructor invocation: instructions.add(new TypeInsnNode(Opcodes.NEW, name)); instructions.add(new InsnNode(Opcodes.DUP)); } else if (!method.isStatic()) { //put "this" on the stack for a non-static method instructions.add(new IntInsnNode(Opcodes.ALOAD, 0)); }/*from w w w . j a v a 2 s . c o m*/ //Unbox arguments Type[] args = Type.getArgumentTypes(methodNode.desc); if (args.length > 0) { for (int i = 0; i < args.length; i++) { instructions.add(new IntInsnNode(Opcodes.ALOAD, firstArgIndex + 2)); instructions.add(createLoadIntConstant(i)); instructions.add(new InsnNode(Opcodes.AALOAD)); Type arg = args[i]; if (arg.getSort() != Type.ARRAY && arg.getSort() != Type.OBJECT) { String objectType = AsmTypeHelper.getObjectType(arg); instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, objectType)); instructions.add(AsmTypeHelper.getUnboxingInstructionForType(arg, objectType)); } else { instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, arg.getInternalName())); } } } //call original method int opcode = Opcodes.INVOKEVIRTUAL; if (method.isStatic()) { opcode = Opcodes.INVOKESTATIC; } else if (isConstructor) { opcode = Opcodes.INVOKESPECIAL; } instructions.add(new MethodInsnNode(opcode, name, method.getName(), method.getSignature())); //box return value Type returnType = Type.getReturnType(methodNode.desc); if (returnType.getSort() != Type.OBJECT && returnType.getSort() != Type.ARRAY && returnType.getSort() != Type.VOID) { instructions.add(AsmTypeHelper.getBoxingInstructionForType(returnType)); instructions.add(new InsnNode(Opcodes.ARETURN)); } else if (returnType.getSort() == Type.VOID && !isConstructor) { instructions.add(new InsnNode(Opcodes.ACONST_NULL)); instructions.add(new InsnNode(Opcodes.ARETURN)); } else { instructions.add(new InsnNode(Opcodes.ARETURN)); } //add the instructions to a new label in the existing switch MethodNode access = getMethod(this.access); addNewLabelToSwitch(access.instructions, instructions, accessId); return true; }
From source file:org.eclipse.objectteams.otredyn.bytecode.asm.CreateSwitchForAccessAdapter.java
License:Open Source License
@Override protected void addInstructionForDefaultLabel(MethodNode method) { if (superClassName.equals("java/lang/Object")) { method.instructions.add(new TypeInsnNode(Opcodes.NEW, "org/objectteams/NoSuchMethodError")); method.instructions.add(new InsnNode(Opcodes.DUP)); method.instructions.add(new IntInsnNode(Opcodes.ILOAD, getFirstArgIndex())); // accessId method.instructions.add(new LdcInsnNode(clazz.getName())); // current class method.instructions.add(new LdcInsnNode("decapsulating access")); // access reason method.instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "org/objectteams/NoSuchMethodError", "<init>", "(ILjava/lang/String;Ljava/lang/String;)V", false)); method.instructions.add(new InsnNode(Opcodes.ATHROW)); } else {//from w w w. j ava2s. c o m Type[] args = Type.getArgumentTypes(method.desc); addInstructionsForLoadArguments(method.instructions, args, getMethod().isStatic()); int opcode = Opcodes.INVOKESPECIAL; if (getMethod().isStatic()) { opcode = Opcodes.INVOKESTATIC; } method.instructions.add( new MethodInsnNode(opcode, superClassName, getMethod().getName(), getMethod().getSignature())); method.instructions.add(new InsnNode(Opcodes.ARETURN)); } }
From source file:org.eclipse.objectteams.otredyn.bytecode.asm.MoveCodeToCallOrigAdapter.java
License:Open Source License
public boolean transform() { MethodNode orgMethod = getMethod(method); if ((orgMethod.access & Opcodes.ACC_ABSTRACT) != 0) return false; MethodNode callOrig = getMethod(this.callOrig); Type returnType = Type.getReturnType(orgMethod.desc); InsnList newInstructions = new InsnList(); //Unboxing arguments Type[] args = Type.getArgumentTypes(orgMethod.desc); int boundMethodIdSlot = firstArgIndex; if (args.length > 0) { // move boundMethodId to a higher slot, to make lower slots available for original locals newInstructions.add(new IntInsnNode(Opcodes.ILOAD, boundMethodIdSlot)); boundMethodIdSlot = callOrig.maxLocals + 1; newInstructions.add(new IntInsnNode(Opcodes.ISTORE, boundMethodIdSlot)); newInstructions.add(new IntInsnNode(Opcodes.ALOAD, firstArgIndex + argOffset + 1)); int slot = firstArgIndex + argOffset; for (int i = argOffset; i < args.length; i++) { if (i < args.length - 1) { newInstructions.add(new InsnNode(Opcodes.DUP)); }/*from ww w . j av a 2 s . co m*/ newInstructions.add(createLoadIntConstant(i)); newInstructions.add(new InsnNode(Opcodes.AALOAD)); Type arg = args[i]; if (arg.getSort() != Type.ARRAY && arg.getSort() != Type.OBJECT) { String objectType = AsmTypeHelper.getObjectType(arg); newInstructions.add(new TypeInsnNode(Opcodes.CHECKCAST, objectType)); newInstructions.add(AsmTypeHelper.getUnboxingInstructionForType(arg, objectType)); } else { newInstructions.add(new TypeInsnNode(Opcodes.CHECKCAST, arg.getInternalName())); } newInstructions.add(new IntInsnNode(args[i].getOpcode(Opcodes.ISTORE), slot)); slot += arg.getSize(); } } if (superIsWeavable) adjustSuperCalls(orgMethod.instructions, orgMethod.name, args, returnType, boundMethodIdSlot); // replace return of the original method with areturn and box the result value if needed replaceReturn(orgMethod.instructions, returnType); newInstructions.add(orgMethod.instructions); addNewLabelToSwitch(callOrig.instructions, newInstructions, boundMethodId); // a minimum stacksize of 3 is needed to box the arguments callOrig.maxStack = Math.max(Math.max(callOrig.maxStack, orgMethod.maxStack), 3); // we have to increment the max. stack size, because we have to put NULL on the stack if (returnType.getSort() == Type.VOID) { callOrig.maxStack += 1; } callOrig.maxLocals = Math.max(callOrig.maxLocals, orgMethod.maxLocals); return true; }
From source file:org.eclipse.objectteams.otredyn.bytecode.asm.MoveCodeToCallOrigAdapter.java
License:Open Source License
/** To avoid infinite recursion, calls super.m(a1, a2) must be translated to super.callOrig(boundMethodId, new Object[] {a1, a2}). */ private void adjustSuperCalls(InsnList instructions, String selector, Type[] args, Type returnType, int boundMethodIdSlot) { // search:// w w w .j a v a 2 s . com List<MethodInsnNode> toReplace = new ArrayList<MethodInsnNode>(); ListIterator<AbstractInsnNode> orgMethodIter = instructions.iterator(); while (orgMethodIter.hasNext()) { AbstractInsnNode orgMethodNode = orgMethodIter.next(); if (orgMethodNode.getOpcode() == Opcodes.INVOKESPECIAL && ((MethodInsnNode) orgMethodNode).name.equals(selector)) toReplace.add((MethodInsnNode) orgMethodNode); } if (toReplace.isEmpty()) return; // replace: for (MethodInsnNode oldNode : toReplace) { // we need to insert into the loading sequence before the invocation, find the insertion points: AbstractInsnNode[] insertionPoints = StackBalanceAnalyzer.findInsertionPointsBefore(oldNode, args); AbstractInsnNode firstInsert = insertionPoints.length > 0 ? insertionPoints[0] : oldNode; // push first arg to _OT$callOrig(): instructions.insertBefore(firstInsert, new IntInsnNode(Opcodes.ILOAD, boundMethodIdSlot)); // prepare array as second arg to _OT$callOrig(): instructions.insertBefore(firstInsert, new IntInsnNode(Opcodes.BIPUSH, args.length)); instructions.insertBefore(firstInsert, new TypeInsnNode(Opcodes.ANEWARRAY, "java/lang/Object")); for (int i = 0; i < insertionPoints.length; i++) { // NB: each iteration has an even stack balance, where the top is the Object[]. instructions.insertBefore(insertionPoints[i], new InsnNode(Opcodes.DUP)); instructions.insertBefore(insertionPoints[i], new IntInsnNode(Opcodes.BIPUSH, i)); // leave the original loading sequence in tact and continue at the next point: AbstractInsnNode insertAt = (i + 1 < insertionPoints.length) ? insertionPoints[i + 1] : oldNode; instructions.insertBefore(insertAt, AsmTypeHelper.getBoxingInstructionForType(args[i])); instructions.insertBefore(insertAt, new InsnNode(Opcodes.AASTORE)); } if (returnType == Type.VOID_TYPE) instructions.insert(oldNode, new InsnNode(Opcodes.POP)); else instructions.insert(oldNode, AsmTypeHelper.getUnboxingInstructionForType(returnType)); instructions.set(oldNode, new MethodInsnNode(Opcodes.INVOKESPECIAL, ((MethodInsnNode) oldNode).owner, callOrig.getName(), callOrig.getSignature())); } }
From source file:org.elasticsearch.plan.a.External.java
License:Apache License
private void variable(final ParserRuleContext source, final String name, final boolean last) { final Variable variable = adapter.getVariable(name); if (variable == null) { throw new IllegalArgumentException(error(source) + "Unknown variable [" + name + "]."); }/* ww w. ja v a 2 s . com*/ final Type type = variable.type; if (last && write != null) { final ExpressionMetadata writeemd = adapter.createExpressionMetadata(write); if (token == CAT) { writeemd.promotion = caster.concat; analyzer.visit(write); writeemd.to = writeemd.from; caster.markCast(writeemd); final Cast cast = caster.getLegalCast(source, standard.stringType, type, false); segments.add(new VariableSegment(source, variable, false)); segments.add(new AppendStringsSegment(source, type, true)); segments.add(new NodeSegment(write)); segments.add(new AppendStringsSegment(write, writeemd.to, false)); segments.add(new ToStringsSegment(source)); segments.add(new CastSegment(source, cast)); if (read) { if (type.metadata.size == 1) { segments.add(new InstructionSegment(source, Opcodes.DUP)); } else if (type.metadata.size == 2) { segments.add(new InstructionSegment(source, Opcodes.DUP2)); } else { throw new IllegalStateException(error(source) + "Unexpected type size."); } } segments.add(new VariableSegment(source, variable, true)); } else if (token > 0) { final boolean increment = type.metadata == TypeMetadata.INT && (token == ADD || token == SUB); current = type; final Cast[] casts = toNumericCasts(source); writeemd.to = current; analyzer.visit(write); if (increment && writeemd.postConst != null) { if (read && post) { segments.add(new VariableSegment(source, variable, false)); } final int value = token == SUB ? -1 * (int) writeemd.postConst : (int) writeemd.postConst; segments.add(new IncrementSegment(source, variable, value)); if (read && !post) { segments.add(new VariableSegment(source, variable, false)); } } else { segments.add(new VariableSegment(source, variable, false)); if (read && post) { if (type.metadata.size == 1) { segments.add(new InstructionSegment(source, Opcodes.DUP)); } else if (type.metadata.size == 2) { segments.add(new InstructionSegment(source, Opcodes.DUP2)); } else { throw new IllegalStateException(error(source) + "Unexpected type size."); } } segments.add(new CastSegment(source, casts[0])); segments.add(new NodeSegment(write)); segments.add(new TokenSegment(source, current, token)); segments.add(new CastSegment(source, casts[1])); if (read && !post) { if (type.metadata.size == 1) { segments.add(new InstructionSegment(source, Opcodes.DUP)); } else if (type.metadata.size == 2) { segments.add(new InstructionSegment(source, Opcodes.DUP2)); } else { throw new IllegalStateException(error(source) + "Unexpected type size."); } } segments.add(new VariableSegment(source, variable, true)); } } else { writeemd.to = type; analyzer.visit(write); segments.add(new NodeSegment(write)); if (read && !post) { if (type.metadata.size == 1) { segments.add(new InstructionSegment(source, Opcodes.DUP)); } else if (type.metadata.size == 2) { segments.add(new InstructionSegment(source, Opcodes.DUP2)); } else { throw new IllegalStateException(error(source) + "Unexpected type size."); } } segments.add(new VariableSegment(source, variable, true)); } current = read ? type : standard.voidType; } else { segments.add(new VariableSegment(source, variable, false)); current = variable.type; } }
From source file:org.elasticsearch.plan.a.External.java
License:Apache License
private void field(final ParserRuleContext source, final String name, final boolean last) { if (current.metadata == TypeMetadata.ARRAY) { if ("length".equals(name)) { if (!read || last && write != null) { throw new IllegalArgumentException(error(source) + "Cannot write to read-only field [length]."); }/* www.j av a 2s .co m*/ segments.add(new LengthSegment(source)); current = standard.intType; } else { throw new IllegalArgumentException(error(source) + "Unexpected array field [" + name + "]."); } } else { final Struct struct = current.struct; final Field field = statik ? struct.statics.get(name) : struct.members.get(name); if (field == null) { throw new IllegalArgumentException( error(source) + "Unknown field [" + name + "] for type [" + struct.name + "]."); } if (last && write != null) { if (java.lang.reflect.Modifier.isFinal(field.field.getModifiers())) { throw new IllegalArgumentException(error(source) + "Cannot write to read-only" + " field [" + name + "] for type [" + struct.name + "]."); } final ExpressionMetadata writeemd = adapter.createExpressionMetadata(write); final Type type = field.type; if (token == CAT) { writeemd.promotion = caster.concat; analyzer.visit(write); writeemd.to = writeemd.from; caster.markCast(writeemd); final Cast cast = caster.getLegalCast(source, standard.stringType, type, false); segments.add(new InstructionSegment(source, Opcodes.DUP_X1)); segments.add(new FieldSegment(source, field, false)); segments.add(new AppendStringsSegment(source, type, true)); segments.add(new NodeSegment(write)); segments.add(new AppendStringsSegment(write, writeemd.to, false)); segments.add(new ToStringsSegment(source)); segments.add(new CastSegment(source, cast)); if (read) { if (type.metadata.size == 1) { segments.add(new InstructionSegment(source, Opcodes.DUP_X1)); } else if (type.metadata.size == 2) { segments.add(new InstructionSegment(source, Opcodes.DUP2_X1)); } else { throw new IllegalStateException(error(source) + "Unexpected type size."); } } segments.add(new FieldSegment(source, field, true)); } else if (token > 0) { current = type; final Cast[] casts = toNumericCasts(source); writeemd.to = current; analyzer.visit(write); segments.add(new InstructionSegment(source, Opcodes.DUP)); segments.add(new FieldSegment(source, field, false)); if (read && post) { if (type.metadata.size == 1) { segments.add(new InstructionSegment(source, Opcodes.DUP_X1)); } else if (type.metadata.size == 2) { segments.add(new InstructionSegment(source, Opcodes.DUP2_X1)); } else { throw new IllegalStateException(error(source) + "Unexpected type size."); } } segments.add(new CastSegment(source, casts[0])); segments.add(new NodeSegment(write)); segments.add(new TokenSegment(source, current, token)); segments.add(new CastSegment(source, casts[1])); if (read && !post) { if (type.metadata.size == 1) { segments.add(new InstructionSegment(source, Opcodes.DUP_X1)); } else if (type.metadata.size == 2) { segments.add(new InstructionSegment(source, Opcodes.DUP2_X1)); } else { throw new IllegalStateException(error(source) + "Unexpected type size."); } } segments.add(new FieldSegment(source, field, true)); } else { writeemd.to = type; analyzer.visit(write); segments.add(new NodeSegment(write)); if (read && !post) { if (type.metadata.size == 1) { segments.add(new InstructionSegment(source, Opcodes.DUP_X1)); } else if (type.metadata.size == 2) { segments.add(new InstructionSegment(source, Opcodes.DUP2_X1)); } else { throw new IllegalStateException(error(source) + "Unexpected type size."); } } segments.add(new FieldSegment(source, field, true)); } current = read ? type : standard.voidType; } else { segments.add(new FieldSegment(source, field, false)); current = field.type; } } }
From source file:org.elasticsearch.plan.a.External.java
License:Apache License
private void method(final ParserRuleContext source, final String name, final List<ExpressionContext> arguments, final boolean last) { final Struct struct = current.struct; Type[] types;//w w w .jav a 2s . c om Segment segment0; Segment segment1 = null; if (current.dimensions > 0) { throw new IllegalArgumentException(error(source) + "Unexpected call [" + name + "] on an array."); } else if (last && write != null) { throw new IllegalArgumentException(error(source) + "Cannot assign a value to a call [" + name + "]."); } else if (statik && "makearray".equals(name)) { if (!read) { throw new IllegalArgumentException(error(source) + "A newly created array must be assigned."); } types = new Type[arguments.size()]; Arrays.fill(types, standard.intType); segment0 = new MakeSegment(source, current, arguments.size()); current = getTypeWithArrayDimensions(struct, arguments.size()); } else { final Constructor constructor = statik ? struct.constructors.get(name) : null; final Method method = statik ? struct.functions.get(name) : struct.methods.get(name); if (constructor != null) { types = new Type[constructor.arguments.size()]; constructor.arguments.toArray(types); segments.add(new NewSegment(source, constructor.owner)); if (read) { segments.add(new InstructionSegment(source, Opcodes.DUP)); } else { current = standard.voidType; statement = true; } segment0 = new ConstructorSegment(source, constructor); } else if (method != null) { types = new Type[method.arguments.size()]; method.arguments.toArray(types); if (!read) { final int size = method.rtn.metadata.size; if (size == 1) { segment1 = new InstructionSegment(source, Opcodes.POP); } else if (size == 2) { segment1 = new InstructionSegment(source, Opcodes.POP2); } else if (size != 0) { throw new IllegalStateException(error(source) + "Unexpected type size."); } current = standard.voidType; statement = true; } else { current = method.rtn; } segment0 = new MethodSegment(source, method); } else { throw new IllegalArgumentException( error(source) + "Unknown call [" + name + "] on type [" + struct.name + "]."); } } if (arguments.size() != types.length) { throw new IllegalArgumentException(); } for (int argument = 0; argument < arguments.size(); ++argument) { final ExpressionContext exprctx = adapter.getExpressionContext(arguments.get(argument)); final ExpressionMetadata expremd = adapter.createExpressionMetadata(exprctx); expremd.to = types[argument]; analyzer.visit(exprctx); segments.add(new NodeSegment(exprctx)); } segments.add(segment0); if (segment1 != null) { segments.add(segment1); } }