📄 compilestack.java
字号:
throw new GroovyBugError("the compile stack contains "+size+" more push instruction"+(size==1?"":"s")+" than pops."); } clear = true; // br experiment with local var table so debuggers can retrieve variable names if (true) {//AsmClassGenerator.CREATE_DEBUG_INFO) { if (thisEndLabel==null) setEndLabels(); if (!scope.isInStaticContext()) { // write "this" mv.visitLocalVariable("this", className, null, thisStartLabel, thisEndLabel, 0); } for (Iterator iterator = usedVariables.iterator(); iterator.hasNext();) { Variable v = (Variable) iterator.next(); String type = BytecodeHelper.getTypeDescription(v.getType()); Label start = v.getStartLabel(); Label end = v.getEndLabel(); mv.visitLocalVariable(v.getName(), type, null, start, end, v.getIndex()); } } pop(); stackVariables.clear(); usedVariables.clear(); scope = null; mv=null; resetVariableIndex(false); superBlockNamedLabels.clear(); currentBlockNamedLabels.clear(); namedLoopBreakLabel.clear(); namedLoopContinueLabel.clear(); continueLabel=null; breakLabel=null; finallyLabel=null; helper = null; thisStartLabel=null; thisEndLabel=null; } /** * 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, String className) { if (!clear) throw new GroovyBugError("CompileStack#init called without calling clear before"); clear=false; pushVariableScope(el); this.mv = mv; this.helper = helper = new BytecodeHelper(mv); defineMethodVariables(parameters,el.isInStaticContext()); this.className = className; } /** * Causes the statestack to add an element and sets * the given scope as new current variable scope. Creates * a element for the state stack so pop has to be called later */ protected void pushVariableScope(VariableScope el) { pushState(); scope = el; superBlockNamedLabels = new HashMap(superBlockNamedLabels); superBlockNamedLabels.putAll(currentBlockNamedLabels); currentBlockNamedLabels = new HashMap(); } /** * Should be called when decending into a loop that defines * also a scope. Calls pushVariableScope and prepares labels * for a loop structure. Creates a element for the state stack * so pop has to be called later */ protected void pushLoop(VariableScope el, String labelName) { pushVariableScope(el); initLoopLabels(labelName); } private void initLoopLabels(String labelName) { continueLabel = new Label(); breakLabel = new Label(); if (labelName!=null) { namedLoopBreakLabel.put(labelName,breakLabel); namedLoopContinueLabel.put(labelName,continueLabel); } } /** * Should be called when decending into a loop that does * not define a scope. Creates a element for the state stack * so pop has to be called later */ protected void pushLoop(String labelName) { pushState(); initLoopLabels(labelName); } /** * Used for <code>break foo</code> inside a loop to end the * execution of the marked loop. This method will return the * break label of the loop if there is one found for the name. * If not, the current break label is returned. */ protected Label getNamedBreakLabel(String name) { Label label = getBreakLabel(); Label endLabel = (Label) namedLoopBreakLabel.get(name); if (endLabel!=null) label = endLabel; return label; } /** * Used for <code>continue foo</code> inside a loop to continue * the execution of the marked loop. This method will return * the break label of the loop if there is one found for the * name. If not, getLabel is used. */ protected Label getNamedContinueLabel(String name) { Label label = getLabel(name); Label endLabel = (Label) namedLoopContinueLabel.get(name); if (endLabel!=null) label = endLabel; return label; } /** * Creates a new Finally label and a element for the state stack * so pop has to be called later */ protected Label pushFinally() { pushState(); finallyLabel = new Label(); return finallyLabel; } /** * Creates a new break label and a element for the state stack * so pop has to be called later */ protected Label pushSwitch(){ pushState(); breakLabel = new Label(); return breakLabel; } /** * because a boolean Expression may not be evaluated completly * it is important to keep the registers clean */ protected void pushBooleanExpression(){ pushState(); } /** * returns the current finally label */ public Label getFinallyLabel() { return finallyLabel; } private Variable defineVar(String name, ClassNode type, boolean methodParameterUsedInClosure) { makeNextVariableID(type); int index = currentVariableIndex; if (methodParameterUsedInClosure) { index = localVariableOffset++; } Variable answer = new Variable(index, type, name); usedVariables.add(answer); answer.setHolder(methodParameterUsedInClosure); return answer; } private void makeLocalVariablesOffset(Parameter[] paras,boolean isInStaticContext) { resetVariableIndex(isInStaticContext); for (int i = 0; i < paras.length; i++) { makeNextVariableID(paras[i].getType()); } localVariableOffset = nextVariableIndex; resetVariableIndex(isInStaticContext); } 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; if (paras[i].isClosureSharedVariable()) { answer = defineVar(name, ClassHelper.getWrapper(paras[i].getType()), true); ClassNode type = paras[i].getType(); helper.load(type,currentVariableIndex); helper.box(type); createReference(answer); hasHolder = true; } else { answer = defineVar(name,paras[i].getType(),false); } answer.setStartLabel(startLabel); stackVariables.put(name, answer); } if (hasHolder) { nextVariableIndex = localVariableOffset; } } private void createReference(Variable reference) { mv.visitTypeInsn(NEW, "groovy/lang/Reference"); mv.visitInsn(DUP_X1); mv.visitInsn(SWAP); mv.visitMethodInsn(INVOKESPECIAL, "groovy/lang/Reference", "<init>", "(Ljava/lang/Object;)V"); mv.visitVarInsn(ASTORE, reference.getIndex()); } /** * 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; } /** * Returns true if a varibale is already defined */ public boolean containsVariable(String name) { return stackVariables.containsKey(name); } /** * Calculates the index of the next free register stores ir * and sets the current variable index to the old value */ private void makeNextVariableID(ClassNode type) { currentVariableIndex = nextVariableIndex; if (type==ClassHelper.long_TYPE || type==ClassHelper.double_TYPE) { nextVariableIndex++; } nextVariableIndex++; } /** * Returns the label for the given name */ public Label getLabel(String name) { if (name==null) return null; Label l = (Label) superBlockNamedLabels.get(name); if (l==null) l = createLocalLabel(name); return l; } /** * creates a new named label */ public Label createLocalLabel(String name) { Label l = (Label) currentBlockNamedLabels.get(name); if (l==null) { l = new Label(); currentBlockNamedLabels.put(name,l); } return l; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -