Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * JBoss, Home of Professional Open Source.
   *
   * Copyright 2012 Red Hat, Inc.
   *
   * 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 org.jboss.classfilewriter.code;
 
 import java.util.List;
 
In immutable stack state, which may be shared between frames

Author(s):
Stuart Douglas
 
 public class StackState {

    
The contents of the stack

This list may be shared between frames, so it must never be modified

The very first element represents the bottom of the stack, with the last element representing the top. Wide elements are stored as Wide, Top, with the StackEntryType.TOP on the top of the stack

 
     private final List<StackEntrycontents;
 
     private final ConstPool constPool;
 
     public StackState(ConstPool constPool) {
         this. = new ArrayList<StackEntry>(0);
         this. = constPool;
     }
 
     public StackState(String exceptionTypeConstPool constPool) {
         this. = new ArrayList<StackEntry>(1);
         this..add(new StackEntry(."L" + exceptionType + ";"constPool));
         this. = constPool;
     }
 
     private StackState(final List<StackEntrycontentsConstPool constPool) {
         this. = contents;
         this. = constPool;
     }

    
checks that the appropriate object type is on top of the stack
 
     public boolean isOnTop(String descriptor) {
         if (.isEmpty()) {
             return false;
         }
         StackEntry entry = StackEntry.of(descriptor);
         StackEntry top = top();
         if (entry.isWide()) {
             if (.size() == 1) {
                 return false;
             }
             return top_1().getType() == entry.getType();
         }
         if (top.getType() == . && entry.getType() == .) {
             return true;
         }
         return top.getType() == entry.getType();
     }
 
     public int size() {
         return .size();
     }

    
push a type on to the top of the stack
 
     public StackState push(String type) {
         StackEntry entry = StackEntry.of(type);
         if (entry.getType() == . || entry.getType() == .) {
             return newStack(entrynew StackEntry(.type));
         }
         return newStack(entry);
     }

    
push a type on to the top of the stack
    public StackState push(StackEntry entry) {
        if (entry.getType() == . || entry.getType() == .) {
            return newStack(entrynew StackEntry(.entry.getDescriptor()));
        }
        return newStack(entry);
    }
    public StackState aconstNull() {
        StackEntry entry = new StackEntry(.null);
        return newStack(entry);
    }

    
pop a non-wide type from the top of the stack
    public StackState pop(int no) {
        if (no == 0) {
            return this;
        }
        if (.size() < no) {
            throw new InvalidBytecodeException("cannot pop" + no + ", only " + .size() + " on stack " + toString());
        }
        StackEntry type = .get(.size() - no);
        if (type.getType() == .) {
            throw new InvalidBytecodeException("Pop" + no + " would split wide type " + toString());
        }
        return new StackState(.subList(0, .size() - no), );
    }
    public StackState dup() {
        if (.isEmpty()) {
            throw new InvalidBytecodeException("cannot dup empty stack");
        }
        StackEntry type = top();
        if (type.getType() == .) {
            throw new InvalidBytecodeException("Cannot dup wide type");
        }
        return newStack(type);
    }
    public StackState dupX1() {
        if (.size() < 2) {
            throw new InvalidBytecodeException("cannot dup_x1, stack does not have enough items");
        }
        StackEntry type = top();
        if (type.getType() == .) {
            throw new InvalidBytecodeException("Cannot dup_x1 wide type");
        }
        ArrayList<StackEntryret = new ArrayList<StackEntry>(1 + .size());
        for (int i = 0; i < .size(); ++i) {
            if (i == .size() - 2) {
                ret.add(top());
            }
            ret.add(.get(i));
        }
        return new StackState(ret);
    }
    public StackState dupX2() {
        if (.size() < 3) {
            throw new InvalidBytecodeException("cannot dup_x1, stack does not have enough items");
        }
        StackEntry type = top();
        if (type.getType() == .) {
            throw new InvalidBytecodeException("Cannot dup_x1 wide type");
        }
        ArrayList<StackEntryret = new ArrayList<StackEntry>(1 + .size());
        for (int i = 0; i < .size(); ++i) {
            if (i == .size() - 3) {
                ret.add(top());
            }
            ret.add(.get(i));
        }
        return new StackState(ret);
    }
    public StackState dup2() {
        if (.size() <2) {
            throw new InvalidBytecodeException("cannot dup2, stack size is " + .size() + " " + toString());
        }
        StackEntry t1 = top();
        StackEntry t2 = top_1();
        if (t2.getType() == .) {
            throw new InvalidBytecodeException("Cannot dup2 when second type on stack is wide: " + toString());
        }
        return newStack(t2t1);
    }
    public StackState dup2X1() {
        if (.size() < 3) {
            throw new InvalidBytecodeException("cannot dup2X1, stack size is " + .size() + " " + toString());
        }
        StackEntry t1 = top();
        StackEntry t2 = top_1();
        StackEntry t3 = top_2();
        if (t2.getType() == .) {
            throw new InvalidBytecodeException("Cannot dup2X1 when second type on stack is wide: " + toString());
        }
        if (t3.getType() == .) {
            throw new InvalidBytecodeException("Cannot dup2X2 when third type on stack is wide: " + toString());
        }
        ArrayList<StackEntryret = new ArrayList<StackEntry>(2 + .size());
        for (int i = 0; i < .size(); ++i) {
            if (i == .size() - 3) {
                ret.add(t2);
                ret.add(t1);
            }
            ret.add(.get(i));
        }
        return new StackState(ret);
    }
    public StackState dup2X2() {
        if (.size() < 4) {
            throw new InvalidBytecodeException("cannot dup2X2, stack size is " + .size() + " " + toString());
        }
        StackEntry t1 = top();
        StackEntry t2 = top_1();
        StackEntry t4 = top_3();
        if (t2.getType() == .) {
            throw new InvalidBytecodeException("Cannot dup2X2 when second type on stack is wide: " + toString());
        }
        if (t4.getType() == .) {
            throw new InvalidBytecodeException("Cannot dup2X2 when fourth type on stack is wide: " + toString());
        }
        ArrayList<StackEntryret = new ArrayList<StackEntry>(2 + .size());
        for (int i = 0; i < .size(); ++i) {
            if (i == .size() - 4) {
                ret.add(t2);
                ret.add(t1);
            }
            ret.add(.get(i));
        }
        return new StackState(ret);
    }
    private StackState newStack(StackEntry... pushValues) {
        ArrayList<StackEntryret = new ArrayList<StackEntry>(pushValues.length + .size());
        ret.addAll();
        for (StackEntry s : pushValues) {
            ret.add(s);
        }
        return new StackState(ret);
    }
    public StackEntry top() {
        return .get(.size() - 1);
    }
    public StackEntry top_1() {
        return .get(.size() - 2);
    }
    public StackEntry top_2() {
        return .get(.size() - 3);
    }
    public StackEntry top_3() {
        return .get(.size() - 4);
    }
    @Override
    public String toString() {
        return "Stack: " + .toString();
    }
    public List<StackEntrygetContents() {
        return Collections.unmodifiableList();
    }
    public StackState constructorCall(int initializedValueStackPositionStackEntry entry) {
        List<StackEntrynewContents = new ArrayList<StackEntry>(.size());
        if (entry.getType() == .) {
            for (int i = 0; i < .size() - 1 - initializedValueStackPosition; ++i) {
                StackEntry stackEntry = .get(i);
                if (stackEntry.getType() == .) {
                    newContents.add(StackEntry.of(stackEntry.getDescriptor(), ));
                } else {
                    newContents.add(stackEntry);
                }
            }
            return new StackState(newContents);
        } else if (entry.getType() == .) {
            for (int i = 0; i < .size() - 1 - initializedValueStackPosition; ++i) {
                StackEntry stackEntry = .get(i);
                if (stackEntry.getType() == .
                        && stackEntry.getNewInstructionLocation() == entry.getNewInstructionLocation()) {
                    newContents.add(StackEntry.of(stackEntry.getDescriptor(), ));
                } else {
                    newContents.add(stackEntry);
                }
            }
            return new StackState(newContents);
        } else {
            throw new InvalidBytecodeException("Object at position " + initializedValueStackPosition
                    + " is not an unitialized object. " + toString());
        }
    }
    public StackState swap() {
        int size = .size();
        List<StackEntrynewContents = new ArrayList<StackEntry>(.subList(0, size - 2));
        newContents.add(.get(size - 1));
        newContents.add(.get(size - 2));
        return new StackState(newContents);
    }
New to GrepCode? Check out our FAQ X