Package erjang.beam.analysis

Source Code of erjang.beam.analysis.TypeMap$XRegMarker

/**
* This file is part of Erjang - A JVM-based Erlang VM
*
* Copyright (c) 2009 by Trifork
*
* 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 erjang.beam.analysis;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import org.objectweb.asm.Type;

import com.trifork.clj_ds.IPersistentMap;
import com.trifork.clj_ds.PersistentHashMap;

import erjang.EObject;
import erjang.ETuple;

@SuppressWarnings("rawtypes")
class TypeMap {
  private static Logger log = Logger.getLogger("erjang.beam");
  private static Type TYPE_EOBJECT = Type.getType(EObject.class);
  private static Type TYPE_ETUPLE = Type.getType(ETuple.class);
  private static String ETUPLE_NAME = TYPE_ETUPLE.getInternalName();

  private static Type[] NO_TYPES = new Type[0];
  private static IPersistentMap NO_XTYPES = PersistentHashMap.EMPTY;
 
  private final IPersistentMap xregs;
  private final Type[] yregs, fregs;
  final int stacksize; // number of y-regs

  final BasicBlock bb;
  final ExceptionHandler exh;

  public TypeMap(BasicBlock bb) {
    xregs = NO_XTYPES;
    yregs = NO_TYPES;
    fregs = NO_TYPES;
    stacksize = 0;
    this.bb = bb;
    exh = null;
  }

  public String toString() {
    StringBuilder sb = new StringBuilder("[");

    boolean first = true;

    IPersistentMap xregs = this.xregs;

    first = printRegs(sb, first, (Map<Integer,Type>)xregs, 'x');
    first = printRegs(sb, first, fregs, 'f');
    first = printYRegs(sb, first);

    sb.append(", s=" + stacksize);

    sb.append(']');
    return sb.toString();

  }

  private boolean printRegs(StringBuilder sb, boolean first, Type[] regs,
      char reg) {
    for (int i = 0; i < regs.length; i++) {
      if (regs[i] != null) {
        if (first == false) {
          sb.append(", ");
        } else {
          first = false;
        }
        sb.append(reg).append(i).append(':');
        sb.append(shortName(regs[i]));
      }
    }
    return first;
  }

  private boolean printRegs(StringBuilder sb, boolean first, Map<Integer,Type> regs,
      char reg) {
    for (int i : regs.keySet()) {
      if (regs.get(i) != null) {
        if (first == false) {
          sb.append(", ");
        } else {
          first = false;
        }
        sb.append(reg).append(i).append(':');
        sb.append(shortName(regs.get(i)));
      }
    }
    return first;
  }

  private boolean printYRegs(StringBuilder sb, boolean first) {
    for (int i = 0; i < stacksize; i++) {
      if (i >= yregs.length)
        continue;
      if (yregs[i] != null) {
        if (first == false) {
          sb.append(", ");
        } else {
          first = false;
        }
        sb.append('y').append(get_ypos(i)).append(':');
        sb.append(shortName(yregs[i]));
      }
    }
    return first;
  }

  private String shortName(Type type) {
    if (type.getSort() != Type.OBJECT) {
      return type.getDescriptor();
    }

    String in = type.getInternalName();
    if (type.getSort() == Type.OBJECT) {
      int idx = in.lastIndexOf('/');
      String sh = in.substring(idx + 1);

      if (sh.length() > 6 && sh.startsWith("ETuple")) {
        return "T" + sh.substring(6);
      } else {
        return sh.substring(1, 3);
      }
    } else {
      return in;
    }
  }

  private TypeMap(IPersistentMap xregs, Type[] yregs, Type[] fregs, int stacksize,
      BasicBlock bb, ExceptionHandler exh) {
    super();
    this.xregs = xregs;
    this.yregs = yregs;
    this.fregs = fregs;
    this.stacksize = stacksize;
    this.bb = bb;
    this.exh = exh;
   
    if (stacksize > 1023) {
      log.warning("stacksize > 1023!");
    }
   
  }

  public boolean equals(Object obj) {
    if (obj instanceof TypeMap) {
      TypeMap other = (TypeMap) obj;

      return eq((Map)xregs, (Map)other.xregs) && eqy(this, other)
          && eq(fregs, other.fregs)
          && eq(exh, other.exh);
    }

    return false;
  }

  private static boolean eqy(TypeMap me, TypeMap other) {
    if (me.stacksize != other.stacksize)
      return false;
    return eqy_prefix(me, other, Math.min(me.stacksize, other.stacksize));
  }

  private static boolean eqy_prefix(TypeMap me, TypeMap other, int count) {
    for (int i = 0; i < count; i++) {
      if (!eq(me.gety(i), other.gety(i)))
        return false;
    }
    return true;
  }

  private boolean eq(Map m1, Map m2) { return m1.equals(m2); }
 
  private boolean eq(Type[] r1, Type[] r2) {
    int max = Math.max(r1.length, r2.length);
    for (int i = 0; i < max; i++) {
      if (!eq(get(r1, i), get(r2, i)))
        return false;
    }
    return true;
  }

  private static boolean eq(Type t1, Type t2) {
    if (t1 == t2)
      return true;
    if (t1 == null || t2 == null)
      return false;
    return t1.equals(t2);
  }

  private static boolean eq(ExceptionHandler e1, ExceptionHandler e2) {
    return (e1==e2) || (e1 != null && e1.equals(e2));
  }

  public TypeMap mergeFrom(TypeMap other) {
    IPersistentMap new_x = eq((Map)xregs, (Map)other.xregs) ? xregs : merge_regs(xregs,
        other.xregs);
    Type[] new_f = eq(fregs, other.fregs) ? fregs : merge_regs(fregs,
        other.fregs);

    Type[] new_y = yregs;
    int new_stacksize = Math.min(stacksize, other.stacksize);
    if (!eqy_prefix(this, other, new_stacksize)) {
      new_y = new Type[new_stacksize];
      boolean differs_from_my_y = false;
      for (int i = 0; i < new_stacksize; i++) {
        Type t1;
        Type res = merge(t1 = this.gety(i), other.gety(i));
        new_y[new_stacksize - i - 1] = res;
        differs_from_my_y = differs_from_my_y ||
          (res!=t1 && (res==null || !res.equals(t1)));
      }
      if (!differs_from_my_y) new_y = yregs;
    }

    ExceptionHandler new_exh;
    try {
      new_exh = ExceptionHandler.merge(exh, other.exh);
    } catch (IllegalArgumentException iae) {
      new_exh = ExceptionHandler.Ambiguous.make(exh, other.exh);
    }

    if (new_x == xregs && new_y == yregs && new_f == fregs &&
        new_stacksize == stacksize && new_exh == exh)
    {
      return this;
    } else {
      return new TypeMap(new_x, new_y, new_f, new_stacksize, bb, new_exh);
    }
  }

  private Type[] merge_regs(Type[] r1, Type[] r2) {
    Type[] res = new Type[Math.max(r1.length, r2.length)];
    boolean differs_from_r1 = false;
    for (int i = 0; i < res.length; i++) {
      Type t1 = get(r1, i);
      Type t2 = get(r2, i);

      res[i] = merge(t1, t2);
      differs_from_r1 = differs_from_r1 ||
          (res[i]!=t1 && (res[i]==null || !res[i].equals(t1)));
    }
    assert(eq(r1,res) || differs_from_r1);
    return differs_from_r1 ? res : r1;
  }

  private IPersistentMap merge_regs(IPersistentMap r1, IPersistentMap r2) {
    IPersistentMap out = PersistentHashMap.EMPTY;
    for (Integer r : ((Map<Integer,Type>)r1).keySet()) {
      Type t1 = (Type) r1.valAt(r);
      Type t2 = (Type) r2.valAt(r);
     
      Type m = merge(t1,t2);
      if (m != null) {
        out = out.assoc(r, m);
      }
    }

    return out;
  }

  private Type merge(Type t1, Type t2) {
    if (t1 == null || t2 == null)
      return null;
    if (t1.equals(t2))
      return t1;

    if (t1.getSort() == Type.OBJECT && t2.getSort() == Type.OBJECT) {
      if (t1.getInternalName().startsWith(ETUPLE_NAME)
          && t2.getInternalName().startsWith(ETUPLE_NAME)) {
        return TYPE_ETUPLE;
      }
    }

    return TYPE_EOBJECT;
  }

  private Type get(Type[] regs, int i) {
    if (i < regs.length)
      return regs[i];
    else
      return null;
  }

  public TypeMap setx(int reg, Type t, XRegMarker marker) {
          marker.mark_xreg_as_used(reg);
    bb.kill_x(reg);

    if (eq(getx(reg), t))
      return this;

    IPersistentMap new_xregs = xregs.assoc(reg, t);
    return new TypeMap(new_xregs, yregs, fregs, stacksize, bb, exh);
  }

  public TypeMap setf(int reg, Type t) {
    bb.kill_fr(reg);

    if (eq(getf(reg), t))
      return this;
    Type[] new_fregs;
    if (fregs.length <= reg) {
      new_fregs = grow(fregs, reg);
    } else {
      new_fregs = copy(fregs);
    }
    new_fregs[reg] = t;
    return new TypeMap(xregs, yregs, new_fregs, stacksize, bb, exh);
  }

  private Type[] copy(Type[] regs) {
    Type[] res = new Type[regs.length];
    for (int i = 0; i < regs.length; i++) {
      res[i] = regs[i];
    }
    return res;
  }

  private static Type[] grow(Type[] regs, int reg) {
    Type[] res = new Type[reg + 6];
    for (int i = 0; i < regs.length; i++) {
      res[i] = regs[i];
    }
    return res;
  }

  public Type getx(int reg) {
    bb.use_x(reg);

    return (Type) xregs.valAt(reg, null);
  }

  public Type getf(int reg) {
    bb.use_fr(reg);

    if (reg >= fregs.length) {
      return null;
    } else {
      return fregs[reg];
    }
  }

  public TypeMap sety(int reg, Type t) {
    bb.kill_y(this, reg);

    if (eq(gety(reg), t))
      return this;

    int pos = get_ypos(reg);

    if (pos < 0 || pos >= stacksize)
      throw new IllegalArgumentException("No Y" + reg + " register here.");

    Type[] new_yregs;
    if (yregs.length <= pos) {
      new_yregs = grow(yregs, pos);
    } else {
      new_yregs = copy(yregs);
    }
    new_yregs[pos] = t;
    return new TypeMap(xregs, new_yregs, fregs, stacksize, bb, exh);
  }

  public Type gety(int reg) {
    bb.use_y(this, reg);

    int pos = get_ypos(reg);
    if (pos < 0 || pos >= stacksize)
      throw new IllegalArgumentException("no Y" + reg + " register");
    if (pos >= yregs.length)
      return null;
    return yregs[pos];
  }

  public int get_ypos(int reg) {
    if (reg < 0 || reg >= stacksize)
      throw new IllegalArgumentException("No Y" + reg + " register here.");
    return stacksize - reg - 1;
  }

  public TypeMap trim_y(int howmuch) {
    return new TypeMap(xregs, yregs, fregs, stacksize - howmuch, bb, exh);
  }

  public TypeMap alloc_y(int howmuch) {
    return new TypeMap(xregs, yregs, fregs, stacksize + howmuch, bb, exh);
  }

  public TypeMap clearLive(BasicBlock bb) {
    return new TypeMap(xregs, yregs, fregs, stacksize, bb, exh);
  }

  public TypeMap pushExceptionHandler(int handlerLabel) {
    ExceptionHandler new_exh = ExceptionHandler.push(exh,handlerLabel);
    return new TypeMap(xregs, yregs, fregs, stacksize, bb, new_exh);
  }

  public TypeMap popExceptionHandler() {
    ExceptionHandler new_exh = (exh instanceof ExceptionHandler.Ambiguous)? null : ExceptionHandler.pop(exh); // Temporary fix - to avoid throws
    return new TypeMap(xregs, yregs, fregs, stacksize, bb, new_exh);
  }

  public void add_succ(BasicBlock succ) {
    bb.succ(succ);
  }

  public void touchx(int from, int to) {
    for (int i = from; i < to; i++) {
      bb.use_x(i);
    }
  }

  public Set<Integer> allXregs() {
    return ((Map)xregs).keySet();
  }

  public int max_freg() {
    int max = 0;
    for (int i = 0; i < fregs.length; i++) {
      if (fregs[i] != null)
        max = i;
    }
    return max + 1;
  }

    interface XRegMarker {
  void mark_xreg_as_used(int reg);
    }
}
TOP

Related Classes of erjang.beam.analysis.TypeMap$XRegMarker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.