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