Example #1
0
void InlinedScope::genCode() {
  _hasBeenGenerated = true;
  prologue();
  // always generate (shared) entry points for ordinary & non-local return
  _returnPoint        = NodeFactory::new_MergeNode(EpilogueBCI);
  _NLReturnPoint      = NodeFactory::new_MergeNode(EpilogueBCI);
  _nlrTestPoint       = NULL;
  _contextInitializer = NULL;
  int nofTemps = method()->number_of_stack_temporaries();
  if (isTop()) {
    _returnPoint->append(NodeFactory::new_ReturnNode(resultPR, EpilogueBCI));
    _NLReturnPoint->append(NodeFactory::new_NLRSetupNode(resultPR, EpilogueBCI));
    Node* first = NodeFactory::new_PrologueNode(key(), nofArguments(), nofTemps);
    theCompiler->firstNode = first;
    gen()->setCurrent(first);
  }
  // allocate space for temporaries - initialization done in the prologue code
  assert(!hasTemporaries(), "should have no temporaries yet\n");
  createTemporaries(nofTemps);
  // allocate space for float temporaries
  int nofFloats = method()->total_number_of_floats();
  if (UseFPUStack) {
    const int FPUStackSize = 8;
    if (method()->float_expression_stack_size() <= FPUStackSize) {
      // float expression stack fits in FPU stack, use it instead
      // and allocate only space for the real float temporaries
      nofFloats = method()->number_of_float_temporaries();
    } else {
      warning("possible performance bug: cannot use FPU stack for float expressions");
    }
  }
  createFloatTemporaries(nofFloats);
  // build the intermediate representation
  assert(gen()->current() != NULL, "current() should have been set before");
  MethodIterator iter(method(), gen());
  if (gen()->aborting()) {
    // ends with dead code -- clean up expression stack
    while (!exprStack()->isEmpty()) exprStack()->pop();
  }
  epilogue();
}
Example #2
0
void InlinedScope::epilogue() {
  // generate epilogue code (i.e., everything after last byte code has been processed)
  assert(exprStack()->isEmpty(), "expr. stack should be empty now");

  // first make sure subScopes are sorted by bci
  _subScopes->sort(compare_scopeBCIs);

  // now remove all subscopes that were created but not used (not inlined)
  while (! _subScopes->isEmpty() && !_subScopes->last()->hasBeenGenerated()) _subScopes->pop();
#ifdef ASSERT
  for (int i = 0; i < _subScopes->length(); i++) {
    if (!_subScopes->at(i)->hasBeenGenerated()) fatal("unused scopes should be at end");
  }
#endif

  if (_nofSends > 0 && containsNLR()) {
    // this scope *could* be the target of a non-inlined NLR; add an UnknownExpr to
    // the scope's result expression to account for this possibility
    // note: to be sure, we'd have to know that at least one nested block wasn't inlined,
    // but this analysis isn't performed until later
    addResult(new UnknownExpr(resultPR, NULL));
    // also make sure we have an NLR test point to catch the NLR
    (void)nlrTestPoint();
    assert(has_nlrTestPoint(), "should have a NLR test point now");
  }

  // generate NLR code if needed
  if (has_nlrTestPoint()) {
    // NB: assertion below is too strict -- may have an nlr node that will be connected
    // only during fixupNLRPoints()
    // assert(nlrTestPoint()->nPredecessors() > 0, "nlr node is unused??");
  } else if (isTop() && theCompiler->nlrTestPoints->nonEmpty()) {
    // the top scope doesn't have an NLR point, but needs one anyway so that inlined
    // scopes have somewhere to jump to
    (void)nlrTestPoint();
  }
  if (!result) result = new NoResultExpr;
  theCompiler->exitScope(this);
}
Example #3
0
  SExpr* SPrimScope::genPrimFailure(PrimNode* call, PReg* errorReg,
                                    Node*& test, MergeNode*& merge,
                                    PReg* resultReg, bool failure) {
    // generate primitive failure code
    // two modes:
    //    if call == NULL, omit the test for failure because it's already
    //          been generated (inlined prim.); in this case, errorReg
    //          must be set
    //    if call != NULL, generate test code (setting test & merge node args)
    // returns the result of the failure branch

    // pop prim args (they're not on the expr stack anymore in the fail branch)
    while (npop-- > 0) exprStack()->pop();
    
    SCodeScope* s = sender();
    NodeGen* ng = theNodeGen;
    if (call) {
      fint b = bci();
      SAPReg* t = new SAPReg(s, b, b);
      // extract tag field and test for mark tag
      ng->append(new ArithRCNode(AndArithOp, call->dest(), Tag_Mask, t));
      ng->append(new ArithRCNode(SubCCArithOp, t, Tag_Mask, ng->noPR));
      test = ng->append(new BranchNode(NEBranchOp));
      // failure branch; load error string
      if (!errorReg) errorReg = new SAPReg(s, b, b);
      ng->current = 
        test->append(new ArithRCNode(SubArithOp, call->dest(),
                                     Mark_Tag-Mem_Tag, errorReg));
    }

    SExpr* failReceiver = hasFailBlock ? failBlock : receiver;
    SendInfo* info = new SendInfo(failReceiver, NormalLookupType, false, false,
                                  (stringOop)failSelector, NULL);
    info->computeNSends(rscope, bci());
    info->primFailure = failure;
    info->restartPrim = call == NULL;   // restart inlined prims (unc. traps)
    s->exprStack->push(failReceiver);
    if (errorReg->isConstPReg()) {
      s->exprStack->push(new ConstantSExpr(((ConstPReg*)errorReg)->constant,
                                           errorReg, ng->current));
    } else {
      s->exprStack->push(new MapSExpr(Memory->stringObj->map()->enclosing_mapOop(),
                                      errorReg, ng->current));
    }
    ConstPReg* failSelReg = new_ConstPReg(s, selector());
    s->exprStack->push(new ConstantSExpr(selector(), failSelReg, NULL));
    SExpr* res = s->inlineSend(info);

    if (res->isNoResultSExpr()) {
      // never returns
      ng->current = merge; // set to NULL if no merge
    } 
    else {
      if (needZap) {
        assert(failBlock->preg()->isBlockPReg(), "should be a block");
        ng->zapBlock((BlockPReg*)failBlock->preg());
      }
      ng->move(res->preg(), resultReg);
      res = res->shallowCopy(resultReg, ng->current);
      // moved creation down from before if res->isNoResult... 
      //   to avoid creating unreachable merge -- dmu
      if (merge == NULL) merge = new MergeNode("genPrimFailure merge"); 
      ng->append(merge);
    }
    return res;
  }