Exemple #1
0
  /**
   * Rewrites a move instruction if it has 2 memory operands. One of the 2 memory operands must be a
   * stack location operand. Move the SP to the appropriate location and use a push or pop
   * instruction.
   *
   * @param s the instruction to rewrite
   */
  private void rewriteMoveInstruction(Instruction s) {
    // first attempt to mutate the move into a noop
    if (mutateMoveToNop(s)) return;

    Operand result = MIR_Move.getResult(s);
    Operand val = MIR_Move.getValue(s);
    if (result instanceof StackLocationOperand) {
      if (val instanceof MemoryOperand || val instanceof StackLocationOperand) {
        int offset = ((StackLocationOperand) result).getOffset();
        byte size = ((StackLocationOperand) result).getSize();
        offset = FPOffset2SPOffset(offset) + size;
        moveESPBefore(s, offset);
        MIR_UnaryNoRes.mutate(s, IA32_PUSH, val);
      }
    } else {
      if (result instanceof MemoryOperand) {
        if (val instanceof StackLocationOperand) {
          int offset = ((StackLocationOperand) val).getOffset();
          offset = FPOffset2SPOffset(offset);
          moveESPBefore(s, offset);
          MIR_Nullary.mutate(s, IA32_POP, result);
        }
      }
    }
  }
  /**
   * expand an FCLEAR pseudo-insruction using FFREEs.
   *
   * @param s the instruction to expand
   * @param ir the containing IR
   */
  private static void expandFClear(Instruction s, IR ir) {
    int nSave = MIR_UnaryNoRes.getVal(s).asIntConstant().value;
    int fpStackHeight = ir.MIRInfo.fpStackHeight;
    PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asIA32();

    for (int i = nSave; i < fpStackHeight; i++) {
      Register f = phys.getFPR(i);
      s.insertBefore(MIR_Nullary.create(IA32_FFREE, D(f)));
    }

    // Remove the FCLEAR.
    s.remove();
  }
Exemple #3
0
  /**
   * Insert the epilogue before a particular return instruction.
   *
   * @param ret the return instruction.
   */
  private void insertEpilogue(Instruction ret) {
    // 1. Restore any saved registers
    if (ir.compiledMethod.isSaveVolatile()) {
      restoreVolatileRegisters(ret);
      restoreFloatingPointState(ret);
    }
    restoreNonVolatiles(ret);

    // 2. Restore caller's stackpointer and framepointer
    int frameSize = getFrameFixedSize();
    ret.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(frameSize)));
    MemoryOperand fpHome =
        MemoryOperand.BD(
            ir.regpool.makeTROp(),
            ArchEntrypoints.framePointerField.getOffset(),
            (byte) WORDSIZE,
            null,
            null);
    ret.insertBefore(MIR_Nullary.create(IA32_POP, fpHome));
  }
Exemple #4
0
  /**
   * Walks through the IR. For each StackLocationOperand, replace the operand with the appropriate
   * MemoryOperand.
   */
  private void rewriteStackLocations() {
    // ESP is initially WORDSIZE above where the framepointer is going to be.
    ESPOffset = getFrameFixedSize() + WORDSIZE;
    Register ESP = ((PhysicalRegisterSet) ir.regpool.getPhysicalRegisterSet()).getESP();

    boolean seenReturn = false;
    for (Enumeration<Instruction> e = ir.forwardInstrEnumerator(); e.hasMoreElements(); ) {
      Instruction s = e.nextElement();

      if (s.isReturn()) {
        seenReturn = true;
        continue;
      }

      if (s.isBranch()) {
        // restore ESP to home location at end of basic block.
        moveESPBefore(s, 0);
        continue;
      }

      if (s.operator() == BBEND) {
        if (seenReturn) {
          // at a return ESP will be at FrameFixedSize,
          seenReturn = false;
          ESPOffset = 0;
        } else {
          moveESPBefore(s, 0);
        }
        continue;
      }

      if (s.operator() == ADVISE_ESP) {
        ESPOffset = MIR_UnaryNoRes.getVal(s).asIntConstant().value;
        continue;
      }

      if (s.operator() == REQUIRE_ESP) {
        // ESP is required to be at the given offset from the bottom of the frame
        moveESPBefore(s, MIR_UnaryNoRes.getVal(s).asIntConstant().value);
        continue;
      }

      if (s.operator() == YIELDPOINT_PROLOGUE
          || s.operator() == YIELDPOINT_BACKEDGE
          || s.operator() == YIELDPOINT_EPILOGUE) {
        moveESPBefore(s, 0);
        continue;
      }

      if (s.operator() == IA32_MOV) {
        rewriteMoveInstruction(s);
      }

      // pop computes the effective address of its operand after ESP
      // is incremented.  Therefore update ESPOffset before rewriting
      // stacklocation and memory operands.
      if (s.operator() == IA32_POP) {
        ESPOffset += WORDSIZE;
      }

      for (Enumeration<Operand> ops = s.getOperands(); ops.hasMoreElements(); ) {
        Operand op = ops.nextElement();
        if (op instanceof StackLocationOperand) {
          StackLocationOperand sop = (StackLocationOperand) op;
          int offset = sop.getOffset();
          if (sop.isFromTop()) {
            offset = FPOffset2SPOffset(offset);
          }
          offset -= ESPOffset;
          byte size = sop.getSize();
          MemoryOperand M =
              MemoryOperand.BD(
                  new RegisterOperand(ESP, PRIMITIVE_TYPE_FOR_WORD),
                  Offset.fromIntSignExtend(offset),
                  size,
                  null,
                  null);
          s.replaceOperand(op, M);
        } else if (op instanceof MemoryOperand) {
          MemoryOperand M = op.asMemory();
          if ((M.base != null && M.base.getRegister() == ESP)
              || (M.index != null && M.index.getRegister() == ESP)) {
            M.disp = M.disp.minus(ESPOffset);
          }
        }
      }

      // push computes the effective address of its operand after ESP
      // is decremented.  Therefore update ESPOffset after rewriting
      // stacklocation and memory operands.
      if (s.operator() == IA32_PUSH) {
        ESPOffset -= WORDSIZE;
      }
    }
  }
Exemple #5
0
  /**
   * Insert the prologue for a normal method.
   *
   * <p>Assume we are inserting the prologue for method B called from method A.
   *
   * <ul>
   *   <li>Perform a stack overflow check.
   *   <li>Store a back pointer to A's frame
   *   <li>Store B's compiled method id
   *   <li>Adjust frame pointer to point to B's frame
   *   <li>Save any used non-volatile registers
   * </ul>
   */
  @Override
  public void insertNormalPrologue() {
    PhysicalRegisterSet phys = (PhysicalRegisterSet) ir.regpool.getPhysicalRegisterSet();
    Register ESP = phys.getESP();
    MemoryOperand fpHome =
        MemoryOperand.BD(
            ir.regpool.makeTROp(),
            ArchEntrypoints.framePointerField.getOffset(),
            (byte) WORDSIZE,
            null,
            null);

    // the prologue instruction
    Instruction plg = ir.firstInstructionInCodeOrder().nextInstructionInCodeOrder();
    // inst is the instruction immediately after the IR_PROLOGUE
    // instruction
    Instruction inst = plg.nextInstructionInCodeOrder();

    int frameFixedSize = getFrameFixedSize();
    ir.compiledMethod.setFrameFixedSize(frameFixedSize);

    // I. Buy a stackframe (including overflow check)
    // NOTE: We play a little game here.  If the frame we are buying is
    //       very small (less than 256) then we can be sloppy with the
    //       stackoverflow check and actually allocate the frame in the guard
    //       region.  We'll notice when this frame calls someone and take the
    //       stackoverflow in the callee. We can't do this if the frame is too big,
    //       because growing the stack in the callee and/or handling a hardware trap
    //       in this frame will require most of the guard region to complete.
    //       See libvm.C.
    if (frameFixedSize >= 256) {
      // 1. Insert Stack overflow check.
      insertBigFrameStackOverflowCheck(plg);

      // 2. Save caller's frame pointer
      inst.insertBefore(MIR_UnaryNoRes.create(IA32_PUSH, fpHome));

      // 3. Set my frame pointer to current value of stackpointer
      inst.insertBefore(
          MIR_Move.create(
              IA32_MOV, fpHome.copy(), new RegisterOperand(ESP, PRIMITIVE_TYPE_FOR_WORD)));

      // 4. Store my compiled method id
      int cmid = ir.compiledMethod.getId();
      inst.insertBefore(MIR_UnaryNoRes.create(IA32_PUSH, VM.BuildFor32Addr ? IC(cmid) : LC(cmid)));
    } else {
      // 1. Save caller's frame pointer
      inst.insertBefore(MIR_UnaryNoRes.create(IA32_PUSH, fpHome));

      // 2. Set my frame pointer to current value of stackpointer
      inst.insertBefore(
          MIR_Move.create(
              IA32_MOV, fpHome.copy(), new RegisterOperand(ESP, PRIMITIVE_TYPE_FOR_WORD)));

      // 3. Store my compiled method id
      int cmid = ir.compiledMethod.getId();
      inst.insertBefore(MIR_UnaryNoRes.create(IA32_PUSH, VM.BuildFor32Addr ? IC(cmid) : LC(cmid)));

      // 4. Insert Stack overflow check.
      insertNormalStackOverflowCheck(plg);
    }

    // II. Save any used volatile and non-volatile registers
    if (ir.compiledMethod.isSaveVolatile()) {
      saveVolatiles(inst);
      saveFloatingPointState(inst);
    }
    saveNonVolatiles(inst);
  }