Exemple #1
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;
}
Exemple #2
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;
  }
Exemple #3
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();
}
Exemple #4
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);
   }
 }
Exemple #5
0
fint Lookup::argCountForLookupError(oop_t selector, fint perform_arg_count, LookupType lookupType) {
  fint argc;

  if (isPerformLookupType(lookupType)) {
    assert(perform_arg_count >= 0); // should have a static selector or a perform arg count
    argc = perform_arg_count;
  } else {
    assert(is_byteVector(selector)); // should be a string if static
    argc = ByteVectorObj::from(selector)->arg_count();
  }
  assert(argc >= 0 && argc < MAX_ARGS);
  return argc;
}
Exemple #6
0
void sendDesc::print() {
  if (isPrimCall()) {
    PrimDesc *pd= getPrimDescOfFirstInstruction(jump_addr(), true);
    lprintf("primitive: %s\n", pd->name());
    return;
  } 
  printIndent();
  printLookupType(raw_lookupType());
  LookupType l= lookupType();
  if (isPerformLookupType(l)) {
    lprintf(": argc: %ld", arg_count());
  } else {
    lprintf(": selector: ");
    selector()->print_real_oop();
  }
  if (l & DelegateeStaticBit) {
    lprintf(": delegatee: ");
    delegatee()->print_real_oop();
  }
  Indent++;
  printIndent();
  lprintf("addr: %#lx", jump_addr());
  if (Memory->code->contains(jump_addr())) {
    lprintf(" (nmethod %#lx)", nmethod::findNMethod(jump_addr()));
  }
  lprintf("; mask: "); printMask(mask());
  lprintf("\n");
  printIndent();
  lprintf("dependency: ");
  dependency()->print();
  lprintf("\n");
  if (pic()) {
    printIndent();
    lprintf("PIC: p ((CacheStub*)%#lx)->print()\n", pic());
  }
  if (countStub()) {
    printIndent();
    lprintf("count stub: p ((CountStub*)%#lx)->print()\n",
            countStub());
  }
  Indent --;
}
Exemple #7
0
void sendDesc::extend(nmethod* nm, mapOop receiverMapOop,
                      CountStub *cs_from_pic) {
  char *addr;
  bool isPerform= isPerformLookupType(raw_lookupType());
  if (   PIC && !isPerform
      && (addr= jump_addr(), addr != lookupRoutine())) {
    // already has at least one nmethod linked to the send
    CacheStub* s= pic();
    # if GENERATE_DEBUGGING_AIDS
      if (CheckAssertions) {
        assert(cs_from_pic==NULL, "discarding countStub?");
        if (!s) {
          // turning monomorphic ic into PIC; PIC will carry dependencies
          assert(dependency()->notEmpty(), "shouldn't be empty");
          // check for duplicate nmethod & rcvr map
          CountStub *oldcs= countStub();
          nmethod *oldnm= oldcs ? oldcs->target() : nmethod::findNMethod(addr);
          assert(   oldnm != nm
                 || receiverMapOop != oldnm->key.receiverMapOop(),
                 "already linked to this nmethod, why rebind?? (maybe I-cache did not get flushed)");
        }
      }
    # endif
    s= s->extend(this, nm, receiverMapOop);
    assert(s, "should have a PIC now");
    assert(dependency()->next == dependency()->prev, "more than one link");
  } else {
    // first time we execute this send, or PICs disabled, or perform, or
    // rebinding after a PIC has been removed, or non-map related misses
    if (isPerform) NumberOfPerformMisses++;
    if (!PIC) {
      CacheStub *s= pic();
      // remove existing PIC
      if (s) s->deallocate();
    }
    rebind(nm, NULL, cs_from_pic);
  }
  MachineCache::flush_instruction_cache_for_debugging();
  if (VerifyZoneOften) verify();
}
Exemple #8
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!
}
Exemple #9
0
bool sendDesc::verify() {
  if (isPrimCall()) return true;
  LookupType l= lookupType();
  bool flag= checkLookupTypeAndEntryPoint();
  
  if (isPerformLookupType(l)) {
    if (arg_count() < 0 || arg_count() > 100) {
      error2("sendDesc %#lx arg count %ld is invalid", this, arg_count());
      flag = false;
    }
  } else {
    if (! oop(selector())->verify_oop()) {
      flag = false;
    } else if (! selector()->is_string()) {
      error1("sendDesc %#lx selector isn't a string", this);
      flag = false;
    }
    nmethod* nm = target();
    if (nm == NULL) {
      CountStub* cs = countStub();
      if (cs) nm = cs->target();
    }
    if (nm == NULL) {
      CacheStub* cs = pic();
      if (cs) {
        nm= cs->get_method(0);
        oop sel= nm->key.selector;
        for (fint i= 1; i < cs->arity(); ++i)
          if (cs->get_method(i)->key.selector != sel)
            error2("sendDesc %#lx: selector != PIC case %d selector",
                   this, i);
      }
    }
    if (nm && nm->key.selector != selector())
      error1("sendDesc %#lx: selector != target nmethod's selector", this);
  }
  if (l & DelegateeStaticBit) {
    if (! delegatee()->verify_oop()) {
      flag = false;
    } else if (baseLookupType(l) == DirectedResendLookupType &&
               ! delegatee()->is_string()) {
      error1("sendDesc %#lx delegatee isn't a string", this);
      flag = false;
    }
  }
  if (!dependency()->verify_list_integrity()) {
    lprintf("\tof sendDesc %#lx\n", this);
    flag = false;
  }
  if (pic()) {
    if (dependency()->next != dependency()->prev)
      error1("sendDesc %#lx: more than one elem in dependency chain", this);
    pic()->verify();
  } else {
    CountStub *cs= countStub();
    if (cs == NULL) {
      if (isCounting() && jump_addr() != lookupRoutine())
        error1("sendDesc %#lx: doesn't have countStub but is counting", this);
    } else {
      if (!isCounting() && !cs->isAgingStub())
        error1("sendDesc %#lx: has countStub but is not counting", this);
      if (dependency()->next != dependency()->prev)
        error1("sendDesc %#lx: more than one elem in dependency chain", this);
      countStub()->verify2(NULL);
    }
  }
  return flag;
}