public AsmClassGenerator( GeneratorContext context, ClassVisitor classVisitor, ClassLoader classLoader, String sourceFile ) { super(classLoader); this.context = context; this.cv = classVisitor; this.sourceFile = sourceFile; this.dummyClassWriter = new ClassWriter(true); dummyGen = new DummyClassGenerator(context, dummyClassWriter, classLoader, sourceFile); compileStack = new CompileStack(); genericParameterNames = new HashMap(); closureClassMap = new HashMap(); }
public void visitContinueStatement(ContinueStatement statement) { onLineNumber(statement, "visitContinueStatement"); visitStatement(statement); String name = statement.getLabel(); Label continueLabel = compileStack.getContinueLabel(); if (name != null) continueLabel = compileStack.getNamedContinueLabel(name); compileStack.applyFinallyBlocks(continueLabel, false); mv.visitJumpInsn(GOTO, continueLabel); }
/** * @return true if the given name is a local variable or a field */ protected boolean isFieldOrVariable(String name) { return compileStack.containsVariable(name) || classNode.getDeclaredField(name) != null; }
protected void evaluatePostfixMethod(String method, Expression expression) { // load expression.visit(this); // save value for later int tempIdx = compileStack.defineTemporaryVariable("postfix_" + method, true); // execute Method execMethodAndStoreForSubscriptOperator(method,expression); // remove the result of the method call mv.visitInsn(POP); //reload saved value mv.visitVarInsn(ALOAD, tempIdx); compileStack.removeVar(tempIdx); }
public void visitBreakStatement(BreakStatement statement) { onLineNumber(statement, "visitBreakStatement"); visitStatement(statement); String name = statement.getLabel(); Label breakLabel = compileStack.getNamedBreakLabel(name); compileStack.applyFinallyBlocks(breakLabel, true); mv.visitJumpInsn(GOTO, breakLabel); }
compileStack.pushLoop(loop.getVariableScope(), loop.getStatementLabel()); Variable variable = compileStack.defineVariable(loop.getVariable(), false); iterator.visit(this); final int iteratorIdx = compileStack.defineTemporaryVariable("iterator", ClassHelper.make(java.util.Iterator.class), true); Label continueLabel = compileStack.getContinueLabel(); Label breakLabel = compileStack.getBreakLabel(); mv.visitLabel(breakLabel); compileStack.pop();
final Statement finallyStatement = statement.getFinallyStatement(); int anyExceptionIndex = compileStack.defineTemporaryVariable("exception", false); if (!finallyStatement.isEmpty()) { compileStack.pushFinallyBlock( new Runnable() { public void run() { mv.visitLabel(catchStart); compileStack.pushState(); compileStack.defineVariable(catchStatement.getVariable(), true); compileStack.pop(); if (!finallyStatement.isEmpty()) compileStack.popFinallyBlock();
if (!compileStack.containsVariable(name) && compileStack.getScope().isReferencedClassVariable(name)) { visitFieldExpression(new FieldExpression(classNode.getDeclaredField(name))); } else { Variable v = compileStack.getVariable(name, classNode.getSuperClass() != ClassHelper.CLOSURE_TYPE); if (v == null) { v = compileStack.defineVariable(param, true); param.setClosureSharedVariable(true); v.setHolder(true);
public void visitClosureListExpression(ClosureListExpression expression) { compileStack.pushVariableScope(expression.getVariableScope()); int listArrayVar = compileStack.defineTemporaryVariable("_listOfClosures", true); compileStack.removeVar(listArrayVar); compileStack.pop();
public void visitSwitch(SwitchStatement statement) { onLineNumber(statement, "visitSwitch"); visitStatement(statement); statement.getExpression().visit(this); // switch does not have a continue label. use its parent's for continue Label breakLabel = compileStack.pushSwitch(); int switchVariableIndex = compileStack.defineTemporaryVariable("switch", true); List caseStatements = statement.getCaseStatements(); int caseCount = caseStatements.size(); Label[] labels = new Label[caseCount + 1]; for (int i = 0; i < caseCount; i++) { labels[i] = new Label(); } int i = 0; for (Iterator iter = caseStatements.iterator(); iter.hasNext(); i++) { CaseStatement caseStatement = (CaseStatement) iter.next(); visitCaseStatement(caseStatement, switchVariableIndex, labels[i], labels[i + 1]); } statement.getDefaultStatement().visit(this); mv.visitLabel(breakLabel); compileStack.pop(); }
private void defineMethodVariables(Parameter[] paras,boolean isInStaticContext) { Label startLabel = new Label(); thisStartLabel = startLabel; mv.visitLabel(startLabel); makeLocalVariablesOffset(paras,isInStaticContext); boolean hasHolder = false; for (int i = 0; i < paras.length; i++) { String name = paras[i].getName(); Variable answer; ClassNode type = paras[i].getType(); if (paras[i].isClosureSharedVariable()) { answer = defineVar(name, type, true); helper.load(type,currentVariableIndex); helper.box(type); createReference(answer); hasHolder = true; } else { answer = defineVar(name,type,false); } answer.setStartLabel(startLabel); stackVariables.put(name, answer); } if (hasHolder) { nextVariableIndex = localVariableOffset; } }
final int index = compileStack.defineTemporaryVariable("synchronized", ClassHelper.Integer_TYPE, true); compileStack.pushFinallyBlock(finallyPart); statement.getCode().visit(this); mv.visitLabel(synchronizedEnd); compileStack.popFinallyBlock(); exceptionBlocks.add(new Runnable() { public void run() {
throwException("Cannot use return statement with an expression on a method that returns void"); compileStack.applyFinallyBlocks(); mv.visitInsn(RETURN); outputReturn = true; if (compileStack.hasFinallyBlocks()) { int returnValueIdx = compileStack.defineTemporaryVariable("returnValue", ClassHelper.OBJECT_TYPE, true); compileStack.applyFinallyBlocks(); helper.load(ClassHelper.OBJECT_TYPE, returnValueIdx);
private void visitStdMethod(MethodNode node, boolean isConstructor, Parameter[] parameters, Statement code) { if (isConstructor && (code == null || !((ConstructorNode) node).firstStatementIsSpecialConstructorCall())) { // invokes the super class constructor mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, BytecodeHelper.getClassInternalName(classNode.getSuperClass()), "<init>", "()V"); } compileStack.init(node.getVariableScope(), parameters, mv, classNode); if (isNotClinit()) { mv.visitMethodInsn(INVOKESTATIC,internalClassName,"$getCallSiteArray","()[Lorg/codehaus/groovy/runtime/callsite/CallSite;"); callSiteArrayVarIndex = compileStack.defineTemporaryVariable("$local$callSiteArray", ClassHelper.make(CallSite[].class), true); } // handle body super.visitConstructorOrMethod(node, isConstructor); if (!outputReturn || node.isVoidMethod()) { mv.visitInsn(RETURN); } compileStack.clear(); final Label finallyStart = new Label(); mv.visitJumpInsn(GOTO, finallyStart); // let's do all the exception blocks for (Iterator iter = exceptionBlocks.iterator(); iter.hasNext();) { Runnable runnable = (Runnable) iter.next(); runnable.run(); } exceptionBlocks.clear(); }
visitAndAutoboxBoolean(expression.getRightExpression()); final int resultVar = compileStack.defineTemporaryVariable("$result", true); mv.visitVarInsn(ALOAD, resultVar ); mv.visitMethodInsn(INVOKEINTERFACE, "org/codehaus/groovy/runtime/callsite/CallSite", "call","(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); compileStack.removeVar(resultVar); return; i++; if (defineVariable) { compileStack.defineVariable(var, true); } else { visitVariableExpression(var); compileStack.defineVariable(var, true); } else {
/** * creates a temporary variable. * * @param name defines type and name * @param store defines if the toplevel argument of the stack should be stored * @return the index used for this temporary variable */ public int defineTemporaryVariable(String name,boolean store) { return defineTemporaryVariable(name, ClassHelper.DYNAMIC_TYPE,store); }
/** * initializes this class for a MethodNode. This method will * automatically define varibales for the method parameters * and will create references if needed. the created variables * can be get by getVariable * */ protected void init(VariableScope el, Parameter[] parameters, MethodVisitor mv, ClassNode cn) { if (!clear) throw new GroovyBugError("CompileStack#init called without calling clear before"); clear=false; pushVariableScope(el); this.mv = mv; this.helper = new BytecodeHelper(mv); defineMethodVariables(parameters,el.isInStaticContext()); this.className = BytecodeHelper.getTypeDescription(cn); }
/** * Defines a new Variable using an AST variable. * @param initFromStack if true the last element of the * stack will be used to initilize * the new variable. If false null * will be used. */ public Variable defineVariable(org.codehaus.groovy.ast.Variable v, boolean initFromStack) { String name = v.getName(); Variable answer = defineVar(name,v.getType(),false); if (v.isClosureSharedVariable()) answer.setHolder(true); stackVariables.put(name, answer); Label startLabel = new Label(); answer.setStartLabel(startLabel); if (answer.isHolder()) { if (!initFromStack) mv.visitInsn(ACONST_NULL); createReference(answer); } else { if (!initFromStack) mv.visitInsn(ACONST_NULL); mv.visitVarInsn(ASTORE, currentVariableIndex); } mv.visitLabel(startLabel); return answer; }
if (type.equals(classNode)) { staticFieldName = "class$0"; if (compileStack.getCurrentClassIndex() != -1) { mv.visitVarInsn(ALOAD, compileStack.getCurrentClassIndex()); return; if (compileStack.getCurrentMetaClassIndex() != -1) { mv.visitVarInsn(ALOAD, compileStack.getCurrentMetaClassIndex()); return; int index = compileStack.defineTemporaryVariable("class$0", ClassHelper.CLASS_Type, true); compileStack.setCurrentClassIndex(index); } else if (type.equals(ClassHelper.METACLASS_TYPE)) { mv.visitInsn(DUP); int index = compileStack.defineTemporaryVariable("meta$class$0", ClassHelper.CLASS_Type, true); compileStack.setCurrentMetaClassIndex(index);