Esempio n. 1
0
 lookupTarget* sicScopeLookupTarget::get_target_for_slot(slotDesc* s,
                                                         simpleLookup* L) {
   Unused(L);
   if (s->name == VMString[LEXICAL_PARENT]) {
     return new sicScopeLookupTarget(scope->parent());
   } else if (s->name == VMString[SELF]) {
     SExpr* t = scope->receiverExpr();
     if (t->isConstantSExpr()) {
       return (new objectLookupTarget(t->constant())) -> be_receiver();
     } else if (t->hasMap()) {
       return ( new mapLookupTarget(t->map())) -> be_receiver();
     } else {
       // don't know the receiver type
       return NULL;
     }
   } else if (! s->is_map_slot()) {
     return NULL;
   } else {
     return new objectLookupTarget(s->data);
   }
 }
Esempio n. 2
0
  SExpr* SPrimScope::inlineIntArithmetic() {
    ArithOpCode op = opcode_for_selector(_selector);
      
    bool intRcvr =
      receiver->hasMap() && receiver->map() == Memory->smi_map;
    SExpr* arg = args->nth(0);
    bool intArg = arg->hasMap() && arg->map() == Memory->smi_map;
    if ( intArg
    &&   arg->isConstantSExpr()
    &&   intRcvr
    &&   arg->constant() == as_smiOop(0)
    &&   can_fold_rcvr_op_zero_to_zero(op)) {
      if (PrintInlining)
        lprintf("%*s*constant-folding %s: 0\n", (void*)(depth-1), "", ArithOpName[op]);
      return receiver;
    }
    if (PrintInlining) lprintf("%*s*inlining %s:\n", (void*)(depth-1),
                               "", ArithOpName[op]);

    if (!TArithRRNode::isOpInlinable(op))
      return NULL;
      
    NodeGen* n = theNodeGen;
    Node* arith = n->append(new TArithRRNode(op, receiver->preg(), arg->preg(),
                                             resultPR, intRcvr, intArg));

    // success case - no overflow, int tags
    MergeNode* ok = (MergeNode*)n->append(new MergeNode("inlineIntArithmetic ok"));
    SExpr* succExpr = new MapSExpr(Memory->smi_map->enclosing_mapOop(), resultPR, ok);
    // merge of success & failure branches
    MergeNode* done = (MergeNode*)ok->append(new MergeNode("inlineIntArithmetic done"));

    // failure case
    n->current = arith->append1(new NopNode);
    if (theSIC->useUncommonTraps &&
        sender()->rscope->isUncommonAt(sender()->bci(), true)) {
      n->uncommonBranch(currentExprStack(0), true);
      n->current = done;
      if (PrintInlining) {
        lprintf("%*s*making arithmetic failure uncommon\n", (void*)(depth-1),
                "");
      }
      return succExpr;
    } else {
      fint b = bci();
      PReg* error = new SAPReg(_sender, b, b);
      if (intRcvr && intArg) {
        // must be overflow
        n->loadOop(VMString[OVERFLOWERROR], error);
      } else {
        arith->hasSideEffects_now = true;    // may fail, so can't eliminate
        if (intRcvr || TARGET_ARCH == I386_ARCH) {
          // arg & TagMask already done by TArithRRNode
          // I386 does 'em all
        } else {
          PReg* t = new TempPReg(this, Temp1, false, true);
          n->append(new ArithRCNode(AndCCArithOp, t, Tag_Mask, t));
          n->current->hasSideEffects_now = true;
        }
        // Note: this code assumes that condcode EQ means overflow
        Node* branch = n->append(new BranchNode(EQBranchOp));
        // no overflow, must be type error
        n->loadOop(VMString[BADTYPEERROR], error);
        MergeNode* cont = (MergeNode*)n->append(
          new MergeNode("inlineIntArithmetic cont"));
        // overflow error
        PReg* err = new_ConstPReg(_sender, VMString[OVERFLOWERROR]);
        n->current = branch->append1(new AssignNode(err, error));
        n->branch(cont);
      }
      Node* dummy;
      SExpr* failExpr = genPrimFailure(NULL, error, dummy, done, resultPR);
      assert(done, "merge should always exist");
      return succExpr->mergeWith(failExpr, done);
    }
  }
Esempio n. 3
0
 const char* NodeGen::splitCondBranch( MergeNode*           targetNode,
                                       bool                 isBackwards,
                                       PReg*                targetPR,
                                       SExpr*               testExpr,
                                       BranchBCTargetStack* targetStack,
                                       SExprStack*          exprStack,
                                       PRegBList*           exprStackPRs, 
                                       SplitSig*            s ) {
   // try to split a conditional branch bc to avoid materializing
   // the boolean
   
   // local splitting only for now
 
   assert(targetPR->isConstPReg(), 
          "cond branch must be testing for constant");
   oop targetOop = ((ConstPReg*)targetPR)->constant;
   
   if (!testExpr->isMergeSExpr()) 
     return "testExpr not MergeSExpr";
   if (!((MergeSExpr*)testExpr)->isSplittable()) 
     return "textExpr not splittable";
   SExprBList* exprs = ((MergeSExpr*)testExpr)->exprs;
   assert(testExpr->node(), "splittable implies node()");
   Node* preceedingMerge = testExpr->node();
   if (current != preceedingMerge)
     return "not local"; // local only for now
   
   if ( preceedingMerge->nPredecessors() != exprs->length() )
     return "would have to iterate over predecessors";
     
   fint i;
   for ( i = 0;  
         i < exprs->length(); 
         ++i) {
      SExpr* e = exprs->nth(i);
      Node* n = e->node();
      if ( !preceedingMerge->isPredecessor(n) )
        return "merge not immediately after expr node";
      if ( !e->isConstantSExpr() )
        return "merge contains non-constant expression";
   }
   MergeNode* mergeForBranching      = new MergeNode("for branching");
   MergeNode* mergeForFallingThrough = new MergeNode("for falling through");
   mergeForBranching     ->setScope(currentScope());
   mergeForFallingThrough->setScope(currentScope());
   for ( i = 0;  
         i < exprs->length();  
         ++i) {
     SExpr* e = exprs->nth(i);
     Node* n = e->node();
     MergeNode* mn = e->constant() == targetOop
       ?  mergeForBranching
       :  mergeForFallingThrough;
     mn->setPrev(n);
     n->moveNext(preceedingMerge, mn);
   }     
   while (preceedingMerge->nPredecessors())
     preceedingMerge->removePrev(preceedingMerge->prev(0));
      
   current = mergeForBranching;
   branchCode( targetNode,
               isBackwards,
               NULL,
               NULL,
               targetStack,
               exprStack,
               exprStackPRs,
               s);
               
   append(mergeForFallingThrough);
   return NULL;
 }
Esempio n. 4
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;
  }
Esempio n. 5
0
 SExpr* SCodeScope::picPredict(SendInfo* info) {
   // check PICs for information
   if (!UsePICRecompilation) return info->rcvr;
   bool canBeUnlikely = theSIC->useUncommonTraps;
   if (rscope->hasSubScopes(_bci)) {
     RScopeBList* l = rscope->subScopes(_bci);
     if (l->first()->isUntakenScope() && l->length() == 1) {
       return picPredictUnlikely(info, (RUntakenScope*)l->first());
     } else if (info->rcvr->containsUnknown()) {
       if (PrintInlining) {
         lprintf("%*s*PIC-type-predicting %s (%ld maps)\n", (void*)depth, "",
                 info->sel->copy_null_terminated(), (void*)l->length());
       }
       for (fint i = 0; i < l->length(); i++) {
         RScope* r = l->nth(i);
         SExpr* expr = r->receiverExpr();
         if (expr->isUnknownSExpr()) {
           // untaken real send (from PIC)
         } else if (expr->map()->is_block()) {
           // for now, doesn't make sense to predict block maps because of
           // map cloning
           if (PrintInlining) {
             lprintf("%*s*not predicting block map\n", (void*)depth, ""); 
           }
           canBeUnlikely = false;
         } else {
           SExpr* alreadyThere = info->rcvr->findMap(expr->myMapOop());
           if (alreadyThere) {
             // generalize to map if only have constant
             if (alreadyThere->isConstantSExpr())
               info->rcvr = info->rcvr->mergeWith(expr, NULL);
           } else {
             // add map only if type isn't already present (for splitting)
             info->predicted = true;
             info->rcvr = info->rcvr->mergeWith(expr, NULL);
             if (expr->hasConstant() && l->length() == 1) {
               // check to see if single predicted receiver is true or false;
               // if so, add other boolean to prediction.  Reduces the number
               // of uncommon branches; not doing so appears to be overly
               // aggressive (as observed experimentally)
               oop c = expr->constant();
               if (c == Memory->trueObj &&
                   !info->rcvr->findMap(Memory->false_mapOop())) {
                 SExpr* f = new ConstantSExpr(Memory->falseObj, NULL, NULL);
                 info->rcvr = info->rcvr->mergeWith(f, NULL);
               } else if (c == Memory->falseObj &&
                          !info->rcvr->findMap(Memory->true_mapOop())) {
                 SExpr* t = new ConstantSExpr(Memory->trueObj, NULL, NULL);
                 info->rcvr = info->rcvr->mergeWith(t, NULL);
               }
             }
           }
         }
       }
     } else {
       // know receiver type precisely
       return info->rcvr;
     }
     // mark unknown branch as unlikely
     UnknownSExpr* u = info->rcvr->findUnknown();
     if (u && canBeUnlikely && theSIC->useUncommonTraps && 
         rscope->isUncommonAt(_bci, false)) {
       info->rcvr = info->rcvr->makeUnknownUnlikely(this);
     }
   } else if (theSIC->useUncommonTraps &&
              info->primFailure &&
              rscope->isUncommonAt(_bci, true)) {
     // this is the failure send of a primitive, and the failure was made
     // uncommon in the recompilee, and it was never taken, so keep it
     // uncommon
     if (PrintInlining) {
       lprintf("%*s*PIC-type-predicting %s as never executed (2)\n",
               (void*)depth, "", info->sel->copy_null_terminated());
     }
     info->rcvr = new UnknownSExpr(info->rcvr->preg(), NULL, true);
   }
    
   assert(info->rcvr->preg(), "should have a preg");
   return info->rcvr;
 }