vm/src/main/java/org/apidesign/vm4brwsr/StackToVariableMapper.java
author Lubomir Nerad <lubomir.nerad@oracle.com>
Fri, 07 Dec 2012 15:02:35 +0100
branchregisters
changeset 281 f2352e0b713e
parent 221 3ee23267706c
permissions -rw-r--r--
Type specific stack variables
     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 import static org.apidesign.javap.RuntimeConstants.ITEM_Bogus;
    23 import static org.apidesign.javap.RuntimeConstants.ITEM_Integer;
    24 import static org.apidesign.javap.RuntimeConstants.ITEM_Float;
    25 import static org.apidesign.javap.RuntimeConstants.ITEM_Double;
    26 import static org.apidesign.javap.RuntimeConstants.ITEM_Long;
    27 import static org.apidesign.javap.RuntimeConstants.ITEM_Null;
    28 import static org.apidesign.javap.RuntimeConstants.ITEM_InitObject;
    29 import static org.apidesign.javap.RuntimeConstants.ITEM_Object;
    30 import static org.apidesign.javap.RuntimeConstants.ITEM_NewObject;
    31 
    32 public final class StackToVariableMapper {
    33     private final TypeArray stackTypeIndexPairs;
    34     private int[] typeCounters;
    35     private int[] typeMaxCounters;
    36 
    37     public StackToVariableMapper() {
    38         stackTypeIndexPairs = new TypeArray();
    39         typeCounters = new int[Variable.LAST_TYPE + 1];
    40         typeMaxCounters = new int[Variable.LAST_TYPE + 1];
    41     }
    42 
    43     public void clear() {
    44         for (int type = 0; type <= Variable.LAST_TYPE; ++type) {
    45             typeCounters[type] = 0;
    46         }
    47         stackTypeIndexPairs.clear();
    48     }
    49 
    50     public void syncWithFrameStack(final TypeArray frameStack) {
    51         clear();
    52 
    53         final int size = frameStack.getSize();
    54         for (int i = 0; i < size; ++i) {
    55             final int frameStackValue = frameStack.get(i);
    56             switch (frameStackValue & 0xff) {
    57                 case ITEM_Integer:
    58                     pushTypeImpl(Variable.TYPE_INT);
    59                     break;
    60                 case ITEM_Float:
    61                     pushTypeImpl(Variable.TYPE_FLOAT);
    62                     break;
    63                 case ITEM_Double:
    64                     pushTypeImpl(Variable.TYPE_DOUBLE);
    65                     break;
    66                 case ITEM_Long:
    67                     pushTypeImpl(Variable.TYPE_LONG);
    68                     break;
    69                 case ITEM_Object:
    70                     pushTypeImpl(Variable.TYPE_REF);
    71                     break;
    72 
    73                 case ITEM_Bogus:
    74                 case ITEM_Null:
    75                 case ITEM_InitObject:
    76                 case ITEM_NewObject:
    77                     /* unclear how to handle for now */
    78                 default:
    79                     throw new IllegalStateException(
    80                                   "Unhandled frame stack type");
    81             }
    82         }
    83     }
    84 
    85     public Variable pushI() {
    86         return pushT(Variable.TYPE_INT);
    87     }
    88 
    89     public Variable pushL() {
    90         return pushT(Variable.TYPE_LONG);
    91     }
    92 
    93     public Variable pushF() {
    94         return pushT(Variable.TYPE_FLOAT);
    95     }
    96 
    97     public Variable pushD() {
    98         return pushT(Variable.TYPE_DOUBLE);
    99     }
   100 
   101     public Variable pushA() {
   102         return pushT(Variable.TYPE_REF);
   103     }
   104 
   105     public Variable pushT(final int type) {
   106         return getVariable(pushTypeImpl(type));
   107     }
   108 
   109     public Variable popI() {
   110         return popT(Variable.TYPE_INT);
   111     }
   112 
   113     public Variable popL() {
   114         return popT(Variable.TYPE_LONG);
   115     }
   116 
   117     public Variable popF() {
   118         return popT(Variable.TYPE_FLOAT);
   119     }
   120 
   121     public Variable popD() {
   122         return popT(Variable.TYPE_DOUBLE);
   123     }
   124 
   125     public Variable popA() {
   126         return popT(Variable.TYPE_REF);
   127     }
   128 
   129     public Variable popT(final int type) {
   130         final Variable variable = getT(0, type);
   131         popImpl(1);
   132         return variable;
   133     }
   134 
   135     public Variable pop() {
   136         final Variable variable = get(0);
   137         popImpl(1);
   138         return variable;
   139     }
   140 
   141     public void pop(final int count) {
   142         final int stackSize = stackTypeIndexPairs.getSize();
   143         if (count > stackSize) {
   144             throw new IllegalStateException("Stack underflow");
   145         }
   146         popImpl(count);
   147     }
   148 
   149     public Variable getI(final int indexFromTop) {
   150         return getT(indexFromTop, Variable.TYPE_INT);
   151     }
   152 
   153     public Variable getL(final int indexFromTop) {
   154         return getT(indexFromTop, Variable.TYPE_LONG);
   155     }
   156 
   157     public Variable getF(final int indexFromTop) {
   158         return getT(indexFromTop, Variable.TYPE_FLOAT);
   159     }
   160 
   161     public Variable getD(final int indexFromTop) {
   162         return getT(indexFromTop, Variable.TYPE_DOUBLE);
   163     }
   164 
   165     public Variable getA(final int indexFromTop) {
   166         return getT(indexFromTop, Variable.TYPE_REF);
   167     }
   168 
   169     public Variable getT(final int indexFromTop, final int type) {
   170         final int stackSize = stackTypeIndexPairs.getSize();
   171         if (indexFromTop >= stackSize) {
   172             throw new IllegalStateException("Stack underflow");
   173         }
   174         final int stackValue =
   175                 stackTypeIndexPairs.get(stackSize - indexFromTop - 1);
   176         if ((stackValue & 0xff) != type) {
   177             throw new IllegalStateException("Type mismatch");
   178         }
   179 
   180         return getVariable(stackValue);
   181     }
   182 
   183     public Variable get(final int indexFromTop) {
   184         final int stackSize = stackTypeIndexPairs.getSize();
   185         if (indexFromTop >= stackSize) {
   186             throw new IllegalStateException("Stack underflow");
   187         }
   188         final int stackValue =
   189                 stackTypeIndexPairs.get(stackSize - indexFromTop - 1);
   190 
   191         return getVariable(stackValue);
   192     }
   193 
   194     private int pushTypeImpl(final int type) {
   195         final int count = typeCounters[type];
   196         final int value = (count << 8) | (type & 0xff);
   197         incCounter(type);
   198         stackTypeIndexPairs.add(value);
   199 
   200         return value;
   201     }
   202 
   203     private void popImpl(final int count) {
   204         final int stackSize = stackTypeIndexPairs.getSize();
   205         for (int i = stackSize - count; i < stackSize; ++i) {
   206             final int value = stackTypeIndexPairs.get(i);
   207             decCounter(value & 0xff);
   208         }
   209 
   210         stackTypeIndexPairs.setSize(stackSize - count);
   211     }
   212 
   213     private void incCounter(final int type) {
   214         final int newValue = ++typeCounters[type];
   215         if (typeMaxCounters[type] < newValue) {
   216             typeMaxCounters[type] = newValue;
   217         }
   218     }
   219 
   220     private void decCounter(final int type) {
   221         --typeCounters[type];
   222     }
   223 
   224     public Variable getVariable(final int typeAndIndex) {
   225         final int type = typeAndIndex & 0xff;
   226         final int index = typeAndIndex >> 8;
   227 
   228         return Variable.getStackVariable(type, index);
   229     }
   230 }