// Generate code for a single tree root. private void generateTree(OPT_BURS_TreeNode k, OPT_BURS_STATE burs) { OPT_BURS_TreeNode child1 = k.child1; OPT_BURS_TreeNode child2 = k.child2; if (child1 != null) { if (child2 != null) { // k has two children; use register labeling to // determine order that minimizes register pressure if (k.isSuperNodeRoot()) { byte act = burs.action[k.rule(k.getNonTerminal())]; if ((act & burs.RIGHT_CHILD_FIRST) != 0) { // rule selected forces order of evaluation generateTree(child2, burs); generateTree(child1, burs); } else { generateTree(child1, burs); generateTree(child2, burs); } } else { generateTree(child1, burs); generateTree(child2, burs); } } else { generateTree(child1, burs); } } else if (child2 != null) { generateTree(child2, burs); } if (k.isSuperNodeRoot()) { int nonterminal = k.getNonTerminal(); int rule = k.rule(nonterminal); burs.code(k, nonterminal, rule); if (DEBUG) VM.sysWrite(k + " " + OPT_BURS_Debug.string[rule] + "\n"); } }
/** * Build a BURS Tree for each OPT_Instruction. Complete BURS trees by adding leaf nodes as needed, * and creating tree edges by calling insertChild1() or insertChild2() This step is also where we * introduce intermediate tree nodes for any LIR instruction that has > 2 "real" operands e.g., a * CALL. * * @param s The instruction for which a tree must be built */ private OPT_BURS_TreeNode buildTree(OPT_Instruction s) { OPT_BURS_TreeNode root = new OPT_BURS_TreeNode(new OPT_DepGraphNode(s)); OPT_BURS_TreeNode cur = root; for (OPT_OperandEnumeration uses = s.getUses(); uses.hasMoreElements(); ) { OPT_Operand op = uses.next(); if (op == null) continue; op.clear(); // Set child = OPT_BURS_TreeNode for operand op OPT_BURS_TreeNode child; if (op instanceof OPT_RegisterOperand) { if (op.asRegister().register.isValidation()) continue; child = Register; } else if (op instanceof OPT_IntConstantOperand) { child = new OPT_BURS_IntConstantTreeNode(((OPT_IntConstantOperand) op).value); } else if (op instanceof OPT_LongConstantOperand) { child = LongConstant; } else if (op instanceof OPT_AddressConstantOperand) { child = AddressConstant; } else if (op instanceof OPT_BranchOperand && s.isCall()) { child = BranchTarget; // -#if RVM_WITH_OSR } else if (op instanceof OPT_InlinedOsrTypeInfoOperand && s.isYieldPoint()) { child = NullTreeNode; // -#endif } else { continue; } // Attach child as child of cur_parent in correct position if (cur.child1 == null) { cur.child1 = child; } else if (cur.child2 == null) { cur.child2 = child; } else { // Create auxiliary node so as to represent // a instruction with arity > 2 in a binary tree. OPT_BURS_TreeNode child1 = cur.child2; OPT_BURS_TreeNode aux = new OPT_BURS_TreeNode(OTHER_OPERAND_opcode); cur.child2 = aux; cur = aux; cur.child1 = child1; cur.child2 = child; } } // patch for calls & return switch (s.getOpcode()) { case CALL_opcode: case SYSCALL_opcode: // -#if RVM_WITH_OSR case YIELDPOINT_OSR_opcode: // -#endif if (cur.child2 == null) cur.child2 = NullTreeNode; // fall through case RETURN_opcode: if (cur.child1 == null) cur.child1 = NullTreeNode; } return root; }
/* node accessors */ protected final OPT_Instruction P(OPT_BURS_TreeNode p) { return p.getInstruction(); }