|
Groovy example source code file (OptimizingStatementWriter.java)
The Groovy OptimizingStatementWriter.java source code/* * Copyright 2003-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.codehaus.groovy.classgen.asm; import java.util.LinkedList; import org.codehaus.groovy.ast.*; import org.codehaus.groovy.ast.expr.*; import org.codehaus.groovy.ast.stmt.*; import org.codehaus.groovy.GroovyBugError; import org.codehaus.groovy.classgen.AsmClassGenerator; import org.codehaus.groovy.classgen.Verifier; import org.codehaus.groovy.control.SourceUnit; import org.codehaus.groovy.runtime.BytecodeInterface8; import org.codehaus.groovy.syntax.Types; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import static org.objectweb.asm.Opcodes.*; import static org.codehaus.groovy.classgen.asm.BinaryExpressionMultiTypeDispatcher.*; import static org.codehaus.groovy.ast.ClassHelper.*; /** * * @author <a href="mailto:blackdrag@gmx.org">Jochen "blackdrag" Theodorou */ public class OptimizingStatementWriter extends StatementWriter { private static class FastPathData { private Label pathStart = new Label(); private Label afterPath = new Label(); } public static class ClassNodeSkip{} public static class StatementMeta { private boolean optimize=false; protected MethodNode target; protected ClassNode type; protected boolean[] involvedTypes = new boolean[typeMapKeyNames.length]; public void chainInvolvedTypes(OptimizeFlagsCollector opt) { for (int i=0; i<typeMapKeyNames.length; i++) { if (opt.current.involvedTypes[i]) { this.involvedTypes[i] = true; } } } public String toString() { String ret = "optimize="+optimize+" target="+target+" type="+type+" involvedTypes="; for (int i=0; i<typeMapKeyNames.length; i++) { if (involvedTypes[i]) ret += " "+typeMapKeyNames[i]; } return ret; } } private static MethodCaller[] guards = { MethodCaller.newStatic(BytecodeInterface8.class, "isOrigInt"), MethodCaller.newStatic(BytecodeInterface8.class, "isOrigZ"), MethodCaller.newStatic(BytecodeInterface8.class, "isOrigD"), MethodCaller.newStatic(BytecodeInterface8.class, "isOrigC"), MethodCaller.newStatic(BytecodeInterface8.class, "isOrigB"), MethodCaller.newStatic(BytecodeInterface8.class, "isOrigS"), MethodCaller.newStatic(BytecodeInterface8.class, "isOrigF"), }; private static final MethodCaller disabledStandardMetaClass = MethodCaller.newStatic(BytecodeInterface8.class, "disabledStandardMetaClass"); private boolean fastPathBlocked = false; private WriterController controller; public OptimizingStatementWriter(WriterController controller) { super(controller); this.controller = controller; } private boolean notEnableFastPath(StatementMeta meta) { // return false if cannot do fast path and if are already on the path return fastPathBlocked || meta==null || !meta.optimize || controller.isFastPath(); } private FastPathData writeGuards(StatementMeta meta, Statement statement) { if (notEnableFastPath(meta)) return null; MethodVisitor mv = controller.getMethodVisitor(); FastPathData fastPathData = new FastPathData(); Label slowPath = new Label(); for (int i=0; i<guards.length; i++) { if (meta.involvedTypes[i]) { guards[i].call(mv); mv.visitJumpInsn(IFEQ, slowPath); } } // meta class check with boolean holder String owner = BytecodeHelper.getClassInternalName(controller.getClassNode()); MethodNode mn = controller.getMethodNode(); if (mn!=null) { mv.visitFieldInsn(GETSTATIC, owner, Verifier.STATIC_METACLASS_BOOL, "Z"); mv.visitJumpInsn(IFNE, slowPath); } //standard metaclass check disabledStandardMetaClass.call(mv); mv.visitJumpInsn(IFNE, slowPath); // other guards here mv.visitJumpInsn(GOTO, fastPathData.pathStart); mv.visitLabel(slowPath); return fastPathData; } private void writeFastPathPrelude(FastPathData meta) { MethodVisitor mv = controller.getMethodVisitor(); mv.visitJumpInsn(GOTO, meta.afterPath); mv.visitLabel(meta.pathStart); controller.switchToFastPath(); } private void writeFastPathEpilogue(FastPathData meta) { MethodVisitor mv = controller.getMethodVisitor(); mv.visitLabel(meta.afterPath); controller.switchToSlowPath(); } @Override public void writeBlockStatement(BlockStatement statement) { StatementMeta meta = (StatementMeta) statement.getNodeMetaData(StatementMeta.class); FastPathData fastPathData = writeGuards(meta, statement); if (fastPathData==null) { // normal mode with different paths // important is to not to have a fastpathblock here, // otherwise the per expression statement improvement // is impossible super.writeBlockStatement(statement); } else { // fast/slow path generation boolean oldFastPathBlock = fastPathBlocked; fastPathBlocked = true; super.writeBlockStatement(statement); fastPathBlocked = oldFastPathBlock; writeFastPathPrelude(fastPathData); super.writeBlockStatement(statement); writeFastPathEpilogue(fastPathData); } } @Override public void writeDoWhileLoop(DoWhileStatement statement) { if (controller.isFastPath()) { super.writeDoWhileLoop(statement); } else { StatementMeta meta = (StatementMeta) statement.getNodeMetaData(StatementMeta.class); FastPathData fastPathData = writeGuards(meta, statement); boolean oldFastPathBlock = fastPathBlocked; fastPathBlocked = true; super.writeDoWhileLoop(statement); fastPathBlocked = oldFastPathBlock; if (fastPathData==null) return; writeFastPathPrelude(fastPathData); super.writeDoWhileLoop(statement); writeFastPathEpilogue(fastPathData); } } @Override protected void writeIteratorHasNext(MethodVisitor mv) { if (controller.isFastPath()) { mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z"); } else { super.writeIteratorHasNext(mv); } } @Override protected void writeIteratorNext(MethodVisitor mv) { if (controller.isFastPath()) { mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;"); } else { super.writeIteratorNext(mv); } } @Override protected void writeForInLoop(ForStatement statement) { if (controller.isFastPath()) { super.writeForInLoop(statement); } else { StatementMeta meta = (StatementMeta) statement.getNodeMetaData(StatementMeta.class); FastPathData fastPathData = writeGuards(meta, statement); boolean oldFastPathBlock = fastPathBlocked; fastPathBlocked = true; super.writeForInLoop(statement); fastPathBlocked = oldFastPathBlock; if (fastPathData==null) return; writeFastPathPrelude(fastPathData); super.writeForInLoop(statement); writeFastPathEpilogue(fastPathData); } } @Override protected void writeForLoopWithClosureList(ForStatement statement) { if (controller.isFastPath()) { super.writeForLoopWithClosureList(statement); } else { StatementMeta meta = (StatementMeta) statement.getNodeMetaData(StatementMeta.class); FastPathData fastPathData = writeGuards(meta, statement); boolean oldFastPathBlock = fastPathBlocked; fastPathBlocked = true; super.writeForLoopWithClosureList(statement); fastPathBlocked = oldFastPathBlock; if (fastPathData==null) return; writeFastPathPrelude(fastPathData); super.writeForLoopWithClosureList(statement); writeFastPathEpilogue(fastPathData); } } @Override public void writeWhileLoop(WhileStatement statement) { if (controller.isFastPath()) { super.writeWhileLoop(statement); } else { StatementMeta meta = (StatementMeta) statement.getNodeMetaData(StatementMeta.class); FastPathData fastPathData = writeGuards(meta, statement); boolean oldFastPathBlock = fastPathBlocked; fastPathBlocked = true; super.writeWhileLoop(statement); fastPathBlocked = oldFastPathBlock; if (fastPathData==null) return; writeFastPathPrelude(fastPathData); super.writeWhileLoop(statement); writeFastPathEpilogue(fastPathData); } } @Override public void writeIfElse(IfStatement statement) { if (controller.isFastPath()) { super.writeIfElse(statement); } else { StatementMeta meta = (StatementMeta) statement.getNodeMetaData(StatementMeta.class); FastPathData fastPathData = writeGuards(meta, statement); boolean oldFastPathBlock = fastPathBlocked; fastPathBlocked = true; super.writeIfElse(statement); fastPathBlocked = oldFastPathBlock; if (fastPathData==null) return; writeFastPathPrelude(fastPathData); super.writeIfElse(statement); writeFastPathEpilogue(fastPathData); } } private boolean isNewPathFork(StatementMeta meta) { // meta.optimize -> can do fast path if (meta==null || meta.optimize==false) return false; // fastPathBlocked -> slow path if (fastPathBlocked) return false; // controller.isFastPath() -> fastPath if (controller.isFastPath()) return false; return true; } @Override public void writeReturn(ReturnStatement statement) { if (controller.isFastPath()) { super.writeReturn(statement); } else { StatementMeta meta = (StatementMeta) statement.getNodeMetaData(StatementMeta.class); if (isNewPathFork(meta) && writeDeclarationExtraction(statement)) { FastPathData fastPathData = writeGuards(meta, statement); boolean oldFastPathBlock = fastPathBlocked; fastPathBlocked = true; super.writeReturn(statement); fastPathBlocked = oldFastPathBlock; if (fastPathData==null) return; writeFastPathPrelude(fastPathData); super.writeReturn(statement); writeFastPathEpilogue(fastPathData); } else { super.writeReturn(statement); } } } @Override public void writeExpressionStatement(ExpressionStatement statement) { if (controller.isFastPath()) { super.writeExpressionStatement(statement); } else { StatementMeta meta = (StatementMeta) statement.getNodeMetaData(StatementMeta.class); // we have to have handle DelcarationExpressions special, since their // entry should be outside the optimization path, we have to do that of // course only if we are actually going to do two different paths, // otherwise it is not needed // // there are several cases to be considered now. // (1) no fast path possible, so just do super // (2) fast path possible, and at path split point (meaning not in // fast path and not in slow path). Here we have to extract the // Declaration and replace by an assignment // (3) fast path possible and in slow or fastPath. Nothing to do here. // // the only case we need to handle is then (2). if (isNewPathFork(meta) && writeDeclarationExtraction(statement)) { FastPathData fastPathData = writeGuards(meta, statement); boolean oldFastPathBlock = fastPathBlocked; fastPathBlocked = true; super.writeExpressionStatement(statement); fastPathBlocked = oldFastPathBlock; if (fastPathData==null) return; writeFastPathPrelude(fastPathData); super.writeExpressionStatement(statement); writeFastPathEpilogue(fastPathData); } else { super.writeExpressionStatement(statement); } } } private boolean writeDeclarationExtraction(Statement statement) { Expression ex = null; if (statement instanceof ReturnStatement) { ReturnStatement rs = (ReturnStatement) statement; ex = rs.getExpression(); } else if (statement instanceof ExpressionStatement) { ExpressionStatement es = (ExpressionStatement) statement; ex = es.getExpression(); } else { throw new GroovyBugError("unknown statement type :"+statement.getClass()); } if (!(ex instanceof DeclarationExpression)) return true; DeclarationExpression declaration = (DeclarationExpression) ex; ex = declaration.getLeftExpression(); if (ex instanceof TupleExpression) return false; // do declaration controller.getCompileStack().defineVariable(declaration.getVariableExpression(), false); // change statement to do assignment only BinaryExpression assignment = new BinaryExpression( declaration.getLeftExpression(), declaration.getOperation(), declaration.getRightExpression()); assignment.setSourcePosition(declaration); assignment.copyNodeMetaData(declaration); // replace statement code if (statement instanceof ReturnStatement) { ReturnStatement rs = (ReturnStatement) statement; rs.setExpression(assignment); } else if (statement instanceof ExpressionStatement) { ExpressionStatement es = (ExpressionStatement) statement; es.setExpression(assignment); } else { throw new GroovyBugError("unknown statement type :"+statement.getClass()); } return true; } public static void setNodeMeta(ClassNode classNode) { if (classNode.getNodeMetaData(ClassNodeSkip.class)!=null) return; new OptVisitor().visitClass(classNode); } private static StatementMeta addMeta(ASTNode node) { StatementMeta metaOld = (StatementMeta) node.getNodeMetaData(StatementMeta.class); StatementMeta meta = metaOld; if (meta==null) meta = new StatementMeta(); meta.optimize = true; if (metaOld==null) node.setNodeMetaData(StatementMeta.class, meta); return meta; } private static StatementMeta addMeta(ASTNode node, OptimizeFlagsCollector opt) { StatementMeta meta = addMeta(node); meta.chainInvolvedTypes(opt); return meta; } private static class OptimizeFlagsCollector { private static class OptimizeFlagsEntry { private boolean canOptimize = false; private boolean shouldOptimize = false; private boolean[] involvedTypes = new boolean[typeMapKeyNames.length]; } private OptimizeFlagsEntry current = new OptimizeFlagsEntry(); private LinkedList<OptimizeFlagsEntry> olderEntries = new LinkedList Other Groovy examples (source code examples)Here is a short list of links related to this Groovy OptimizingStatementWriter.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.