view src/share/vm/oops/symbolKlass.cpp @ 1091:6aa7255741f3

6906727: UseCompressedOops: some card-marking fixes related to object arrays Summary: Introduced a new write_ref_array(HeapWords* start, size_t count) method that does the requisite MemRegion range calculation so (some of the) clients of the erstwhile write_ref_array(MemRegion mr) do not need to worry. This removed all external uses of array_size(), which was also simplified and made private. Asserts were added to catch other possible issues. Further, less essential, fixes stemming from this investigation are deferred to CR 6904516 (to follow shortly in hs17). Reviewed-by: kvn, coleenp, jmasa
author ysr
date Thu, 03 Dec 2009 15:01:57 -0800
parents 2a1a77d3458f
children 4e6abf09f540
line wrap: on
line source

/*
 * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 *
 */

# include "incls/_precompiled.incl"
# include "incls/_symbolKlass.cpp.incl"

symbolOop symbolKlass::allocate_symbol(u1* name, int len, TRAPS) {
  // Don't allow symbol oops to be created which cannot fit in a symbolOop.
  if (len > symbolOopDesc::max_length()) {
    THROW_MSG_0(vmSymbols::java_lang_InternalError(),
                "name is too long to represent");
  }
  int size = symbolOopDesc::object_size(len);
  symbolKlassHandle h_k(THREAD, as_klassOop());
  symbolOop sym = (symbolOop)
    CollectedHeap::permanent_obj_allocate(h_k, size, CHECK_NULL);
  assert(!sym->is_parsable(), "not expecting parsability yet.");
  No_Safepoint_Verifier no_safepoint;
  sym->set_utf8_length(len);
  for (int i = 0; i < len; i++) {
    sym->byte_at_put(i, name[i]);
  }
  // Let the first emptySymbol be created and
  // ensure only one is ever created.
  assert(sym->is_parsable() || Universe::emptySymbol() == NULL,
         "should be parsable here.");
  return sym;
}

bool symbolKlass::allocate_symbols(int names_count, const char** names,
                                   int* lengths, symbolOop* sym_oops, TRAPS) {
  if (UseConcMarkSweepGC || UseParallelGC) {
    // Concurrent GC needs to mark all the allocated symbol oops after
    // the remark phase which isn't done below (except the first symbol oop).
    // So return false which will let the symbols be allocated one by one.
    // The parallel collector uses an object start array to find the
    // start of objects on a dirty card.  The object start array is not
    // updated for the start of each symbol so is not precise.  During
    // object array verification this causes a verification failure.
    // In a product build this causes extra searching for the start of
    // a symbol.  As with the concurrent collector a return of false will
    // cause each symbol to be allocated separately and in the case
    // of the parallel collector will cause the object
    // start array to be updated.
    return false;
  }

  assert(names_count > 0, "can't allocate 0 symbols");

  int total_size = 0;
  int i, sizes[SymbolTable::symbol_alloc_batch_size];
  for (i=0; i<names_count; i++) {
    int len = lengths[i];
    if (len > symbolOopDesc::max_length()) {
      return false;
    }
    int sz = symbolOopDesc::object_size(len);
    sizes[i] = sz * HeapWordSize;
    total_size += sz;
  }
  symbolKlassHandle h_k(THREAD, as_klassOop());
  HeapWord* base = Universe::heap()->permanent_mem_allocate(total_size);
  if (base == NULL) {
    return false;
  }

  // CAN'T take any safepoint during the initialization of the symbol oops !
  No_Safepoint_Verifier nosafepoint;

  klassOop sk = h_k();
  int pos = 0;
  for (i=0; i<names_count; i++) {
    symbolOop s = (symbolOop) (((char*)base) + pos);
    s->set_mark(markOopDesc::prototype());
    s->set_klass(sk);
    s->set_utf8_length(lengths[i]);
    const char* name = names[i];
    for (int j=0; j<lengths[i]; j++) {
      s->byte_at_put(j, name[j]);
    }

    assert(s->is_parsable(), "should be parsable here.");

    sym_oops[i] = s;
    pos += sizes[i];
  }
  return true;
}

klassOop symbolKlass::create_klass(TRAPS) {
  symbolKlass o;
  KlassHandle h_this_klass(THREAD, Universe::klassKlassObj());
  KlassHandle k = base_create_klass(h_this_klass, header_size(), o.vtbl_value(), CHECK_NULL);
  // Make sure size calculation is right
  assert(k()->size() == align_object_size(header_size()), "wrong size for object");
//  java_lang_Class::create_mirror(k, CHECK_NULL); // Allocate mirror
  return k();
}

int symbolKlass::oop_size(oop obj) const {
  assert(obj->is_symbol(),"must be a symbol");
  symbolOop s = symbolOop(obj);
  int size = s->object_size();
  return size;
}

bool symbolKlass::oop_is_parsable(oop obj) const {
  assert(obj->is_symbol(),"must be a symbol");
  symbolOop s = symbolOop(obj);
  return s->object_is_parsable();
}

void symbolKlass::oop_follow_contents(oop obj) {
  assert (obj->is_symbol(), "object must be symbol");
  // Performance tweak: We skip iterating over the klass pointer since we
  // know that Universe::symbolKlassObj never moves.
  // Note: do not follow next link here (see SymbolTable::follow_contents)
}

#ifndef SERIALGC
void symbolKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) {
  assert (obj->is_symbol(), "object must be symbol");
  // Performance tweak: We skip iterating over the klass pointer since we
  // know that Universe::symbolKlassObj never moves.
  // Note: do not follow next link here (see SymbolTable::follow_contents)
}
#endif // SERIALGC

int symbolKlass::oop_oop_iterate(oop obj, OopClosure* blk) {
  assert(obj->is_symbol(), "object must be symbol");
  symbolOop s = symbolOop(obj);
  // Get size before changing pointers.
  // Don't call size() or oop_size() since that is a virtual call.
  int size = s->object_size();
  // Performance tweak: We skip iterating over the klass pointer since we
  // know that Universe::symbolKlassObj never moves.
  return size;
}


int symbolKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr) {
  assert(obj->is_symbol(), "object must be symbol");
  symbolOop s = symbolOop(obj);
  // Get size before changing pointers.
  // Don't call size() or oop_size() since that is a virtual call.
  int size = s->object_size();
  // Performance tweak: We skip iterating over the klass pointer since we
  // know that Universe::symbolKlassObj never moves.
  return size;
}


int symbolKlass::oop_adjust_pointers(oop obj) {
  assert(obj->is_symbol(), "should be symbol");
  symbolOop s = symbolOop(obj);
  // Get size before changing pointers.
  // Don't call size() or oop_size() since that is a virtual call.
  int size = s->object_size();
  // Performance tweak: We skip iterating over the klass pointer since we
  // know that Universe::symbolKlassObj never moves.
  return size;
}


#ifndef SERIALGC
void symbolKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
  assert(obj->is_symbol(), "should be symbol");
}

void symbolKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
  assert(obj->is_symbol(), "should be symbol");
}

int symbolKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
  assert(obj->is_symbol(), "should be symbol");
  return symbolOop(obj)->object_size();
}

int symbolKlass::oop_update_pointers(ParCompactionManager* cm, oop obj,
                                     HeapWord* beg_addr, HeapWord* end_addr) {
  assert(obj->is_symbol(), "should be symbol");
  return symbolOop(obj)->object_size();
}
#endif // SERIALGC

#ifndef PRODUCT
// Printing

void symbolKlass::oop_print_on(oop obj, outputStream* st) {
  st->print("Symbol: '");
  symbolOop(obj)->print_symbol_on(st);
  st->print("'");
}

void symbolKlass::oop_print_value_on(oop obj, outputStream* st) {
  symbolOop sym = symbolOop(obj);
  st->print("'");
  for (int i = 0; i < sym->utf8_length(); i++) {
    st->print("%c", sym->byte_at(i));
  }
  st->print("'");
}

#endif //PRODUCT

const char* symbolKlass::internal_name() const {
  return "{symbol}";
}