Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/BCMethod.java
URL: 
http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/BCMethod.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/BCMethod.java 
(added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/BCMethod.java Wed 
Jun 28 12:46:13 2006
@@ -0,0 +1,498 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * 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 serp.bytecode;
+
+import serp.bytecode.visitor.*;
+
+import serp.util.*;
+
+
+/**
+ *  <p>A method of a class.</p>
+ *
+ *  @author Abe White
+ */
+public class BCMethod extends BCMember implements VisitAcceptor {
+    BCMethod(BCClass owner) {
+        super(owner);
+    }
+
+    /////////////////////
+    // Access operations
+    /////////////////////
+
+    /**
+     *  Manipulate the method access flags.
+     */
+    public boolean isSynchronized() {
+        return (getAccessFlags() & Constants.ACCESS_SYNCHRONIZED) > 0;
+    }
+
+    /**
+     *  Manipulate the method access flags.
+     */
+    public void setSynchronized(boolean on) {
+        if (on) {
+            setAccessFlags(getAccessFlags() | Constants.ACCESS_SYNCHRONIZED);
+        } else {
+            setAccessFlags(getAccessFlags() & ~Constants.ACCESS_SYNCHRONIZED);
+        }
+    }
+
+    /**
+     *  Manipulate the method access flags.
+     */
+    public boolean isNative() {
+        return (getAccessFlags() & Constants.ACCESS_NATIVE) > 0;
+    }
+
+    /**
+     *  Manipulate the method access flags.
+     */
+    public void setNative(boolean on) {
+        if (on) {
+            setAccessFlags(getAccessFlags() | Constants.ACCESS_NATIVE);
+        } else {
+            setAccessFlags(getAccessFlags() & ~Constants.ACCESS_NATIVE);
+        }
+    }
+
+    /**
+     *  Manipulate the method access flags.
+     */
+    public boolean isAbstract() {
+        return (getAccessFlags() & Constants.ACCESS_ABSTRACT) > 0;
+    }
+
+    /**
+     *  Manipulate the method access flags.
+     */
+    public void setAbstract(boolean on) {
+        if (on) {
+            setAccessFlags(getAccessFlags() | Constants.ACCESS_ABSTRACT);
+        } else {
+            setAccessFlags(getAccessFlags() & ~Constants.ACCESS_ABSTRACT);
+        }
+    }
+
+    /**
+     *  Manipulate the method access flags.
+     */
+    public boolean isStrict() {
+        return (getAccessFlags() & Constants.ACCESS_STRICT) > 0;
+    }
+
+    /**
+     *  Manipulate the method access flags.
+     */
+    public void setStrict(boolean on) {
+        if (on) {
+            setAccessFlags(getAccessFlags() | Constants.ACCESS_STRICT);
+        } else {
+            setAccessFlags(getAccessFlags() & ~Constants.ACCESS_STRICT);
+        }
+    }
+
+    /////////////////////
+    // Return operations
+    /////////////////////
+
+    /**
+     *  Return the name of the type returned by this method.  The name
+     *  will be given in a form suitable for a [EMAIL PROTECTED] 
Class#forName} call.
+     *
+     *  @see BCMember#getDescriptor
+     */
+    public String getReturnName() {
+        return getProject().getNameCache()
+                   .getExternalForm(getProject().getNameCache()
+                                        
.getDescriptorReturnName(getDescriptor()),
+            false);
+    }
+
+    /**
+     *  Return the [EMAIL PROTECTED] Class} object for the return type of this 
method.
+     *
+     *  @see BCMember#getDescriptor
+     */
+    public Class getReturnType() {
+        return Strings.toClass(getReturnName(), getClassLoader());
+    }
+
+    /**
+     *  Return the bytecode for the return type of this method.
+     *
+     *  @see BCMember#getDescriptor
+     */
+    public BCClass getReturnBC() {
+        return getProject().loadClass(getReturnName(), getClassLoader());
+    }
+
+    /**
+      *  Set the return type of this method.
+     */
+    public void setReturn(String name) {
+        setDescriptor(getProject().getNameCache()
+                          .getDescriptor(name, getParamNames()));
+    }
+
+    /**
+     *  Set the return type of this method.
+     */
+    public void setReturn(Class type) {
+        setReturn(type.getName());
+    }
+
+    /**
+     *  Set the return type of this method.
+     */
+    public void setReturn(BCClass type) {
+        setReturn(type.getName());
+    }
+
+    ////////////////////////
+    // Parameter operations
+    ////////////////////////
+
+    /**
+     *  Return the names of all the parameter types for this method.  The names
+     *  will be returned in a form suitable for a [EMAIL PROTECTED] 
Class#forName} call.
+     *
+     *  @see BCMember#getDescriptor
+     */
+    public String[] getParamNames() {
+        // get the parameter types from the descriptor
+        String[] params = getProject().getNameCache()
+                              .getDescriptorParamNames(getDescriptor());
+
+        // convert them to external form
+        for (int i = 0; i < params.length; i++)
+            params[i] = getProject().getNameCache()
+                            .getExternalForm(params[i], false);
+
+        return params;
+    }
+
+    /**
+     *  Return the [EMAIL PROTECTED] Class} objects for all the parameter 
types for this
+     *  method.
+     *
+     *  @see BCMember#getDescriptor
+     */
+    public Class[] getParamTypes() {
+        String[] paramNames = getParamNames();
+        Class[] params = new Class[paramNames.length];
+
+        for (int i = 0; i < paramNames.length; i++)
+            params[i] = Strings.toClass(paramNames[i], getClassLoader());
+
+        return params;
+    }
+
+    /**
+     *  Return the bytecode for all the parameter types for this
+     *  method.
+     *
+     *  @see BCMember#getDescriptor
+     */
+    public BCClass[] getParamBCs() {
+        String[] paramNames = getParamNames();
+        BCClass[] params = new BCClass[paramNames.length];
+
+        for (int i = 0; i < paramNames.length; i++)
+            params[i] = getProject().loadClass(paramNames[i], 
getClassLoader());
+
+        return params;
+    }
+
+    /**
+      *  Set the parameter types of this method.
+     *
+     *  @see BCMember#setDescriptor
+     */
+    public void setParams(String[] names) {
+        if (names == null) {
+            names = new String[0];
+        }
+
+        setDescriptor(getProject().getNameCache()
+                          .getDescriptor(getReturnName(), names));
+    }
+
+    /**
+     *  Set the parameter type of this method.
+     *
+     *  @see BCMember#setDescriptor
+     */
+    public void setParams(Class[] types) {
+        if (types == null) {
+            setParams((String[]) null);
+        } else {
+            String[] names = new String[types.length];
+
+            for (int i = 0; i < types.length; i++)
+                names[i] = types[i].getName();
+
+            setParams(names);
+        }
+    }
+
+    /**
+     *  Set the parameter type of this method.
+     *
+     *  @see BCMember#setDescriptor
+     */
+    public void setParams(BCClass[] types) {
+        if (types == null) {
+            setParams((String[]) null);
+        } else {
+            String[] names = new String[types.length];
+
+            for (int i = 0; i < types.length; i++)
+                names[i] = types[i].getName();
+
+            setParams(names);
+        }
+    }
+
+    /**
+     *  Add a parameter type to this method.
+     */
+    public void addParam(String type) {
+        String[] origParams = getParamNames();
+        String[] params = new String[origParams.length + 1];
+
+        for (int i = 0; i < origParams.length; i++)
+            params[i] = origParams[i];
+
+        params[origParams.length] = type;
+        setParams(params);
+    }
+
+    /**
+     *  Add a parameter type to this method.
+     */
+    public void addParam(Class type) {
+        addParam(type.getName());
+    }
+
+    /**
+     *  Add a parameter type to this method.
+     */
+    public void addParam(BCClass type) {
+        addParam(type.getName());
+    }
+
+    /**
+     *  Add a parameter type to this method.
+     *
+     *  @see java.util.List#add(int,Object)
+     */
+    public void addParam(int pos, String type) {
+        String[] origParams = getParamNames();
+
+        if ((pos < 0) || (pos >= origParams.length)) {
+            throw new IndexOutOfBoundsException("pos = " + pos);
+        }
+
+        String[] params = new String[origParams.length + 1];
+
+        for (int i = 0, index = 0; i < params.length; i++) {
+            if (i == pos) {
+                params[i] = type;
+            } else {
+                params[i] = origParams[index++];
+            }
+        }
+
+        setParams(params);
+    }
+
+    /**
+     *  Add a parameter type to this method.
+     *
+     *  @see java.util.List#add(int,Object)
+     */
+    public void addParam(int pos, Class type) {
+        addParam(pos, type.getName());
+    }
+
+    /**
+     *  Add a parameter type to this method.
+     *
+     *  @see java.util.List#add(int,Object)
+     */
+    public void addParam(int pos, BCClass type) {
+        addParam(pos, type.getName());
+    }
+
+    /**
+     *  Change a parameter type of this method.
+     *
+     *  @see java.util.List#set(int,Object)
+     */
+    public void setParam(int pos, String type) {
+        String[] origParams = getParamNames();
+
+        if ((pos < 0) || (pos >= origParams.length)) {
+            throw new IndexOutOfBoundsException("pos = " + pos);
+        }
+
+        String[] params = new String[origParams.length];
+
+        for (int i = 0; i < params.length; i++) {
+            if (i == pos) {
+                params[i] = type;
+            } else {
+                params[i] = origParams[i];
+            }
+        }
+
+        setParams(params);
+    }
+
+    /**
+     *  Change a parameter type of this method.
+     *
+     *  @see java.util.List#set(int,Object)
+     */
+    public void setParam(int pos, Class type) {
+        setParam(pos, type.getName());
+    }
+
+    /**
+     *  Change a parameter type of this method.
+     *
+     *  @see java.util.List#set(int,Object)
+     */
+    public void setParam(int pos, BCClass type) {
+        setParam(pos, type.getName());
+    }
+
+    /**
+     *  Clear all parameters from this method.
+     */
+    public void clearParams() {
+        setParams((String[]) null);
+    }
+
+    /**
+     *  Remove a parameter from this method.
+     */
+    public void removeParam(int pos) {
+        String[] origParams = getParamNames();
+
+        if ((pos < 0) || (pos >= origParams.length)) {
+            throw new IndexOutOfBoundsException("pos = " + pos);
+        }
+
+        String[] params = new String[origParams.length - 1];
+
+        for (int i = 0, index = 0; i < origParams.length; i++)
+            if (i != pos) {
+                params[index++] = origParams[i];
+            }
+
+        setParams(params);
+    }
+
+    ///////////////////////
+    // Convenience methods
+    ///////////////////////
+
+    /**
+     *  Return the checked exceptions information for the method.
+     *  Acts internally through the [EMAIL PROTECTED] Attributes} interface.
+     *
+     *  @param add                if true, a new exceptions attribute will be 
added
+     *                                  if not already present
+     *  @return the exceptions information, or null if none and the
+     *                                  <code>add</code> param is set to false
+     */
+    public Exceptions getExceptions(boolean add) {
+        Exceptions exceptions = (Exceptions) 
getAttribute(Constants.ATTR_EXCEPTIONS);
+
+        if (!add || (exceptions != null)) {
+            return exceptions;
+        }
+
+        if (exceptions == null) {
+            exceptions = (Exceptions) addAttribute(Constants.ATTR_EXCEPTIONS);
+        }
+
+        return exceptions;
+    }
+
+    /**
+     *  Remove the exceptions attribute for the method.
+     *  Acts internally through the [EMAIL PROTECTED] Attributes} interface.
+     *
+     *  @return true if there was a value to remove
+     */
+    public boolean removeExceptions() {
+        return removeAttribute(Constants.ATTR_EXCEPTIONS);
+    }
+
+    /**
+     *  Return the code for the method.  If the code already exists, its
+     *  iterator will be reset to the first instruction.
+     *  Acts internally through the [EMAIL PROTECTED] Attributes} interface.
+     *
+     *  @param add                if true, a new code attribute will be added
+     *                                  if not already present
+     *  @return the code for the metohd, or null if none and the
+     *                                  <code>add</code> param is set to false
+     */
+    public Code getCode(boolean add) {
+        Code code = (Code) getAttribute(Constants.ATTR_CODE);
+
+        if (code != null) {
+            code.beforeFirst();
+
+            return code;
+        }
+
+        if (!add) {
+            return null;
+        }
+
+        return (Code) addAttribute(Constants.ATTR_CODE);
+    }
+
+    /**
+     *  Remove the code attribute from the method.
+     *  Acts internally through the [EMAIL PROTECTED] Attributes} interface.
+     *
+     *  @return true if there was a value to remove
+     */
+    public boolean removeCode() {
+        return removeAttribute(Constants.ATTR_CODE);
+    }
+
+    ////////////////////////////////
+    // VisitAcceptor implementation
+    ////////////////////////////////
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterBCMethod(this);
+        visitAttributes(visit);
+        visit.exitBCMethod(this);
+    }
+
+    void initialize(String name, String descriptor) {
+        super.initialize(name, descriptor);
+        makePublic();
+    }
+}

Propchange: 
incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/BCMethod.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ClassConstantInstruction.java
URL: 
http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ClassConstantInstruction.java?rev=417860&view=auto
==============================================================================
--- 
incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ClassConstantInstruction.java
 (added)
+++ 
incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ClassConstantInstruction.java
 Wed Jun 28 12:46:13 2006
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * 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 serp.bytecode;
+
+import serp.bytecode.lowlevel.*;
+
+import java.util.*;
+
+
+/**
+ *  <p>Pseudo-instruction used to place [EMAIL PROTECTED] Class} objects onto 
the stack.
+ *  This logical instruction may actually involve a large chunk of code, and
+ *  may even add static synthetic fields and methods to the owning class.
+ *  Therefore, once the type of class being loaded is set, it cannot
+ *  be changed.  Also, this instruction is invalid as the target of
+ *  any jump instruction or exception handler.</p>
+ *
+ *  @author Abe White
+ */
+public class ClassConstantInstruction {
+    private static final Class[] _params = new Class[] { String.class };
+    private static final Map _wrappers = new HashMap();
+
+    static {
+        _wrappers.put(byte.class.getName(), Byte.class);
+        _wrappers.put(boolean.class.getName(), Boolean.class);
+        _wrappers.put(char.class.getName(), Character.class);
+        _wrappers.put(double.class.getName(), Double.class);
+        _wrappers.put(float.class.getName(), Float.class);
+        _wrappers.put(int.class.getName(), Integer.class);
+        _wrappers.put(long.class.getName(), Long.class);
+        _wrappers.put(short.class.getName(), Short.class);
+    }
+
+    private Instruction _ins = null;
+    private Code _code = null;
+    private BCClass _class = null;
+    private boolean _invalid = false;
+
+    ClassConstantInstruction(BCClass bc, Code code, Instruction nop) {
+        _class = bc;
+        _code = code;
+        _ins = nop;
+    }
+
+    /**
+     *  Set the type of class being loaded.
+     *
+     *  @return the first Instruction of the block added by setting
+     *                          the type
+     *  @throws IllegalStateException if type has already been set
+     */
+    public Instruction setClass(String name) {
+        name = _class.getProject().getNameCache().getExternalForm(name, false);
+        setClassName(name, getWrapperClass(name));
+
+        return _ins;
+    }
+
+    /**
+     *  Set the type of class being loaded.
+     *
+     *  @return the first Instruction of the block added by setting
+     *                          the type
+     *  @throws IllegalStateException if type has already been set
+     */
+    public Instruction setClass(Class type) {
+        return setClass(type.getName());
+    }
+
+    /**
+     *  Set the type of class being loaded.
+     *
+     *  @return the first Instruction of the block added by setting
+     *                          the type
+     *  @throws IllegalStateException if type has already been set
+     */
+    public Instruction setClass(BCClass type) {
+        return setClass(type.getName());
+    }
+
+    /**
+     *  Set the name of the class to load.
+     */
+    private void setClassName(String name, Class wrapper) {
+        if (_invalid) {
+            throw new IllegalStateException();
+        }
+
+        // remember the position of the code iterator
+        Instruction before = (_code.hasNext()) ? _code.next() : null;
+        _code.before(_ins);
+        _code.next();
+
+        if (wrapper != null) {
+            _code.getstatic().setField(wrapper, "TYPE", Class.class);
+        } else {
+            setObject(name);
+        }
+
+        // move to the old position
+        if (before != null) {
+            _code.before(before);
+        } else {
+            _code.afterLast();
+        }
+
+        _invalid = true;
+    }
+
+    /**
+     *  Adds fields and methods as necessary to load a class constant of
+     *  an object type.
+     */
+    private void setObject(String name) {
+        BCField field = addClassField(name);
+        BCMethod method = addClassLoadMethod();
+
+        // copied from the way jikes loads classes
+        _code.getstatic().setField(field);
+
+        JumpInstruction ifnull = _code.ifnull();
+
+        _code.getstatic().setField(field);
+
+        JumpInstruction go2 = _code.go2();
+
+        ifnull.setTarget(_code.constant().setValue(name));
+        _code.invokestatic().setMethod(method);
+        _code.dup();
+        _code.putstatic().setField(field);
+
+        go2.setTarget(_code.nop());
+    }
+
+    /**
+     *  Adds a static field to hold the loaded class constant.
+     */
+    private BCField addClassField(String name) {
+        String fieldName = "class$L" +
+            name.replace('.', '$').replace('[', '$').replace(';', '$');
+
+        BCField field = _class.getDeclaredField(fieldName);
+
+        if (field == null) {
+            field = _class.declareField(fieldName, Class.class);
+            field.makePackage();
+            field.setStatic(true);
+            field.setSynthetic(true);
+        }
+
+        return field;
+    }
+
+    /**
+     *  Adds the standard <code>class$<code> method used inernally by classes
+     *  to load class constants for object types.
+     */
+    private BCMethod addClassLoadMethod() {
+        BCMethod method = _class.getDeclaredMethod("class$", _params);
+
+        if (method != null) {
+            return method;
+        }
+
+        // add the special synthetic method
+        method = _class.declareMethod("class$", Class.class, _params);
+        method.setStatic(true);
+        method.makePackage();
+        method.setSynthetic(true);
+
+        // copied directly from the output of the jikes compiler
+        Code code = method.getCode(true);
+        code.setMaxStack(3);
+        code.setMaxLocals(2);
+
+        Instruction tryStart = code.aload().setLocal(0);
+        code.invokestatic()
+            .setMethod(Class.class, "forName", Class.class, _params);
+
+        Instruction tryEnd = code.areturn();
+        Instruction handlerStart = code.astore().setLocal(1);
+        code.anew().setType(NoClassDefFoundError.class);
+        code.dup();
+        code.aload().setLocal(1);
+        code.invokevirtual()
+            .setMethod(Throwable.class, "getMessage", String.class, null);
+        code.invokespecial()
+            .setMethod(NoClassDefFoundError.class, "<init>", void.class, 
_params);
+        code.athrow();
+
+        code.addExceptionHandler(tryStart, tryEnd, handlerStart,
+            ClassNotFoundException.class);
+
+        return method;
+    }
+
+    /**
+     *  Return the wrapper type for the given primitive class, or null
+     *  if the given name is not a primitive type.  The given name should
+     *  be in external form.
+     */
+    private static Class getWrapperClass(String name) {
+        if (name == null) {
+            return null;
+        }
+
+        return (Class) _wrappers.get(name);
+    }
+}

Propchange: 
incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ClassConstantInstruction.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ClassInstruction.java
URL: 
http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ClassInstruction.java?rev=417860&view=auto
==============================================================================
--- 
incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ClassInstruction.java 
(added)
+++ 
incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ClassInstruction.java 
Wed Jun 28 12:46:13 2006
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * 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 serp.bytecode;
+
+import serp.bytecode.lowlevel.*;
+
+import serp.bytecode.visitor.*;
+
+import java.io.*;
+
+
+/**
+ *  <p>An instruction that takes as an argument a class to operate
+ *  on.         Examples include <code>anewarray, checkcast, instance, 
anew</code>,
+ *  etc.</p>
+ *
+ *  @author Abe White
+ */
+public class ClassInstruction extends TypedInstruction {
+    private int _index = 0;
+
+    ClassInstruction(Code owner, int opcode) {
+        super(owner, opcode);
+    }
+
+    public int getLogicalStackChange() {
+        return getStackChange();
+    }
+
+    public int getStackChange() {
+        if (getOpcode() == Constants.NEW) {
+            return 1;
+        }
+
+        return 0;
+    }
+
+    int getLength() {
+        return super.getLength() + 2;
+    }
+
+    /**
+     *  Return the [EMAIL PROTECTED] ConstantPool} index of the
+     *  [EMAIL PROTECTED] ClassEntry} describing the class for this 
instruction.
+     */
+    public int getTypeIndex() {
+        return _index;
+    }
+
+    /**
+     *  Set the [EMAIL PROTECTED] ConstantPool} index of the
+     *  [EMAIL PROTECTED] ClassEntry} describing the class for this 
instruction.
+     *
+      *  @return this instruction, for method chaining
+     */
+    public ClassInstruction setTypeIndex(int index) {
+        _index = index;
+
+        return this;
+    }
+
+    public String getTypeName() {
+        if (_index == 0) {
+            return null;
+        }
+
+        ClassEntry entry = (ClassEntry) getPool().getEntry(_index);
+
+        return getProject().getNameCache()
+                   .getExternalForm(entry.getNameEntry().getValue(), false);
+    }
+
+    public TypedInstruction setType(String type) {
+        if (type == null) {
+            setTypeIndex(0);
+        } else {
+            type = getProject().getNameCache().getInternalForm(type, false);
+            setTypeIndex(getPool().findClassEntry(type, true));
+        }
+
+        return this;
+    }
+
+    /**
+     *  ClassInstructions are equal if the type they reference is the same or
+     *  unset and if their opcodes are equal.
+     */
+    public boolean equalsInstruction(Instruction other) {
+        if (other == this) {
+            return true;
+        }
+
+        if (!super.equalsInstruction(other)) {
+            return false;
+        }
+
+        String type = getTypeName();
+        String otherType = ((ClassInstruction) other).getTypeName();
+
+        return (type == null) || (otherType == null) || type.equals(otherType);
+    }
+
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterClassInstruction(this);
+        visit.exitClassInstruction(this);
+    }
+
+    void read(Instruction other) {
+        super.read(other);
+        setType(((ClassInstruction) other).getTypeName());
+    }
+
+    void read(DataInput in) throws IOException {
+        super.read(in);
+        setTypeIndex(in.readUnsignedShort());
+    }
+
+    void write(DataOutput out) throws IOException {
+        super.write(out);
+        out.writeShort(getTypeIndex());
+    }
+}

Propchange: 
incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ClassInstruction.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/CmpInstruction.java
URL: 
http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/CmpInstruction.java?rev=417860&view=auto
==============================================================================
--- 
incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/CmpInstruction.java 
(added)
+++ 
incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/CmpInstruction.java 
Wed Jun 28 12:46:13 2006
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * 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 serp.bytecode;
+
+import serp.bytecode.visitor.*;
+
+
+/**
+ *  <p>An instruction comparing two stack values.  Examples include
+ *  <code>lcmp, fcmpl</code>, etc.</p>
+ *
+ *  @author Abe White
+ */
+public class CmpInstruction extends TypedInstruction {
+    private static Class[][] _mappings = new Class[][] {
+            { int.class, long.class },
+            { byte.class, long.class },
+            { char.class, long.class },
+            { short.class, long.class },
+            { boolean.class, long.class },
+            { void.class, long.class },
+            { Object.class, long.class },
+        };
+
+    CmpInstruction(Code owner) {
+        super(owner);
+    }
+
+    CmpInstruction(Code owner, int opcode) {
+        super(owner, opcode);
+    }
+
+    public int getLogicalStackChange() {
+        switch (getOpcode()) {
+        case Constants.NOP:
+            return 0;
+
+        default:
+            return -1;
+        }
+    }
+
+    public int getStackChange() {
+        switch (getOpcode()) {
+        case Constants.LCMP:
+        case Constants.DCMPL:
+        case Constants.DCMPG:
+            return -3;
+
+        case Constants.NOP:
+            return 0;
+
+        default:
+            return -1;
+        }
+    }
+
+    public String getTypeName() {
+        switch (getOpcode()) {
+        case Constants.LCMP:
+            return long.class.getName();
+
+        case Constants.FCMPL:
+        case Constants.FCMPG:
+            return float.class.getName();
+
+        case Constants.DCMPL:
+        case Constants.DCMPG:
+            return double.class.getName();
+
+        default:
+            return null;
+        }
+    }
+
+    public TypedInstruction setType(String type) {
+        type = mapType(type, _mappings, true);
+
+        if (type == null) {
+            return (TypedInstruction) setOpcode(Constants.NOP);
+        }
+
+        int opcode = getOpcode();
+
+        switch (type.charAt(0)) {
+        case 'l':
+            return (TypedInstruction) setOpcode(Constants.LCMP);
+
+        case 'f':
+
+            if ((opcode == Constants.FCMPL) || (opcode == Constants.DCMPL)) {
+                return (TypedInstruction) setOpcode(Constants.FCMPL);
+            }
+
+            return (TypedInstruction) setOpcode(Constants.FCMPG);
+
+        case 'd':
+
+            if ((opcode == Constants.FCMPL) || (opcode == Constants.DCMPL)) {
+                return (TypedInstruction) setOpcode(Constants.DCMPL);
+            }
+
+            return (TypedInstruction) setOpcode(Constants.DCMPG);
+
+        default:
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     *  Return the number that will be placed on the stack if this instruction
+     *  is of type float or double and one of the operands is NaN.  For
+     *  FCMPG or DCMPG, this value will be 1; for FCMPL or DCMPL this value
+     *  will be -1.  For LCMP or if the type is unset, this value will be 0.
+     */
+    public int getNaNValue() {
+        switch (getOpcode()) {
+        case Constants.FCMPL:
+        case Constants.DCMPL:
+            return -1;
+
+        case Constants.FCMPG:
+        case Constants.DCMPG:
+            return 1;
+
+        default:
+            return 0;
+        }
+    }
+
+    /**
+     *  Set the number that will be placed on the stack if this instruction
+     *  is of type float or double and one of the operands is NaN.  For
+     *  FCMPG or DCMPG, this value should be 1; for FCMPL or DCMPL this value
+     *  should be -1.  For LCMP, this value should be 0.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public CmpInstruction setNaNValue(int nan) {
+        switch (getOpcode()) {
+        case Constants.FCMPL:
+        case Constants.FCMPG:
+
+            if (nan == 1) {
+                setOpcode(Constants.FCMPG);
+            } else if (nan == -1) {
+                setOpcode(Constants.FCMPL);
+            } else {
+                throw new IllegalArgumentException("Invalid nan for type");
+            }
+
+        case Constants.DCMPL:
+        case Constants.DCMPG:
+
+            if (nan == 1) {
+                setOpcode(Constants.DCMPG);
+            } else if (nan == -1) {
+                setOpcode(Constants.DCMPL);
+            } else {
+                throw new IllegalArgumentException("Invalid nan for type");
+            }
+
+        default:
+
+            if (nan != 0) {
+                throw new IllegalArgumentException("Invalid nan for type");
+            }
+        }
+
+        return this;
+    }
+
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterCmpInstruction(this);
+        visit.exitCmpInstruction(this);
+    }
+}

Propchange: 
incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/CmpInstruction.java
------------------------------------------------------------------------------
    svn:executable = *


Reply via email to