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

apparat.bytecode.MarkerManager.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/
 *
 */
package apparat.bytecode

import collection.mutable.HashMap
import operations.AbstractOp
import collection.immutable.{SortedMap, TreeMap}

class MarkerManager {
	private var numMarkers = 0
	private var markers = HashMap[AbstractOp, Marker]()
	private var unresolved = TreeMap[Int, Marker]()

	def apply(op: AbstractOp) = getMarkerFor(op)

	def forwardMarker(from: AbstractOp, to: AbstractOp) = {
		markers get from match {
			case Some(marker) => {
				marker.op = Some(to)
				markers -= from
				markers += to -> marker
			}
			case None =>
		}
	}
	def patchMissing(ops: List[AbstractOp], exceptions: Array[BytecodeExceptionHandler], op: AbstractOp) = {
		var toRemove = List.empty[AbstractOp]
		var toPatch = List.empty[Marker]

		for((markedOp, marker) <- markers) {
			if(!(ops exists (_ == markedOp))) {
				marker.op = Some(op)
				toPatch = marker :: toPatch
				toRemove = markedOp :: toRemove
			}
		}

		if(toPatch.nonEmpty) {
			if(toPatch.length > 1) {
				error("Missing implementation: Fold")
				//
				// Old code:
				//
				// Jump L0
				// Jump L1
				// L0: a
				// L1: b
				//
				// New code:
				//
				// Jump L0
				// Jump L1
				// L0, L1: c
				//
				//
				// TODO Use only one label
				// We have to remove L1 and patch
				// all occurrences (also exceptions!) to
				// use only L0 since only one marker is
				// allowed.
				//
				// Correct result:
				//
				// Jump L0
				// Jump L0
				// L0: c
				//
			} else {
				markers += op -> toPatch.head
				markers -= toRemove.head
			}
		}
	}

	def hasMarkerFor(op: AbstractOp) = markers get op match {
		case Some(_) => true
		case None => false
	}

	def getMarkerFor(op: AbstractOp) = markers get op

	def mark(op: AbstractOp) = markers get op getOrElse {
		val marker = new Marker(numMarkers)
		marker.op = Some(op)
		markers += op -> marker
		numMarkers += 1
		marker
	}
	
	protected[bytecode] def hasMarkerAt(position: Int) = unresolved get position match {
		case Some(_) => true
		case None => false
	}

	protected[bytecode] def getMarkerAt(position: Int) = unresolved get position

	protected[bytecode] def putMarkerAt(position: Int) = {
		if(hasMarkerAt(position)) {
			getMarkerAt(position).getOrElse(error("Internal error."))
		} else {
			val marker = new Marker(numMarkers)
			marker.position = position
			unresolved = unresolved + (position -> marker)
			numMarkers += 1
			marker
		}
	}

	protected[bytecode] def solve(map: SortedMap[Int, AbstractOp]) = {
		var previous: Option[Int] = None
		for((position, op) <- map) {
			unresolved range (0, position + 1) lastOption match {
				case Some((markerPosition, marker)) => if(!previous.isDefined || markerPosition > previous.get) {
					if(marker.op.isDefined) error("Illegal marker at " + markerPosition + ".")
					marker.op = Some(op)
					markers += op -> marker
				}
				case None => {} 
			}

			previous = Some(position)
		}

		unresolved = TreeMap.empty
		this
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy