/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.compilers.opt.runtimesupport;
import java.util.Enumeration;
import org.jikesrvm.VM;
import org.jikesrvm.compilers.opt.inlining.CallSiteTree;
import org.jikesrvm.compilers.opt.inlining.CallSiteTreeNode;
import org.jikesrvm.compilers.opt.util.TreeNode;
import org.vmmagic.pragma.Interruptible;
import org.vmmagic.pragma.Uninterruptible;
/**
* Suppose the following inlining actions have been taken
* <pre>
* (<callerMID, bcIndex, calleeMID>):
*
* <A, 12, B>, <A,14,C>, <A,16,D>, < B,3,E>, < B,5,F >, <C,10,G>, <G,20,H>,
* <H,30,I>
* </pre>
*
* Then the <code>OptEncodedCallSiteTree </code> would be:
*
* <pre>
* -1, A, -2, 12, B, 14, C, 16, D, -6, 3, E, 5, F, -9, 10, G, -2, 20 H -2 30 I
* </pre>
*/
@Uninterruptible
public final class OptEncodedCallSiteTree {
private OptEncodedCallSiteTree() {
// no instantiation
}
public static int getMethodID(int entryOffset, int[] encoding) {
return encoding[entryOffset + 1];
}
static void setMethodID(int entryOffset, int[] encoding, int methodID) {
encoding[entryOffset + 1] = methodID;
}
public static int getByteCodeOffset(int entryOffset, int[] encoding) {
return encoding[entryOffset];
}
@Interruptible
public static int[] getEncoding(CallSiteTree tree) {
int size = 0;
if (tree.isEmpty()) {
return null;
} else {
Enumeration<TreeNode> e = tree.elements();
while (e.hasMoreElements()) {
TreeNode x = e.nextElement();
if (x.getLeftChild() == null) {
size += 2;
} else {
size += 3;
}
}
int[] encoding = new int[size];
getEncoding((CallSiteTreeNode) tree.getRoot(), 0, -1, encoding);
return encoding;
}
}
@Interruptible
static int getEncoding(CallSiteTreeNode current, int offset, int parent, int[] encoding) {
int i = offset;
if (parent != -1) {
encoding[i++] = parent - offset;
}
CallSiteTreeNode x = current;
int j = i;
while (x != null) {
x.encodedOffset = j;
int byteCodeIndex = x.callSite.getBcIndex();
encoding[j++] = (byteCodeIndex >= 0) ? byteCodeIndex : -1;
encoding[j++] = x.callSite.getMethod().getId();
x = (CallSiteTreeNode) x.getRightSibling();
}
x = current;
int thisParent = i;
while (x != null) {
if (x.getLeftChild() != null) {
j = getEncoding((CallSiteTreeNode) x.getLeftChild(), j, thisParent, encoding);
}
thisParent += 2;
x = (CallSiteTreeNode) x.getRightSibling();
}
return j;
}
public static int getParent(int index, int[] encodedTree) {
while (index >= 0 && encodedTree[index] >= -1) {
index--;
}
if (index < 0) {
return -1;
} else {
return index + encodedTree[index];
}
}
public static boolean edgePresent(int desiredCaller, int desiredBCIndex, int desiredCallee, int[] encoding) {
if (encoding.length < 3) return false; // Why are we creating an encoding with no real data???
if (VM.VerifyAssertions) {
VM._assert(encoding[0] == -1);
VM._assert(encoding[2] == -2);
}
int idx = 3;
int parent = encoding[1];
while (idx < encoding.length) {
if (encoding[idx] < 0) {
parent = idx + encoding[idx];
idx++;
}
if (parent == desiredCaller) {
if (encoding[idx] == desiredBCIndex && encoding[idx + 1] == desiredCallee) {
return true;
}
}
idx += 2;
}
return false;
}
}