001    /*
002     * Copyright 2010-2015 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.kotlin.codegen.optimization.boxing;
018    
019    import com.intellij.openapi.util.Pair;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    import org.jetbrains.kotlin.codegen.AsmUtil;
023    import org.jetbrains.org.objectweb.asm.Type;
024    import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
025    import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue;
026    
027    import java.util.ArrayList;
028    import java.util.HashSet;
029    import java.util.List;
030    import java.util.Set;
031    
032    public class BoxedBasicValue extends BasicValue {
033        private final Set<AbstractInsnNode> associatedInsns = new HashSet<AbstractInsnNode>();
034        private final Set<Pair<AbstractInsnNode, Type>> unboxingWithCastInsns = new HashSet<Pair<AbstractInsnNode, Type>>();
035        private final AbstractInsnNode boxingInsn;
036        private final Set<Integer> associatedVariables = new HashSet<Integer>();
037        private final Set<BoxedBasicValue> mergedWith = new HashSet<BoxedBasicValue>();
038        private final Type primitiveType;
039        private final ProgressionIteratorBasicValue progressionIterator;
040        private boolean isSafeToRemove = true;
041    
042        public BoxedBasicValue(
043                @NotNull Type boxedType,
044                @NotNull AbstractInsnNode boxingInsn,
045                @Nullable ProgressionIteratorBasicValue progressionIterator
046        ) {
047            super(boxedType);
048            this.primitiveType = AsmUtil.unboxType(boxedType);
049            this.boxingInsn = boxingInsn;
050            this.progressionIterator = progressionIterator;
051        }
052    
053        @Override
054        public boolean equals(Object o) {
055            return this == o;
056        }
057    
058        public boolean typeEquals(Object o) {
059            if (o == null || getClass() != o.getClass()) return false;
060    
061            BoxedBasicValue that = (BoxedBasicValue) o;
062    
063            return getType().equals(that.getType());
064        }
065    
066        @Override
067        public int hashCode() {
068            return System.identityHashCode(this);
069        }
070    
071        public List<AbstractInsnNode> getAssociatedInsns() {
072            return new ArrayList<AbstractInsnNode>(associatedInsns);
073        }
074    
075        public void addInsn(AbstractInsnNode insnNode) {
076            associatedInsns.add(insnNode);
077        }
078    
079        public void addVariableIndex(int index) {
080            associatedVariables.add(index);
081        }
082    
083        public List<Integer> getVariablesIndexes() {
084            return new ArrayList<Integer>(associatedVariables);
085        }
086    
087        public Type getPrimitiveType() {
088            return primitiveType;
089        }
090    
091        public void addMergedWith(@NotNull BoxedBasicValue value) {
092            mergedWith.add(value);
093        }
094    
095        @NotNull
096        public Iterable<BoxedBasicValue> getMergedWith() {
097            return mergedWith;
098        }
099    
100        public void markAsUnsafeToRemove() {
101            isSafeToRemove = false;
102        }
103    
104        public boolean isSafeToRemove() {
105            return isSafeToRemove;
106        }
107    
108        public boolean isDoubleSize() {
109            return getPrimitiveType().getSize() == 2;
110        }
111    
112        @NotNull
113        public AbstractInsnNode getBoxingInsn() {
114            return boxingInsn;
115        }
116    
117        public boolean isFromProgressionIterator() {
118            return progressionIterator != null;
119        }
120    
121        @Nullable
122        public ProgressionIteratorBasicValue getProgressionIterator() {
123            return progressionIterator;
124        }
125    
126        public void addUnboxingWithCastTo(@NotNull AbstractInsnNode insn, @NotNull Type type) {
127            unboxingWithCastInsns.add(Pair.create(insn, type));
128        }
129    
130        @NotNull
131        public Set<Pair<AbstractInsnNode, Type>> getUnboxingWithCastInsns() {
132            return unboxingWithCastInsns;
133        }
134    }