PRIM_DECL_2(behaviorPrimitives::setSuperclass, oop receiver, oop newSuper) {
  PROLOGUE_2("setSuperclass", receiver, newSuper);
  if (!receiver->is_klass())
    return markSymbol(vmSymbols::receiver_has_wrong_type());
  if (!(newSuper->is_klass() || newSuper == nilObj))
    return markSymbol(vmSymbols::first_argument_has_wrong_type());

  Klass* receiverClass = klassOop(receiver)->klass_part();
  klassOop newSuperclass;
  if (receiverClass->superKlass() == newSuper) return receiver; // no change
  if (receiverClass->superKlass() == nilObj) {
    newSuperclass = klassOop(newSuper);
    if (newSuperclass->klass_part()->number_of_instance_variables() > 0)
      return markSymbol(vmSymbols::argument_is_invalid());
  } else {
    Klass* oldSuperclass = receiverClass->superKlass()->klass_part();
    if (newSuper == nilObj) {
      newSuperclass = klassOop(nilObj);
      if (oldSuperclass->number_of_instance_variables() > 0)
        return markSymbol(vmSymbols::argument_is_invalid());
    } else {
      newSuperclass = klassOop(newSuper);

      if (!oldSuperclass->has_same_inst_vars_as(newSuperclass))
        return markSymbol(vmSymbols::invalid_klass());
    }
  }
  receiverClass->set_superKlass(newSuperclass);
  
  Universe::flush_inline_caches_in_methods();
  Universe::code->clear_inline_caches();

  lookupCache::flush();
  DeltaCallCache::clearAll();

  return receiver;
}