001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.nabla.algorithmic.forward.trimming;
018    
019    import org.objectweb.asm.Opcodes;
020    import org.objectweb.asm.tree.AbstractInsnNode;
021    import org.objectweb.asm.tree.InsnList;
022    import org.objectweb.asm.tree.VarInsnNode;
023    
024    /** Trimmer replacing (DUP2_X2, POP2, DSTORE i, DSTORE j) with (DSTORE j, DSTORE i).
025     */
026    public class SwappedDstoreTrimmer extends BytecodeTrimmer {
027    
028        // CHECKSTYLE: stop HideUtilityClassConstructor
029        /** Holder for the singleton instance.*/
030        private static class LazyHolder  {
031            /** The singleton instance. */
032            private static final BytecodeTrimmer INSTANCE = new SwappedDstoreTrimmer();
033        }
034        // CHECKSTYLE: resume HideUtilityClassConstructor
035    
036        /** Hidden constructor.
037         */
038        private SwappedDstoreTrimmer() {
039            super(4);
040        }
041    
042        /** Get the singleton instance.
043         * <p>We use here the Initialization on Demand Holder idiom.</p>
044         * @return the singleton instance
045         */
046        public static BytecodeTrimmer getInstance() {
047            return LazyHolder.INSTANCE;
048        }
049    
050        /** {@inheritDoc} */
051        @Override
052        protected boolean trimWindow(final InsnList instructions,
053                                     final AbstractInsnNode[] window) {
054    
055            if ((window[0].getOpcode() == Opcodes.DUP2_X2) &&
056                (window[1].getOpcode() == Opcodes.POP2) &&
057                (window[2].getOpcode() == Opcodes.DSTORE) &&
058                (window[3].getOpcode() == Opcodes.DSTORE)) {
059    
060                // reverse the DSTORE orders
061                final int tmp = ((VarInsnNode) window[2]).var;
062                ((VarInsnNode) window[2]).var = ((VarInsnNode) window[3]).var;
063                ((VarInsnNode) window[3]).var = tmp;
064    
065                // remove the operand stack swap instructions
066                instructions.remove(window[0]);
067                instructions.remove(window[1]);
068    
069                // update lookahead instructions
070                window[0] = window[2];
071                window[1] = window[3];
072                window[2] = window[1].getNext();
073                window[3] = (window[2] == null) ? null : window[2].getNext();
074                return true;
075    
076            }
077    
078            // nothing have been done
079            return false;
080    
081        }
082    
083    }