Package xscript.runtime.clazz

Source Code of xscript.runtime.clazz.XClass

package xscript.runtime.clazz;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import xscript.runtime.XAnnotation;
import xscript.runtime.XChecks;
import xscript.runtime.XModifier;
import xscript.runtime.XRuntimeException;
import xscript.runtime.XVirtualMachine;
import xscript.runtime.genericclass.XClassPtr;
import xscript.runtime.genericclass.XGenericClass;
import xscript.runtime.method.XMethod;
import xscript.runtime.object.XObject;

public class XClass extends XPackage{

  public final int OUTERMODIFIER = XModifier.PUBLIC | XModifier.FINAL | XModifier.ABSTRACT;
  public final int INNERMODIFIER = XModifier.PUBLIC | XModifier.PRIVATE | XModifier.PROTECTED
      | XModifier.FINAL | XModifier.ABSTRACT | XModifier.STATIC;
 
  public static final int STATE_CREATED=0;
  public static final int STATE_LOADING=1;
  public static final int STATE_LOADED=2;
  public static final int STATE_POST_LOADING=3;
  public static final int STATE_RUNNABLE=4;
  public static final int STATE_ERRORED=5;
 
  protected XVirtualMachine virtualMachine;
 
  protected int modifier;
  protected XClassPtr[] superClasses;
  protected boolean[] canBeDiamondExtender;
 
  protected XField[] fields;
  protected XMethod[] methods;
 
  protected XGenericInfo[] genericInfos;
 
  protected XAnnotation[] annotations;
 
  protected int classIndex;
  protected XClassTable[] classTable;
  protected XMethod[] virtualMethods;
 
  protected int staticFieldCount;
  protected int fieldCount;
  protected int methodCount;
 
  protected int objectFieldCount;
 
  private byte[] staticData;
 
  protected int state;
 
  protected XClass(XVirtualMachine virtualMachine, String name) {
    super(name);
    state = STATE_CREATED;
    this.virtualMachine = virtualMachine;
  }
 
  @Override
  public void addChild(XPackage child) {
    throw new UnsupportedOperationException();
  }
 
  public XVirtualMachine getVirtualMachine(){
    return virtualMachine;
  }
 
  public int getModifier(){
    return modifier;
  }
 
  public XAnnotation[] getAnnotations(){
    return annotations;
  }
 
  public XClass getOuterClass(){
    return parent instanceof XClass?((XClass)parent):null;
  }
 
  public XPackage getPackage() {
    return parent instanceof XClass?((XClass)parent).getPackage():parent;
  }
 
  public XMethod getOuterMethod() {
    return parent instanceof XMethod?((XMethod)parent):null;
  }
 
  public boolean isObjectClass(){
    return superClasses.length==0;
  }
 
  public boolean isAnnotation(){
    return superClasses[0].getXClass(virtualMachine).getName().equals("xscript.lang.Annotation");
  }
 
  public boolean isEnum(){
    return superClasses[0].getXClass(virtualMachine).getName().equals("xscript.lang.Enum");
  }
 
  public int getGenericID(String genericName) {
    for(int i=0; i<genericInfos.length; i++){
      if(genericInfos[i].getName().equals(genericName)){
        return i;
      }
    }
    throw new XRuntimeException("Can't find generic class %s", genericName);
  }

  public int getGenericParams() {
    return genericInfos.length;
  }

  public XClassTable getClassTable(XClass xClass){
    if(isObjectClass()){
      return classTable[0];
    }
    int ci = xClass.classIndex;
    if(classTable.length>ci){
      XClassTable ct = classTable[ci];
      if(ct!=null && ct.getXClass()==xClass)
        return ct;
    }
    return null;
  }
 
  public boolean canCastTo(XClass xClass){
    return xClass.getClassTable(this)!=null;
  }
 
  public XGenericClass getGeneric(XGenericClass genericClass, int genericID) {
    if(genericClass.getXClass()==this){
      return genericClass.getGeneric(genericID);
    }
    XClassTable classTable = genericClass.getXClass().getClassTable(this);
    if(classTable==null)
      throw new XRuntimeException("Can't get generic %s of class %s in class %s", "", this, genericClass);
    return classTable.getGenericPtr(genericID).getXClass(virtualMachine, genericClass, null);
  }

  public int getObjectSize() {
    return objectFieldCount;
  }

  public void markObjectObjectsVisible(XObject object) {
    for(int i=0; i<fields.length; i++){
      if(!XModifier.isStatic(fields[i].getModifier())){
        if(fields[i].getTypePrimitive()==XPrimitive.OBJECT){
          long pointer = fields[i].get(object);
          XObject obj = virtualMachine.getObjectProvider().getObject(pointer);
          if(obj!=null)
            obj.markVisible();
        }
      }
    }
    for(int i=0; i<superClasses.length; i++){
      superClasses[i].getXClassNonNull(virtualMachine).markObjectObjectsVisible(object);
    }
  }
 
  @Override
  public void markVisible(){
    super.markVisible();
    for(int i=0; i<fields.length; i++){
      if(XModifier.isStatic(fields[i].getModifier())){
        if(fields[i].getTypePrimitive()==XPrimitive.OBJECT){
          long pointer = fields[i].get(null);
          XObject obj = virtualMachine.getObjectProvider().getObject(pointer);
          if(obj!=null)
            obj.markVisible();
        }
      }
    }
  }

  public byte[] getStaticData() {
    return staticData;
  }

  public XMethod getVirtualMethod(int i) {
    return virtualMethods[i];
  }

  public XField getField(String name){
    for(int i=0; i<fields.length; i++){
      if(fields[i].getSimpleName().equals(name)){
        return fields[i];
      }
    }
    return null;
  }
 
  public XField getFieldAndParents(String name){
    for(int i=0; i<fields.length; i++){
      if(fields[i].getSimpleName().equals(name)){
        return fields[i];
      }
    }
    for(int i=0; i<superClasses.length; i++){
      XField field = superClasses[i].getXClass(virtualMachine).getFieldAndParents(name);
      if(field!=null)
        return field;
    }
    return null;
  }
 
  public XMethod getMethod(String methodName, String[] paramNames, String retName) {
    for(int i=0; i<methods.length; i++){
      if(methods[i].getSimpleName().equals(name)){
        return methods[i];
      }
    }
    return null;
  }
 
  public XMethod getMethod(String name) {
    for(int i=0; i<methods.length; i++){
      if(methods[i].getSimpleName().equals(name)){
        return methods[i];
      }
    }
    return null;
  }

  protected void load(XInputStream inputStream) throws IOException {
    if(state==STATE_CREATED){
      try{
        state = STATE_LOADING;
        String className = inputStream.readUTF();
        if(!getName().equals(className))
          throw new XRuntimeException("Wrong class name %s expect %s", getName(), className);
        modifier = inputStream.readUnsignedShort();
        if(getPackage() instanceof XClass){
          XChecks.checkModifier(this, modifier, INNERMODIFIER);
        }else if(getPackage() instanceof XMethod){
          XChecks.checkModifier(this, modifier, INNERMODIFIER);
        }else{
          XChecks.checkModifier(this, modifier, OUTERMODIFIER);
        }
        annotations = new XAnnotation[inputStream.readUnsignedByte()];
        for(int i=0; i<annotations.length; i++){
          annotations[i] = new XAnnotation(inputStream);
        }
        int childCount = inputStream.readUnsignedByte();
        for(int i=0; i<childCount; i++){
          XClass xClass = new XClass(virtualMachine, inputStream.readUTF());
          super.addChild(xClass);
          xClass.load(inputStream);
        }
        superClasses = new XClassPtr[inputStream.readUnsignedByte()];
        canBeDiamondExtender = new boolean[superClasses.length];
        for(int i=0; i<superClasses.length; i++){
          (superClasses[i] = XClassPtr.load(inputStream)).getXClassNonNull(virtualMachine);
          canBeDiamondExtender[i] = true;
        }
        checkDiamonds(new HashMap<XClass, XClass>());
        genericInfos = new XGenericInfo[inputStream.readUnsignedByte()];
        for(int i=0; i<genericInfos.length; i++){
          genericInfos[i] = new XGenericInfo(virtualMachine, inputStream);
        }
        fields = new XField[inputStream.readUnsignedShort()];
        for(int i=0; i<fields.length; i++){
          super.addChild(fields[i] = new XField(this, inputStream));
        }
        methods = new XMethod[inputStream.readUnsignedShort()];
        for(int i=0; i<methods.length; i++){
          super.addChild(methods[i] = new XMethod(this, inputStream));
          if(methods[i].isConstructor() && !XModifier.isStatic(methods[i].getModifier())){
            XClass[] superClasses = methods[i].getExplizitSuperInvokes();
            for(int j=0; j<superClasses.length; j++){
              for(int k=0; k<this.superClasses.length; k++){
                if(superClasses[j] == this.superClasses[k].getXClassNonNull(virtualMachine)){
                  canBeDiamondExtender[k] = false;
                  break;
                }
              }
            }
          }
        }
        state = STATE_LOADED;
        virtualMachine.getClassProvider().addClassForLoading(this);
      }catch(Throwable e){
        state = STATE_ERRORED;
        if(!(e instanceof XRuntimeException)){
          e = new XRuntimeException(e, "Error while loading class %s", getName());
        }
        throw (XRuntimeException)e;
      }
    }
  }
 
  private void checkDiamonds(HashMap<XClass, XClass> checkedClasses) {
    for(int i=0; i<superClasses.length; i++){
      XClass xClass = superClasses[i].getXClassNonNull(virtualMachine);
      XClass first = checkedClasses.get(xClass);
      if(first == null){
        checkedClasses.put(xClass, this);
      }else{
        first.checkDiamondAbleFor(xClass);
      }
      xClass.checkDiamonds(checkedClasses);
    }
  }

  private void checkDiamondAbleFor(XClass xClass) {
    for(int i=0; i<superClasses.length; i++){
      if(superClasses[i].getXClassNonNull(virtualMachine)==xClass){
        if(canBeDiamondExtender[i])
          return;
        throw new XRuntimeException("Class %s can be used as diamond base", xClass);
      }
    }
    throw new XRuntimeException("Oh, this should never be happened, this is a fatal error :(");
  }

  protected void postLoad() {
    virtualMachine.getClassProvider().removeClassForLoading(this);
    if(state==STATE_LOADED){
      try{
        state = STATE_POST_LOADING;
        for(int i=0; i<superClasses.length; i++){
          XClass xClass = superClasses[i].getXClass(virtualMachine);
          xClass.postLoad();
          if(xClass.state!=STATE_RUNNABLE){
            throw new XRuntimeException("Class %s isn't inited correctly, so %s can't inited", xClass, this);
          }
        }
       
        state = STATE_RUNNABLE;
        XMethod xMethod = getMethod("<staticInit>", new String[0], "void");
        virtualMachine.getThreadProvider().importantInterrupt("Static "+getName(), xMethod, new XGenericClass[0], new long[0]);
      }catch(Throwable e){
        state = STATE_ERRORED;
        if(!(e instanceof XRuntimeException)){
          e = new XRuntimeException(e, "Error while post loading class %s", getName());
        }
        throw (XRuntimeException)e;
      }
    }
  }

  public int getStaticFieldIndex(int sizeInObject) {
    if(state!=STATE_LOADING)
      throw new XRuntimeException("You can't get a field index now");
    int ret = staticFieldCount;
    staticFieldCount += sizeInObject;
    return ret;
  }

  public int getFieldIndex(int sizeInObject) {
    if(state!=STATE_LOADING)
      throw new XRuntimeException("You can't get a field index now");
    int ret = fieldCount;
    fieldCount += sizeInObject;
    return ret;
  }

  public int getMethodIndex() {
    if(state!=STATE_LOADING)
      throw new XRuntimeException("You can't get a method index now");
    return methodCount++;
  }

  public int getState() {
    return state;
  }
 
  public void save(XOutputStream outputStream) throws IOException{
    outputStream.writeUTF(getName());
    outputStream.writeShort(modifier);
    outputStream.writeShort(annotations.length);
    for(int i=0; i<annotations.length; i++){
      annotations[i].save(outputStream);
    }
   
    List<XClass> classChilds = new ArrayList<XClass>();
   
    for(XPackage p:childs.values()){
      if(p instanceof XClass){
        classChilds.add((XClass)p);
      }
    }
   
    outputStream.writeByte(classChilds.size());
    for(XClass classChild:classChilds){
      classChild.save(outputStream);
    }
   
    outputStream.writeByte(superClasses.length);
    for(int i=0; i<superClasses.length; i++){
      superClasses[i].save(outputStream);
    }
   
    outputStream.writeByte(genericInfos.length);
    for(int i=0; i<genericInfos.length; i++){
      genericInfos[i].save(outputStream);
    }

    outputStream.writeShort(fields.length);
    for(int i=0; i<fields.length; i++){
      fields[i].save(outputStream);
    }
   
    outputStream.writeShort(methods.length);
    for(int i=0; i<methods.length; i++){
      methods[i].save(outputStream);
    }
   
  }
 
}
TOP

Related Classes of xscript.runtime.clazz.XClass

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.