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

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

There is a newer version: 2.1.0-RC
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 org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.org.objectweb.asm.Type
import java.util.*

open class FrameMap : FrameMapBase()

open class FrameMapBase {
    private val myVarIndex = TObjectIntHashMap()
    private val myVarSizes = TObjectIntHashMap()
    var currentSize = 0
        private set

    open fun enter(key: T, type: Type): Int {
        val index = currentSize
        myVarIndex.put(key, index)
        currentSize += type.size
        myVarSizes.put(key, type.size)
        return index
    }

    open fun leave(key: T): Int {
        val size = myVarSizes.get(key)
        currentSize -= size
        myVarSizes.remove(key)
        val oldIndex = myVarIndex.remove(key)
        if (oldIndex != currentSize) {
            throw IllegalStateException("Descriptor can be left only if it is last: $key")
        }
        return oldIndex
    }

    fun enterTemp(type: Type): Int {
        val result = currentSize
        currentSize += type.size
        return result
    }

    fun leaveTemp(type: Type) {
        currentSize -= type.size
    }

    open fun getIndex(descriptor: T): Int {
        return if (myVarIndex.contains(descriptor)) myVarIndex.get(descriptor) else -1
    }

    fun mark(): Mark {
        return Mark(currentSize)
    }

    fun skipTo(target: Int): Mark {
        return mark().also {
            if (currentSize < target)
                currentSize = target
        }
    }

    inner class Mark(private val myIndex: Int) {

        fun dropTo() {
            val descriptorsToDrop = ArrayList()
            val iterator = myVarIndex.iterator()
            while (iterator.hasNext()) {
                iterator.advance()
                if (iterator.value() >= myIndex) {
                    descriptorsToDrop.add(iterator.key())
                }
            }
            for (declarationDescriptor in descriptorsToDrop) {
                myVarIndex.remove(declarationDescriptor)
                myVarSizes.remove(declarationDescriptor)
            }
            currentSize = myIndex
        }
    }

    override fun toString(): String {
        val sb = StringBuilder()

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

        val descriptors = Lists.newArrayList>()

        for (descriptor0 in myVarIndex.keys()) {
            @Suppress("UNCHECKED_CAST") val descriptor = descriptor0 as T
            val varIndex = myVarIndex.get(descriptor)
            val varSize = myVarSizes.get(descriptor)
            descriptors.add(Trinity.create(descriptor, varIndex, varSize))
        }

        descriptors.sortBy { left -> left.second }

        sb.append("size=").append(currentSize)

        var first = true
        for (t in 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