⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 codeattr.java

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
    emitDup(size, 0);  }  public void emitDup (Type type)  {    emitDup(type.size > 4 ? 2 : 1, 0);  }  public void enterScope (Scope scope)  {    scope.setStartPC(this);    locals.enterScope(scope);  }  public Scope pushScope () {    Scope scope = new Scope ();    if (locals == null)      locals = new LocalVarsAttr(getMethod());    enterScope(scope);    if (locals.parameter_scope == null)       locals.parameter_scope = scope;    return scope;  }  public Scope getCurrentScope()  {    return locals.current_scope;  }  public Scope popScope () {    Scope scope = locals.current_scope;    locals.current_scope = scope.parent;    scope.freeLocals(this);    scope.end = getLabel();    return scope;  }  /** Get the index'th parameter. */  public Variable getArg (int index)  {    return locals.parameter_scope.getVariable(index);  }  /**   * Search by name for a Variable   * @param name name to search for   * @return the Variable, or null if not found (in any scope of this Method).   */  public Variable lookup (String name)  {    Scope scope = locals.current_scope;    for (; scope != null;  scope = scope.parent)      {	Variable var = scope.lookup (name);	if (var != null)	  return var;      }    return null;  }  /** Add a new local variable (in the current scope).   * @param type type of the new Variable.   * @return the new Variable. */  public Variable addLocal (Type type)  {    return locals.current_scope.addVariable(this, type, null);  }  /** Add a new local variable (in the current scope).   * @param type type of the new Variable.   * @param name name of the new Variable.   * @return the new Variable. */  public Variable addLocal (Type type, String name)  {    return locals.current_scope.addVariable (this, type, name);  }  /** Call addLocal for parameters (as implied by method type). */  public void addParamLocals()  {    Method method = getMethod();    if ((method.access_flags & Access.STATIC) == 0)      addLocal(method.classfile).setParameter(true);    int arg_count = method.arg_types.length;    for (int i = 0;  i < arg_count;  i++)      addLocal(method.arg_types[i]).setParameter(true);  }  public final void emitPushConstant(int val, Type type)  {    switch (type.getSignature().charAt(0))      {      case 'B':  case 'C':  case 'I':  case 'Z':  case 'S':	emitPushInt(val);  break;      case 'J':	emitPushLong((long)val);  break;      case 'F':	emitPushFloat((float)val);  break;      case 'D':	emitPushDouble((double)val);  break;      default:	throw new Error("bad type to emitPushConstant");      }  }  /* Low-level method to pust a ConstantPool entry.   * Does not do the appropriatre <code>pushType</code>. */  public final void emitPushConstant (CpoolEntry cnst)  {    reserve(3);    int index = cnst.index;    if (cnst instanceof CpoolValue2)      {      	put1 (20); // ldc2_w	put2 (index);      }    else if (index < 256)      {	put1(18); // ldc	put1(index);      }    else      {	put1(19); // ldc_w	put2(index);      }  }  public final void emitPushInt(int i)  {    reserve(3);    if (i >= -1 && i <= 5)      put1(i + 3);  // iconst_m1 .. iconst_5    else if (i >= -128 && i < 128)      {	put1(16); // bipush	put1(i);      }    else if (i >= -32768 && i < 32768)      {	put1(17); // sipush	put2(i);      }    else      {	emitPushConstant(getConstants().addInt(i));      }    pushType(Type.int_type);  }  public void emitPushLong (long i)  {    if (i == 0 || i == 1)      {	reserve(1);	put1 (9 + (int) i);  // lconst_0 .. lconst_1      }    else if ((long) (int) i == i)      {	emitPushInt ((int) i);	reserve(1);	popType();	put1 (133); // i2l      }    else      {	emitPushConstant(getConstants().addLong(i));      }    pushType(Type.long_type);  }  public void emitPushFloat (float x)  {    int xi = (int) x;    if ((float) xi == x && xi >= -128 && xi < 128)      {	if (xi >= 0 && xi <= 2)	  {	    reserve(1);	    put1(11 + xi);  // fconst_0 .. fconst_2	    if (xi == 0 && Float.floatToIntBits(x) != 0) // x == -0.0	      {		reserve(1);		put1(118);  // fneg	      }	  }	else	  {	    // Saves space in the constant pool	    // Probably faster, at least on modern CPUs.	    emitPushInt (xi);	    reserve(1);	    popType();	    put1 (134); // i2f	  }      }    else      {	emitPushConstant(getConstants().addFloat(x));      }    pushType(Type.float_type);  }  public void emitPushDouble (double x)  {    int xi = (int) x;    if ((double) xi == x && xi >= -128 && xi < 128)      {	if (xi == 0 || xi == 1)	  {	    reserve(1);	    put1(14+xi);  // dconst_0 or dconst_1	    if (xi == 0 && Double.doubleToLongBits(x) != 0L) // x == -0.0	      {		reserve(1);		put1(119);  // dneg	      }	  }	else	  {	    // Saves space in the constant pool	    // Probably faster, at least on modern CPUs.	    emitPushInt (xi);	    reserve(1);	    popType();	    put1 (135); // i2d	  }      }    else      {	emitPushConstant(getConstants().addDouble(x));      }    pushType(Type.double_type);  }  /** Calculate how many CONSTANT_String constants we need for a string.   * Each CONSTANT_String can be at most 0xFFFF bytes (as a UTF8 string).   * Returns a String, where each char, coerced to an int, is the length   * of a substring of the input that is at most 0xFFFF bytes.   */  public final String calculateSplit (String str)  {    int strLength = str.length();    StringBuffer sbuf = new StringBuffer(20);    // Where the current segments starts, as an index in 'str':    int segmentStart = 0;    int byteLength = 0; // Length in bytes of current segment so far.    for (int i = 0;  i < strLength; i++)      {	char ch = str.charAt(i);	int bytes = ch >= 0x0800 ? 3 : ch >= 0x0080 || ch == 0 ? 2 : 1;	if (byteLength + bytes > 0xFFFF)	  {	    sbuf.append((char) (i - segmentStart));	    segmentStart = i;	    byteLength = 0;	  }	byteLength += bytes;      }    sbuf.append((char) (strLength - segmentStart));    return sbuf.toString();  }  /** Emit code to push the value of a constant String.   * Uses CONSTANT_String and CONSTANT_Utf8 constant pool entries as needed.   * Can handle Strings whose UTF8 length is greates than 0xFFFF bytes   * (the limit of a CONSTANT_Utf8) by generating String concatenation.   */  public final void emitPushString (String str)  {    if (str == null)      emitPushNull();    else      {	int length = str.length();	String segments = calculateSplit(str);	int numSegments = segments.length();	if (numSegments <= 1)	  emitPushConstant(getConstants().addString(str));	else	  {	    if (numSegments == 2)	      {		int firstSegment = (int) segments.charAt(0);		emitPushString(str.substring(0, firstSegment));		emitPushString(str.substring(firstSegment));		Method concatMethod		  = Type.string_type.getDeclaredMethod("concat", 1);		emitInvokeVirtual(concatMethod);	      }	    else	      {		ClassType sbufType = ClassType.make("java.lang.StringBuffer");		emitNew(sbufType);		emitDup(sbufType);		emitPushInt(length);		Type[] args1 = { Type.int_type };		emitInvokeSpecial(sbufType.getDeclaredMethod("<init>", args1));		Type[] args2 = { Type.string_type };		Method appendMethod		  = sbufType.getDeclaredMethod("append", args2);		int segStart = 0;		for (int seg = 0;  seg < numSegments;  seg++)		  {		    emitDup(sbufType);		    int segEnd = segStart + (int) segments.charAt(seg);		    emitPushString(str.substring(segStart, segEnd));		    emitInvokeVirtual(appendMethod);		    segStart = segEnd;		  }		emitInvokeVirtual(Type.toString_method);	      }	    if (str == str.intern())	      emitInvokeVirtual(Type.string_type.getDeclaredMethod("intern", 0));	    return;	  }	pushType(Type.string_type);      }  }  /** Push a class constant pool entry.   * This is only supported by JDK 1.5 and later. */  public final void emitPushClass (String name)  {    emitPushConstant(getConstants().addClass(name));    pushType(Type.java_lang_Class_type);  }  public void emitPushNull ()  {    reserve(1);    put1(1);  // aconst_null    pushType(Type.pointer_type);  }  public final void emitPushThis()  {    reserve(1);    put1(42);  // aload_0    pushType(getMethod().getDeclaringClass());  }  /** Emit code to push a constant primitive array.   * @param value The array value that we want the emitted code to re-create.   * @param arrayType The ArrayType that matches value.   */  public final void emitPushPrimArray(Object value, ArrayType arrayType)  {    Type elementType = arrayType.getComponentType();    int len = java.lang.reflect.Array.getLength(value);    emitPushInt(len);    emitNewArray(elementType);    char sig = elementType.getSignature().charAt(0);    for (int i = 0;  i < len;  i++)      {	long ival = 0;  float fval = 0;  double dval = 0;	switch (sig)	  {	  case 'J':	    ival = ((long[]) value)[i];	    if (ival == 0)	      continue;	    break;	  case 'I':	    ival = ((int[]) value)[i];	    if (ival == 0)	      continue;	    break;	  case 'S':	    ival = ((short[]) value)[i];	    if (ival == 0)	      continue;	    break;	  case 'C':	    ival = ((char[]) value)[i];	    if (ival == 0)	      continue;	    break;	  case 'B':	    ival = ((byte[]) value)[i];	    if (ival == 0)	      continue;	    break;	  case 'Z':	    ival = ((boolean[]) value)[i] ? 1 : 0;	    if (ival == 0)	      continue;	    break;	  case 'F':	    fval = ((float[]) value)[i];	    if (fval == 0.0)	      continue;	    break;	  case 'D':	    dval = ((double[]) value)[i];	    if (dval == 0.0)	      continue;	    break;	  }	emitDup(arrayType);	emitPushInt(i);	switch (sig)	  {	  case 'Z':	  case 'C':	  case 'B':	  case 'S':	  case 'I':	    emitPushInt((int) ival);	    break;	  case 'J':	    emitPushLong(ival);	    break;	  case 'F':	    emitPushFloat(fval);	    break;	  case 'D':	    emitPushDouble(dval);	    break;	  }	emitArrayStore(elementType);      }  }  void emitNewArray (int type_code)  {    reserve(2);    put1(188);  // newarray    put1(type_code);  }  public final void emitArrayLength ()  {    if (! (popType() instanceof ArrayType))      throw new Error( "non-array type in emitArrayLength" );        reserve(1);    put1(190);  // arraylength    pushType(Type.int_type);  }  /* Returns an integer in the range 0 (for 'int') through 4 (for object     reference) to 7 (for 'short') which matches the pattern of how JVM     opcodes typically depend on the operand type. */  private int adjustTypedOp  (char sig)  {    switch (sig)      {      case 'I':  return 0;  // int      case 'J':  return 1;  // long      case 'F':  return 2;  // float      case 'D':  return 3;  // double      default:   return 4;  // object      case 'B':      case 'Z':  return 5;  // byte or boolean      case 'C':  return 6;  // char      case 'S':  return 7;  // short      }  }  private int adjustTypedOp  (Type type)  {    return adjustTypedOp(type.getSignature().charAt(0));  }  private void emitTypedOp (int op, Type type)  {    reserve(1);    put1(op + adjustTypedOp(type));  }  private void emitTypedOp (int op, char sig)  {    reserve(1);    put1(op + adjustTypedOp(sig));  }  /** Store into an element of an array.   * Must already have pushed the array reference, the index,   * and the new value (in that order).   * Stack:  ..., array, index, value => ...   */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -