Example #1
0
// Test the size of the assembler generated sendDesc in 
// EnterSelf (<machine>.runtime.s). Lars July 92
void sendDesc::init() {
  sendDesc::init_platform();
  
  # if HOST_ARCH == PPC_ARCH && TARGET_ARCH == I386_ARCH
    if (true) return; // just testing asm
  # endif
  sendDesc* f = sendDesc::first_sendDesc();

  // cannot do this test on sparc, it has a register-call which does not read as a call
  // if (!isCall((int32*)f->jump_addr_addr()))
  //  fatal("first_sendDesc() does not have a call");
  
  if (f->raw_lookupType() != StaticNormalLookupType)
    fatal5("first_sendDesc() has wrong lookup type: 0x%x, should be: 0x%x\n"
            "  firstSelfFrame_returnPC: 0x%x,  first_inst_addr:  0x%x, first_sendDesc 0x%x",
            f->raw_lookupType(), StaticNormalLookupType,
            firstSelfFrame_returnPC, 
            first_inst_addr((void*)firstSelfFrame_returnPC), 
            sendDesc::first_sendDesc());

  char* computedEnd = (char*) f + f->endOffset();
  char* realEnd     = first_inst_addr((void*)firstSelfFrameSendDescEnd);
  if (computedEnd != realEnd)
    fatal2("sendDesc of firstSelfFrame has wrong size, "
           "computedEnd = 0x%x, realEnd = 0x%x", computedEnd, realEnd);
}
Example #2
0
char* abstractSlotRef::interpretForCompiledSender(oop receiver, oop sel,
                                                  oop arg1 ) {
  oop res = interpretData( receiver, sel, arg1 );
  if ( res != badOop ) {
    ReturnResult_stub_result = res;
    return first_inst_addr(ReturnResult_stub);
  } else {
    sneaky_method_argument_to_interpret = contents();
    return first_inst_addr(interpret_from_compiled_sender);
  }
}
Example #3
0
void InterruptedContext::setupPreemptionFromSignal() {
    InterruptedContext::the_interrupted_context->must_be_in_self_thread();
  
    if (continuePC) fatal("recursive setSPLimit");
    if ( the_interrupted_context->pc()      >= first_inst_addr( setSPLimitAndContinue )
     &&  the_interrupted_context->pc()      <  first_inst_addr( setSPLimitAndContinueEnd )
    ||   the_interrupted_context->next_pc() >= first_inst_addr( setSPLimitAndContinue )
     &&  the_interrupted_context->next_pc() <  first_inst_addr( setSPLimitAndContinueEnd )) {
      return;                   // already patched or just about to do it
    }
    newSPLimit = currentProcess->stackEnd();
    set_continuation_address(first_inst_addr(setSPLimitAndContinue), false, true);
}
Example #4
0
Label* CodeGen::cPrimCall(PrimDesc* p, RegisterState* s,
                          bool continueNLR, bool trust_fns_arg_count, fint arg_and_rcvr_count) {

  a.Comment("cPrimCall");
  Label* where_nlr_jumps_to = NULL;
  // WARNING: following code sequences are known to get_target_of_Self_call_site
  // and set_target_of_Self_call_site
  // Also, getPrimCallEndOffset assumes continuation is right after sequence.

  a.call( (int32) first_inst_addr(p->fn()), PVMAddressOperand );
  
  // inline cache:
  Label past_nlr(a.printing); 
  a.jmp(&past_nlr);  // skip over mask and nlr code
  s->genMask(); // used register mask for GC
   
  if ( p->needsNLRCode() ) {
    if (continueNLR) { // NLR returns from this method, up NLR chain (only for calling intr check after stack overflow & nonLifo trap)
      continueNonLocalReturn();
    } 
    else { // do the NLR bit
      where_nlr_jumps_to = new Label(a.printing);
      a.jmp(where_nlr_jumps_to);
    }
  }
  past_nlr.define(); 

  return where_nlr_jumps_to;
}
Example #5
0
 Label* CodeGen::cPrimCall(PrimDesc* p, RegisterState* s,
                           bool continueNLR, bool /*trust_fn_arg_count */, fint /* arg_and_rcvr_count */) {
   //   call <primitive>
   //   add o7, oopSize, o7            // so C skips the mask
   //   .data mask                     // need mask for scavenging
   // *if needsNLRCode
   //   <continueNonLocalReturn>       // for prims like AbortProcess
   // *endif
   
   a.CallP( first_inst_addr( p->fn() ) );
   a.AddI(CalleeReturnAddr, 
          p->needsNLRCode()
             ? sendDesc::abortable_prim_end_offset - sendDesc::nonabortable_prim_end_offset + oopSize
             : oopSize, 
          CalleeReturnAddr);
   // skip register mask upon return
   s->genMask();    // used register mask
   
   if ( !p->needsNLRCode()) {
     return NULL;
   }
   else if (continueNLR) {
     continueNonLocalReturn();
     return NULL;
   } 
   else {
     Label* l = a.BraForward(true);
     a.Nop();
     return l;
   }
 }
Example #6
0
bool SignalInterface::handle_SIC_OS_signal(int ossig, char* addr, int32 code) {
  InterruptedContext::the_interrupted_context->must_be_in_self_thread();
  
  assert( !(ossig == SIGNonLifo && code == ST_ShouldNeverHappen),
          "SIC compiler error: should never get to this trap instruction");

  if ( FastMapTest
  &&   is_map_load_signal(ossig)
  &&   isMapLoad((int32*)InterruptedContext::the_interrupted_context->pc())) {
    FlagSetting fs2(_is_in_map_load, true);
    handleMapLoadTrap(InterruptedContext::the_interrupted_context);
    return true;
  }
  if (ossig == SIGUncommon && handleUncommonTrap())
    // was uncommon branch trap
    return true;
    
  if (ossig == SIGNonLifo     &&  is_uplevel_trap(code) 
  ||  ossig == SIGBadHomeRef  &&  NLRSupport::is_bad_home_reference(addr)
                              &&  Memory->code->contains(InterruptedContext::the_interrupted_context->pc())) {
    // continue in NLRSupport::non_lifo_abort
    // This is much easier than doing it here because the stack is in a mess right now.
    InterruptedContext::continue_abort_at(first_inst_addr(NLRSupport::non_lifo_abort_from_continuePC), false);
    return true;
  } 

  return false;
}
Example #7
0
  bool Conversion::createFrame(fint i, nmethod *newNM) {    
    // create new frame, store it in newFr and initialize it
    // XXXX what if fr is interp frame?

    // this routine seems to use sd and sp,
    //  and to set sd, sp, and newFr

    // figure out new value for sd and if isInInterruptCheck

    sendDesc* prev_sd= vf[i]->fr->send_desc();

    // Have to be careful when converting a frame at the bottom of the
    // stack which has just returned from interruptCheck, after a process
    // switch, or while single stepping -- otherwise the next send is
    // omitted.  MIW 6/8/94

    bool isInInterruptCheck=
              prev_sd // eliminate uncommon branches
          && prev_sd->isPrimCall()
          && prev_sd->jump_addr() == first_inst_addr(interruptCheck);

    assert(vf[i]->fr->is_aligned(), "frame alignment check");
    sendDesc* sd_of_created_frame = newNM->sendDescFor(vf[i], isInInterruptCheck);	  
  
    assert( i == 1   ||  newVF[i-1],  "Mac has no null check");
    
    RegisterLocator* caller_rl_before_creating_frame = 
      i == 1
        ?  nonvols_for_caller // vf[0] could be null, so don't do vf[0]->reg_loc()
           // going to be smashing regs saved below last created frame, so copy them
        :  newVF[i-1]->reg_loc()->for_copied_frame(NULL);

    // ppc frames contain their own return addresses, so use sd_of_created_frame
    ppc_sp*   newSP = ((ppc_sp*)  sp)->push_new_sp( sd_of_created_frame->return_pc(),
                                                    newNM->frameSize(),
                                                    true );
    if (stk->isStackOverflow(newSP)) {
      fatal("stack overflow while converting stack frame");
    }
    sp = (char*)newSP;
    
    newFr = (frame*)newSP;
    rlFr  = (frame*)newSP->push_new_sp((char*)&ReturnTrap_returnPC,
                                       ReturnTrap_frame_size,
                                       true); // PPC needs frame for all saved regs
    newFrRl = RegisterLocator::for_NonVolSaving_frame(rlFr);    
    RegisterLocator* caller_rl_after_creating_frame  = newFrRl->sender();
    
    // make sure all saved non vol regs for higher frames
    // are saved in either this frame or the spoof SaveNonVolRegs frame
    for (fint i = LowestLocalNonVolReg;  i <= HighestNonVolReg;  ++i ) {
      oop* srcp = caller_rl_before_creating_frame->address_of(Location(i));
      oop* dstp = caller_rl_after_creating_frame ->address_of(Location(i));
      *dstp = *srcp;
    }
    sd = sd_of_created_frame;    
    return isInInterruptCheck;
  }
Example #8
0
 void AgingStub::init(nmethod* nm) {
   CountCodePattern* patt = CountStub::pattern[Comparing];
   set_recompile_addr(first_inst_addr(MakeOld_stub));
   set_count_addr(patt, (int32)&sendCounts[id()]);
   int32* p = (int32*)(int32(insts()) + patt->limit_offset);
   assert(*p == patt->initial_limit, "???"); 
   fint limit = nm->agingLimit();
   *p = limit;
   set_count(1);    
 } 
Example #9
0
 void BlockCloneNode::genCall() {
   Location dest = block()->loc;
   genHelper->loadImmediateOop(block()->block, CReceiverReg);   // load block Oop
   theAssembler->CallP(first_inst_addr(blockClone->fn()));
   theAssembler->OrR(SP, G0, Arg1);                    // load home frame
   assert(!blockClone->canScavenge() && !blockClone->needsNLRCode(),
          "need to rewrite this");
   genHelper->moveRegToLoc(ResultReg, dest);
   if (block()->uplevelR && isRegister(dest)) {
     // flush to stack
     theAssembler->StoreI(SP, spOffset(dest), dest);
   }
 }
Example #10
0
 void AgingStub::init(nmethod* nm) {
   CountCodePattern* patt = CountStub::pattern[Comparing];
   int32* p = (int32*)insts();
   set_recompile_addr(first_inst_addr(MakeOld_stub));
   set_count_addr(patt, (int32)&sendCounts[id()]);
   fint limit = nm->agingLimit();
   if (limit > 1023) {
     setSetHiImm(p + patt->limit_sethi_offset, limit);
   } else {
     // setHi would set to 0, so use an add instead
     p[patt->limit_sethi_offset] = add_inst;
     setArithImm(p + patt->limit_sethi_offset, limit);
   }
   set_count(1);
 }
Example #11
0
 void PrimNode::gen() {
   BasicNode::gen();
   assert(bci() != IllegalBCI, "should have legal bci");
   if (pd->canWalkStack()) genPcDesc();
   theAssembler->CallP(first_inst_addr(pd->fn()));
   fint skip = pd->canScavenge() ? oopSize : 0;      // reg. mask
   if (pd->needsNLRCode()) skip += sendDesc::abortable_prim_end_offset - sendDesc::nonabortable_prim_end_offset;
   if (skip) {
     // skip register mask / NLR code upon return
     theAssembler->AddI(CalleeReturnAddr, skip, CalleeReturnAddr);
     theAssembler->Data(mask());
     if (pd->needsNLRCode()) nlrCode();
   } else {
     theAssembler->Nop();
   }
 }
Example #12
0
  void SICGenHelper::checkRecompilation(fint countID) {
    // test for recompilation
    //   sethi &counter, t3
    //   load  [t3 + lo%(&counter)], t4
    //   add t4, 1, t4
    //   cmp t4, recompileLimit
    //   bne ok
    //   store t4, [t3 + lo%(&counter)]
    //   <jumpTo recompiler>
    //   nop
    // ok:

    // di recompilation doesn't work right now - see recompile.c
    if (theSIC->diLink) return;
    Assembler* ass = theAssembler;

    ass->Comment("test for recompilation");
    void* counter = &useCount[countID];
    ass->SetHiA(counter, Temp3);
    ass->LoadA(Temp3, counter, Temp2);
    ass->AddI(Temp2, 1, Temp2);
    fint limit = recompileLimit(0);
    if (limit < maxImmediate) {
      ass->SubCCI(Temp2, limit, G0);
    } else {
      ass->SetHiI2(limit, Temp1);           // limit is multiple of 1024
      ass->SubCCR(Temp2, Temp1, G0);
    }
    Label* ok = ass->BneForward(false);
    // call recompiler
    void* fnaddr = first_inst_addr(
                     theSIC->diLink ? Memory->zone->DIRecompile_stub_td()
                                    : Memory->zone->  Recompile_stub_td() );
    Location linkReg = theSIC->diLink ? DIRecompileLinkReg : RecompileLinkReg;
    jumpTo(fnaddr, linkReg, linkReg);
    // The store below is always executed so that we will call the recompiler 
    // exactly once (even if it cannot recompile for some reason).
    ok->define();
    assert(Temp3 != linkReg, "counter addr reg will be trashed by jump");
    ass->StoreA(Temp3, counter, Temp2);
  }
Example #13
0
// Handle an OS signal that won't be passed to Self
void SignalInterface::handle_OS_signal(int ossig, char* addr, int32 code) {

  FlagSettingInt fs(errno, 0);  // save errno

  if (eventLog != NULL) // might not exist yet
    LOG_EVENT3("signal %ld pc %#lx npc %#lx",
               ossig, InterruptedContext::the_interrupted_context->pc(), InterruptedContext::the_interrupted_context->next_pc());
            
  # if TARGET_OS_VERSION != MACOSX_VERSION
  assert(!is_off_signal_stack(), "should be on interrupt stack");
  # endif
  // Linux???
  
  if (handle_SIC_OS_signal(ossig, addr, code))
    return;
# if TARGET_OS_VERSION == LINUX_VERSION
  lprintf("\nInternal error: signal %d code %d addr 0x%lx pc 0x%lx.\n",
         (void*)ossig, (void*)code, (void*)(long unsigned)addr,
         (void*)(long unsigned)(InterruptedContext::the_interrupted_context->pc()));
# else
  lprintf("\nInternal error: signal %d (sig%s) code %d addr 0x%lx pc 0x%lx.\n",
         (void*)ossig, (void*)sys_signame[ossig],
         (void*)code, (void*)(long unsigned)addr,
         (void*)(long unsigned)(InterruptedContext::the_interrupted_context->pc()));
# endif
  error_breakpoint();
  if (WizardAbortMode) {
    // for better VM debugging - see regs and stack undisturbed, but
    // printing/traversing Self stack may break
    InterruptedContext::fatal_menu();
  } 
  else {
    // let user print the stack etc; easier to do in user context
    WizardAbortMode = true; // next bit might fail over and over
    InterruptedContext::continue_abort_at(first_inst_addr(InterruptedContext::fatal_menu), true);
    AbortContext.set(InterruptedContext::the_interrupted_context);
  }
}
Example #14
0
Location frame::location_of_interpreter_of_block_scope(void* entry_point) {
  return  entry_point == first_inst_addr(interpret)  
            ?  CReceiverReg
            :  IllegalLocation;
}
Example #15
0
sendDesc* sendDesc::first_sendDesc() {
  // assertion is in sendDes::init
  return sendDesc::sendDesc_from_return_PC(
           first_inst_addr((void*)firstSelfFrame_returnPC));
}
Example #16
0
void handleMapLoadTrap(InterruptedContext* c) {
    int32* pc = (int32*)c->pc();
    assert(isMapLoad(pc), "not a map load");
    assert(c->next_pc() == c->pc() + 4, "flow should be sequential");
    Location dest = Location(rd(pc));
    mapOop resultMap;
    
    // get the result map to load
    # if  TARGET_OS_VERSION == SOLARIS_VERSION_broken
        // disabled for now -- there's some bug in get_reg  --Urs 8/94
        Location src = Location(rs1(pc));
        fint rcvrTag = int(c->get_reg(src)) & Tag_Mask;
        if (rcvrTag == Int_Tag) {
          resultMap = Memory->smi_map->enclosing_mapOop();
        } else if (rcvrTag == Float_Tag) {
          resultMap = Memory->float_map->enclosing_mapOop();
        } else {
          fatal("bad receiver tag in map load trap");
        }
    # else
        // Can't read registers, and signal handler doesn't get faulting address,
        // so don't know what the correct map is.  But it's not really needed
        // (only important thing is that it's different from any mem map) since
        // the map testing code always checks the tag if an immediate is expected.
        resultMap = NULL;
    # endif

    NCodeBase* thing = findThing(pc);
    if (!thing->isNMethod()) {
      // a PIC -- no problem, will fix itself to eliminate trap
    } else {
      nmethod* nm = findNMethod(pc);
      if ((char*)pc >= nm->verifiedEntryPoint()) {
        // the trap happened in the body, not in the prologue
        if (nm->flags.trapCount > MapLoadTrapLimit) {
          // recompile the nmethod on next invocation to eliminate the traps
          nm->makeToBeRecompiled();
          if (nm->isYoung())
            // manipulate counters to provoke recompilation
            nm->makeVeryYoung();
          else
            nm->makeYoung();
        } else {
          nm->flags.trapCount++;
          if (nm->flags.trapCount <= 0) {
            // counter overflowed
            nm->flags.trapCount--;
          }
        }
      }
    }
    # if  TARGET_OS_VERSION == SOLARIS_VERSION
        // simply set the destination register and continue
        c->set_reg(dest, resultMap);
        c->set_pc(c->next_pc());
        c->set_next_pc(c->pc() + 4);
    # elif  TARGET_OS_VERSION == SUNOS_VERSION
        // can't set register in interrupt handler - argh!!
        if (mapLoadHandler[dest]) {
          char* cont = c->next_pc();
          InterruptedContext::set_continuation_address(first_inst_addr(mapLoadHandler[dest]), true, true);
          continuePC = cont;
          mapToLoad = resultMap;
        } else {
          fatal1("map load trap: bad destination register %d", dest);
        }
    # endif
}
Example #17
0
Location frame::location_of_interpreter_of_block_scope(void* entry_point) {
  return  entry_point == first_inst_addr(interpret)  
            ?  Location(IArgLocation(0))  
            :  IllegalLocation;
}