rt/vm/src/main/java/org/apidesign/vm4brwsr/StackMapper.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 15 Feb 2014 14:36:43 +0100
branchReducedStack
changeset 1453 e046cfcb8f00
parent 810 9eb750594b15
child 1454 ca83b2adebb5
permissions -rw-r--r--
Centralizing the stack pushes into single assign method
     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 java.io.IOException;
    21 import org.apidesign.vm4brwsr.ByteCodeParser.TypeArray;
    22 
    23 final class StackMapper {
    24     private final TypeArray stackTypeIndexPairs;
    25     private int[] typeCounters;
    26     private int[] typeMaxCounters;
    27 
    28     public StackMapper() {
    29         stackTypeIndexPairs = new TypeArray();
    30         typeCounters = new int[VarType.LAST + 1];
    31         typeMaxCounters = new int[VarType.LAST + 1];
    32     }
    33 
    34     public void clear() {
    35         for (int type = 0; type <= VarType.LAST; ++type) {
    36             typeCounters[type] = 0;
    37         }
    38         stackTypeIndexPairs.clear();
    39     }
    40 
    41     public void syncWithFrameStack(final TypeArray frameStack) {
    42         clear();
    43 
    44         final int size = frameStack.getSize();
    45         for (int i = 0; i < size; ++i) {
    46             pushTypeImpl(VarType.fromStackMapType(frameStack.get(i)));
    47         }
    48     }
    49 
    50     public Variable pushI() {
    51         return pushT(VarType.INTEGER);
    52     }
    53 
    54     public Variable pushL() {
    55         return pushT(VarType.LONG);
    56     }
    57 
    58     public Variable pushF() {
    59         return pushT(VarType.FLOAT);
    60     }
    61 
    62     public Variable pushD() {
    63         return pushT(VarType.DOUBLE);
    64     }
    65 
    66     public Variable pushA() {
    67         return pushT(VarType.REFERENCE);
    68     }
    69 
    70     public Variable pushT(final int type) {
    71         return getVariable(pushTypeImpl(type));
    72     }
    73 
    74     void assign(Appendable out, int varType, CharSequence s) throws IOException {
    75         ByteCodeToJavaScript.emit(out, "var @1 = @2;", pushT(varType), s);
    76     }
    77     
    78     public Variable popI() {
    79         return popT(VarType.INTEGER);
    80     }
    81 
    82     public Variable popL() {
    83         return popT(VarType.LONG);
    84     }
    85 
    86     public Variable popF() {
    87         return popT(VarType.FLOAT);
    88     }
    89 
    90     public Variable popD() {
    91         return popT(VarType.DOUBLE);
    92     }
    93 
    94     public Variable popA() {
    95         return popT(VarType.REFERENCE);
    96     }
    97 
    98     public Variable popT(final int type) {
    99         final Variable variable = getT(0, type);
   100         popImpl(1);
   101         return variable;
   102     }
   103 
   104     public Variable pop() {
   105         final Variable variable = get(0);
   106         popImpl(1);
   107         return variable;
   108     }
   109 
   110     public void pop(final int count) {
   111         final int stackSize = stackTypeIndexPairs.getSize();
   112         if (count > stackSize) {
   113             throw new IllegalStateException("Stack underflow");
   114         }
   115         popImpl(count);
   116     }
   117 
   118     public Variable getI(final int indexFromTop) {
   119         return getT(indexFromTop, VarType.INTEGER);
   120     }
   121 
   122     public Variable getL(final int indexFromTop) {
   123         return getT(indexFromTop, VarType.LONG);
   124     }
   125 
   126     public Variable getF(final int indexFromTop) {
   127         return getT(indexFromTop, VarType.FLOAT);
   128     }
   129 
   130     public Variable getD(final int indexFromTop) {
   131         return getT(indexFromTop, VarType.DOUBLE);
   132     }
   133 
   134     public Variable getA(final int indexFromTop) {
   135         return getT(indexFromTop, VarType.REFERENCE);
   136     }
   137 
   138     public Variable getT(final int indexFromTop, final int type) {
   139         final int stackSize = stackTypeIndexPairs.getSize();
   140         if (indexFromTop >= stackSize) {
   141             throw new IllegalStateException("Stack underflow");
   142         }
   143         final int stackValue =
   144                 stackTypeIndexPairs.get(stackSize - indexFromTop - 1);
   145         if ((stackValue & 0xff) != type) {
   146             throw new IllegalStateException("Type mismatch");
   147         }
   148 
   149         return getVariable(stackValue);
   150     }
   151 
   152     public Variable get(final int indexFromTop) {
   153         final int stackSize = stackTypeIndexPairs.getSize();
   154         if (indexFromTop >= stackSize) {
   155             throw new IllegalStateException("Stack underflow");
   156         }
   157         final int stackValue =
   158                 stackTypeIndexPairs.get(stackSize - indexFromTop - 1);
   159 
   160         return getVariable(stackValue);
   161     }
   162 
   163     private int pushTypeImpl(final int type) {
   164         final int count = typeCounters[type];
   165         final int value = (count << 8) | (type & 0xff);
   166         incCounter(type);
   167         stackTypeIndexPairs.add(value);
   168 
   169         return value;
   170     }
   171 
   172     private void popImpl(final int count) {
   173         final int stackSize = stackTypeIndexPairs.getSize();
   174         for (int i = stackSize - count; i < stackSize; ++i) {
   175             final int value = stackTypeIndexPairs.get(i);
   176             decCounter(value & 0xff);
   177         }
   178 
   179         stackTypeIndexPairs.setSize(stackSize - count);
   180     }
   181 
   182     private void incCounter(final int type) {
   183         final int newValue = ++typeCounters[type];
   184         if (typeMaxCounters[type] < newValue) {
   185             typeMaxCounters[type] = newValue;
   186         }
   187     }
   188 
   189     private void decCounter(final int type) {
   190         --typeCounters[type];
   191     }
   192 
   193     public Variable getVariable(final int typeAndIndex) {
   194         final int type = typeAndIndex & 0xff;
   195         final int index = typeAndIndex >> 8;
   196 
   197         return Variable.getStackVariable(type, index);
   198     }
   199 }