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

📄 label.java

📁 这是一个Linux下的集成开发环境
💻 JAVA
字号:
// Copyright (c) 1997  Per M.A. Bothner.// This is free software;  for terms and warranty disclaimer see ./COPYING.package gnu.bytecode;import java.io.*;/** * A Label represents a location in a Code attribute. *//* * Java VM control transfer instructions contain PC-relative offsets * to the target (location/Label).  (The offsets are relative to the * start of the instruction.)  A complication is that some instructions * use 2-byte relative offsets, while others use 4-byte relative offsets. * A few instructions exist in both "narrow" 2-byte and "wide" 4-byte forms. * * This library uses a very simple data structure to accumulate * generated instructions - just a simple byte array of opcodes and * operands, just as in the final .class file.  When emitting a forward * branch, we cannot emit the relative addresss of the still-unknown * target.  Instead, we emit the negative of the PC of the instruction, * and later add the address of the target by back-patching. * We keep track of which locations need back-patching in the fixups and * wide_fixups arrays (for 2-byte and 4-byte offsets, respectively). * This is simple, fast, and concise.  However, if it turns out that * the target is more than 32767 bytes away, we have problem:  Once an * instruction has been emitted, we cannot change its size (e.g. change * a 2-byte jump offset into a 4-byte offset).  (I.e. there is no * "relaxation" as is done by many assemblers.) * * Since very few methods actually need 4-byte jump offsets, the code * generator optimistically assumes that when it emits a forward branch * the not-yet-defined label will later be defined within the 2-byte span * of the current instruction.  (Except of course for instructions like * tableswitch and lookupswitch that only exist in 4-byte-offset form.) * * But what do we do if it turns out that the branch target is > 32767 * bytes away?  In that case, we emit what I call a "spring" *before* * we get out of range.  A "spring" is a trivial basic block that * contains only a single wide goto.  The branches that are close to * the limit are patched to point to the "spring" instead.  Before * every instruction Method.instruction_start_hook is called. * It checks if there are any pending banches that are getting close * to the limit for 2-byte offsets, in which case it calls Label.emit_spring * to generate the spring. * * Note that we may also need a spring even if the target is known, * if we need a 2-byte offset, and the target is too far away. * * Note that while the Java bytecodes supports 32-bit relative address, * there are limitations in the .class file format that limit each * method to 2*16 bytes.  This may change.  In any case, this code has * been written to support "wide jumps" - but that has not been tested! */public class Label {  Label next;  // The PC of where the label is, or -1 if not yet defined.  int position;  // If >= 0, this is the location of a "spring" to this Label.  int spring_position;  // Array of PC locations that reference this Label.  // Elements that are -1 provide room to grow.  // For an element fi in fixups (where fi >= 0), the 2-byte  // sequence code[fi]:code[fi+1] will need to be adjusted (relocated) by  // the relative position of this Label, or alternatively spring_postion.  // After relcocation, code[fi]:code[fi+1] will be a reference to   // this label (usually a PC-relative reference).  // The lowest element fi (>= 0) is first, but fixups is otherwise unsorted.  // Normally, if defined(), then fixups is null.  // However, we may still need fixups even if defined(), if  // position is further away than allowed by a 16-bit offset.  int[] fixups;  // Similar to fixups, but each element is a 4-byte relative jump offset.  int[] wide_fixups;  public final boolean defined () { return position >= 0; }  public Label (Method method)  {    this(method.code);  }  public Label (CodeAttr code)  {    position = -1;    if (code.labels != null)      {	next = code.labels.next;	code.labels.next = this;      }    else      code.labels = this;  }  /* Make all narrow fixups for this label point (relatively) to target. */  final private void relocate_fixups (CodeAttr code, int target) {    if (fixups == null)      return;    for (int i = fixups.length; --i >= 0; )      {	int pos = fixups[i];	/* Adjust the 2-byte offset at pos in method by (target-pos). */	if (pos >= 0)	  {	    byte[] insns = code.getCode();	    int code_val = ((insns[pos] & 0xFF) << 8) | (insns[pos+1] & 0xFF);	    code_val += target - pos;	    if (code_val < -32768 || code_val >= 32768)	      throw new Error ("overflow in label fixup");	    insns[pos] = (byte) (code_val >> 8);	    insns[pos+1] = (byte) (code_val);	  }      }    if (this != code.labels)      code.reorder_fixups ();    fixups = null;  }  /* Adjust the 4-byte offset at pos in method by (target-pos). */  static final void relocate_wide (CodeAttr code, int pos, int target) {    if (pos >= 0) {      byte[] insns = code.getCode();      int code_val	= ((insns[pos] & 0xFF) << 24) | ((insns[pos+1] & 0xFF) << 16)	| ((insns[pos+2] & 0xFF) << 8) | (insns[pos+3] & 0xFF);      code_val += target-pos;      insns[pos] = (byte) (code_val >> 24);      insns[pos+1] = (byte) (code_val >> 16);      insns[pos+2] = (byte) (code_val >> 8);      insns[pos+3] = (byte) code_val;    }  }  /**   * Define the value of a label as having the current location.   * @param code the "Code" attribute of the current method   */  public void define (CodeAttr code)  {    code.unreachable_here = false;    if (position >= 0)      throw new Error ("label definition more than once");    position = code.PC;    /* Remove redundant goto in:  goto L; L:       These tend to be generated when compiling IfExp's,       so it is worth checking for them.    */    int goto_pos = position - 3;  // Position of hypothetical goto.    if (code.readPC <= goto_pos        && fixups != null && wide_fixups == null	&& goto_pos > 0 && code.getCode()[goto_pos] == (167-256) /* goto */)      {	int i;	goto_pos++;  // Skip goto opcode.	for (i = fixups.length;  -- i >= 0; )	  {	    if (fixups[i] == goto_pos)	      break;	  }	if (i >= 0)	  {	    position -= 3;	    code.PC = position;	    fixups[i] = -1;	  }      }    code.readPC = position;    relocate_fixups (code, position);    if (wide_fixups != null) {      for (int i = wide_fixups.length; --i >= 0; )	relocate_wide (code, wide_fixups[i], position);      wide_fixups = null;    }  }  /**   * Emit goto_w as target for far-away gotos in large methods.   * Needs to be invoked if the earliest still-pending fixup   * is at the limit of a 2-byte relative jump.   * To solve the problem, we emit a goto_w for the label,   * and change all pending (short) fixups to point here.   * We also have to jump past this goto.   */     void emit_spring (CodeAttr code)  {    code.reserve(8);    if (!code.unreachable_here)      {	code.put1 (167);  // goto PC+6	code.put2 (6);      }    spring_position = code.PC;    relocate_fixups (code, spring_position);    code.put1 (200);  // goto_w    add_wide_fixup (code.PC);    code.put4 (1);    code.readPC = code.PC;  }  /* Save a fixup so we can later backpatch code[method.PC..method.PC+1]. */  private void add_fixup (CodeAttr code)  {    int PC = code.PC;    int i;    if (fixups == null)      {	fixups = new int[2];	fixups[0] = PC;	fixups[1] = -1;      }    else      {	int fixups_length = fixups.length;	for (i = 0; i < fixups_length && fixups[i] >= 0; ) i++;	if (i == fixups_length)	  {	    int[] new_fixups = new int[2 * fixups.length];	    System.arraycopy (fixups, 0, new_fixups, 0, fixups.length);	    i = new_fixups.length;	    do { new_fixups[--i] = -1; } while (i > fixups_length);	    fixups = new_fixups;	  }	if (PC < fixups[0])	  {	    fixups[i] = fixups[0];	    fixups[0] = PC;	  }	else	  fixups[i] = PC;      }    if (this != code.labels	&& (code.labels.fixups == null	    || PC < code.labels.fixups[0]))      code.reorder_fixups ();  }    private void add_wide_fixup (int PC)  {    int i;    if (wide_fixups == null) {      wide_fixups = new int[2];      wide_fixups[0] = PC;      wide_fixups[1] = -1;      return;    }    for (i = 0; i < wide_fixups.length; i++ ) {      if (wide_fixups[i] < 0) {	wide_fixups[i] = PC;	return;      }    }    int[] new_fixups = new int[2 * wide_fixups.length];    System.arraycopy (wide_fixups, 0, new_fixups, 0, wide_fixups.length);    new_fixups[wide_fixups.length] = PC;    for (i = wide_fixups.length; ++i < new_fixups.length; )      new_fixups[i] = -1;    wide_fixups = new_fixups;  }  /**   * Emit a reference to the current label.   * @param method the current method   * Emit the reference as a 2-byte difference relative to PC-1.   */     public void emit (CodeAttr code) {    int PC_rel = 1 - code.PC;    int delta = PC_rel;    if (defined ()) {      delta += position;      if (delta < -32768) {	if (spring_position >= 0 && spring_position + PC_rel >= -32768)	  delta = spring_position + PC_rel;	else {	  add_fixup (code);	  delta = PC_rel;	}      }    } else      add_fixup (code);    code.put2 (1);  }  /**   * Emit a wide reference to the current label.   * @param method the current method   * Emit the reference as a 4-byte difference relative to PC-offset.   */  public void emit_wide (CodeAttr code, int start_offset)  {    int delta = 1 - code.PC;    if (defined ())      delta += position;    else      add_wide_fixup (code.PC);    code.put4 (start_offset);  }}

⌨️ 快捷键说明

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