Пример #1
0
  SExpr* SPrimScope::inlineAtPut(bool objVector) {
    assert(_selector == VMString[objVector ? _AT_PUT_ : _BYTE_AT_PUT_],
           "bad selector");
    bool okRcvr = receiver->hasMap();
    Map* rm;
    if (okRcvr) {
      rm = receiver->map();
      if (objVector) {
        okRcvr = rm->is_objVector();
      } else {
        okRcvr = rm->is_byteVector();
      }
    }
    if (!okRcvr) {
      // receiver type not known statically
      return NULL;
    }
    if (PrintInlining)
      lprintf("%*s*inlining _%sAtPut:\n", (void*)(depth-1),
              "", objVector ? "" :"Byte");
    
    SExpr* arg = args->nth(1);
    NodeGen* ng = theNodeGen;
    if (SICDebug) ng->comment("inlined _At:Put:/_ByteAt:Put:");
    fint b = bci();
    bool intArg   = arg->hasMap() && arg->map() == Memory->smi_map;
    bool willFail = arg->hasMap() && arg->map() != Memory->smi_map;
    bool useUncommonTrap = !willFail && theSIC->useUncommonTraps &&
      sender()->rscope->isUncommonAt(sender()->bci(), true);
    PReg* errorPR = useUncommonTrap ? NULL : new SAPReg(_sender, b, b);
    Node* at;
    if (objVector) {
      PReg* elementArgPR = args->nth(0)->preg();
      
      // materialize value arg
      theNodeGen->materializeBlock(elementArgPR, _sender->sig, new PRegBList(1));
      
      fint size = ((slotsMap*)rm)->empty_vector_object_size();
      at = new ArrayAtPutNode(receiver->preg(), arg->preg(), intArg,
                              elementArgPR, resultPR, errorPR,
                              size * oopSize - Mem_Tag);
    } 
    else {
      SExpr* value = args->nth(0);
      bool intVal = value->hasMap() && value->map() == Memory->smi_map;
      willFail   |= value->hasMap() && value->map() != Memory->smi_map;
      at = new ByteArrayAtPutNode(receiver->preg(), arg->preg(), intArg, 
                                  value->preg(), intVal, resultPR, errorPR);
    }
    ng->append(at);
    
    // success case - int index, in bounds
    MergeNode* ok = (MergeNode*)ng->append(new NopNode);
    // merge of success & failure branches
    MergeNode* done = (MergeNode*)ok->append(new MergeNode("inlineAtPut done"));

    // failure case
    SExpr* res = receiver->shallowCopy(resultPR, ok);
    ng->current = at->append1(new MergeNode("inlineAtPut current"));
    if (useUncommonTrap) {
      if (PrintInlining) {
        lprintf("%*s*making atPut: failure uncommon\n", (void*)(depth-1), "");
      }
      ng->uncommonBranch(currentExprStack(0), true);
      ng->current = done;
    } else {
      Node* dummy;
      SExpr* failExpr = genPrimFailure(NULL, errorPR, dummy, done, resultPR);
      assert(done, "node should always exist");
      res = res->mergeWith(failExpr, done);
    }
    return res;
  }
Пример #2
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;
 }
Пример #3
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);
    }
  }
Пример #4
0
Expr* PrimInliner::smi_ArithmeticOp(ArithOpCode op, Expr* arg1, Expr* arg2) {
  assert_failure_block();
  assert_receiver();
  
  // parameters & result registers
  bool       intArg1      = arg1->is_smi();
  bool       intArg2      = arg2->is_smi();
  bool       intBoth      = intArg1 && intArg2;			// if true, tag error cannot occur
  SAPReg*    resPReg      = new SAPReg(_scope);			// holds the result if primitive didn't fail
  SAPReg*    errPReg      = new SAPReg(_scope);			// holds the error message if primitive failed
  MergeNode* failureStart = NodeFactory::new_MergeNode(_failure_block->begin_bci());

  // n1: operation & treatment of tag error
  Node* n1;
  AssignNode*  n1Err;
  ConstantExpr* n1Expr = NULL;
  if (intBoth) {
    // tag error cannot occur
    n1 = NodeFactory::new_ArithRRNode(resPReg, arg1->preg(), op, arg2->preg());
  } else {
    // tag error can occur
    n1 = NodeFactory::new_TArithRRNode(resPReg, arg1->preg(), op, arg2->preg(), intArg1, intArg2);
    if (shouldUseUncommonTrap()) {
      // simply jump to uncommon branch code
      n1->append(1, failureStart);
    } else {
      ConstPReg* n1PReg = new_ConstPReg(_scope, vmSymbols::first_argument_has_wrong_type());
      n1Err = NodeFactory::new_AssignNode(n1PReg, errPReg);
      n1Expr = new ConstantExpr(n1PReg->constant, errPReg, n1Err);
      n1->append(1, n1Err);
      n1Err->append(failureStart);
    }
  }
  _gen->append(n1);
  Expr* result = new KlassExpr(smiKlassObj, resPReg, n1);

  // n2: overflow check & treatment of overflow
  const bool taken_is_uncommon = true;
  BranchNode* n2 = NodeFactory::new_BranchNode(VSBranchOp, taken_is_uncommon);
  AssignNode* n2Err;
  ConstantExpr* n2Expr = NULL;
  if (shouldUseUncommonTrap()) {
    // simply jump to uncommon branch code
    n2->append(1, failureStart);
  } else {
    ConstPReg* n2PReg = new_ConstPReg(_scope, vmSymbols::smi_overflow());
    n2Err = NodeFactory::new_AssignNode(n2PReg, errPReg);
    n2Expr = new ConstantExpr(n2PReg->constant, errPReg, n2Err);
    n2->append(1, n2Err);
    n2Err->append(failureStart);
  }
  _gen->append(n2);

  // continuation
  if (shouldUseUncommonTrap()) {
    // uncommon branch instead of failure code
    failureStart->append(NodeFactory::new_UncommonNode(_gen->copyCurrentExprStack(), _bci /*_failure_block->begin_bci()*/));
  } else {
    assert(n2Expr != NULL, "no error message defined");
    Expr* error;
    if (n1Expr != NULL) {
      error = new MergeExpr(n1Expr, n2Expr, errPReg, failureStart);
    } else {
      error = n2Expr;
    }
    result = merge_failure_block(n2, result, failureStart, error, false);
  }
  return result;
}