Esempio n. 1
0
void Compiler::initLimits() {
  if (recompileeRScope) {
    // We're compiling from the inlining data base
    _nextLevel = MaxRecompilationLevels - 1;
  } else if (recompilee) {
    if (DeltaProcess::active()->isUncommon()) {
      // when recompiling because of an uncommon trap, reset level
      _nextLevel = 0;
    } else {
      _nextLevel = recompilee->level() + 1;
      if (_nextLevel >= MaxRecompilationLevels) {
	warning("recompilation level too high -- should not happen");
	_nextLevel = MaxRecompilationLevels;
      }
    }
  } else {
    // new nmethod
    _nextLevel = 0;
  }
  _noInlinableSends = true;

#ifdef LATER
  inlineLimit[NormalFnLimit] 	     = getLimit(limits[NormalFnLimit],		level);
  inlineLimit[BlockFnLimit] 	     = getLimit(limits[BlockFnLimit],		level);
  inlineLimit[BlockArgFnLimit]       = getLimit(limits[BlockArgFnLimit],	level);
  inlineLimit[NormalFnInstrLimit]    = getLimit(limits[NormalFnInstrLimit],	level);
  inlineLimit[BlockFnInstrLimit]     = getLimit(limits[BlockFnInstrLimit],	level);
  inlineLimit[BlockArgFnInstrLimit]  = getLimit(limits[BlockArgFnInstrLimit],	level);
  inlineLimit[SplitCostLimit]        = getLimit(limits[SplitCostLimit],		level);
  inlineLimit[NmInstrLimit]          = getLimit(limits[NmInstrLimit],		level);

  if (CompilerAdjustLimits) {
    // adjust NmInstrLimit if top-level method is large
    int cost = sicCost((methodKlass*)method->klass(), topScope, costP);
    if (cost > NormalMethodLen) {
      float l = (float)cost / NormalMethodLen * inlineLimit[NmInstrLimit];
      inlineLimit[NmInstrLimit] = min(int(l), CompilerInstructionsSize / 3);
    }
  }
#endif
}
Esempio n. 2
0
  void SICompiler::initLimits() {
    fint level;
    if (currentProcess->isUncommon()) {
      // when recompiling because of an uncommon trap, reset level
      level = nextLevel = 0;
    } else {
      level = AbstractCompiler::level();
      nextLevel = MaxRecompilationLevels - 1;
      if (nstages > 1 && recompilee == NULL) {
        // always use a counter in first version
        nextLevel = nstages - 1;
      }
    }
    noInlinableSends = true;

    inlineLimit[NormalFnLimit]         = getLimit(limits[NormalFnLimit],
                                                  level);
    inlineLimit[BlockFnLimit]          = getLimit(limits[BlockFnLimit],
                                                  level);
    inlineLimit[BlockArgFnLimit]       = getLimit(limits[BlockArgFnLimit],
                                                  level);
    inlineLimit[NormalFnInstrLimit]    = getLimit(limits[NormalFnInstrLimit],
                                                  level);
    inlineLimit[BlockFnInstrLimit]     = getLimit(limits[BlockFnInstrLimit],
                                                  level);
    inlineLimit[BlockArgFnInstrLimit]  = getLimit(limits[BlockArgFnInstrLimit],
                                                  level);
    inlineLimit[SplitCostLimit]        = getLimit(limits[SplitCostLimit],
                                                  level);
    inlineLimit[NmInstrLimit]          = getLimit(limits[NmInstrLimit],
                                                  level);
    if (SICAdjustLimits) {
      // adjust NmInstrLimit if top-level method is large
      fint cost = sicCost( method(), topScope, costP);
      if (cost > NormalMethodLen) {
        float l = (float)cost / NormalMethodLen * inlineLimit[NmInstrLimit];
        inlineLimit[NmInstrLimit] = min(int(l), SICInstructionsSize / 3);
      }
    }
  }
Esempio n. 3
0
  bool SCodeScope::shouldInlineSend(SendInfo* info, RScope* rs, SExpr* rcvr,
                                    oop m, InlineLimitType limitType) {
    MethodLookupKey* k = info->key;
    if (!k->selector->is_string()) return false;

    if (isRecursiveCall(m, k->receiverMapOop(), MaxRecursionUnroll)) {
      info->uninlinable = true;
      return false;
    }
    
    if (!Inline) {
      assert(InlineSTMessages, "shouldn't be here");
      // NB: works only with rewritten whileTrue/False (using _Restart)
      if (isSmalltalkInlined(k->selector)) return true;
      if (isSmalltalkInlined(selector())) return true;
      return false;
    }

    if (limitType == NormalFnLimit) {
      // check args to see if any of them is a block; if so, increase limit
      fint top = exprStack->length();
      fint argc = stringOop(k->selector)->arg_count();
      for (fint i = argc; i > 0; i--) {
        if (exprStack->nth(top - i)->preg()->isBlockPReg()) {
          limitType = BlockArgFnLimit;
          goto done;
        }
      }
      // check receiver
      if (lookupReceiverIsSelf(k->lookupType)) {
        if (self->preg()->isBlockPReg()) limitType = BlockArgFnLimit;
      } else if (exprStack->nth(top - argc - 1)->preg()->isBlockPReg()) {
        limitType = BlockArgFnLimit;
      }
    }
    
   done:
    if (calleeTooBig(info, rs, limitType)) {
      // register this send as uninlinable
      theSIC->registerUninlinable(info, limitType, 9999);
      return false;
    }

    // NB: this test comes after calleeTooBig to prevent forced inlining of
    // e.g. a really complicated user-defined '+' for matrices
    if (isCheapMessage(stringOop(k->selector))) {
      msgCost = costP->cheapSendCost;
      return true;
    }

    fint cutoff = theSIC->inlineLimit[limitType];
    msgCost = sicCost( m, this, costP);
    if (info->primFailure &&
        info->nsends < MinPrimFailureInvocations) {
      if (rs->isPICScope() && ((RPICScope*)rs)->sd->isOptimized()) {
        // the fail block send is optimized, it's probably executed frequently
      } else if (rs->isSelfScope()) {
        // was inlined in previous version, so do it again
      } else {
        // don't inline error block unless trivial or taken often
        if (msgCost > MaxTrivialPrimFailureCost) return false;
        // should also look at block method, not default value:With:
        Map* map = rcvr->map();
        if (map->is_block()) {
          slotsOop method = ((blockMap*)map)->value();
          msgCost = sicCost( method, this, failCostP);
          // bug: should estimate real length of prim failure; e.g. could
          // have single send (cost 1) but that method sends more and more
          // msgs...i.e. need concept of "being in fail branch" so that
          // no further inlining takes place -- fix this
          if (msgCost > MaxTrivialPrimFailureCost) return false;
        }
      }
    }
    if (msgCost > cutoff) {
      if (calleeIsSmall(info, rs, limitType)) return true;
      theSIC->registerUninlinable(info, limitType, msgCost);
      return false;
    }
    return true;
  }