📄 objecttree.java
字号:
/* JPC: A x86 PC Hardware Emulator for a pure Java Virtual Machine Release Version 2.0 A project from the Physics Dept, The University of Oxford Copyright (C) 2007 Isis Innovation Limited This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Details (including contact information) can be found at: www.physics.ox.ac.uk/jpc*/package org.jpc.emulator.memory.codeblock.cache;import java.util.*;import org.jpc.emulator.memory.*;//what size to switch between// -changing at about 8-16 element from narrow to wide seems to work// -this balances the number of wide nodes (more wides, much fewer narrows)//maybe just use a narrow array instead of hashmap??//better then HashMap// -have both a hashmap (NarrowNode) and explicit (OctalNode)// RootNode -- array (0-256 children) (== to wide?)// BinaryNode -- two childs (0-2 children)// NarrowNode -- map (2-100? children)// WideNode -- array (100?-256 children)// LeafNode -- no children only codeblock// SingularNode -- one child// SequenceNode -- one child (indexed by sequence of multiple bytes)/** * Holds Objects in a tree that is indexed by an x86 instruction sequence. * * @author Mike Moleschi */public class ObjectTree{ /** root node of tree */ private Node root; private Hashtable leafIndex; /** * Makes a new empty tree */ public ObjectTree() { leafIndex = new Hashtable(); clearAllObjects(); } /** * Defines a node in the tree. */ public static abstract class Node { /** * Defines at what size a Narrow Node should grow to before it changes * itself to a wide node. */ static final int MAX_NARROW_SIZE = 8; /** * Return the size of the node (number of children) * * @return number of children this node indexes */ public abstract int size(); /** * Add a child node to represent an index. (or replace if index is * already used) <br/> * Because this may add more children than the structure can handle, * the current node may have to replace itself! A reference to the * resulting valid structure is returned. (this could be the same, or * it could be a new replacement node)<br/> * If the node passed is null, its reference and index will be * cleared. If that means this node is then emtpy, it will return null * so that the parent can remove it. In this way a dead end path will * be cleared. * * @param n node to add as child to current node * @param mem memory holding a sequence of x86 bytes to search for * @param offset offset into memory of current x86 byte in sequence * @return a reference to the currently valid node (null if this node is empty) */ public abstract Node setNode(Node n, ByteArray mem, int offset, int maxOffset); /** * Get a child node that represents an index. * * @param mem memory holding a sequence of x86 bytes to search for * @param offset offset into memory of current x86 byte in sequence * @return a reference to the child node */ public abstract Node getNode(ByteArray mem, int offset); /** * Get the Object that represents a x86 byte sequence (if it exists). * * @param mem memory holding a sequence of x86 bytes to search for * @param offset offset into memory of current x86 byte in sequence * @return a reference to the code obj that represents the x86 sequnce or null if it doesn't exist */ public Object getObject(ByteArray mem, int offset) { Node child = getNode(mem, offset); if (child == null) return null; return child.getObject(mem, offset+1); } /** * Sets the Object that represents a x86 byte sequence. * (overwrites if already exists). If obj is null, it will remove any * codeobj stored for that sequence and remove any unique parts of * that sequence. * * @param obj code obj representing the sequence of x86 bytes * @param mem memory holding a sequence of x86 bytes which the code obj represets * @param offset offset into memory of current x86 byte in sequence * @param maxOffset offset into memory of last x86 byte in sequence * @return a reference to this node, incase this node transforms itself (return null if there are no node indexes in this node) */ public Node setObject(Object obj, ByteArray mem, int offset, int maxOffset) { Node child = getNode(mem, offset); if (child == null) { child = new SequenceNode(new LeafNode(obj), mem, offset+1, maxOffset); return setNode(child, mem, offset, maxOffset); } Node result = child.setObject(obj, mem, offset+1, maxOffset); if (result == child) return this; return setNode(result, mem, offset, maxOffset); } /** * Allows a visitor to enter the node. Will call visitNodes in all the * node's children. * * @param visitor visitor for the node * @return whether the visitor should continue (if the visitor is complete, allows it to stop) * @see ObjectTreeVisitor */ public boolean visitNodes(ObjectTreeVisitor visitor) { return visitor.visitNode(this); } public void print(String indent) { System.out.println(indent+getClass().getName()); } } public static class WideNode extends Node { private int valid; private Node[] nodes; /** Create a new wide node */ WideNode() { nodes = new Node[0x100]; valid = 0; } public int size() { return valid; } public Node setNode(Node n, ByteArray mem, int offset, int maxOffset) { int idx = 0xFF & mem.getByte(offset); if (nodes[idx] == null) valid++; nodes[idx] = n; if (n == null) valid--; return this; } public Node getNode(ByteArray mem, int offset) { int idx = 0xFF & mem.getByte(offset); return nodes[idx]; } public boolean visitNodes(ObjectTreeVisitor visitor) { if (!super.visitNodes(visitor)) return false; for(int i = 0; i < nodes.length; i++) { if (nodes[i] == null) continue; if (!nodes[i].visitNodes(visitor)) return false; } return true; } public void print(String indent) { System.out.println(indent+"Wide Node"); for (int i=0; i<nodes.length; i++) { if (nodes[i] != null) { System.out.println(indent+i); nodes[i].print(indent+" "); } } } } public static class NarrowNode extends Node { private Hashtable nodes; /** Create a new narrow node */ NarrowNode() { nodes = new Hashtable(0); } public int size() { return nodes.size(); } public Node getNode(ByteArray mem, int offset) { Byte b = new Byte(mem.getByte(offset)); return (Node) nodes.get(b); } public Node setNode(Node n, ByteArray mem, int offset, int maxOffset) { Byte index = new Byte(mem.getByte(offset)); if (n == null) { nodes.remove(index); if (nodes.size() == 0) return null; return this; } nodes.put(index, n); if (nodes.size() <= MAX_NARROW_SIZE) return this; /* nodes are full, therefore must change to different node type */ Node replacementNode = new WideNode(); SimpleByteArray dummy = new SimpleByteArray(1); Enumeration enumer = nodes.keys(); while(enumer.hasMoreElements()) { Byte b = (Byte) enumer.nextElement(); Node nn = (Node) nodes.get(b); dummy.setByte(0, b.byteValue()); replacementNode = replacementNode.setNode(nn, dummy, 0, 0); } replacementNode = replacementNode.setNode(n, mem, offset, maxOffset); return replacementNode; } public boolean visitNodes(ObjectTreeVisitor visitor) { if (!super.visitNodes(visitor)) return false; Enumeration enumer = nodes.keys(); while (enumer.hasMoreElements()) { Integer i = (Integer) enumer.nextElement(); Node child = (Node) nodes.get(i); if (!((Node) nodes.get(i)).visitNodes(visitor)) return false; } return true; } } public static class BinaryNode extends Node { private Node leftNode, rightNode; private byte leftIndex, rightIndex; private boolean leftUsed, rightUsed; /** Create a new binary node */ BinaryNode() { leftUsed = false; rightUsed = false; } public int size() { if ((leftUsed) && (rightUsed)) return 2; else if ((leftUsed) || (rightUsed)) return 1; else return 0; } public Node setNode(Node n, ByteArray mem, int offset, int maxOffset) { byte index = mem.getByte(offset); boolean inserted = false; if (!leftUsed || (leftUsed && (leftIndex == index))) { leftIndex = index; leftNode = n; leftUsed = true; if (n == null) leftUsed = false; inserted = true; } else if (!rightUsed || (rightUsed && (rightIndex == index))) { rightIndex = index; rightNode = n; rightUsed = true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -