예제 #1
0
char* sendDesc::fastCacheLookupAndBackpatch( LookupType t,
                                             mapOop receiverMapOop,
                                             oop sel,
                                             oop del ) {
  if (needsDelegatee(t) || isResendLookupType(t) || isPerformLookupType(t)) {
    // too complicated to short-circuit these lookups
    return NULL;
  }
  // try mh-independent 
  MethodLookupKey key(t, MH_TBD, receiverMapOop, sel, del);
  nmethod* nm= Memory->code->lookup(key);
  
  if (nm == NULL) {
    NumberOfFastLookupMisses++;
    return NULL;
  }
  NumberOfFastLookupHits++;

  if (nm->needToRecompileFor(this))
    return NULL;

  if (InlineCache) {
    NumberOfICMisses++;
    extend(nm, receiverMapOop, NULL);
  }
  return nm->verifiedEntryPoint();
}
예제 #2
0
 void SendNode::gen() {
   BasicNode::gen();
   offset = theAssembler->offset();
   assert(bci() != IllegalBCI, "should have legal bci");
   genPcDesc();
   genBreakpointBeforeCall();
   theAssembler->CallB(Memory->code->trapdoors->SendMessage_stub_td());
   theAssembler->Nop();
   theAssembler->Data(mask());
   nlrCode();
   theAssembler->Zero();       // nmlns
   theAssembler->Zero();
   if (sel != badOop) {
     if (isPerformLookupType(l)) {
       assert_smi(sel, "should be an integer argcount");
       theAssembler->Data(smiOop(sel)->value());       // really arg count
     } else {
       assert_string(sel, "should be a string constant");
       theAssembler->Data(sel);                        // constant selector
     }
   }
   if ((l & UninlinableSendMask) == 0) theSIC->noInlinableSends = false;
   theAssembler->Data(l);
   verifySendInfo();
   if (del) {
     assert(needsDelegatee(l), "shouldn't have a delegatee");
     theAssembler->Data(del);
   }
 }
예제 #3
0
Label* CodeGen::SendDesc(RegisterState* s, LookupType lookupType,
                         oop selector, oop delegatee) {
  a.Comment("begin SendDesc");
  Label past_send_desc(a.printing);
  a.jmp(&past_send_desc);
  s->genMask();                               // mask of used regs
  Label* l = new Label(a.printing);
  a.jmp(l);                      // non-local return code
  assert((a.offset() & Tag_Mask) == 0, "must be aligned");
  a.Zero();   // nmlns
  a.Zero();
  if (selector != badOop) {
    if (isPerformLookupType(lookupType)) {
      assert_smi(selector, "should be an integer argcount");
      a.Data(smiOop(selector)->value(), true);      // really arg count
    } else {
      assert_string(selector, "should be a string constant");
      a.Data(selector, true);                       // constant selector
    }
  }
  
#   ifdef SIC_COMPILER
  if (theCompiler->containsLoop) {
    // need counters for the sends to know how often the loop executes
    a.Data(withCountBits(lookupType, Counting), true);
  } 
  else {
    a.Data(lookupType, true);
  }
#   else
    a.Data(lookupType, true);
#   endif
  
#   if GENERATE_DEBUGGING_AIDS
  if (CheckAssertions)
    switch (lookupType) {
     case DirectedResendLookupType:
      assert(lookupType & DelegateeStaticBit, "should have static delegatee");
      assert_string(delegatee, "should be a string");
      // fall through
     case ImplicitSelfLookupType:
     case ResendLookupType:
     case StaticNormalLookupType:
     case NormalLookupType:
      assert(!isPerformLookupType(lookupType),
             "should have a static selector");
      assert_string(selector, "should be a string");
      break;
     default: break;
    }
#   endif
  if (delegatee != badOop) {
    assert(needsDelegatee(lookupType), "shouldn't have a delegatee");
    a.Data(delegatee, true);
  }
  past_send_desc.define();
  a.Comment("end SendDesc");
  return l;
}
예제 #4
0
fint sendDesc::endOffset(LookupType l) {
  fint offset =  normal_sendDesc_end_offset;
  if (needsDelegatee(l) && (l & DelegateeStaticBit)) {
    // add space for delegatee word
    offset += sizeof(oop);
  }
  return offset;
}
예제 #5
0
  Label* CodeGen::SendDesc(RegisterState* s, LookupType lookupType,
                           oop selector, oop delegatee) {
    s->genMask();                               // mask of used regs
    Label* l = a.BraForward(true);              // non-local return code
    a.Nop();
    a.Zero();   // nmlns
    a.Zero();
    if (selector != badOop) {
      if (isPerformLookupType(lookupType)) {
        assert_smi(selector, "should be an integer argcount");
        a.Data(smiOop(selector)->value());      // really arg count
      } else {
        assert_string(selector, "should be a string constant");
        a.Data(selector);                       // constant selector
      }
    }
    
    if (theCompiler->containsLoop) {
      // need counters for the sends to know how often the loop executes
      a.Data(withCountBits(lookupType, Counting));
    } else {
      a.Data(lookupType);
    }
    
#   if GENERATE_DEBUGGING_AIDS
    if (CheckAssertions)
      switch (lookupType) {
       case DirectedResendLookupType:
        assert(lookupType & DelegateeStaticBit, "should have static delegatee");
        assert_string(delegatee, "should be a string");
        // fall through
       case ImplicitSelfLookupType:
       case ResendLookupType:
       case StaticNormalLookupType:
       case NormalLookupType:
        assert(!isPerformLookupType(lookupType),
               "should have a static selector");
        assert_string(selector, "should be a string");
        break;
       default: break;
      }
#   endif
    if (delegatee != badOop) {
      assert(needsDelegatee(lookupType), "shouldn't have a delegatee");
      a.Data(delegatee);
    }
    return l;
  }
예제 #6
0
bool cacheProbingLookup::mightBeAbleToReuseNMethod() {

  if ( !canReuseNM )  return false; // user-disabled

  if ( compiler != NIC )  // haven't figured out SIC reuse yet
    return false; 

  // calling convention is different for methods with a static delegatee
  // send desc is one word longer to hold del, so return has different offset

  LookupType l= lookupType();
  if ( needsDelegatee(l)  &&  isDelegateeStatic() )
    return false;

  if ( isPerformLookupType(l) ) return false; // send desc is also different

  // for immediate oops, the prologue is different so cannot reuse
  //  non-imm oop method for immediate, and imms have no descendants

  if ( key.receiverMap()->is_smi()  ||  key.receiverMap()->is_float() )
    return false;

  // accessor methods not reusable cause offset might not match &
  // we don't check it yet
  
  switch ( resultType() ) {
   case dataResult:
   case assignmentResult:
    return false;
   default:
    break;
  }
  // cannot deal with DI, so forget it if have dc (DI desc)
  if (dc != NULL)  return false;

  return true; // TA DA!
}
예제 #7
0
void CodeGen::prologue(bool isAccessMethod, fint nargs) {
  /*
    ; make stack
    enter 1-last_extra_offset*4, $0 // make space for current_pc nmethod_frame_chain
  */
  
  // *if not DI child
  //    <smi/float/memOop prologue>
  // _verified:                       (entry point from PICs)
  //    if necessary <check selector>
  //    if necessary <check delegatee>
  // *endif DI
  
  // _diCheck:                        (entry point after recompile)
  //    <verify assignable parents>
  
  // *if using recompilation
  //    <checkRecompilation>
  // *endif
  
  // *if haveStackFrame
  //    save sp, -frameSize*oopSize, sp
  // *endif
  
  // <clear stack temporaries and excess argument locations

  // CAUTION: use only Temp1/4 for temps in prologue; other temps
  // may contain lookup parameters.
  

  a.Comment("prologue");
  fint assignableParents = L->adeps->length();
  MethodKind kind =
    isAccessMethod ? MethodKind(-1) : theCompiler->method()->kind();
  _incoming_arg_count = nargs; // for eventual putting into nmethod
  
  if (diLink == 0) {
    if (!L->isReceiverStatic()) {
      // test receiver map
#       if GENERATE_DEBUGGING_AIDS
        if (CheckAssertions)
          switch (L->lookupType()) {
           case NormalLookupType:  break;
           case StaticNormalLookupType:
           case ImplicitSelfLookupType:
           case ResendLookupType:
           case DirectedResendLookupType: fatal("shouldn't miss"); break;
           default: break;
          }
#       endif
      Map* m = L->receiverMap();
      bool imm = m == Memory->smi_map || m == Memory->float_map;
      if (m == Memory->smi_map) {
        smiOop_prologue();
      } else if (m == Memory->float_map) {
        floatOop_prologue();
      } else {
        memOop_prologue();
      }
    }
    
    verifiedOffset = a.offset();
    Label generalMiss(a.printing, NULL);
    a.Comment("verified entry point:");
    
    if (L->isPerform()) {
      a.Comment("check selector");
      checkOop(generalMiss, L->selector(), PerformSelectorLoc);
    }
    
    if (needsDelegatee(L->lookupType()) && !L->isDelegateeStatic()) {
      a.Comment("check delegatee");
      checkOop(generalMiss, L->delegatee(), PerformDelegateeLoc);
    }
  } else {
    // don't check receiver map, selector, delegatee if a DI cache miss
    assert(assignableParents > 0, "should have some di parents to check");
  }
  diCheckOffset = a.offset();
  a.Comment("DI entry point:");
  
  if (assignableParents > 0) {
    a.Comment("verify state of assignable parents");
    fint count = 0;
    for (fint i = 0; i < assignableParents; i ++) {
      objectLookupTarget* target = L->adeps->start()[i];
      Location t = loadPath(Temp2, target, LReceiverReg, Temp1);
      count = verifyParents(target, t, count);
    }
  }

  bool recomp = needRecompileCode(theCompiler->level());
  if (recomp) checkRecompilation();

  if (!haveStackFrame) {
     prologueAddr = NULL;
  }
  else {
    a.Comment("make stack frame (next instruction will be backpatched)");
    a.enter(-0 * oopSize); // will be backpatched for locals
    prologueAddr = a.addr(); // will be used to patch enter with right frame size
    frameCreationOffset = a.offset(); // used by nmethod to find save instr, must have frame by this point  XXXintel really?
    callPatchAddr = a.addr();
    a.nop(); a.nop(); a.nop(); a.nop(); a.nop(); 
    endCallPatchAddr = a.addr();
  }
  if (GenerateCountCode) {
    int32* counter;
    if (assignableParents != 0) {
      counter = &NumberOfDIMethodCalls;
    } else if (isAccessMethod) {
      counter = &NumberOfAccessMethodCalls;
    } else if (kind == BlockMethodType) {
      counter = &NumberOfBlockMethodCalls;
    } else {
      counter = &NumberOfMethodCalls;
    }
    genCountCode(counter);
  }

  if (!isAccessMethod) {
    if (!recomp && GenerateLRUCode) {
      // this code is rarely generated in practice (recomp is usually true)
      a.Comment("reset unused bit");
      void* unused_addr = &LRUflag[Memory->code->nextNMethodID()];
      a.movl(0, NumberOperand, no_reg, int32(unused_addr), VMAddressOperand);
    }
  
    // don't keep uplevel-accessed names in regs
    // (for now, just flush everything)
    assert(haveStackFrame, "just checking");
  }
  else {
    assert(!haveStackFrame, "just checking");
  }    
  a.Comment("End Prologue");
}
예제 #8
0
  void CodeGen::prologue(bool isAccessMethod, fint nargs ) {
    // *if not DI child
    //    <smi/float/memOop prologue>
    // _verified:                       (entry point from PICs)
    //    if necessary <check selector>
    //    if necessary <check delegatee>
    // *endif DI
    
    // _diCheck:                        (entry point after recompile)
    //    <verify assignable parents>
    
    // *if using recompilation
    //    <checkRecompilation>
    // *endif
    
    // *if haveStackFrame
    //    save sp, -frameSize*oopSize, sp
    // *endif
    
    // <flush register windows if neceessary>
    // <clear stack temporaries and excess argument locations

    // CAUTION: use only Temp1/4 for temps in prologue; other temps
    // may contain lookup parameters.
    assert(Temp1 != PerformSelectorLoc && Temp1 != PerformDelegateeLoc,
           "will trash lookup parameters");
    assert(Temp2 != PerformSelectorLoc && Temp2 != PerformDelegateeLoc,
           "will trash lookup parameters");

    fint assignableParents = L->adeps->length();
    MethodKind kind =
      isAccessMethod ? MethodKind(-1) : theCompiler->method()->kind();
    _incoming_arg_count = nargs; // for eventual putting into nmethod

    
    if (diLink == 0) {
      if (!L->isReceiverStatic()) {
        // test receiver map
#       if GENERATE_DEBUGGING_AIDS
          if (CheckAssertions)
            switch (L->lookupType()) {
             case NormalLookupType:  break;
             case StaticNormalLookupType:
             case ImplicitSelfLookupType:
             case ResendLookupType:
             case DirectedResendLookupType: fatal("shouldn't miss"); break;
             default: break;
            }
#       endif
          Map* m = L->receiverMap();
        bool imm = m == Memory->smi_map || m == Memory->float_map;
        if (SICCountTypeTests) {
          a.startTypeTest(1, true, imm);
          a.doOneTypeTest();
        }
        if (m == Memory->smi_map) {
          smiOop_prologue(Memory->code->trapdoors->SendMessage_stub_td());
        } else if (m == Memory->float_map) {
          floatOop_prologue(Memory->code->trapdoors->SendMessage_stub_td());
        } else {
          memOop_prologue(Memory->code->trapdoors->SendMessage_stub_td());
        }
      }
      
      verifiedOffset = a.offset();
      if (SICCountTypeTests) a.endTypeTest();
      Label generalMiss(a.printing, NULL);
      a.Comment("verified entry point:");
      
      if (L->isPerform()) {
        a.Comment("check selector");
        checkOop(generalMiss, L->selector(), PerformSelectorLoc);
      }
      
      if (needsDelegatee(L->lookupType()) && !L->isDelegateeStatic()) {
        a.Comment("check delegatee");
        checkOop(generalMiss, L->delegatee(), PerformDelegateeLoc);
      }
    } else {
      // don't check receiver map, selector, delegatee if a DI cache miss
      assert(assignableParents > 0, "should have some di parents to check");
    }
    
    diCheckOffset = a.offset();
    a.Comment("DI entry point:");
    
    if (assignableParents > 0) {
      a.Comment("verify state of assignable parents");
      fint count = 0;
      for (fint i = 0; i < assignableParents; i ++) {
        objectLookupTarget* target = L->adeps->start()[i];
        Location t = loadPath(Temp2, target, ReceiverReg, Temp1);
        count = verifyParents(target, t, count);
      }
    }

    bool recomp = needRecompileCode(theCompiler->level());
    if (recomp) checkRecompilation();

    if (haveStackFrame) {
      prologueAddr = a.addr();
      a.SaveI(SP, -1, SP);     // correct frame size is patched in later
      frameCreationOffset = a.offset();
    } else {
      prologueAddr = NULL;
    }

    if (GenerateCountCode) {
      int32* counter;
      if (assignableParents != 0) {
        counter = &NumberOfDIMethodCalls;
      } else if (isAccessMethod) {
        counter = &NumberOfAccessMethodCalls;
      } else if (kind == BlockMethodType) {
        counter = &NumberOfBlockMethodCalls;
      } else {
        counter = &NumberOfMethodCalls;
      }
      genCountCode(counter);
    }

    if (!isAccessMethod) {
      if (!recomp && GenerateLRUCode) {
        // this code is rarely generated in practice (recomp is usually true)
        a.Comment("reset unused bit");
        void* unused_addr = &LRUflag[Memory->code->nextNMethodID()];
        a.SetHiA(unused_addr, Temp2);
        a.StoreA(Temp2, unused_addr, G0);
      }
    
      // don't keep uplevel-accessed names in regs
      // (for now, just flush everything)
      if (nargs > NumIArgRegisters) nargs = NumIArgRegisters;
      a.Comment("flush incoming args to stack");
      for (fint i = 0; i < nargs; i++) {
        flushToStack(IArgLocation(i), NULL);
      }
      flushToStack(IReceiverReg, NULL);       // flush receiver to stack

      switch (kind) {
       case BlockMethodType:
        if (theCompiler->needRegWindowFlushes) flushRegisterWindows();
        break;
       case OuterMethodType:
        if (needToFlushRegWindow) {     // we inlined the receiver block
          if (theCompiler->needRegWindowFlushes) flushRegisterWindows();
        } else {
          // receiver is parent, do nothing
        }
        break;
       default:
        fatal1("unknown kind: %ld", kind);
        break;
      }
    }
      
    a.Comment("End Prologue");
  }