rt/vm/src/main/java/org/apidesign/vm4brwsr/StackMapper.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 26 Feb 2013 16:54:16 +0100
changeset 772 d382dacfd73f
parent 310 vm/src/main/java/org/apidesign/vm4brwsr/StackMapper.java@ec7d8bc17725
child 810 9eb750594b15
permissions -rw-r--r--
Moving modules around so the runtime is under one master pom and can be built without building other modules that are in the repository
     1 /**
     2  * Back 2 Browser Bytecode Translator
     3  * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4  *
     5  * This program is free software: you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation, version 2 of the License.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program. Look for COPYING file in the top folder.
    16  * If not, see http://opensource.org/licenses/GPL-2.0.
    17  */
    18 package org.apidesign.vm4brwsr;
    19 
    20 import org.apidesign.javap.TypeArray;
    21 
    22 final class StackMapper {
    23     private final TypeArray stackTypeIndexPairs;
    24     private int[] typeCounters;
    25     private int[] typeMaxCounters;
    26 
    27     public StackMapper() {
    28         stackTypeIndexPairs = new TypeArray();
    29         typeCounters = new int[VarType.LAST + 1];
    30         typeMaxCounters = new int[VarType.LAST + 1];
    31     }
    32 
    33     public void clear() {
    34         for (int type = 0; type <= VarType.LAST; ++type) {
    35             typeCounters[type] = 0;
    36         }
    37         stackTypeIndexPairs.clear();
    38     }
    39 
    40     public void syncWithFrameStack(final TypeArray frameStack) {
    41         clear();
    42 
    43         final int size = frameStack.getSize();
    44         for (int i = 0; i < size; ++i) {
    45             pushTypeImpl(VarType.fromStackMapType(frameStack.get(i)));
    46         }
    47     }
    48 
    49     public Variable pushI() {
    50         return pushT(VarType.INTEGER);
    51     }
    52 
    53     public Variable pushL() {
    54         return pushT(VarType.LONG);
    55     }
    56 
    57     public Variable pushF() {
    58         return pushT(VarType.FLOAT);
    59     }
    60 
    61     public Variable pushD() {
    62         return pushT(VarType.DOUBLE);
    63     }
    64 
    65     public Variable pushA() {
    66         return pushT(VarType.REFERENCE);
    67     }
    68 
    69     public Variable pushT(final int type) {
    70         return getVariable(pushTypeImpl(type));
    71     }
    72 
    73     public Variable popI() {
    74         return popT(VarType.INTEGER);
    75     }
    76 
    77     public Variable popL() {
    78         return popT(VarType.LONG);
    79     }
    80 
    81     public Variable popF() {
    82         return popT(VarType.FLOAT);
    83     }
    84 
    85     public Variable popD() {
    86         return popT(VarType.DOUBLE);
    87     }
    88 
    89     public Variable popA() {
    90         return popT(VarType.REFERENCE);
    91     }
    92 
    93     public Variable popT(final int type) {
    94         final Variable variable = getT(0, type);
    95         popImpl(1);
    96         return variable;
    97     }
    98 
    99     public Variable pop() {
   100         final Variable variable = get(0);
   101         popImpl(1);
   102         return variable;
   103     }
   104 
   105     public void pop(final int count) {
   106         final int stackSize = stackTypeIndexPairs.getSize();
   107         if (count > stackSize) {
   108             throw new IllegalStateException("Stack underflow");
   109         }
   110         popImpl(count);
   111     }
   112 
   113     public Variable getI(final int indexFromTop) {
   114         return getT(indexFromTop, VarType.INTEGER);
   115     }
   116 
   117     public Variable getL(final int indexFromTop) {
   118         return getT(indexFromTop, VarType.LONG);
   119     }
   120 
   121     public Variable getF(final int indexFromTop) {
   122         return getT(indexFromTop, VarType.FLOAT);
   123     }
   124 
   125     public Variable getD(final int indexFromTop) {
   126         return getT(indexFromTop, VarType.DOUBLE);
   127     }
   128 
   129     public Variable getA(final int indexFromTop) {
   130         return getT(indexFromTop, VarType.REFERENCE);
   131     }
   132 
   133     public Variable getT(final int indexFromTop, final int type) {
   134         final int stackSize = stackTypeIndexPairs.getSize();
   135         if (indexFromTop >= stackSize) {
   136             throw new IllegalStateException("Stack underflow");
   137         }
   138         final int stackValue =
   139                 stackTypeIndexPairs.get(stackSize - indexFromTop - 1);
   140         if ((stackValue & 0xff) != type) {
   141             throw new IllegalStateException("Type mismatch");
   142         }
   143 
   144         return getVariable(stackValue);
   145     }
   146 
   147     public Variable get(final int indexFromTop) {
   148         final int stackSize = stackTypeIndexPairs.getSize();
   149         if (indexFromTop >= stackSize) {
   150             throw new IllegalStateException("Stack underflow");
   151         }
   152         final int stackValue =
   153                 stackTypeIndexPairs.get(stackSize - indexFromTop - 1);
   154 
   155         return getVariable(stackValue);
   156     }
   157 
   158     private int pushTypeImpl(final int type) {
   159         final int count = typeCounters[type];
   160         final int value = (count << 8) | (type & 0xff);
   161         incCounter(type);
   162         stackTypeIndexPairs.add(value);
   163 
   164         return value;
   165     }
   166 
   167     private void popImpl(final int count) {
   168         final int stackSize = stackTypeIndexPairs.getSize();
   169         for (int i = stackSize - count; i < stackSize; ++i) {
   170             final int value = stackTypeIndexPairs.get(i);
   171             decCounter(value & 0xff);
   172         }
   173 
   174         stackTypeIndexPairs.setSize(stackSize - count);
   175     }
   176 
   177     private void incCounter(final int type) {
   178         final int newValue = ++typeCounters[type];
   179         if (typeMaxCounters[type] < newValue) {
   180             typeMaxCounters[type] = newValue;
   181         }
   182     }
   183 
   184     private void decCounter(final int type) {
   185         --typeCounters[type];
   186     }
   187 
   188     public Variable getVariable(final int typeAndIndex) {
   189         final int type = typeAndIndex & 0xff;
   190         final int index = typeAndIndex >> 8;
   191 
   192         return Variable.getStackVariable(type, index);
   193     }
   194 }