All Downloads are FREE. Search and download functionalities are using the official Maven repository.

apparat.graph.BytecodeControlFlowGraph.scala Maven / Gradle / Ivy

/*
 * This file is part of Apparat.
 *
 * Apparat is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Apparat is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Apparat. If not, see .
 *
 * Copyright (C) 2009 Joa Ebert
 * http://www.joa-ebert.com/
 *
 * User: Patrick Le Clec'h
 * Date: 31 janv. 2010
 * Time: 21:34:43
 */
package apparat.graph

import apparat.bytecode.operations._
import annotation.tailrec
import collection.mutable.ListBuffer
import apparat.bytecode.{BytecodeExceptionHandler, MarkerManager, Marker, Bytecode}
import immutable.BytecodeControlFlowGraphBuilder

class BytecodeControlFlowGraph[V <: BlockVertex[AbstractOp]](graph: GraphLike[V], entryVertex: V, exitVertex: V) extends ControlFlowGraph[AbstractOp, V](graph, entryVertex, exitVertex) {
	def this(graph: ControlFlowGraph[AbstractOp, V]) = this (graph, graph.entryVertex, graph.exitVertex)

	override def toString = "[BytecodeControlFlowGraph]"

	override def optimized = simplified

	private lazy val simplified = {
		var g = super.optimized
		var g2 = g

		def reducible(edge: E) = (edge.startVertex != entryVertex) &&
				(edge.endVertex != exitVertex) &&
				(g.outdegreeOf(edge.startVertex) == 1) &&
				(g.indegreeOf(edge.endVertex) == 1) &&
				(!g.outgoingOf(edge.endVertex).exists(_.isInstanceOf[ThrowEdge[_]]))

		// coalesce successive block A jump B jump C into ABC
		@tailrec def coalesce() {
			g.edgesIterator.find(reducible(_)) match {
				case Some(branch) => {
					val newVertex = (branch.startVertex ++ branch.endVertex.block).asInstanceOf[V]
					val edges = g2.outgoingOf(branch.endVertex)
					g2 = g2 - branch
					g2 = g2.replace(branch.startVertex, newVertex)
					for (edge <- edges) {
						g2 = g2 + Edge.copy(edge, Some(newVertex))
					}
					g2 = g2 - branch.endVertex
				}
				case _ =>
			}
			if (g != g2) {
				g = g2
				coalesce()
			}
		}

		coalesce()

		new BytecodeControlFlowGraph(g, entryVertex, exitVertex)
	}

	def fromBytecode(bytecode: Bytecode) = BytecodeControlFlowGraphBuilder(_)

	lazy val bytecode = ControlFlowGraphBytecodeBuilder(optimized)

	override def edgeToString(edge: E) = {
		def headLabel(vertex: V) = " headlabel=\"" + ({
			if (vertex.length == 0)
				""
			else {
				vertex.last match {
					case op: OpWithMarker => op.marker.toString
					case _ => ""
				}
			}
		}) + "\""

		"[" + (edge match {
			case DefaultEdge(x, y) => label("")
			case JumpEdge(x, y) => label("  jump  ")
			case TrueEdge(x, y) => label("  true  ")
			case FalseEdge(x, y) => label("  false  ")
			case DefaultCaseEdge(x, y) => label("  default  ")
			case CaseEdge(x, y) => label("  case  ")
			case NumberedCaseEdge(x, y, n) => label("  case " + n)
			case ThrowEdge(x, y) => label("  throw  ") + " style=\"dashed\""
			case ReturnEdge(x, y) => label("  return  ")
		}) + "]"
	}
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy