You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pc...@apache.org on 2006/06/28 21:46:19 UTC

svn commit: r417860 [8/12] - in /incubator/openjpa/trunk: ./ openjpa-lib/ openjpa-lib/main/ openjpa-lib/src/ openjpa-lib/src/main/ openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ openjpa-lib/src/test/ openjpa-lib/src/test/java/ openjpa-lib/src/t...

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LocalVariableInstruction.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LocalVariableInstruction.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LocalVariableInstruction.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LocalVariableInstruction.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,177 @@
+/*
+ * 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 that has an argument of an index into the
+ *  local variable table of the current frame.  This includes most of the
+ *  <code>load</code> and <code>store</code> instructions.</p>
+ *
+ *  <p>The local variable table size is fixed by the <code>maxLocals</code>
+ *  property of the code block.  Long and double types take up 2 local variable
+ *  indexes.</p>
+ *
+ *  <p>Parameter values to methods are loaded into the local variable table
+ *  prior to the execution of the first instruction.  The 0 index of the
+ *  table is set to the instance of the class the method is being invoked
+ *  on.</p>
+ *
+ *  @author Abe White
+ */
+public abstract class LocalVariableInstruction extends TypedInstruction {
+    private int _index = -1;
+
+    LocalVariableInstruction(Code owner) {
+        super(owner);
+    }
+
+    LocalVariableInstruction(Code owner, int opcode) {
+        super(owner, opcode);
+        calculateLocal();
+    }
+
+    public String getTypeName() {
+        return null;
+    }
+
+    public TypedInstruction setType(String type) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+      *  Return the index of the local variable that this instruction
+     *  operates on.
+     */
+    public int getLocal() {
+        return _index;
+    }
+
+    /**
+      *  Set the index of the local variable that this instruction
+     *  operates on.
+      *
+     *  @return this instruction, for method chaining
+     */
+    public LocalVariableInstruction setLocal(int index) {
+        _index = index;
+        calculateOpcode();
+
+        return this;
+    }
+
+    /**
+     *  Return the parameter that this instruction operates on, or -1 if none.
+     */
+    public int getParam() {
+        return getCode().getParamsIndex(getLocal());
+    }
+
+    /**
+     *  Set the method parameter that this instruction operates on.  This
+     *  will set both the local index and the type of the instruction based
+     *  on the current method parameters.
+     */
+    public LocalVariableInstruction setParam(int param) {
+        int local = getCode().getLocalsIndex(param);
+
+        if (local != -1) {
+            BCMethod method = getCode().getMethod();
+            setType(method.getParamNames()[param]);
+        }
+
+        return setLocal(local);
+    }
+
+    /**
+      *  Return the local variable object this instruction
+     *  operates on, or null if none.
+     *
+     *  @see LocalVariableTable#getLocalVariable(int)
+     */
+    public LocalVariable getLocalVariable() {
+        LocalVariableTable table = getCode().getLocalVariableTable(false);
+
+        if (table == null) {
+            return null;
+        }
+
+        return table.getLocalVariable(getLocal());
+    }
+
+    /**
+      *  Set the local variable object this instruction
+     *  operates on.  This method will set both the type and local index
+     *  of this instruction from the given local variable.
+      *
+     *  @return this instruction, for method chaining
+     */
+    public LocalVariableInstruction setLocalVariable(LocalVariable local) {
+        if (local == null) {
+            return setLocal(-1);
+        } else {
+            String type = local.getTypeName();
+
+            if (type != null) {
+                setType(type);
+            }
+
+            return setLocal(local.getLocal());
+        }
+    }
+
+    /**
+     *  Two local variable instructions are equal if the local index they
+     *  reference is equal or if either index is 0/unset.
+     */
+    public boolean equalsInstruction(Instruction other) {
+        if (this == other) {
+            return true;
+        }
+
+        if (!getClass().equals(other.getClass())) {
+            return false;
+        }
+
+        LocalVariableInstruction ins = (LocalVariableInstruction) other;
+        int index = getLocal();
+        int insIndex = ins.getLocal();
+
+        return (index == -1) || (insIndex == -1) || (index == insIndex);
+    }
+
+    void read(Instruction orig) {
+        super.read(orig);
+        setLocal(((LocalVariableInstruction) orig).getLocal());
+    }
+
+    /**
+     *  Subclasses with variable opcodes can use this method to be
+     *  notified that information possibly affecting the opcode has been
+     *  changed.
+     */
+    void calculateOpcode() {
+    }
+
+    /**
+     *  Subclasses can use this method to calculate
+     *  the locals index based on their opcode.
+     */
+    void calculateLocal() {
+    }
+}

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

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LocalVariableTable.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LocalVariableTable.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LocalVariableTable.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LocalVariableTable.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,121 @@
+/*
+ * 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>Code blocks compiled from source have local variable tables mapping
+ *  locals used in opcodes to their names and descriptions.</p>
+ *
+ *  @author Abe White
+ */
+public class LocalVariableTable extends LocalTable {
+    LocalVariableTable(int nameIndex, Attributes owner) {
+        super(nameIndex, owner);
+    }
+
+    /**
+     *  Return all the locals of this method.
+     */
+    public LocalVariable[] getLocalVariables() {
+        return (LocalVariable[]) getLocals();
+    }
+
+    /**
+     *  Return the local with the given locals index, or null if none.
+     */
+    public LocalVariable getLocalVariable(int local) {
+        return (LocalVariable) getLocal(local);
+    }
+
+    /**
+     *  Return the local with the given name, or null if none.  If multiple
+     *  locals have the given name, which is returned is undefined.
+     */
+    public LocalVariable getLocalVariable(String name) {
+        return (LocalVariable) getLocal(name);
+    }
+
+    /**
+     *  Return all locals with the given name, or empty array if none.
+     */
+    public LocalVariable[] getLocalVariables(String name) {
+        return (LocalVariable[]) getLocals(name);
+    }
+
+    /**
+     *  Import a local from another method/class.  Note that
+     *  the program counter and length from the given local is copied
+      *  directly, and thus will be incorrect unless this method is the same
+      *  as the one the local is copied from, or the pc and length are reset.
+     */
+    public LocalVariable addLocalVariable(LocalVariable local) {
+        return (LocalVariable) addLocal(local);
+    }
+
+    /**
+     *  Add a local to this table.
+     */
+    public LocalVariable addLocalVariable() {
+        return (LocalVariable) addLocal();
+    }
+
+    /**
+     *  Add a local to this table.
+     */
+    public LocalVariable addLocalVariable(String name, String type) {
+        return (LocalVariable) addLocal(name, type);
+    }
+
+    /**
+     *  Add a local to this table.
+     */
+    public LocalVariable addLocalVariable(String name, Class type) {
+        String typeName = (type == null) ? null : type.getName();
+
+        return addLocalVariable(name, typeName);
+    }
+
+    /**
+     *  Add a local to this table.
+     */
+    public LocalVariable addLocalVariable(String name, BCClass type) {
+        String typeName = (type == null) ? null : type.getName();
+
+        return addLocalVariable(name, typeName);
+    }
+
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterLocalVariableTable(this);
+
+        LocalVariable[] locals = (LocalVariable[]) getLocals();
+
+        for (int i = 0; i < locals.length; i++)
+            locals[i].acceptVisit(visit);
+
+        visit.exitLocalVariableTable(this);
+    }
+
+    protected Local newLocal() {
+        return new LocalVariable(this);
+    }
+
+    protected Local[] newLocalArray(int size) {
+        return new LocalVariable[size];
+    }
+}

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

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LocalVariableType.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LocalVariableType.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LocalVariableType.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LocalVariableType.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,43 @@
+/*
+ * 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>A local variable type contains the name, signature, index and scope
+ *  of a generics-using local used in opcodes.</p>
+ *
+ *  @author Abe White
+ */
+public class LocalVariableType extends Local {
+    LocalVariableType(LocalVariableTypeTable owner) {
+        super(owner);
+    }
+
+    /**
+     *  The owning table.
+     */
+    public LocalVariableTypeTable getLocalVariableTypeTable() {
+        return (LocalVariableTypeTable) getTable();
+    }
+
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterLocalVariableType(this);
+        visit.exitLocalVariableType(this);
+    }
+}

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

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LocalVariableTypeTable.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LocalVariableTypeTable.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LocalVariableTypeTable.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LocalVariableTypeTable.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,103 @@
+/*
+ * 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>Code blocks compiled from source have local variable type tables mapping
+ *  generics-using locals used in opcodes to their names and signatures.</p>
+ *
+ *  @author Abe White
+ */
+public class LocalVariableTypeTable extends LocalTable {
+    LocalVariableTypeTable(int nameIndex, Attributes owner) {
+        super(nameIndex, owner);
+    }
+
+    /**
+     *  Return all the locals of this method.
+     */
+    public LocalVariableType[] getLocalVariableTypes() {
+        return (LocalVariableType[]) getLocals();
+    }
+
+    /**
+     *  Return the local with the given locals index, or null if none.
+     */
+    public LocalVariableType getLocalVariableType(int local) {
+        return (LocalVariableType) getLocal(local);
+    }
+
+    /**
+     *  Return the local with the given name, or null if none.  If multiple
+     *  locals have the given name, which is returned is undefined.
+     */
+    public LocalVariableType getLocalVariableType(String name) {
+        return (LocalVariableType) getLocal(name);
+    }
+
+    /**
+     *  Return all locals with the given name, or empty array if none.
+     */
+    public LocalVariableType[] getLocalVariableTypes(String name) {
+        return (LocalVariableType[]) getLocals(name);
+    }
+
+    /**
+     *  Import a local from another method/class.  Note that
+     *  the program counter and length from the given local is copied
+      *  directly, and thus will be incorrect unless this method is the same
+      *  as the one the local is copied from, or the pc and length are reset.
+     */
+    public LocalVariableType addLocalVariableType(LocalVariableType local) {
+        return (LocalVariableType) addLocal(local);
+    }
+
+    /**
+     *  Add a local to this table.
+     */
+    public LocalVariableType addLocalVariableType() {
+        return (LocalVariableType) addLocal();
+    }
+
+    /**
+     *  Add a local to this table.
+     */
+    public LocalVariableType addLocalVariableType(String name, String type) {
+        return (LocalVariableType) addLocal(name, type);
+    }
+
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterLocalVariableTypeTable(this);
+
+        LocalVariableType[] locals = (LocalVariableType[]) getLocals();
+
+        for (int i = 0; i < locals.length; i++)
+            locals[i].acceptVisit(visit);
+
+        visit.exitLocalVariableTypeTable(this);
+    }
+
+    protected Local newLocal() {
+        return new LocalVariableType(this);
+    }
+
+    protected Local[] newLocalArray(int size) {
+        return new LocalVariableType[size];
+    }
+}

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

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LookupSwitchInstruction.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LookupSwitchInstruction.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LookupSwitchInstruction.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/LookupSwitchInstruction.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,255 @@
+/*
+ * 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.*;
+
+import java.io.*;
+
+import java.util.*;
+
+
+/**
+ *  <p>The <code>lookupswitch</code> instruction.</p>
+ *
+ *  @author Abe White
+ */
+public class LookupSwitchInstruction extends JumpInstruction {
+    // case info
+    private List _matches = new LinkedList();
+    private List _cases = new LinkedList();
+
+    LookupSwitchInstruction(Code owner) {
+        super(owner, Constants.LOOKUPSWITCH);
+    }
+
+    int getLength() {
+        // don't call super.getLength(), cause JumpInstruction will return
+        // value assuming this is an 'if' or 'goto' instruction
+        int length = 1;
+
+        // make the first byte of the 'default' a multiple of 4 from the
+        // start of the method
+        int byteIndex = getByteIndex() + 1;
+
+        for (; (byteIndex % 4) != 0; byteIndex++, length++)
+            ;
+
+        // default, npairs
+        length += 8;
+
+        // pairs
+        length += (8 * _matches.size());
+
+        return length;
+    }
+
+    public int getLogicalStackChange() {
+        return getStackChange();
+    }
+
+    public int getStackChange() {
+        return -1;
+    }
+
+    /**
+     *  Synonymous with {@link #getTarget}.
+     */
+    public Instruction getDefaultTarget() {
+        return getTarget();
+    }
+
+    /**
+     *  Synonymous with {@link #setTarget}.
+     */
+    public LookupSwitchInstruction setDefaultTarget(Instruction ins) {
+        return (LookupSwitchInstruction) setTarget(ins);
+    }
+
+    /**
+     *  Synonymous with {@link #getOffset}.
+     */
+    public int getDefaultOffset() {
+        return getOffset();
+    }
+
+    /**
+     *  Synonymous with {@link #setOffset}.
+     */
+    public LookupSwitchInstruction setDefaultOffset(int offset) {
+        setOffset(offset);
+
+        return this;
+    }
+
+    /**
+     *  Set the match-jumppt pairs for this switch.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public LookupSwitchInstruction setCases(int[] matches, Instruction[] targets) {
+        _matches.clear();
+        _cases.clear();
+
+        for (int i = 0; i < matches.length; i++)
+            _matches.add(Numbers.valueOf(matches[i]));
+
+        for (int i = 0; i < targets.length; i++) {
+            InstructionPtrStrategy next = new InstructionPtrStrategy(this);
+            next.setTargetInstruction(targets[i]);
+            _cases.add(next);
+        }
+
+        return this;
+    }
+
+    public int[] getOffsets() {
+        int bi = getByteIndex();
+        int[] offsets = new int[_cases.size()];
+
+        for (int i = 0; i < offsets.length; i++)
+            offsets[i] = ((InstructionPtrStrategy) _cases.get(i)).getByteIndex() -
+                bi;
+
+        return offsets;
+    }
+
+    /**
+     *  Return the values of the case statements for this switch.
+     */
+    public int[] getMatches() {
+        int[] matches = new int[_matches.size()];
+        Iterator itr = _matches.iterator();
+
+        for (int i = 0; i < matches.length; i++)
+            matches[i] = ((Integer) itr.next()).intValue();
+
+        return matches;
+    }
+
+    /**
+     *  Return the targets of the case statements for this switch.
+     */
+    public Instruction[] getTargets() {
+        Instruction[] result = new Instruction[_cases.size()];
+
+        for (int i = 0; i < result.length; i++)
+            result[i] = ((InstructionPtrStrategy) _cases.get(i)).getTargetInstruction();
+
+        return result;
+    }
+
+    /**
+     *  Add a case to this switch.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public LookupSwitchInstruction addCase(int match, Instruction target) {
+        _matches.add(Numbers.valueOf(match));
+        _cases.add(new InstructionPtrStrategy(this, target));
+
+        return this;
+    }
+
+    private Instruction findJumpPoint(int jumpByteIndex, List inss) {
+        Instruction ins;
+
+        for (Iterator itr = inss.iterator(); itr.hasNext();) {
+            ins = (Instruction) itr.next();
+
+            if (ins.getByteIndex() == jumpByteIndex) {
+                return ins;
+            }
+        }
+
+        return null;
+    }
+
+    public void updateTargets() {
+        super.updateTargets();
+
+        for (Iterator itr = _cases.iterator(); itr.hasNext();)
+            ((InstructionPtrStrategy) itr.next()).updateTargets();
+    }
+
+    public void replaceTarget(Instruction oldTarget, Instruction newTarget) {
+        super.replaceTarget(oldTarget, newTarget);
+
+        for (Iterator itr = _cases.iterator(); itr.hasNext();)
+            ((InstructionPtrStrategy) itr.next()).replaceTarget(oldTarget,
+                newTarget);
+    }
+
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterLookupSwitchInstruction(this);
+        visit.exitLookupSwitchInstruction(this);
+    }
+
+    void read(Instruction orig) {
+        super.read(orig);
+
+        LookupSwitchInstruction ins = (LookupSwitchInstruction) orig;
+        _matches = new LinkedList(ins._matches);
+        _cases.clear();
+
+        for (Iterator itr = ins._cases.iterator(); itr.hasNext();) {
+            InstructionPtrStrategy origPtr = (InstructionPtrStrategy) itr.next();
+            InstructionPtrStrategy newPtr = new InstructionPtrStrategy(this);
+            newPtr.setByteIndex(origPtr.getByteIndex());
+            _cases.add(newPtr);
+        }
+    }
+
+    void read(DataInput in) throws IOException {
+        // don't call super
+        int bi = getByteIndex();
+
+        for (int byteIndex = bi + 1; (byteIndex % 4) != 0; byteIndex++)
+            in.readByte();
+
+        setOffset(in.readInt());
+
+        _matches.clear();
+        _cases.clear();
+
+        for (int i = 0, pairCount = in.readInt(); i < pairCount; i++) {
+            _matches.add(Numbers.valueOf(in.readInt()));
+
+            InstructionPtrStrategy next = new InstructionPtrStrategy(this);
+            next.setByteIndex(bi + in.readInt());
+            _cases.add(next);
+        }
+    }
+
+    void write(DataOutput out) throws IOException {
+        // don't call super
+        int bi = getByteIndex();
+
+        for (int byteIndex = bi + 1; (byteIndex % 4) != 0; byteIndex++)
+            out.writeByte(0);
+
+        out.writeInt(getOffset());
+        out.writeInt(_matches.size());
+
+        for (int i = 0; i < _matches.size(); i++) {
+            out.writeInt(((Integer) _matches.get(i)).intValue());
+            out.writeInt(((InstructionPtrStrategy) _cases.get(i)).getByteIndex() -
+                bi);
+        }
+    }
+}

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

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MathInstruction.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MathInstruction.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MathInstruction.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MathInstruction.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,294 @@
+/*
+ * 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 java.util.*;
+
+
+/**
+ *  <p>One of the math operations defined in the {@link Constants} interface.
+ *  Changing the type or operation of the instruction will automatically
+ *  update the underlying opcode.</p>
+ *
+ *  @author Abe White
+ */
+public class MathInstruction extends TypedInstruction {
+    private static final Class[][] _mappings = new Class[][] {
+            { byte.class, int.class },
+            { boolean.class, int.class },
+            { char.class, int.class },
+            { short.class, int.class },
+            { void.class, int.class },
+            { Object.class, int.class },
+        };
+    private int _op = -1;
+    private String _type = null;
+
+    MathInstruction(Code owner) {
+        super(owner);
+    }
+
+    MathInstruction(Code owner, int opcode) {
+        super(owner, opcode);
+        _op = getOperation();
+    }
+
+    public int getStackChange() {
+        int op = getOperation();
+
+        if ((op == Constants.MATH_NEG) || (getOpcode() == Constants.NOP)) {
+            return 0;
+        }
+
+        String type = getTypeName();
+
+        if (long.class.getName().equals(type) ||
+                double.class.getName().equals(type)) {
+            switch (getOpcode()) {
+            case (Constants.LSHL):
+            case (Constants.LSHR):
+            case (Constants.LUSHR):
+                return -1;
+
+            default:
+                return -2;
+            }
+        }
+
+        return -1;
+    }
+
+    public int getLogicalStackChange() {
+        int op = getOperation();
+
+        if ((op == Constants.MATH_NEG) || (getOpcode() == Constants.NOP)) {
+            return 0;
+        }
+
+        return -1;
+    }
+
+    public String getTypeName() {
+        switch (getOpcode()) {
+        case Constants.IADD:
+        case Constants.ISUB:
+        case Constants.IMUL:
+        case Constants.IDIV:
+        case Constants.IREM:
+        case Constants.INEG:
+        case Constants.ISHL:
+        case Constants.ISHR:
+        case Constants.IUSHR:
+        case Constants.IAND:
+        case Constants.IOR:
+        case Constants.IXOR:
+            return int.class.getName();
+
+        case Constants.LADD:
+        case Constants.LSUB:
+        case Constants.LMUL:
+        case Constants.LDIV:
+        case Constants.LREM:
+        case Constants.LNEG:
+        case Constants.LSHL:
+        case Constants.LSHR:
+        case Constants.LUSHR:
+        case Constants.LAND:
+        case Constants.LOR:
+        case Constants.LXOR:
+            return long.class.getName();
+
+        case Constants.FADD:
+        case Constants.FSUB:
+        case Constants.FMUL:
+        case Constants.FDIV:
+        case Constants.FREM:
+        case Constants.FNEG:
+            return float.class.getName();
+
+        case Constants.DADD:
+        case Constants.DSUB:
+        case Constants.DMUL:
+        case Constants.DDIV:
+        case Constants.DREM:
+        case Constants.DNEG:
+            return double.class.getName();
+
+        default:
+            return _type;
+        }
+    }
+
+    public TypedInstruction setType(String type) {
+        type = mapType(type, _mappings, true);
+
+        // if an invalid type or op, revert to nop
+        if ((type == null) || (_op < 0)) {
+            _type = type;
+
+            return (TypedInstruction) setOpcode(Constants.NOP);
+        }
+
+        // valid opcode, unset saved type
+        _type = null;
+
+        switch (type.charAt(0)) {
+        case 'i':
+            return (TypedInstruction) setOpcode(_op);
+
+        case 'l':
+            return (TypedInstruction) setOpcode(_op + 1);
+
+        case 'f':
+            return (TypedInstruction) setOpcode(_op + 2);
+
+        case 'd':
+            return (TypedInstruction) setOpcode(_op + 3);
+
+        default:
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+      *  Set the math operation to be performed.  This should be one of the
+     *  math constant defined in {@link Constants}.
+      *
+     *  @return this instruction, for method chaining
+     */
+    public MathInstruction setOperation(int operation) {
+        _op = operation;
+
+        // this calculates the opcode
+        setType(getTypeName());
+
+        return this;
+    }
+
+    /**
+      *  Return the operation for this math instruction; will be one of the
+     *  math constant defined in {@link Constants}, or -1 if
+      *  unset.
+     */
+    public int getOperation() {
+        switch (getOpcode()) {
+        case Constants.IADD:
+        case Constants.LADD:
+        case Constants.FADD:
+        case Constants.DADD:
+            return Constants.MATH_ADD;
+
+        case Constants.ISUB:
+        case Constants.LSUB:
+        case Constants.FSUB:
+        case Constants.DSUB:
+            return Constants.MATH_SUB;
+
+        case Constants.IMUL:
+        case Constants.LMUL:
+        case Constants.FMUL:
+        case Constants.DMUL:
+            return Constants.MATH_MUL;
+
+        case Constants.IDIV:
+        case Constants.LDIV:
+        case Constants.FDIV:
+        case Constants.DDIV:
+            return Constants.MATH_DIV;
+
+        case Constants.IREM:
+        case Constants.LREM:
+        case Constants.FREM:
+        case Constants.DREM:
+            return Constants.MATH_REM;
+
+        case Constants.INEG:
+        case Constants.LNEG:
+        case Constants.FNEG:
+        case Constants.DNEG:
+            return Constants.MATH_NEG;
+
+        case Constants.ISHL:
+        case Constants.LSHL:
+            return Constants.MATH_SHL;
+
+        case Constants.ISHR:
+        case Constants.LSHR:
+            return Constants.MATH_SHR;
+
+        case Constants.IUSHR:
+        case Constants.LUSHR:
+            return Constants.MATH_USHR;
+
+        case Constants.IAND:
+        case Constants.LAND:
+            return Constants.MATH_AND;
+
+        case Constants.IOR:
+        case Constants.LOR:
+            return Constants.MATH_OR;
+
+        case Constants.IXOR:
+        case Constants.LXOR:
+            return Constants.MATH_XOR;
+
+        default:
+            return _op;
+        }
+    }
+
+    /**
+     *  MathInstructions are equal if they have the same operation and type,
+     *  or the operation and type of either is unset.
+     */
+    public boolean equalsInstruction(Instruction other) {
+        if (this == other) {
+            return true;
+        }
+
+        if (!(other instanceof MathInstruction)) {
+            return false;
+        }
+
+        MathInstruction ins = (MathInstruction) other;
+
+        int op = getOperation();
+        int otherOp = ins.getOperation();
+        boolean opEq = (op == -1) || (otherOp == -1) || (op == otherOp);
+
+        String type = getTypeName();
+        String otherType = ins.getTypeName();
+        boolean typeEq = (type == null) || (otherType == null) ||
+            type.equals(otherType);
+
+        return opEq && typeEq;
+    }
+
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterMathInstruction(this);
+        visit.exitMathInstruction(this);
+    }
+
+    void read(Instruction orig) {
+        super.read(orig);
+
+        MathInstruction ins = (MathInstruction) orig;
+        _type = ins._type;
+        _op = ins._op;
+    }
+}

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

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MethodInstruction.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MethodInstruction.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MethodInstruction.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MethodInstruction.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,777 @@
+/*
+ * 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 serp.util.*;
+
+import java.io.*;
+
+import java.lang.reflect.*;
+
+
+/**
+ *  <p>An instruction that invokes a method.</p>
+ *
+ *  @author Abe White
+ */
+public class MethodInstruction extends Instruction {
+    private int _index = 0;
+
+    MethodInstruction(Code owner, int opcode) {
+        super(owner, opcode);
+    }
+
+    int getLength() {
+        if (getOpcode() == Constants.INVOKEINTERFACE) {
+            return super.getLength() + 4;
+        }
+
+        return super.getLength() + 2;
+    }
+
+    public int getLogicalStackChange() {
+        String ret = getMethodReturnName();
+
+        if (ret == null) {
+            return 0;
+        }
+
+        int stack = 0;
+
+        // subtract a stack pos for the this ptr
+        if (getOpcode() != Constants.INVOKESTATIC) {
+            stack--;
+        }
+
+        // and for each arg
+        String[] params = getMethodParamNames();
+
+        for (int i = 0; i < params.length; i++)
+            stack--;
+
+        // add for the return value, if any
+        if (!void.class.getName().equals(ret)) {
+            stack++;
+        }
+
+        return stack;
+    }
+
+    public int getStackChange() {
+        String ret = getMethodReturnName();
+
+        if (ret == null) {
+            return 0;
+        }
+
+        int stack = 0;
+
+        // subtract a stack pos for the this ptr
+        if (getOpcode() != Constants.INVOKESTATIC) {
+            stack--;
+        }
+
+        // and for each arg (2 for longs, doubles)
+        String[] params = getMethodParamNames();
+
+        for (int i = 0; i < params.length; i++, stack--)
+            if (long.class.getName().equals(params[i]) ||
+                    double.class.getName().equals(params[i])) {
+                stack--;
+            }
+
+        // add for the return value, if any
+        if (!void.class.getName().equals(ret)) {
+            stack++;
+        }
+
+        if (long.class.getName().equals(ret) ||
+                double.class.getName().equals(ret)) {
+            stack++;
+        }
+
+        return stack;
+    }
+
+    /////////////////////
+    // Method operations
+    /////////////////////
+
+    /**
+     *  Return the index in the class {@link ConstantPool} of the
+     *  {@link ComplexEntry} describing the method to operate on.
+     */
+    public int getMethodIndex() {
+        return _index;
+    }
+
+    /**
+     *  Set the index in the class {@link ConstantPool} of the
+     *  {@link ComplexEntry} describing the method to operate on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public MethodInstruction setMethodIndex(int index) {
+        _index = index;
+
+        return this;
+    }
+
+    /**
+     *  Return the method this instruction operates on, or null if not set.
+     */
+    public BCMethod getMethod() {
+        String dec = getMethodDeclarerName();
+
+        if (dec == null) {
+            return null;
+        }
+
+        BCClass bc = getProject().loadClass(dec, getClassLoader());
+        BCMethod[] meths = bc.getMethods(getMethodName(), getMethodParamNames());
+
+        if (meths.length == 0) {
+            return null;
+        }
+
+        return meths[0];
+    }
+
+    /**
+      *  Set the method this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public MethodInstruction setMethod(BCMethod method) {
+        if (method == null) {
+            return setMethodIndex(0);
+        }
+
+        return setMethod(method.getDeclarer().getName(), method.getName(),
+            method.getReturnName(), method.getParamNames());
+    }
+
+    /**
+     *  Set the method this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public MethodInstruction setMethod(Method method) {
+        if (method == null) {
+            return setMethodIndex(0);
+        }
+
+        return setMethod(method.getDeclaringClass(), method.getName(),
+            method.getReturnType(), method.getParameterTypes());
+    }
+
+    /**
+     *  Set the method this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public MethodInstruction setMethod(Constructor method) {
+        if (method == null) {
+            return setMethodIndex(0);
+        }
+
+        setOpcode(Constants.INVOKESPECIAL);
+
+        return setMethod(method.getDeclaringClass(), "<init>", void.class,
+            method.getParameterTypes());
+    }
+
+    /**
+     *  Set the method this instruction operates on.
+     *
+     *  @param dec                        the full class name of the method's declaring class
+     *  @param name                the method name
+     *  @param returnType        the full class name of the method return type
+     *  @param param                the full class names of the method param types
+     *  @return this instruction, for method chaining
+     */
+    public MethodInstruction setMethod(String dec, String name,
+        String returnType, String[] params) {
+        if ((name == null) && (returnType == null) && (dec == null) &&
+                ((params == null) || (params.length == 0))) {
+            return setMethodIndex(0);
+        }
+
+        if (dec == null) {
+            dec = "";
+        }
+
+        if (name == null) {
+            name = "";
+        }
+
+        if (returnType == null) {
+            returnType = "";
+        }
+
+        if (params == null) {
+            params = new String[0];
+        }
+
+        NameCache cache = getProject().getNameCache();
+        returnType = cache.getInternalForm(returnType, true);
+        dec = cache.getInternalForm(dec, false);
+
+        for (int i = 0; i < params.length; i++)
+            params[i] = cache.getInternalForm(params[i], true);
+
+        String desc = cache.getDescriptor(returnType, params);
+
+        if (getOpcode() == Constants.INVOKEINTERFACE) {
+            return setMethodIndex(getPool()
+                                      .findInterfaceMethodEntry(dec, name,
+                    desc, true));
+        }
+
+        return setMethodIndex(getPool().findMethodEntry(dec, name, desc, true));
+    }
+
+    /**
+     *  Set the method this instruction operates on, for methods that are
+     *  declared by the current class.
+      *
+     *  @param name                the method name
+     *  @param returnType        the full class name of the method return type
+     *  @param param                the full class names of the method param types
+     *  @return this instruction, for method chaining
+     */
+    public MethodInstruction setMethod(String name, String returnType,
+        String[] params) {
+        BCClass owner = getCode().getMethod().getDeclarer();
+
+        return setMethod(owner.getName(), name, returnType, params);
+    }
+
+    /**
+     *  Set the method this instruction operates on.
+     *
+     *  @param dec                        the method's declaring class
+     *  @param name                the method name
+     *  @param returnType        the class of the method return type
+     *  @param param                the class of the method param types
+     *  @return this instruction, for method chaining
+     */
+    public MethodInstruction setMethod(Class dec, String name,
+        Class returnType, Class[] params) {
+        String decName = (dec == null) ? null : dec.getName();
+        String returnName = (returnType == null) ? null : returnType.getName();
+        String[] paramNames = null;
+
+        if (params != null) {
+            paramNames = new String[params.length];
+
+            for (int i = 0; i < params.length; i++)
+                paramNames[i] = params[i].getName();
+        }
+
+        return setMethod(decName, name, returnName, paramNames);
+    }
+
+    /**
+     *  Set the method this instruction operates on, for methods that are
+     *  declared by the current class.
+      *
+     *  @param name                the method name
+     *  @param returnType        the class of the method return type
+     *  @param param                the class of the method param types
+     *  @return this instruction, for method chaining
+     */
+    public MethodInstruction setMethod(String name, Class returnType,
+        Class[] params) {
+        BCClass owner = getCode().getMethod().getDeclarer();
+        String returnName = (returnType == null) ? null : returnType.getName();
+        String[] paramNames = null;
+
+        if (params != null) {
+            paramNames = new String[params.length];
+
+            for (int i = 0; i < params.length; i++)
+                paramNames[i] = params[i].getName();
+        }
+
+        return setMethod(owner.getName(), name, returnName, paramNames);
+    }
+
+    /**
+     *  Set the method this instruction operates on.
+     *
+     *  @param dec                        the method's declaring class
+     *  @param name                the method name
+     *  @param returnType        the class of the method return type
+     *  @param param                the class of the method param types
+     *  @return this instruction, for method chaining
+     */
+    public MethodInstruction setMethod(BCClass dec, String name,
+        BCClass returnType, BCClass[] params) {
+        String decName = (dec == null) ? null : dec.getName();
+        String returnName = (returnType == null) ? null : returnType.getName();
+        String[] paramNames = null;
+
+        if (params != null) {
+            paramNames = new String[params.length];
+
+            for (int i = 0; i < params.length; i++)
+                paramNames[i] = params[i].getName();
+        }
+
+        return setMethod(decName, name, returnName, paramNames);
+    }
+
+    /**
+     *  Set the method this instruction operates on, for methods that are
+     *  declared by the current class.
+      *
+     *  @param name                the method name
+     *  @param returnType        the class of the method return type
+     *  @param param                the class of the method param types
+     *  @return this instruction, for method chaining
+     */
+    public MethodInstruction setMethod(String name, BCClass returnType,
+        BCClass[] params) {
+        BCClass owner = getCode().getMethod().getDeclarer();
+        String returnName = (returnType == null) ? null : returnType.getName();
+        String[] paramNames = null;
+
+        if (params != null) {
+            paramNames = new String[params.length];
+
+            for (int i = 0; i < params.length; i++)
+                paramNames[i] = params[i].getName();
+        }
+
+        return setMethod(owner.getName(), name, returnName, paramNames);
+    }
+
+    /////////////////////////////////////////
+    // Name, Return, Param, Owner operations
+    /////////////////////////////////////////
+
+    /**
+     *  Return the name of the method this instruction operates on, or null
+     *  if not set.
+     */
+    public String getMethodName() {
+        int index = getMethodIndex();
+
+        if (index == 0) {
+            return null;
+        }
+
+        ComplexEntry entry = (ComplexEntry) getPool().getEntry(index);
+        String name = entry.getNameAndTypeEntry().getNameEntry().getValue();
+
+        if (name.length() == 0) {
+            return null;
+        }
+
+        return name;
+    }
+
+    /**
+     *  Set the name of the method this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public MethodInstruction setMethodName(String name) {
+        return setMethod(getMethodDeclarerName(), name, getMethodReturnName(),
+            getMethodParamNames());
+    }
+
+    /**
+     *  Return the return type of the method this instruction operates on,
+     *  or null        if not set.
+     */
+    public String getMethodReturnName() {
+        int index = getMethodIndex();
+
+        if (index == 0) {
+            return null;
+        }
+
+        ComplexEntry entry = (ComplexEntry) getPool().getEntry(index);
+        String desc = entry.getNameAndTypeEntry().getDescriptorEntry().getValue();
+        NameCache cache = getProject().getNameCache();
+        String name = cache.getExternalForm(cache.getDescriptorReturnName(desc),
+                false);
+
+        if (name.length() == 0) {
+            return null;
+        }
+
+        return name;
+    }
+
+    /**
+     *  Return the return type of the method this instruction operates on,
+     *  or null        if not set.
+     */
+    public Class getMethodReturnType() {
+        String type = getMethodReturnName();
+
+        if (type == null) {
+            return null;
+        }
+
+        return Strings.toClass(type, getClassLoader());
+    }
+
+    /**
+     *  Return the return type of the method this instruction operates on,
+     *  or null        if not set.
+     */
+    public BCClass getMethodReturnBC() {
+        String type = getMethodReturnName();
+
+        if (type == null) {
+            return null;
+        }
+
+        return getProject().loadClass(type, getClassLoader());
+    }
+
+    /**
+     *  Set the return type of the method this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public MethodInstruction setMethodReturn(String type) {
+        return setMethod(getMethodDeclarerName(), getMethodName(), type,
+            getMethodParamNames());
+    }
+
+    /**
+     *  Set the return type of the method this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public MethodInstruction setMethodReturn(Class type) {
+        String name = null;
+
+        if (type != null) {
+            name = type.getName();
+        }
+
+        return setMethodReturn(name);
+    }
+
+    /**
+     *  Set the return type of the method this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public MethodInstruction setMethodReturn(BCClass type) {
+        String name = null;
+
+        if (type != null) {
+            name = type.getName();
+        }
+
+        return setMethodReturn(name);
+    }
+
+    /**
+     *  Return the param types of the method this instruction operates on,
+     *  or empty array if none.
+     */
+    public String[] getMethodParamNames() {
+        int index = getMethodIndex();
+
+        if (index == 0) {
+            return null;
+        }
+
+        ComplexEntry entry = (ComplexEntry) getPool().getEntry(index);
+        String desc = entry.getNameAndTypeEntry().getDescriptorEntry().getValue();
+        NameCache cache = getProject().getNameCache();
+        String[] names = cache.getDescriptorParamNames(desc);
+
+        for (int i = 0; i < names.length; i++)
+            names[i] = cache.getExternalForm(names[i], false);
+
+        return names;
+    }
+
+    /**
+     *  Return the param types of the method this instruction operates on,
+     *  or empty array if none.
+     */
+    public Class[] getMethodParamTypes() {
+        String[] paramNames = getMethodParamNames();
+        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 param types of the method this instruction operates on,
+     *  or empty array if none.
+     */
+    public BCClass[] getMethodParamBCs() {
+        String[] paramNames = getMethodParamNames();
+        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 param types of the method this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public MethodInstruction setMethodParams(String[] types) {
+        return setMethod(getMethodDeclarerName(), getMethodName(),
+            getMethodReturnName(), types);
+    }
+
+    /**
+     *  Set the param types of the method this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public void setMethodParams(Class[] types) {
+        if (types == null) {
+            setMethodParams((String[]) null);
+        } else {
+            String[] names = new String[types.length];
+
+            for (int i = 0; i < types.length; i++)
+                names[i] = types[i].getName();
+
+            setMethodParams(names);
+        }
+    }
+
+    /**
+     *  Set the param types of the method this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public void setMethodParams(BCClass[] types) {
+        if (types == null) {
+            setMethodParams((String[]) null);
+        } else {
+            String[] names = new String[types.length];
+
+            for (int i = 0; i < types.length; i++)
+                names[i] = types[i].getName();
+
+            setMethodParams(names);
+        }
+    }
+
+    /**
+     *  Return the declaring type of the method this instruction operates on,
+     *  or null        if not set.
+     */
+    public String getMethodDeclarerName() {
+        int index = getMethodIndex();
+
+        if (index == 0) {
+            return null;
+        }
+
+        ComplexEntry entry = (ComplexEntry) getPool().getEntry(index);
+        String name = getProject().getNameCache()
+                          .getExternalForm(entry.getClassEntry().getNameEntry()
+                                                .getValue(), false);
+
+        if (name.length() == 0) {
+            return null;
+        }
+
+        return name;
+    }
+
+    /**
+     *  Return the declaring type of the method this instruction operates on,
+     *  or null        if not set.
+     */
+    public Class getMethodDeclarerType() {
+        String type = getMethodDeclarerName();
+
+        if (type == null) {
+            return null;
+        }
+
+        return Strings.toClass(type, getClassLoader());
+    }
+
+    /**
+     *  Return the declaring type of the method this instruction operates on,
+     *  or null        if not set.
+     */
+    public BCClass getMethodDeclarerBC() {
+        String type = getMethodDeclarerName();
+
+        if (type == null) {
+            return null;
+        }
+
+        return getProject().loadClass(type, getClassLoader());
+    }
+
+    /**
+     *  Set the declaring type of the method this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public MethodInstruction setMethodDeclarer(String type) {
+        return setMethod(type, getMethodName(), getMethodReturnName(),
+            getMethodParamNames());
+    }
+
+    /**
+     *  Set the declaring type of the method this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public MethodInstruction setMethodDeclarer(Class type) {
+        String name = null;
+
+        if (type != null) {
+            name = type.getName();
+        }
+
+        return setMethodDeclarer(name);
+    }
+
+    /**
+     *  Set the declaring type of the method this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public MethodInstruction setMethodDeclarer(BCClass type) {
+        String name = null;
+
+        if (type != null) {
+            name = type.getName();
+        }
+
+        return setMethodDeclarer(name);
+    }
+
+    /**
+     *  MethodInstructions are equal if the method they reference is the same,
+     *  or if the method of either is unset.
+     */
+    public boolean equalsInstruction(Instruction other) {
+        if (other == this) {
+            return true;
+        }
+
+        if (!(other instanceof MethodInstruction)) {
+            return false;
+        }
+
+        if (!super.equalsInstruction(other)) {
+            return false;
+        }
+
+        MethodInstruction ins = (MethodInstruction) other;
+
+        String s1 = getMethodName();
+        String s2 = ins.getMethodName();
+
+        if (!((s1 == null) || (s2 == null) || s1.equals(s2))) {
+            return false;
+        }
+
+        s1 = getMethodReturnName();
+        s2 = ins.getMethodReturnName();
+
+        if (!((s1 == null) || (s2 == null) || s1.equals(s2))) {
+            return false;
+        }
+
+        s1 = getMethodDeclarerName();
+        s2 = ins.getMethodDeclarerName();
+
+        if (!((s1 == null) || (s2 == null) || s1.equals(s2))) {
+            return false;
+        }
+
+        String[] p1 = getMethodParamNames();
+        String[] p2 = ins.getMethodParamNames();
+
+        if (!((p1.length == 0) || (p2.length == 0) || (p1.length == p2.length))) {
+            return false;
+        }
+
+        for (int i = 0; i < p1.length; i++)
+            if (!((p1[i] == null) || (p2[i] == null) || p1[i].equals(p2[i]))) {
+                return false;
+            }
+
+        return true;
+    }
+
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterMethodInstruction(this);
+        visit.exitMethodInstruction(this);
+    }
+
+    void read(Instruction orig) {
+        super.read(orig);
+
+        MethodInstruction ins = (MethodInstruction) orig;
+        setMethod(ins.getMethodDeclarerName(), ins.getMethodName(),
+            ins.getMethodReturnName(), ins.getMethodParamNames());
+    }
+
+    void read(DataInput in) throws IOException {
+        super.read(in);
+        setMethodIndex(in.readUnsignedShort());
+
+        if (getOpcode() == Constants.INVOKEINTERFACE) {
+            in.readByte();
+            in.readByte();
+        }
+    }
+
+    void write(DataOutput out) throws IOException {
+        super.write(out);
+        out.writeShort(getMethodIndex());
+
+        if (getOpcode() == Constants.INVOKEINTERFACE) {
+            String[] args = getMethodParamNames();
+            int count = 1;
+
+            for (int i = 0; i < args.length; i++, count++)
+                if (long.class.getName().equals(args[i]) ||
+                        double.class.getName().equals(args[i])) {
+                    count++;
+                }
+
+            out.writeByte(count);
+            out.writeByte(0);
+        }
+    }
+}

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

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MonitorEnterInstruction.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MonitorEnterInstruction.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MonitorEnterInstruction.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MonitorEnterInstruction.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,37 @@
+/*
+ * 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 java.io.*;
+
+
+/**
+ *  <p>The <code>monitorenter</code> instruction.</p>
+ *
+ *  @author Abe White
+ */
+public class MonitorEnterInstruction extends MonitorInstruction {
+    MonitorEnterInstruction(Code owner) {
+        super(owner, Constants.MONITORENTER);
+    }
+
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterMonitorEnterInstruction(this);
+        visit.exitMonitorEnterInstruction(this);
+    }
+}

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

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MonitorExitInstruction.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MonitorExitInstruction.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MonitorExitInstruction.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MonitorExitInstruction.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,35 @@
+/*
+ * 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>The <code>monitorexit</code> instruction.</p>
+ *
+ *  @author Abe White
+ */
+public class MonitorExitInstruction extends MonitorInstruction {
+    MonitorExitInstruction(Code owner) {
+        super(owner, Constants.MONITOREXIT);
+    }
+
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterMonitorExitInstruction(this);
+        visit.exitMonitorExitInstruction(this);
+    }
+}

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

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MonitorInstruction.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MonitorInstruction.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MonitorInstruction.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MonitorInstruction.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+
+/**
+ *  <p>A synchronization instruction.</p>
+ *
+ *  @author Abe White
+ */
+public abstract class MonitorInstruction extends Instruction {
+    MonitorInstruction(Code owner, int opcode) {
+        super(owner, opcode);
+    }
+
+    public int getLogicalStackChange() {
+        return getStackChange();
+    }
+
+    public int getStackChange() {
+        return -1;
+    }
+}

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

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MultiANewArrayInstruction.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MultiANewArrayInstruction.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MultiANewArrayInstruction.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/MultiANewArrayInstruction.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,110 @@
+/*
+ * 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 java.io.*;
+
+
+/**
+ *  <p>The <code>multianewarray</code> instruction, which creates a new
+ *  multi-dimensional array.</p>
+ *
+ *  @author Abe White
+ */
+public class MultiANewArrayInstruction extends ClassInstruction {
+    private int _dims = -1;
+
+    MultiANewArrayInstruction(Code owner) {
+        super(owner, Constants.MULTIANEWARRAY);
+    }
+
+    int getLength() {
+        return super.getLength() + 1;
+    }
+
+    public int getLogicalStackChange() {
+        return getStackChange();
+    }
+
+    public int getStackChange() {
+        return -(getDimensions()) + 1;
+    }
+
+    /**
+      *  Return the dimensions of the array, or -1 if not set.
+     */
+    public int getDimensions() {
+        return _dims;
+    }
+
+    /**
+     *  Set the dimensions of the array.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public MultiANewArrayInstruction setDimensions(int dims) {
+        _dims = dims;
+
+        return this;
+    }
+
+    /**
+     *  Two MultiANewArray instructions are equal if they have the same
+     *  type and dimensions, or if the type and dimensions of either
+     *  is unset.
+     */
+    public boolean equalsInstruction(Instruction other) {
+        if (other == this) {
+            return true;
+        }
+
+        if (!(other instanceof MultiANewArrayInstruction)) {
+            return false;
+        }
+
+        if (!super.equalsInstruction(other)) {
+            return false;
+        }
+
+        MultiANewArrayInstruction ins = (MultiANewArrayInstruction) other;
+        int dims = getDimensions();
+        int otherDims = ins.getDimensions();
+
+        return (dims == -1) || (otherDims == -1) || (dims == otherDims);
+    }
+
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterMultiANewArrayInstruction(this);
+        visit.exitMultiANewArrayInstruction(this);
+    }
+
+    void read(Instruction orig) {
+        super.read(orig);
+        setDimensions(((MultiANewArrayInstruction) orig).getDimensions());
+    }
+
+    void read(DataInput in) throws IOException {
+        super.read(in);
+        setDimensions(in.readUnsignedByte());
+    }
+
+    void write(DataOutput out) throws IOException {
+        super.write(out);
+        out.writeByte(getDimensions());
+    }
+}

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

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/NameCache.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/NameCache.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/NameCache.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/NameCache.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,296 @@
+/*
+ * 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 java.util.*;
+
+
+/**
+ *  <p>Caching and conversion of names in both internal and external form.</p>
+ *
+ *  @author Abe White
+ */
+public class NameCache {
+    static final Object[][] _codes = new Object[][] {
+            { byte.class, "B" },
+            { char.class, "C" },
+            { double.class, "D" },
+            { float.class, "F" },
+            { int.class, "I" },
+            { long.class, "J" },
+            { short.class, "S" },
+            { boolean.class, "Z" },
+            { void.class, "V" },
+        };
+
+    // caches of internal and external forms of strings
+    private final Map _internal = new HashMap();
+    private final Map _internalDescriptor = new HashMap();
+    private final Map _external = new HashMap();
+    private final Map _externalHuman = new HashMap();
+
+    /**
+      *  Converts the given class name to its internal form.
+     *
+     *  @param className        the name to convert
+     *  @param descriptor        true if the name is to be used for a descriptor
+     *                                          section -- the difference seems to be that for
+     *                                          descriptors, non-primitives are prefixed with 'L'
+     *                                          and ended with ';'
+     */
+    public String getInternalForm(String className, boolean descriptor) {
+        if ((className == null) || (className.length() == 0)) {
+            return className;
+        }
+
+        Map cache = (descriptor) ? _internalDescriptor : _internal;
+        String cached = (String) cache.get(className);
+
+        if (cached != null) {
+            return cached;
+        }
+
+        String ret = getInternalFormInternal(className, descriptor);
+        cache.put(className, ret);
+
+        return ret;
+    }
+
+    /**
+     *  @see #getInternalForm
+     */
+    private String getInternalFormInternal(String cls, boolean descriptor) {
+        // handle array types, whether already in internal form or not
+        StringBuffer prefix = new StringBuffer();
+
+        while (true) {
+            if (cls.endsWith("[]")) {
+                prefix.append("[");
+                cls = cls.substring(0, cls.length() - 2);
+            } else if (cls.startsWith("[")) {
+                prefix.append("[");
+                cls = cls.substring(1);
+            } else {
+                break;
+            }
+        }
+
+        // handle primitive array types
+        for (int i = 0; i < _codes.length; i++)
+            if (cls.equals(_codes[i][1].toString()) ||
+                    cls.equals(_codes[i][0].toString())) {
+                return prefix.append(_codes[i][1]).toString();
+            }
+
+        // if in descriptor form, strip leading 'L' and trailing ';'
+        if (cls.startsWith("L") && cls.endsWith(";")) {
+            cls = cls.substring(1, cls.length() - 1);
+        }
+
+        // non-primitive; make sure we don't prefix method descriptors with 'L'
+        cls = cls.replace('.', '/');
+
+        if ((descriptor || (prefix.length() > 0)) && (cls.charAt(0) != '(')) {
+            return prefix.append("L").append(cls).append(";").toString();
+        }
+
+        return prefix.append(cls).toString();
+    }
+
+    /**
+     *  Given the internal name of the class, return the 'normal' java name.
+     *
+     *  @param internalName        the internal name being used
+     *  @param humanReadable        if the returned name should be in human-readable
+     *                                                  form, rather than a form suitable for a
+     *                                                  {@link Class#forName} call -- the difference
+     *                                                  lies in the handling of        arrays
+     */
+    public String getExternalForm(String internalName, boolean humanReadable) {
+        if ((internalName == null) || (internalName.length() == 0)) {
+            return internalName;
+        }
+
+        Map cache = (humanReadable) ? _externalHuman : _external;
+        String cached = (String) cache.get(internalName);
+
+        if (cached != null) {
+            return cached;
+        }
+
+        String ret = getExternalFormInternal(internalName, humanReadable);
+        cache.put(internalName, ret);
+
+        return ret;
+    }
+
+    /**
+     *  @see #getExternalForm
+     */
+    private String getExternalFormInternal(String intern, boolean humanReadable) {
+        if (!humanReadable) {
+            // check against primitives
+            for (int i = 0; i < _codes.length; i++) {
+                if (intern.equals(_codes[i][1].toString())) {
+                    return _codes[i][0].toString();
+                }
+
+                if (intern.equals(_codes[i][0].toString())) {
+                    return intern;
+                }
+            }
+
+            intern = getInternalForm(intern, false);
+
+            return intern.replace('/', '.');
+        }
+
+        // handle arrays
+        StringBuffer postfix = new StringBuffer(2);
+
+        while (intern.startsWith("[")) {
+            intern = intern.substring(1);
+            postfix.append("[]");
+        }
+
+        // strip off leading 'L' and trailing ';'
+        if (intern.endsWith(";")) {
+            intern = intern.substring(1, intern.length() - 1);
+        }
+
+        // check primitives
+        for (int i = 0; i < _codes.length; i++)
+            if (intern.equals(_codes[i][1].toString())) {
+                return _codes[i][0].toString() + postfix;
+            }
+
+        return intern.replace('/', '.') + postfix;
+    }
+
+    /**
+     *  Construct a method descriptor from the given return and parameter
+     *  types, which will be converted to internal form.
+     */
+    public String getDescriptor(String returnType, String[] paramTypes) {
+        StringBuffer buf = new StringBuffer();
+        buf.append("(");
+
+        if (paramTypes != null) {
+            for (int i = 0; i < paramTypes.length; i++) {
+                if (paramTypes[i] == null) {
+                    throw new NullPointerException("paramTypes[" + i +
+                        "] = null");
+                }
+
+                buf.append(getInternalForm(paramTypes[i], true));
+            }
+        }
+
+        buf.append(")");
+
+        if (returnType == null) {
+            throw new NullPointerException("returnType = null");
+        }
+
+        buf.append(getInternalForm(returnType, true));
+
+        return buf.toString();
+    }
+
+    /**
+     *  Return the return type, in internal form, for the given method
+     *  descriptor string.
+     */
+    public String getDescriptorReturnName(String descriptor) {
+        int index = descriptor.indexOf(')');
+
+        if (index == -1) {
+            return "";
+        }
+
+        return descriptor.substring(descriptor.indexOf(')') + 1);
+    }
+
+    /**
+     *  Return the parameter types, in internal form, for the given method
+     *  descriptor string.
+     */
+    public String[] getDescriptorParamNames(String descriptor) {
+        if ((descriptor == null) || (descriptor.length() == 0)) {
+            return new String[0];
+        }
+
+        int index = descriptor.indexOf(')');
+
+        if (index == -1) {
+            return new String[0];
+        }
+
+        // get rid of the parens and the return type
+        descriptor = descriptor.substring(1, index);
+
+        // break the param string into individual params
+        List tokens = new LinkedList();
+
+        while (descriptor.length() > 0) {
+            index = 0;
+
+            // skip the '[' up to the first letter code
+            while (!Character.isLetter(descriptor.charAt(index)))
+                index++;
+
+            // non-primitives always start with 'L' and end with ';'
+            if (descriptor.charAt(index) == 'L') {
+                index = descriptor.indexOf(';');
+            }
+
+            tokens.add(descriptor.substring(0, index + 1));
+            descriptor = descriptor.substring(index + 1);
+        }
+
+        return (String[]) tokens.toArray(new String[tokens.size()]);
+    }
+
+    /**
+     *  Return the component type name for the given array type, or null
+     *  if the given string does not represent an array type name.  The name
+     *  given should be in proper {@link Class#forName} form.
+     */
+    public String getComponentName(String name) {
+        if ((name == null) || !name.startsWith("[")) {
+            return null;
+        }
+
+        name = name.substring(1);
+
+        if (!name.startsWith("[") && name.endsWith(";")) {
+            name = name.substring(1, name.length() - 1);
+        }
+
+        // will convert primitive type codes to names
+        return getExternalForm(name, false);
+    }
+
+    /**
+     *  Clear the cache.
+     */
+    public void clear() {
+        _internal.clear();
+        _internalDescriptor.clear();
+        _external.clear();
+        _externalHuman.clear();
+    }
+}

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

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/NewArrayInstruction.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/NewArrayInstruction.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/NewArrayInstruction.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/NewArrayInstruction.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,173 @@
+/*
+ * 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 java.io.*;
+
+import java.util.*;
+
+
+/**
+ *  <p>The <code>newarray</code> instruction, which is used to create new
+ *  arrays of primitive types.</p>
+ *
+ *  @author Abe White
+ */
+public class NewArrayInstruction extends TypedInstruction {
+    private static final Class[][] _mappings = new Class[][] {
+            { void.class, int.class },
+            { Object.class, int.class },
+        };
+    private int _code = -1;
+
+    NewArrayInstruction(Code owner) {
+        super(owner, Constants.NEWARRAY);
+    }
+
+    int getLength() {
+        return super.getLength() + 1;
+    }
+
+    public String getTypeName() {
+        switch (getTypeCode()) {
+        case Constants.ARRAY_BOOLEAN:
+            return boolean.class.getName();
+
+        case Constants.ARRAY_CHAR:
+            return char.class.getName();
+
+        case Constants.ARRAY_FLOAT:
+            return float.class.getName();
+
+        case Constants.ARRAY_DOUBLE:
+            return double.class.getName();
+
+        case Constants.ARRAY_BYTE:
+            return byte.class.getName();
+
+        case Constants.ARRAY_SHORT:
+            return short.class.getName();
+
+        case Constants.ARRAY_INT:
+            return int.class.getName();
+
+        case Constants.ARRAY_LONG:
+            return long.class.getName();
+
+        default:
+            return null;
+        }
+    }
+
+    public TypedInstruction setType(String type) {
+        type = mapType(type, _mappings, true);
+
+        if (type == null) {
+            return setTypeCode(-1);
+        }
+
+        switch (type.charAt(0)) {
+        case 'b':
+
+            if (boolean.class.getName().equals(type)) {
+                return setTypeCode(Constants.ARRAY_BOOLEAN);
+            }
+
+            return setTypeCode(Constants.ARRAY_BYTE);
+
+        case 'c':
+            return setTypeCode(Constants.ARRAY_CHAR);
+
+        case 'f':
+            return setTypeCode(Constants.ARRAY_FLOAT);
+
+        case 'd':
+            return setTypeCode(Constants.ARRAY_DOUBLE);
+
+        case 's':
+            return setTypeCode(Constants.ARRAY_SHORT);
+
+        case 'i':
+            return setTypeCode(Constants.ARRAY_INT);
+
+        case 'l':
+            return setTypeCode(Constants.ARRAY_LONG);
+
+        default:
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     *  Return the array code used in the lowlevel bytecode, or -1 if unset.
+     */
+    public int getTypeCode() {
+        return _code;
+    }
+
+    /**
+     *  Set the array code used in the lowlevel bytecode.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public NewArrayInstruction setTypeCode(int code) {
+        _code = code;
+
+        return this;
+    }
+
+    /**
+     *  NewArray instructions are equal if the array type is the same,
+     *  of if the array type of either is unset.
+     */
+    public boolean equalsInstruction(Instruction other) {
+        if (this == other) {
+            return true;
+        }
+
+        if (!(other instanceof NewArrayInstruction)) {
+            return false;
+        }
+
+        NewArrayInstruction ins = (NewArrayInstruction) other;
+        int code = getTypeCode();
+        int otherCode = ins.getTypeCode();
+
+        return (code == -1) || (otherCode == -1) || (code == otherCode);
+    }
+
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterNewArrayInstruction(this);
+        visit.exitNewArrayInstruction(this);
+    }
+
+    void read(Instruction orig) {
+        super.read(orig);
+        setTypeCode(((NewArrayInstruction) orig).getTypeCode());
+    }
+
+    void read(DataInput in) throws IOException {
+        super.read(in);
+        setTypeCode(in.readUnsignedByte());
+    }
+
+    void write(DataOutput out) throws IOException {
+        super.write(out);
+        out.writeByte(getTypeCode());
+    }
+}

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

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ObjectState.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ObjectState.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ObjectState.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ObjectState.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,143 @@
+/*
+ * 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>State implementing the behavior of an object type.</p>
+ *
+ *  @author Abe White
+ */
+class ObjectState extends State {
+    private final ConstantPool _pool = new ConstantPool();
+    private final NameCache _names;
+    private int _index = 0;
+    private int _superclassIndex = 0;
+    private int _magic = Constants.VALID_MAGIC;
+    private int _major = Constants.MAJOR_VERSION;
+    private int _minor = Constants.MINOR_VERSION;
+    private int _access = Constants.ACCESS_PUBLIC | Constants.ACCESS_SUPER;
+    private final Collection _interfaces = new HashSet();
+    private final Collection _fields = new LinkedList();
+    private final Collection _methods = new LinkedList();
+    private final Collection _attributes = new LinkedList();
+
+    public ObjectState(NameCache names) {
+        _names = names;
+    }
+
+    public int getMagic() {
+        return _magic;
+    }
+
+    public void setMagic(int magic) {
+        _magic = magic;
+    }
+
+    public int getMajorVersion() {
+        return _major;
+    }
+
+    public void setMajorVersion(int major) {
+        _major = major;
+    }
+
+    public int getMinorVersion() {
+        return _minor;
+    }
+
+    public void setMinorVersion(int minor) {
+        _minor = minor;
+    }
+
+    public int getAccessFlags() {
+        return _access;
+    }
+
+    public void setAccessFlags(int access) {
+        _access = access;
+    }
+
+    public int getIndex() {
+        return _index;
+    }
+
+    public void setIndex(int index) {
+        _index = index;
+    }
+
+    public int getSuperclassIndex() {
+        return _superclassIndex;
+    }
+
+    public void setSuperclassIndex(int index) {
+        _superclassIndex = index;
+    }
+
+    public Collection getInterfacesHolder() {
+        return _interfaces;
+    }
+
+    public Collection getFieldsHolder() {
+        return _fields;
+    }
+
+    public Collection getMethodsHolder() {
+        return _methods;
+    }
+
+    public Collection getAttributesHolder() {
+        return _attributes;
+    }
+
+    public ConstantPool getPool() {
+        return _pool;
+    }
+
+    public String getName() {
+        if (_index == 0) {
+            return null;
+        }
+
+        return _names.getExternalForm(((ClassEntry) _pool.getEntry(_index)).getNameEntry()
+                                       .getValue(), false);
+    }
+
+    public String getSuperclassName() {
+        if (_superclassIndex == 0) {
+            return null;
+        }
+
+        return _names.getExternalForm(((ClassEntry) _pool.getEntry(
+                _superclassIndex)).getNameEntry().getValue(), false);
+    }
+
+    public String getComponentName() {
+        return null;
+    }
+
+    public boolean isPrimitive() {
+        return false;
+    }
+
+    public boolean isArray() {
+        return false;
+    }
+}

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

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/PrimitiveState.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/PrimitiveState.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/PrimitiveState.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/PrimitiveState.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,96 @@
+/*
+ * 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>State implementing the behavior of a primitive class.</p>
+ *
+ *  @author Abe White
+ */
+class PrimitiveState extends State {
+    private final Class _type;
+    private final NameCache _names;
+
+    public PrimitiveState(Class type, NameCache names) {
+        _type = type;
+        _names = names;
+    }
+
+    public int getMagic() {
+        return Constants.VALID_MAGIC;
+    }
+
+    public int getMajorVersion() {
+        return Constants.MAJOR_VERSION;
+    }
+
+    public int getMinorVersion() {
+        return Constants.MINOR_VERSION;
+    }
+
+    public int getAccessFlags() {
+        return Constants.ACCESS_PUBLIC | Constants.ACCESS_FINAL;
+    }
+
+    public int getIndex() {
+        return 0;
+    }
+
+    public int getSuperclassIndex() {
+        return 0;
+    }
+
+    public Collection getInterfacesHolder() {
+        return Collections.EMPTY_LIST;
+    }
+
+    public Collection getFieldsHolder() {
+        return Collections.EMPTY_LIST;
+    }
+
+    public Collection getMethodsHolder() {
+        return Collections.EMPTY_LIST;
+    }
+
+    public Collection getAttributesHolder() {
+        return Collections.EMPTY_LIST;
+    }
+
+    public String getName() {
+        return _names.getExternalForm(_type.getName(), false);
+    }
+
+    public String getSuperclassName() {
+        return null;
+    }
+
+    public String getComponentName() {
+        return null;
+    }
+
+    public boolean isPrimitive() {
+        return true;
+    }
+
+    public boolean isArray() {
+        return false;
+    }
+}

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