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

net.sandius.rembulan.compiler.analysis.SlotAllocator Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2016 Miroslav Janíček
 *
 * 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 net.sandius.rembulan.compiler.analysis;

import net.sandius.rembulan.compiler.IRFunc;
import net.sandius.rembulan.compiler.ir.*;
import net.sandius.rembulan.util.Check;

import java.util.*;

public class SlotAllocator {

	private final IRFunc fn;

	private final Map valSlots;
	private final Map varSlots;

	private IRNode currentNode;

	public SlotAllocator(IRFunc fn) {
		this.fn = Check.notNull(fn);
		this.valSlots = new HashMap<>();
		this.varSlots = new HashMap<>();
	}

	public static SlotAllocInfo allocateSlots(IRFunc fn) {
		SlotAllocator allocator = new SlotAllocator(fn);
		return allocator.process();
	}

	private IRNode node() {
		if (currentNode == null) {
			throw new IllegalStateException("Current node is null");
		}
		return currentNode;
	}

	private boolean hasSlot(Var v) {
		return varSlots.get(Check.notNull(v)) != null;
	}

	private boolean hasSlot(AbstractVal v) {
		return valSlots.get(Check.notNull(v)) != null;
	}

	private int slotOf(Var v) {
		Check.notNull(v);
		Integer idx = varSlots.get(v);
		if (idx == null) {
			throw new NoSuchElementException("Slot not defined for variable " + v);
		}
		else {
			return idx;
		}
	}

	private int slotOf(AbstractVal v) {
		Check.notNull(v);
		Integer idx = valSlots.get(v);
		if (idx == null) {
			throw new NoSuchElementException("Slot not defined for value " + v);
		}
		else {
			return idx;
		}
	}

	private BitSet occupiedSlots(LivenessInfo liveness, IRNode node) {
		BitSet occupied = new BitSet();

		LivenessInfo.Entry e = liveness.entry(node);

		for (Var v : e.inVar()) {
			int idx = slotOf(v);
			if (occupied.get(idx)) {
				throw new IllegalStateException("Slot " + idx + " already occupied");
			}
			if (e.outVar().contains(v)) {
				occupied.set(slotOf(v));
			}
		}
		for (AbstractVal v : e.inVal()) {
			int idx = slotOf(v);
			if (occupied.get(idx)) {
				throw new IllegalStateException("Slot " + idx + " already occupied");
			}
			if (e.outVal().contains(v)) {
				occupied.set(slotOf(v));
			}
		}
		return occupied;
	}

	private int findFreeSlot(LivenessInfo liveness, IRNode node) {
		BitSet occupied = occupiedSlots(liveness, node);

		int idx = 0;
		while (occupied.get(idx)) {
			idx++;
		}

		assert (!occupied.get(idx));

		return idx;
	}

	private void assignParamSlots(List params) {
		int idx = 0;
		for (Var v : params) {
			varSlots.put(v, idx++);
		}
	}

	private void assignSlot(Var v, LivenessInfo liveness, IRNode node) {
		if (hasSlot(v)) {
			throw new IllegalStateException("Slot already assigned for variable " + v);
		}
		varSlots.put(v, findFreeSlot(liveness, node));
	}

	private void assignSlot(AbstractVal v, LivenessInfo liveness, IRNode node) {
		if (hasSlot(v)) {
			throw new IllegalStateException("Slot already assigned for value " + v);
		}
		valSlots.put(v, findFreeSlot(liveness, node));
	}

	public SlotAllocInfo process() {
		LivenessInfo liveness = LivenessAnalyser.computeLiveness(fn);

		Set




© 2015 - 2024 Weber Informatics LLC | Privacy Policy