Example #1
0
Expr* PrimInliner::obj_new() {
  // replace generic allocation primitive by size-specific primitive, if possible
  Expr* rcvr = parameter(0);
  if (!rcvr->isConstantExpr() || !rcvr->constant()->is_klass()) return NULL;
  Klass* klass = klassOop(rcvr->constant())->klass_part();	// class being instantiated
  if (klass->oop_is_indexable()) return NULL;			// would fail (extremely unlikely)
  int size = klass->non_indexable_size();			// size in words

  if (klass->can_inline_allocation()) {
    // These special compiler primitives only work for memOop klasses
    int number_of_instance_variables = size - memOopDesc::header_size();
    switch (number_of_instance_variables) {
      case 0: _pdesc = primitives::new0(); break;
      case 1: _pdesc = primitives::new1(); break;
      case 2: _pdesc = primitives::new2(); break;
      case 3: _pdesc = primitives::new3(); break;
      case 4: _pdesc = primitives::new4(); break;
      case 5: _pdesc = primitives::new5(); break;
      case 6: _pdesc = primitives::new6(); break;
      case 7: _pdesc = primitives::new7(); break;
      case 8: _pdesc = primitives::new8(); break;
      case 9: _pdesc = primitives::new9(); break;
      default:  ; // use generic primitives
    }
  }
  Expr* u = genCall(true);
  return new KlassExpr(klass->as_klassOop(), u->preg(), u->node());
}
Example #2
0
Expr* PrimInliner::array_size() {
  assert(_failure_block == NULL, "primitive must have no failure block");
  assert_receiver();

  // parameters & result registers
  Expr*  array = parameter(0);
  Klass* klass = array->klass()->klass_part();
  int    lenOffs = klass->non_indexable_size();

  // get size
  SAPReg* res = new SAPReg(_scope);
  _gen->append(NodeFactory::new_LoadOffsetNode(res, array->preg(), lenOffs, true));
  return new KlassExpr(smiKlassObj, res, _gen->_current);
}
Example #3
0
Expr* PrimInliner::array_at_put_ifFail(ArrayAtPutNode::AccessType access_type) {
  assert_failure_block();
  assert_receiver();

  // parameters & result registers
  Expr*   array      = parameter(0);
  Expr*   index      = parameter(1);
  Expr*   element    = parameter(2);
  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
  Klass*  klass      = array->klass()->klass_part();
  int     lenOffs    = klass->non_indexable_size();
  int     arrOffs    = lenOffs + 1;
  bool    storeCheck = (access_type == ArrayAtPutNode::object_at_put) && element->needsStoreCheck();
  
  if (access_type == ArrayAtPutNode::object_at_put) {
    // make sure blocks stored into array are created
    _gen->materialize(element->preg(), NULL);
  }

  // atPut node
  ArrayAtPutNode* atPut = NodeFactory::new_ArrayAtPutNode(
    access_type, array->preg(), index->preg(), index->is_smi(), element->preg(), element->is_smi(), NULL, errPReg, arrOffs, lenOffs, storeCheck
  );
  _gen->append(atPut);

  // continuation
  Expr* resExpr = array;
  if (atPut->canFail()) {
    if (shouldUseUncommonTrap()) {
      // uncommon branch instead of failure code
      atPut->append(1, NodeFactory::new_UncommonNode(_gen->copyCurrentExprStack(), _bci /*_failure_block->begin_bci()*/));
    } else {
      // append failure code
      NopNode* err = NodeFactory::new_NopNode();
      atPut->append(1, err);
      Expr* errExpr = new KlassExpr(Universe::symbolKlassObj(), errPReg, atPut);
      resExpr = merge_failure_block(atPut, resExpr, err, errExpr, true);
    }
  }
  return resExpr;
}
Example #4
0
Expr* PrimInliner::array_at_ifFail(ArrayAtNode::AccessType access_type) {
  assert_failure_block();
  assert_receiver();

  // parameters & result registers
  Expr*   array    = parameter(0);
  Expr*   index    = parameter(1);
  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
  Klass*  klass    = array->klass()->klass_part();
  int     lenOffs  = klass->non_indexable_size();
  int     arrOffs  = lenOffs + 1;
  
  // at node
  ArrayAtNode* at = NodeFactory::new_ArrayAtNode(
    access_type, array->preg(), index->preg(), index->is_smi(), resPReg, errPReg, arrOffs, lenOffs
  );
  _gen->append(at);

  // continuation
  Expr* resExpr;
  switch (access_type) {
    case ArrayAtNode::byte_at	    : // fall through
    case ArrayAtNode::double_byte_at: resExpr = new KlassExpr(Universe::smiKlassObj(), resPReg, at);		break;
    case ArrayAtNode::character_at  : resExpr = new KlassExpr(Universe::characterKlassObj(), resPReg, at);	break;
    case ArrayAtNode::object_at	    : resExpr = new UnknownExpr(resPReg, at);					break;
    default			    : ShouldNotReachHere();
  }
  if (at->canFail()) {
    if (shouldUseUncommonTrap()) {
      // uncommon branch instead of failure code
      at->append(1, NodeFactory::new_UncommonNode(_gen->copyCurrentExprStack(), _bci /*_failure_block->begin_bci()*/));
    } else {
      // append failure code
      NopNode* err = NodeFactory::new_NopNode();
      at->append(1, err);
      Expr* errExpr = new KlassExpr(Universe::symbolKlassObj(), errPReg, at);
      resExpr = merge_failure_block(at, resExpr, err, errExpr, false);
    }
  }
  return resExpr;
}