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());
}
Expr* PrimInliner::tryConstantFold() {
  // Returns the result if the primitive call has been constant folded
  // successfully; returns NULL otherwise.
  // Note: The result may be a marked oop - which has to be unmarked
  // before using it - and which indicates that the primitive will fail
  // always.
  if (!_pdesc->can_be_constant_folded()) {
    // check for Symbol>>at: before declaring failure
    if ((equal(_pdesc->name(), "primitiveIndexedByteAt:ifFail:") ||
         equal(_pdesc->name(), "primitiveIndexedByteCharacterAt:ifFail:")) &&
        parameter(0)->hasKlass() && parameter(0)->klass() == Universe::symbolKlassObj()) {
      // the at: primitive can be constant-folded for symbols
      // what if the receiver is a constant string? unfortunately, Smalltalk has
      // "assignable constants" like Fortran...
    } else {
      return NULL;
    }
  }
  // get parameters
  int i = number_of_parameters();
  oop* args = NEW_RESOURCE_ARRAY(oop, i);
  while (i > 0) {
    i--;
    Expr* arg = parameter(i);
    if (!arg->isConstantExpr()) return NULL;
    args[i] = arg->constant();
  }
  // all parameters are constants, so call primitive
  oop res = _pdesc->eval(args);
  if (res->is_mark()) {
    // primitive failed
    return primitiveFailure(unmarkSymbol(res));
  } else if (res->is_mem() && !res->is_old()) {
    // must tenure result because nmethods aren't scavenged
    if (res->is_double()) {
      res = oopFactory::clone_double_to_oldspace(doubleOop(res));
    } else {
      // don't know how to tenure non-doubles
      warning("const folding: primitive %s is returning non-tenured object", _pdesc->name());
      return NULL;
    }
  }
  ConstPReg* constResult = new_ConstPReg(_scope, res);
  SAPReg* result = new SAPReg(_scope);
  _gen->append(NodeFactory::new_AssignNode(constResult, result));
  if (CompilerDebug) cout(PrintInlining)->print("%*sconstant-folding %s --> %#x\n", _scope->depth + 2, "", _pdesc->name(), res);
  assert(!constResult->constant->is_mark(), "result must not be marked");
  return new ConstantExpr(res, constResult, _gen->current());
}