All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.codegen.FrameMap Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * Copyright 2010-2015 JetBrains s.r.o.
 *
 * 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.jetbrains.kotlin.codegen;

import com.google.common.collect.Lists;
import com.intellij.openapi.util.Trinity;
import gnu.trove.TObjectIntHashMap;
import gnu.trove.TObjectIntIterator;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.org.objectweb.asm.Type;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class FrameMap {
    private final TObjectIntHashMap myVarIndex = new TObjectIntHashMap<>();
    private final TObjectIntHashMap myVarSizes = new TObjectIntHashMap<>();
    private int myMaxIndex = 0;

    public int enter(DeclarationDescriptor descriptor, Type type) {
        int index = myMaxIndex;
        myVarIndex.put(descriptor, index);
        myMaxIndex += type.getSize();
        myVarSizes.put(descriptor, type.getSize());
        return index;
    }

    public int leave(DeclarationDescriptor descriptor) {
        int size = myVarSizes.get(descriptor);
        myMaxIndex -= size;
        myVarSizes.remove(descriptor);
        int oldIndex = myVarIndex.remove(descriptor);
        if (oldIndex != myMaxIndex) {
            throw new IllegalStateException("Descriptor can be left only if it is last: " + descriptor);
        }
        return oldIndex;
    }

    public int enterTemp(Type type) {
        int result = myMaxIndex;
        myMaxIndex += type.getSize();
        return result;
    }

    public void leaveTemp(Type type) {
        myMaxIndex -= type.getSize();
    }

    public int getIndex(DeclarationDescriptor descriptor) {
        return myVarIndex.contains(descriptor) ? myVarIndex.get(descriptor) : -1;
    }

    public Mark mark() {
        return new Mark(myMaxIndex);
    }

    public int getCurrentSize() {
        return myMaxIndex;
    }

    public class Mark {
        private final int myIndex;

        public Mark(int index) {
            myIndex = index;
        }

        public void dropTo() {
            List descriptorsToDrop = new ArrayList<>();
            TObjectIntIterator iterator = myVarIndex.iterator();
            while (iterator.hasNext()) {
                iterator.advance();
                if (iterator.value() >= myIndex) {
                    descriptorsToDrop.add(iterator.key());
                }
            }
            for (DeclarationDescriptor declarationDescriptor : descriptorsToDrop) {
                myVarIndex.remove(declarationDescriptor);
                myVarSizes.remove(declarationDescriptor);
            }
            myMaxIndex = myIndex;
        }
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();

        if (myVarIndex.size() != myVarSizes.size()) {
            return "inconsistent";
        }

        List> descriptors = Lists.newArrayList();

        for (Object descriptor0 : myVarIndex.keys()) {
            DeclarationDescriptor descriptor = (DeclarationDescriptor) descriptor0;
            int varIndex = myVarIndex.get(descriptor);
            int varSize = myVarSizes.get(descriptor);
            descriptors.add(Trinity.create(descriptor, varIndex, varSize));
        }

        descriptors.sort(Comparator.comparingInt(left -> left.second));

        sb.append("size=").append(myMaxIndex);

        boolean first = true;
        for (Trinity t : descriptors) {
            if (!first) {
                sb.append(", ");
            }
            first = false;
            sb.append(t.first).append(",i=").append(t.second).append(",s=").append(t.third);
        }

        return sb.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy