hotspot/src/share/vm/compiler/oopMap.cpp
changeset 30590 14f7f48c1377
parent 25715 d5a8dbdc5150
child 30774 6745424a720f
child 30764 fec48bf5a827
equal deleted inserted replaced
30589:4722e25bfd6d 30590:14f7f48c1377
    40 #include "opto/optoreg.hpp"
    40 #include "opto/optoreg.hpp"
    41 #endif
    41 #endif
    42 
    42 
    43 // OopMapStream
    43 // OopMapStream
    44 
    44 
    45 OopMapStream::OopMapStream(OopMap* oop_map) {
    45 OopMapStream::OopMapStream(OopMap* oop_map, int oop_types_mask) {
    46   if(oop_map->omv_data() == NULL) {
    46   _stream = new CompressedReadStream(oop_map->write_stream()->buffer());
    47     _stream = new CompressedReadStream(oop_map->write_stream()->buffer());
    47   _mask = oop_types_mask;
    48   } else {
       
    49     _stream = new CompressedReadStream(oop_map->omv_data());
       
    50   }
       
    51   _mask = OopMapValue::type_mask_in_place;
       
    52   _size = oop_map->omv_count();
    48   _size = oop_map->omv_count();
    53   _position = 0;
    49   _position = 0;
    54   _valid_omv = false;
    50   _valid_omv = false;
    55 }
    51 }
    56 
    52 
    57 
    53 OopMapStream::OopMapStream(const ImmutableOopMap* oop_map, int oop_types_mask) {
    58 OopMapStream::OopMapStream(OopMap* oop_map, int oop_types_mask) {
    54   _stream = new CompressedReadStream(oop_map->data_addr());
    59   if(oop_map->omv_data() == NULL) {
       
    60     _stream = new CompressedReadStream(oop_map->write_stream()->buffer());
       
    61   } else {
       
    62     _stream = new CompressedReadStream(oop_map->omv_data());
       
    63   }
       
    64   _mask = oop_types_mask;
    55   _mask = oop_types_mask;
    65   _size = oop_map->omv_count();
    56   _size = oop_map->count();
    66   _position = 0;
    57   _position = 0;
    67   _valid_omv = false;
    58   _valid_omv = false;
    68 }
    59 }
    69 
    60 
    70 
    61 
    85 // frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd
    76 // frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd
    86 // slots to hold 4-byte values like ints and floats in the LP64 build.
    77 // slots to hold 4-byte values like ints and floats in the LP64 build.
    87 OopMap::OopMap(int frame_size, int arg_count) {
    78 OopMap::OopMap(int frame_size, int arg_count) {
    88   // OopMaps are usually quite so small, so pick a small initial size
    79   // OopMaps are usually quite so small, so pick a small initial size
    89   set_write_stream(new CompressedWriteStream(32));
    80   set_write_stream(new CompressedWriteStream(32));
    90   set_omv_data(NULL);
       
    91   set_omv_count(0);
    81   set_omv_count(0);
    92 
    82 
    93 #ifdef ASSERT
    83 #ifdef ASSERT
    94   _locs_length = VMRegImpl::stack2reg(0)->value() + frame_size + arg_count;
    84   _locs_length = VMRegImpl::stack2reg(0)->value() + frame_size + arg_count;
    95   _locs_used   = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length);
    85   _locs_used   = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length);
   100 
    90 
   101 OopMap::OopMap(OopMap::DeepCopyToken, OopMap* source) {
    91 OopMap::OopMap(OopMap::DeepCopyToken, OopMap* source) {
   102   // This constructor does a deep copy
    92   // This constructor does a deep copy
   103   // of the source OopMap.
    93   // of the source OopMap.
   104   set_write_stream(new CompressedWriteStream(source->omv_count() * 2));
    94   set_write_stream(new CompressedWriteStream(source->omv_count() * 2));
   105   set_omv_data(NULL);
       
   106   set_omv_count(0);
    95   set_omv_count(0);
   107   set_offset(source->offset());
    96   set_offset(source->offset());
   108 
    97 
   109 #ifdef ASSERT
    98 #ifdef ASSERT
   110   _locs_length = source->_locs_length;
    99   _locs_length = source->_locs_length;
   123 
   112 
   124 OopMap* OopMap::deep_copy() {
   113 OopMap* OopMap::deep_copy() {
   125   return new OopMap(_deep_copy_token, this);
   114   return new OopMap(_deep_copy_token, this);
   126 }
   115 }
   127 
   116 
   128 
   117 void OopMap::copy_data_to(address addr) const {
   129 void OopMap::copy_to(address addr) {
   118   memcpy(addr, write_stream()->buffer(), write_stream()->position());
   130   memcpy(addr,this,sizeof(OopMap));
   119 }
   131   memcpy(addr + sizeof(OopMap),write_stream()->buffer(),write_stream()->position());
       
   132   OopMap* new_oop = (OopMap*)addr;
       
   133   new_oop->set_omv_data_size(write_stream()->position());
       
   134   new_oop->set_omv_data((unsigned char *)(addr + sizeof(OopMap)));
       
   135   new_oop->set_write_stream(NULL);
       
   136 }
       
   137 
       
   138 
   120 
   139 int OopMap::heap_size() const {
   121 int OopMap::heap_size() const {
   140   int size = sizeof(OopMap);
   122   int size = sizeof(OopMap);
   141   int align = sizeof(void *) - 1;
   123   int align = sizeof(void *) - 1;
   142   if(write_stream() != NULL) {
   124   size += write_stream()->position();
   143     size += write_stream()->position();
       
   144   } else {
       
   145     size += omv_data_size();
       
   146   }
       
   147   // Align to a reasonable ending point
   125   // Align to a reasonable ending point
   148   size = ((size+align) & ~align);
   126   size = ((size+align) & ~align);
   149   return size;
   127   return size;
   150 }
   128 }
   151 
   129 
   217   int new_size = om_size() * 2;
   195   int new_size = om_size() * 2;
   218   OopMap** new_data = NEW_RESOURCE_ARRAY(OopMap*, new_size);
   196   OopMap** new_data = NEW_RESOURCE_ARRAY(OopMap*, new_size);
   219   memcpy(new_data,om_data(),om_size() * sizeof(OopMap*));
   197   memcpy(new_data,om_data(),om_size() * sizeof(OopMap*));
   220   set_om_size(new_size);
   198   set_om_size(new_size);
   221   set_om_data(new_data);
   199   set_om_data(new_data);
   222 }
       
   223 
       
   224 
       
   225 void OopMapSet::copy_to(address addr) {
       
   226   address temp = addr;
       
   227   int align = sizeof(void *) - 1;
       
   228   // Copy this
       
   229   memcpy(addr,this,sizeof(OopMapSet));
       
   230   temp += sizeof(OopMapSet);
       
   231   temp = (address)((intptr_t)(temp + align) & ~align);
       
   232   // Do the needed fixups to the new OopMapSet
       
   233   OopMapSet* new_set = (OopMapSet*)addr;
       
   234   new_set->set_om_data((OopMap**)temp);
       
   235   // Allow enough space for the OopMap pointers
       
   236   temp += (om_count() * sizeof(OopMap*));
       
   237 
       
   238   for(int i=0; i < om_count(); i++) {
       
   239     OopMap* map = at(i);
       
   240     map->copy_to((address)temp);
       
   241     new_set->set(i,(OopMap*)temp);
       
   242     temp += map->heap_size();
       
   243   }
       
   244   // This "locks" the OopMapSet
       
   245   new_set->set_om_size(-1);
       
   246 }
   200 }
   247 
   201 
   248 
   202 
   249 void OopMapSet::add_gc_map(int pc_offset, OopMap *map ) {
   203 void OopMapSet::add_gc_map(int pc_offset, OopMap *map ) {
   250   assert(om_size() != -1,"Cannot grow a fixed OopMapSet");
   204   assert(om_size() != -1,"Cannot grow a fixed OopMapSet");
   332 #ifndef PRODUCT
   286 #ifndef PRODUCT
   333 static void trace_codeblob_maps(const frame *fr, const RegisterMap *reg_map) {
   287 static void trace_codeblob_maps(const frame *fr, const RegisterMap *reg_map) {
   334   // Print oopmap and regmap
   288   // Print oopmap and regmap
   335   tty->print_cr("------ ");
   289   tty->print_cr("------ ");
   336   CodeBlob* cb = fr->cb();
   290   CodeBlob* cb = fr->cb();
   337   OopMapSet* maps = cb->oop_maps();
   291   ImmutableOopMapSet* maps = cb->oop_maps();
   338   OopMap* map = cb->oop_map_for_return_address(fr->pc());
   292   const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc());
   339   map->print();
   293   map->print();
   340   if( cb->is_nmethod() ) {
   294   if( cb->is_nmethod() ) {
   341     nmethod* nm = (nmethod*)cb;
   295     nmethod* nm = (nmethod*)cb;
   342     // native wrappers have no scope data, it is implied
   296     // native wrappers have no scope data, it is implied
   343     if (nm->is_native_method()) {
   297     if (nm->is_native_method()) {
   369   CodeBlob* cb = fr->cb();
   323   CodeBlob* cb = fr->cb();
   370   assert(cb != NULL, "no codeblob");
   324   assert(cb != NULL, "no codeblob");
   371 
   325 
   372   NOT_PRODUCT(if (TraceCodeBlobStacks) trace_codeblob_maps(fr, reg_map);)
   326   NOT_PRODUCT(if (TraceCodeBlobStacks) trace_codeblob_maps(fr, reg_map);)
   373 
   327 
   374   OopMapSet* maps = cb->oop_maps();
   328   ImmutableOopMapSet* maps = cb->oop_maps();
   375   OopMap* map = cb->oop_map_for_return_address(fr->pc());
   329   const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc());
   376   assert(map != NULL, "no ptr map found");
   330   assert(map != NULL, "no ptr map found");
   377 
   331 
   378   // handle derived pointers first (otherwise base pointer may be
   332   // handle derived pointers first (otherwise base pointer may be
   379   // changed before derived pointer offset has been collected)
   333   // changed before derived pointer offset has been collected)
   380   OopMapValue omv;
   334   OopMapValue omv;
   481 
   435 
   482   // Scan through oopmap and find location of all callee-saved registers
   436   // Scan through oopmap and find location of all callee-saved registers
   483   // (we do not do update in place, since info could be overwritten)
   437   // (we do not do update in place, since info could be overwritten)
   484 
   438 
   485   address pc = fr->pc();
   439   address pc = fr->pc();
   486   OopMap* map  = cb->oop_map_for_return_address(pc);
   440   const ImmutableOopMap* map  = cb->oop_map_for_return_address(pc);
   487   assert(map != NULL, "no ptr map found");
   441   assert(map != NULL, "no ptr map found");
   488   DEBUG_ONLY(int nof_callee = 0;)
   442   DEBUG_ONLY(int nof_callee = 0;)
   489 
   443 
   490   for (OopMapStream oms(map, OopMapValue::callee_saved_value); !oms.is_done(); oms.next()) {
   444   for (OopMapStream oms(map, OopMapValue::callee_saved_value); !oms.is_done(); oms.next()) {
   491     OopMapValue omv = oms.current();
   445     OopMapValue omv = oms.current();
   506 //=============================================================================
   460 //=============================================================================
   507 // Non-Product code
   461 // Non-Product code
   508 
   462 
   509 #ifndef PRODUCT
   463 #ifndef PRODUCT
   510 
   464 
   511 bool OopMap::has_derived_pointer() const {
   465 bool ImmutableOopMap::has_derived_pointer() const {
   512 #ifndef TIERED
   466 #ifndef TIERED
   513   COMPILER1_PRESENT(return false);
   467   COMPILER1_PRESENT(return false);
   514 #endif // !TIERED
   468 #endif // !TIERED
   515 #ifdef COMPILER2
   469 #ifdef COMPILER2
   516   OopMapStream oms((OopMap*)this,OopMapValue::derived_oop_value);
   470   OopMapStream oms((OopMap*)this,OopMapValue::derived_oop_value);
   548   default:
   502   default:
   549     ShouldNotReachHere();
   503     ShouldNotReachHere();
   550   }
   504   }
   551 }
   505 }
   552 
   506 
   553 
       
   554 void OopMapValue::print_on(outputStream* st) const {
   507 void OopMapValue::print_on(outputStream* st) const {
   555   reg()->print_on(st);
   508   reg()->print_on(st);
   556   st->print("=");
   509   st->print("=");
   557   print_register_type(type(),content_reg(),st);
   510   print_register_type(type(),content_reg(),st);
   558   st->print(" ");
   511   st->print(" ");
   559 }
   512 }
   560 
   513 
       
   514 void ImmutableOopMap::print_on(outputStream* st) const {
       
   515   OopMapValue omv;
       
   516   st->print("ImmutableOopMap{");
       
   517   for(OopMapStream oms(this); !oms.is_done(); oms.next()) {
       
   518     omv = oms.current();
       
   519     omv.print_on(st);
       
   520   }
       
   521   st->print("}");
       
   522 }
   561 
   523 
   562 void OopMap::print_on(outputStream* st) const {
   524 void OopMap::print_on(outputStream* st) const {
   563   OopMapValue omv;
   525   OopMapValue omv;
   564   st->print("OopMap{");
   526   st->print("OopMap{");
   565   for(OopMapStream oms((OopMap*)this); !oms.is_done(); oms.next()) {
   527   for(OopMapStream oms((OopMap*)this); !oms.is_done(); oms.next()) {
   567     omv.print_on(st);
   529     omv.print_on(st);
   568   }
   530   }
   569   st->print("off=%d}", (int) offset());
   531   st->print("off=%d}", (int) offset());
   570 }
   532 }
   571 
   533 
       
   534 void ImmutableOopMapSet::print_on(outputStream* st) const {
       
   535   const ImmutableOopMap* last = NULL;
       
   536   for (int i = 0; i < _count; ++i) {
       
   537     const ImmutableOopMapPair* pair = pair_at(i);
       
   538     const ImmutableOopMap* map = pair->get_from(this);
       
   539     if (map != last) {
       
   540       st->cr();
       
   541       map->print_on(st);
       
   542       st->print("pc offsets: ");
       
   543     }
       
   544     last = map;
       
   545     st->print("%d ", pair->pc_offset());
       
   546   }
       
   547 }
   572 
   548 
   573 void OopMapSet::print_on(outputStream* st) const {
   549 void OopMapSet::print_on(outputStream* st) const {
   574   int i, len = om_count();
   550   int i, len = om_count();
   575 
   551 
   576   st->print_cr("OopMapSet contains %d OopMaps\n",len);
   552   st->print_cr("OopMapSet contains %d OopMaps\n",len);
   581     m->print_on(st);
   557     m->print_on(st);
   582     st->cr();
   558     st->cr();
   583   }
   559   }
   584 }
   560 }
   585 
   561 
       
   562 bool OopMap::equals(const OopMap* other) const {
       
   563   if (other->_omv_count != _omv_count) {
       
   564     return false;
       
   565   }
       
   566   if (other->write_stream()->position() != write_stream()->position()) {
       
   567     return false;
       
   568   }
       
   569   if (memcmp(other->write_stream()->buffer(), write_stream()->buffer(), write_stream()->position()) != 0) {
       
   570     return false;
       
   571   }
       
   572   return true;
       
   573 }
       
   574 
       
   575 const ImmutableOopMap* ImmutableOopMapSet::find_map_at_offset(int pc_offset) const {
       
   576   ImmutableOopMapPair* pairs = get_pairs();
       
   577   ImmutableOopMapPair* last = NULL;
       
   578 
       
   579   for (int i = 0; i < _count; ++i) {
       
   580     if (pairs[i].pc_offset() >= pc_offset) {
       
   581       last = &pairs[i];
       
   582       break;
       
   583     }
       
   584   }
       
   585 
       
   586   assert(last->pc_offset() == pc_offset, "oopmap not found");
       
   587   return last->get_from(this);
       
   588 }
       
   589 
       
   590 const ImmutableOopMap* ImmutableOopMapPair::get_from(const ImmutableOopMapSet* set) const {
       
   591   return set->oopmap_at_offset(_oopmap_offset);
       
   592 }
       
   593 
       
   594 ImmutableOopMap::ImmutableOopMap(const OopMap* oopmap) : _count(oopmap->count()) {
       
   595   address addr = data_addr();
       
   596   oopmap->copy_data_to(addr);
       
   597 }
       
   598 
       
   599 class ImmutableOopMapBuilder {
       
   600 private:
       
   601   class Mapping;
       
   602 
       
   603 private:
       
   604   const OopMapSet* _set;
       
   605   const OopMap* _empty;
       
   606   const OopMap* _last;
       
   607   int _empty_offset;
       
   608   int _last_offset;
       
   609   int _offset;
       
   610   Mapping* _mapping;
       
   611   ImmutableOopMapSet* _new_set;
       
   612 
       
   613   /* Used for bookkeeping when building ImmutableOopMaps */
       
   614   class Mapping : public ResourceObj {
       
   615   public:
       
   616     enum kind_t { OOPMAP_UNKNOWN = 0, OOPMAP_NEW = 1, OOPMAP_EMPTY = 2, OOPMAP_DUPLICATE = 3 };
       
   617 
       
   618     kind_t _kind;
       
   619     int _offset;
       
   620     int _size;
       
   621     const OopMap* _map;
       
   622     const OopMap* _other;
       
   623 
       
   624     Mapping() : _kind(OOPMAP_UNKNOWN), _offset(-1), _size(-1), _map(NULL) {}
       
   625 
       
   626     void set(kind_t kind, int offset, int size, const OopMap* map = 0, const OopMap* other = 0) {
       
   627       _kind = kind;
       
   628       _offset = offset;
       
   629       _size = size;
       
   630       _map = map;
       
   631       _other = other;
       
   632     }
       
   633   };
       
   634 
       
   635 public:
       
   636   ImmutableOopMapBuilder(const OopMapSet* set) : _set(set), _new_set(NULL), _empty(NULL), _last(NULL), _empty_offset(-1), _last_offset(-1), _offset(0) {
       
   637     _mapping = NEW_RESOURCE_ARRAY(Mapping, _set->size());
       
   638   }
       
   639 
       
   640   int heap_size();
       
   641   ImmutableOopMapSet* build();
       
   642 private:
       
   643   bool is_empty(const OopMap* map) const {
       
   644     return map->count() == 0;
       
   645   }
       
   646 
       
   647   bool is_last_duplicate(const OopMap* map) {
       
   648     if (_last != NULL && _last->count() > 0 && _last->equals(map)) {
       
   649       return true;
       
   650     }
       
   651     return false;
       
   652   }
       
   653 
       
   654 #ifdef ASSERT
       
   655   void verify(address buffer, int size);
       
   656 #endif
       
   657 
       
   658   bool has_empty() const {
       
   659     return _empty_offset != -1;
       
   660   }
       
   661 
       
   662   int size_for(const OopMap* map) const;
       
   663   void fill_pair(ImmutableOopMapPair* pair, const OopMap* map, int offset);
       
   664   int fill_map(ImmutableOopMapPair* pair, const OopMap* map, int offset);
       
   665   void fill(ImmutableOopMapSet* set, int size);
       
   666 };
       
   667 
       
   668 int ImmutableOopMapBuilder::size_for(const OopMap* map) const {
       
   669   return align_size_up(sizeof(ImmutableOopMap) + map->data_size(), 8);
       
   670 }
       
   671 
       
   672 int ImmutableOopMapBuilder::heap_size() {
       
   673   int base = sizeof(ImmutableOopMapSet);
       
   674   base = align_size_up(base, 8);
       
   675 
       
   676   // all of ours pc / offset pairs
       
   677   int pairs = _set->size() * sizeof(ImmutableOopMapPair);
       
   678   pairs = align_size_up(pairs, 8);
       
   679 
       
   680   for (int i = 0; i < _set->size(); ++i) {
       
   681     int size = 0;
       
   682     OopMap* map = _set->at(i);
       
   683 
       
   684     if (is_empty(map)) {
       
   685       /* only keep a single empty map in the set */
       
   686       if (has_empty()) {
       
   687         _mapping[i].set(Mapping::OOPMAP_EMPTY, _empty_offset, 0, map, _empty);
       
   688       } else {
       
   689         _empty_offset = _offset;
       
   690         _empty = map;
       
   691         size = size_for(map);
       
   692         _mapping[i].set(Mapping::OOPMAP_NEW, _offset, size, map);
       
   693       }
       
   694     } else if (is_last_duplicate(map)) {
       
   695       /* if this entry is identical to the previous one, just point it there */
       
   696       _mapping[i].set(Mapping::OOPMAP_DUPLICATE, _last_offset, 0, map, _last);
       
   697     } else {
       
   698       /* not empty, not an identical copy of the previous entry */
       
   699       size = size_for(map);
       
   700       _mapping[i].set(Mapping::OOPMAP_NEW, _offset, size, map);
       
   701       _last_offset = _offset;
       
   702       _last = map;
       
   703     }
       
   704 
       
   705     assert(_mapping[i]._map == map, "check");
       
   706     _offset += size;
       
   707   }
       
   708 
       
   709   int total = base + pairs + _offset;
       
   710   DEBUG_ONLY(total += 8);
       
   711   return total;
       
   712 }
       
   713 
       
   714 void ImmutableOopMapBuilder::fill_pair(ImmutableOopMapPair* pair, const OopMap* map, int offset) {
       
   715   new ((address) pair) ImmutableOopMapPair(map->offset(), offset);
       
   716 }
       
   717 
       
   718 int ImmutableOopMapBuilder::fill_map(ImmutableOopMapPair* pair, const OopMap* map, int offset) {
       
   719   fill_pair(pair, map, offset);
       
   720   address addr = (address) pair->get_from(_new_set); // location of the ImmutableOopMap
       
   721 
       
   722   new (addr) ImmutableOopMap(map);
       
   723   return align_size_up(sizeof(ImmutableOopMap) + map->data_size(), 8);
       
   724 }
       
   725 
       
   726 void ImmutableOopMapBuilder::fill(ImmutableOopMapSet* set, int sz) {
       
   727   ImmutableOopMapPair* pairs = set->get_pairs();
       
   728 
       
   729   for (int i = 0; i < set->count(); ++i) {
       
   730     const OopMap* map = _mapping[i]._map;
       
   731     ImmutableOopMapPair* pair = NULL;
       
   732     int size = 0;
       
   733 
       
   734     if (_mapping[i]._kind == Mapping::OOPMAP_NEW) {
       
   735       size = fill_map(&pairs[i], map, _mapping[i]._offset);
       
   736     } else if (_mapping[i]._kind == Mapping::OOPMAP_DUPLICATE || _mapping[i]._kind == Mapping::OOPMAP_EMPTY) {
       
   737       fill_pair(&pairs[i], map, _mapping[i]._offset);
       
   738     }
       
   739 
       
   740     const ImmutableOopMap* nv = set->find_map_at_offset(map->offset());
       
   741     assert(memcmp(map->data(), nv->data_addr(), map->data_size()) == 0, "check identity");
       
   742   }
       
   743 }
       
   744 
       
   745 #ifdef ASSERT
       
   746 void ImmutableOopMapBuilder::verify(address buffer, int size) {
       
   747   for (int i = 0; i < 8; ++i) {
       
   748     assert(buffer[size - 8 + i] == (unsigned char) 0xff, "overwritten memory check");
       
   749   }
       
   750 }
       
   751 #endif
       
   752 
       
   753 ImmutableOopMapSet* ImmutableOopMapBuilder::build() {
       
   754   int required = heap_size();
       
   755 
       
   756   // We need to allocate a chunk big enough to hold the ImmutableOopMapSet and all of its ImmutableOopMaps
       
   757   address buffer = (address) NEW_C_HEAP_ARRAY(unsigned char, required, mtCode);
       
   758   DEBUG_ONLY(memset(&buffer[required-8], 0xff, 8));
       
   759 
       
   760   _new_set = new (buffer) ImmutableOopMapSet(_set, required);
       
   761   fill(_new_set, required);
       
   762 
       
   763   DEBUG_ONLY(verify(buffer, required));
       
   764 
       
   765   return _new_set;
       
   766 }
       
   767 
       
   768 ImmutableOopMapSet* ImmutableOopMapSet::build_from(const OopMapSet* oopmap_set) {
       
   769   ResourceMark mark;
       
   770   ImmutableOopMapBuilder builder(oopmap_set);
       
   771   return builder.build();
       
   772 }
   586 
   773 
   587 
   774 
   588 //------------------------------DerivedPointerTable---------------------------
   775 //------------------------------DerivedPointerTable---------------------------
   589 
   776 
   590 #ifdef COMPILER2
   777 #ifdef COMPILER2