/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html * or packager/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at packager/legal/LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package com.sun.jdo.api.persistence.enhancer.classfile; import java.io.PrintStream; /** * An instruction which requires a single constant from the constant * pool as an immediate operand */ public class InsnConstOp extends Insn { /* The constant from the constant pool */ private ConstBasic constValue; /* public accessors */ public int nStackArgs() { int n = VMOp.ops[opcode()].nStackArgs(); if (n >= 0) return n; switch (opcode()) { case opc_putstatic: case opc_putfield: { ConstFieldRef fld = (ConstFieldRef) constValue; String sig = fld.nameAndType().signature().asString(); if (sig.equals("J") || sig.equals("D"))//NOI18N return (opcode() == opc_putfield) ? 3 : 2; return (opcode() == opc_putfield) ? 2 : 1; } case opc_invokevirtual: case opc_invokespecial: case opc_invokestatic: /* handle interface invoke too */ case opc_invokeinterface: { ConstBasicMemberRef meth = (ConstBasicMemberRef) constValue; String sig = meth.nameAndType().signature().asString(); int nMethodArgWords = Descriptor.countMethodArgWords(sig); return nMethodArgWords + ((opcode() == opc_invokestatic) ? 0 : 1); } default: throw new InsnError("unexpected variable opcode");//NOI18N } } public int nStackResults() { int n = VMOp.ops[opcode()].nStackResults(); if (n >= 0) return n; switch (opcode()) { case opc_getstatic: case opc_getfield: { ConstFieldRef fld = (ConstFieldRef) constValue; String sig = fld.nameAndType().signature().asString(); if (sig.equals("J") || sig.equals("D"))//NOI18N return 2; return 1; } case opc_invokevirtual: case opc_invokespecial: case opc_invokestatic: /* handle interface invoke too */ case opc_invokeinterface: { ConstBasicMemberRef meth = (ConstBasicMemberRef) constValue; return Descriptor.countMethodReturnWords( meth.nameAndType().signature().asString()); } default: throw new InsnError("unexpected variable opcode");//NOI18N } } public String argTypes() { switch (opcode()) { case opc_putstatic: case opc_putfield: { ConstFieldRef fld = (ConstFieldRef) constValue; String sig = fld.nameAndType().signature().asString(); if (opcode() == opc_putstatic) return sig; else return descriptorTypeOfObject(fld) + sig; } case opc_invokevirtual: case opc_invokespecial: case opc_invokestatic: /* handle interface invoke too */ case opc_invokeinterface: { ConstBasicMemberRef meth = (ConstBasicMemberRef) constValue; String argSig = Descriptor.extractArgSig(meth.nameAndType().signature().asString()); if (opcode() == opc_invokestatic) return argSig; else return descriptorTypeOfObject(meth) + argSig; } default: return VMOp.ops[opcode()].argTypes(); } } public String resultTypes() { switch (opcode()) { case opc_invokevirtual: case opc_invokespecial: case opc_invokestatic: /* handle interface invoke too */ case opc_invokeinterface: { ConstBasicMemberRef meth = (ConstBasicMemberRef) constValue; String resultSig = Descriptor.extractResultSig( meth.nameAndType().signature().asString()); if (resultSig.equals("V"))//NOI18N return "";//NOI18N return resultSig; } case opc_getstatic: case opc_getfield: { ConstFieldRef fld = (ConstFieldRef) constValue; return fld.nameAndType().signature().asString(); } case opc_ldc: case opc_ldc_w: case opc_ldc2_w: { ConstValue constVal = (ConstValue) constValue; return constVal.descriptor(); } default: return VMOp.ops[opcode()].resultTypes(); } } public boolean branches() { /* invokes don't count as a branch */ return false; } /** * Return the constant pool entry which is the immediate operand */ public ConstBasic value() { return constValue; } /** * Modify the referenced constant */ public void setValue(ConstBasic newValue) { checkConstant(newValue); constValue = newValue; } /* package local methods */ void print (PrintStream out, int indent) { ClassPrint.spaces(out, indent); out.println(offset() + " " + opName(opcode()) + " pool(" + //NOI18N constValue.getIndex() + ")");//NOI18N } int store(byte[] buf, int index) { if (opcode() == opc_ldc && !isNarrowldc()) buf[index++] = (byte) opc_ldc_w; else buf[index++] = (byte) opcode(); int constIndex = constValue.getIndex(); if (size() == 3) buf[index++] = (byte) (constIndex >> 8); buf[index++] = (byte)(constIndex & 0xff); return index; } int size() { return isNarrowldc() ? 2 : 3; } private boolean isNarrowldc() { return (opcode() == opc_ldc && constValue.getIndex() < 256); } InsnConstOp (int theOpcode, ConstBasic theOperand) { this(theOpcode, theOperand, NO_OFFSET); } InsnConstOp (int theOpcode, ConstBasic theOperand, int pc) { super(theOpcode, pc); constValue = theOperand; checkConstant(theOperand); if (theOpcode == opc_invokeinterface) throw new InsnError("attempt to create an " + opName(theOpcode) +//NOI18N " as an InsnConstOp instead of InsnInterfaceInvoke");//NOI18N } /* used only by InsnInterfaceInvoke, to make sure that opc_invokeinterface cannot * come through the wrong path and miss its extra nArgsOp */ InsnConstOp (int theOpcode, ConstInterfaceMethodRef theOperand, int pc) { super(theOpcode, pc); constValue = theOperand; checkConstant(theOperand); } private void checkConstant (ConstBasic operand) { switch(opcode()) { case opc_ldc: case opc_ldc_w: case opc_ldc2_w: /* ConstValue */ if (operand == null || (! (operand instanceof ConstValue))) throw new InsnError ("attempt to create an " + opName(opcode()) +//NOI18N " without a ConstValue operand");//NOI18N break; case opc_getstatic: case opc_putstatic: case opc_getfield: case opc_putfield: /* ConstFieldRef */ if (operand == null || (! (operand instanceof ConstFieldRef))) throw new InsnError ("attempt to create an " + opName(opcode()) +//NOI18N " without a ConstFieldRef operand");//NOI18N break; case opc_invokevirtual: case opc_invokespecial: case opc_invokestatic: /* ConstMethodRef */ if (operand == null || (! (operand instanceof ConstMethodRef))) throw new InsnError ("attempt to create an " + opName(opcode()) +//NOI18N " without a ConstMethodRef operand");//NOI18N break; case opc_invokeinterface: /* ConstInterfaceMethodRef */ if (operand == null || (! (operand instanceof ConstInterfaceMethodRef))) throw new InsnError("Attempt to create an " + opName(opcode()) +//NOI18N " without a ConstInterfaceMethodRef operand");//NOI18N break; case opc_new: case opc_anewarray: case opc_checkcast: case opc_instanceof: /* ConstClass */ if (operand == null || (! (operand instanceof ConstClass))) throw new InsnError ("attempt to create an " + opName(opcode()) +//NOI18N " without a ConstClass operand");//NOI18N break; default: throw new InsnError ("attempt to create an " + opName(opcode()) +//NOI18N " with a constant operand");//NOI18N } } private final String descriptorTypeOfObject(ConstBasicMemberRef memRef) { String cname = memRef.className().className().asString(); return "L" + cname + ";";//NOI18N } }