Beispiel #1
0
 SSelfScope* SCodeScope::notify(stringOop selector, const char* msg) {
   if (PrintInlining) {
     lprintf("%*s*cannot inline %s, cost = %ld (%s)\n", (void*)depth, "",
             selector_string(selector), (void*)msgCost, msg);
   }
   return NULL;        // cheap trick to make calls more convenient
 }
Beispiel #2
0
void ShowCompileInMonitor::do_show_compile(oop sel, char* compiler, bool optimize) {
  method_being_compiled = selector_string(sel);
  current_compiler_name = compiler;
  current_compiler_ticks = &compiler_ticks[optimize];
  assert(optimize == 0 || optimize == 1, "should use true or false");
  recompiling = recompilee != NULL;
}
Beispiel #3
0
 bool SCodeScope::calleeTooBig(SendInfo* info, RScope* rs,
                               InlineLimitType limitType) {
   // try to see if the potential inlinee is too big
   fint size = calleeSize(rs);
   // NB: continue even if size == 0 to bring current estimated size into play
   assert(limitType <= BlockFnLimit, "bad limit");
   limitType = InlineLimitType(limitType + NormalFnInstrLimit-NormalFnLimit);
   fint cutoff = theSIC->inlineLimit[limitType];
   fint estimated = theSIC->estimatedSize();
   fint limit = theSIC->inlineLimit[NmInstrLimit];
   // reject if inlinee too large, but correct for well-known cheap messages
   bool bad = size > cutoff &&
     !(info->rcvr->hasMap() &&
       isCheapMessage(info->sel, info->rcvr->myMapOop()));
   if (bad && estimated + size < limit / 2) {
     // allow inlining if recompilee itself is small (i.e., a forwarder)
     if (recompilee &&
         recompilee->instsLen() - oopSize * PrologueSize < cutoff) {
       bad = false;
     }
   }
   // also reject if est. total size too large (except for ifTrue et al)
   // but don't trust the isCheap thing if we're way over the limit
   bad = bad || estimated + size >= limit;
   if (bad &&
       estimated + size < 2 * limit &&
       (size == 0 || size < cutoff / 8) &&
       info->rcvr->hasMap() &&
       isReallyCheapMessage(info->sel, info->rcvr->myMapOop())) {
     bad = false;
   }
   if (bad && PrintInlining) {
     lprintf("%*s*not inlining %s: callee too big (%d/%d/%d/%d)\n", (void*)depth, "",
             selector_string(info->sel),
             (void*)size, (void*)cutoff, (void*)estimated, (void*)limit);
   }
   if (SICDebug && bad && estimated > limit)
     warning4("SIC: (while compiling %s/%s) estimated nmethod size > limit (%ld > %ld)",
              selector_string(theSIC->L->selector()),
              selector_string(info->sel), estimated, limit);
   return bad;
 }
Beispiel #4
0
 SExpr* SCodeScope::doInline(SSelfScope* s, SExpr* rcvr, Node* start,
                             MergeNode* end) {
   s->receiver = rcvr->asReceiver();
   if (PrintInlining) {
     lprintf("%*s*inlining %s, cost %ld/size %ld (%#lx)%s\n", (void*)depth, "",
             (s->isCodeScope() 
               ? sprintName((methodMap*)s->method()->map(), s->selector())
               : selector_string(s->selector())), // was: selector_string(s->selector()),
              (void*)msgCost, (void*)calleeSize(s->rscope),
             s, s->rscope->isNullScope() ? "" : "*");
   }
   Node* next = start->next();
   if (next) start->removeNext(next);
   theNodeGen->current = start;
   s->genCode();
   if (next && end) theNodeGen->branch(end);
   return s->result;
 }
Beispiel #5
0
 bool SCodeScope::calleeIsSmall(SendInfo* info, RScope* rs,
                                InlineLimitType limitType) {
   // try to see if the potential inlinee is small
   fint size = calleeSize(rs);
   if (!size) return false;    // no size info
   assert(limitType <= BlockFnLimit, "bad limit");
   limitType = InlineLimitType(limitType + NormalFnInstrLimit-NormalFnLimit);
   fint cutoff = theSIC->inlineLimit[limitType];
   fint estimated = theSIC->estimatedSize();
   fint limit = theSIC->inlineLimit[NmInstrLimit];
   bool ok = size <= cutoff && estimated + size < limit;
   if (ok && PrintInlining) {
     lprintf("%*s*inlining %s anyway: callee is small (%d/%d/%d/%d)\n",
             (void*)depth, "", selector_string(info->sel),
             (void*)size, (void*)cutoff, (void*)estimated, (void*)limit);
   }
   return ok;
 }
Beispiel #6
0
char* InliningDatabase::compute_file_name(LookupKey* outer, LookupKey* inner, bool create_directories) {
  char* name = NEW_RESOURCE_ARRAY(char, 1024);

  // Outer key
  char* outer_klass_name    = mangle_name(klass_string(outer->klass()));
  char* outer_selector_name = mangle_name(selector_string(outer->selector()));

  if (create_directories) {
    if (!check_directory(directory())) return NULL;
  }

  strcpy(name, directory());
  strcat(name, "\\");
  strcat(name, outer_klass_name);

  if (create_directories) {
    if (!check_directory(name)) return NULL;
  }

  strcat(name, "\\");
  strcat(name, outer_selector_name);

  if (inner) {
    // Inner key
    char* inner_klass_name  = mangle_name(klass_string(inner->klass()));
    char* inner_method_name = mangle_name(method_string(inner->method()));

    if (create_directories) {
      if (!check_directory(name)) return NULL;
    }
    strcat(name, "\\");
    strcat(name, inner_klass_name);

    if (create_directories) {
      if (!check_directory(name)) return NULL;
    }
    strcat(name, "\\");
    strcat(name, inner_method_name);
  }
  strcat(name, ".txt");
  return name;
}
Beispiel #7
0
  SExpr* SCodeScope::inlineMerge(SendInfo* info, MergeNode*& merge) {
    // inline the send by type-casing; return uninlined cases in others list
    // If merge has no predecessors, return NULL for merge ref.
    SExpr* res = NULL;
    assert(info->rcvr->isMergeSExpr(), "must be a merge");
    MergeSExpr* r = (MergeSExpr*)info->rcvr;
    stringOop sel = info->sel;
    merge = NULL;

    if (r->isSplittable() && shouldSplit(info)) {
      return splitMerge(info, merge);
    }
                    
    fint ncases = r->exprs->length();
    if (ncases > SICTypeCaseLimit) {
      info->needRealSend = true;
      if (PrintInlining) {
        lprintf("%*s*not type-casing %s (%ld > SICTypeCaseLimit)\n",
                (void*)depth, "", selector_string(sel), (void*)ncases);
      }
      return res;
    }
    assert( merge == NULL, "I assume merge is out param only");
    merge = new MergeNode("inlineMerge merge");

    if (SICDebug) {
      char* s = NEW_RESOURCE_ARRAY(char, 200);
      sprintf(s, "begin type-case of %s (ends at node N%ld)",
              sel->copy_null_terminated(), long(merge->id()));
      theNodeGen->comment(s);
    }
    if (PrintInlining) {
      lprintf("%*s*type-casing %s\n", (void*)depth, "", selector_string(sel));
    }

    // build list of cases to inline
    // (add only immediate maps at first, collect others in ...2 lists
    SSelfScopeBList* slist  = new SSelfScopeBList(ncases);
    SSelfScopeBList* slist2 = new SSelfScopeBList(ncases);
    SExprBList* elist  = new SExprBList(ncases);
    SExprBList* elist2 = new SExprBList(ncases);
    SExprBList* others = new SExprBList(ncases);
    OopBList* mlist  = new OopBList(ncases);
    OopBList* mlist2 = new OopBList(ncases);
    bool needMapLoad = false;
    fint i;
    for (i = 0; i < ncases; i++) {    
      SExpr* nth = r->exprs->nth(i);
      assert(!nth->isConstantSExpr() || nth->next == NULL ||
             nth->constant() == nth->next->constant(),
             "shouldn't happen: merged consts - convert to map");
      SSelfScope* s;

      if (!nth->hasMap()  ||  (s = tryLookup(info, nth)) == NULL) {
        // cannot inline
        others->append(nth);
        info->needRealSend = true;
        continue;
      }
      // can inline this case

      // Notice that for immediates, instead of putting the constants in the mlist,
      // we put the maps. No point in optimizing just for 17. -- dmu 6/05
      Map* map = nth->map();
      if (map == Memory->smi_map  ||  map == Memory->float_map) {
        slist ->append(s);        // immediate maps go first
        // Bug fix: instead of nth->shallowCopy, must generalize to any 
        // with same map, not just the same constant, because other ints (for example)
        // will pass the type test, too. -- dmu 6/05
        elist ->append(new MapSExpr(map->enclosing_mapOop(), r->preg(), NULL));
        mlist ->append(map->enclosing_mapOop());
        continue;
      }
      // can inline but not immediate map
      slist2->append(s);        // append later
      elist2->append(nth->shallowCopy(r->preg(), NULL)); // use preg of merge
      if (nth->isConstantSExpr()) {
        mlist2->append(nth->constant());
      }
      else {
        needMapLoad = true; // will need to load map of testee
        mlist2->append(map->enclosing_mapOop());
      }
    }

    mlist->appendList(mlist2);
    elist->appendList(elist2);
    slist->appendList(slist2);
        
    // now do the type test and inline the individual cases
    if (slist->length() > 0) {
      memoizeBlocks(sel);
      
      Node* typeCase =
        theNodeGen->append(new TypeTestNode(r->preg(), mlist, needMapLoad,
                                            info->needRealSend));
      Node* fallThrough = typeCase->append(new NopNode);
      for (i = 0; i < slist->length(); i++) {
        theNodeGen->current = typeCase->append(i + 1, new NopNode);
        SExpr* e = doInline(slist->nth(i), elist->nth(i), theNodeGen->current, merge);
        if (!e->isNoResultSExpr()) {
          theNodeGen->append(new NopNode);
          e = e->shallowCopy(info->resReg, theNodeGen->current);
          res = res ? res->mergeWith(e, merge) : e;
        }
        theNodeGen->branch(merge);
      }
      theNodeGen->current = fallThrough;
    }
    if (res && res->isMergeSExpr()) 
      res->setNode(merge, info->resReg);
      
    assert( info->needRealSend &&  others->length() ||
           !info->needRealSend && !others->length(), "inconsistent");
           
    // NB: *must* use uncommon branch if marked unlikely because
    // future type tests won't test for unknown
                      
    if (others->isEmpty()) {
      // typecase cannot fail
      theNodeGen->deadEnd();
    }
    else if ( others->length() == 1
         &&   others->first()->isUnknownSExpr()
         &&   ((UnknownSExpr*)others->first())->isUnlikely()) {
            // generate an uncommon branch for the unknown case, not a send
            theNodeGen->uncommonBranch(currentExprStack(0), info->restartPrim);
            info->needRealSend = false;
            if (PrintInlining)
              lprintf("%*s*making %s uncommon (2)\n", (void*)depth,"",selector_string(sel));
    }
    return res;
  }
Beispiel #8
0
  SExpr* SCodeScope::inlineSend(SendInfo* info) {
    stringOop sel = info->sel;
    SExpr* res = NULL;
    info->resReg = new SAPReg(this);
    MergeNode* merge = NULL;
    fint argc = sel->arg_count();

    if (!Inline && !InlineSTMessages) {
      // don't do any inlining
      info->needRealSend = true;
    } else {
      info->rcvr = picPredict(info);
      UnknownSExpr* u = info->rcvr->findUnknown();
      if (u && !u->isUnlikely()) {
        info->rcvr = typePredict(info);
      }
      
      if (info->rcvr->really_hasMap(this)) {
        // single map - try to inline this send
        SSelfScope* s = tryLookup(info, info->rcvr);
        if (s) {
          SExpr* r = doInline(s, info->rcvr, theNodeGen->current, NULL);
          if (r->isNoResultSExpr()) {
            res = r;
          } else {
            theNodeGen->append(new NopNode());   // to get right scope for r
            res = r->shallowCopy(r->preg(), theNodeGen->current);
          }
        } else {
          if (PrintInlining) {
            lprintf("%*s*marking %s send ReceiverStatic\n",
                    (void*)depth,"", selector_string(sel));
          }
          // receiver type is constant (but e.g. method was too big to inline)
          info->l |= ReceiverStaticBit;
          info->needRealSend = true;
        }
      } else if (info->rcvr->isMergeSExpr()) {
        res = inlineMerge(info, merge);
      } else {
        // unknown receiver
        // NB: *must* use uncommon branch if marked unlikely because
        // future type tests won't test for unknown
        if (info->rcvr->findUnknown()->isUnlikely()) {
          // generate an uncommon branch for the unknown case, not a send
          theNodeGen->current = theNodeGen->uncommonBranch(currentExprStack(0),
                                                           info->restartPrim);
          info->needRealSend = false;
          if (PrintInlining) {
            lprintf("%*s*making %s uncommon\n", (void*)depth,"",selector_string(sel));
          }
        } else {
          info->needRealSend = true;
        }
      }
    }
    
    if (info->needRealSend) {
      SExpr* r = genRealSend(info);
      res = res ? res->mergeWith(r, merge) : r;
    }
    if (merge && res && !res->isNoResultSExpr()) theNodeGen->branch(merge);

    // now pop expr stack
    for (fint i = 0; i < argc; i++) exprStack->pop();
    if (!info->isSelfImplicit) exprStack->pop();
    if (!res) res = new NoResultSExpr;
    return res;
  }