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

apparat.graph.mutable.MutableBytecodeControlFlowGraph.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: 9 janv. 2010
 * Time: 16:08:01
 */
package apparat.graph.mutable

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

class MutableAbstractOpBlockVertex(block: List[AbstractOp] = Nil) extends MutableBlockVertex[AbstractOp](block)

class MutableBytecodeControlFlowGraph extends MutableControlFlowGraph[AbstractOp, MutableAbstractOpBlockVertex] {
	type V = MutableAbstractOpBlockVertex

	protected[graph] def newEntryVertex = new V() with EntryVertex

	protected[graph] def newExitVertex = new V() with ExitVertex

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

	override def toString = "[MutableBytecodeControlFlowGraph]"

	override def optimized = {simplified(); this}

	private def simplified() {
		super.optimized

		val g = this
		var modified = false

		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() {
			var verticesToRemove = List.empty[V]

			g.edgesIterator.find(reducible(_)) match {
				case Some(branch) => {
					val newVertex = (branch.startVertex ++ branch.endVertex.block).asInstanceOf[V]
					val edges = g.outgoingOf(branch.endVertex)

					g -= branch

					for (edge <- edges) {
						g += Edge.copy(edge, Some(newVertex))
					}

					verticesToRemove = branch.endVertex :: verticesToRemove

					modified = true
				}
				case _ =>
			}
			if (modified) {
				for (vertex <- verticesToRemove) g -= vertex

				modified = false
				coalesce()
			}
		}

		coalesce()
	}

	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