klass.cpp

Go to the documentation of this file.
00001 /* Copyright 1994, 1995 LongView Technologies L.L.C. $Revision: 1.55 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00020 
00021 
00022 */
00023 
00024 # include "incls/_precompiled.incl"
00025 # include "incls/_klass.cpp.incl" 
00026 
00027 void Klass::initialize() {
00028   set_untagged_contents(false);
00029   set_classVars(objArrayOop(oopFactory::new_objArray(0)));
00030   set_methods(objArrayOop(oopFactory::new_objArray(0)));
00031   set_superKlass(klassOop(nilObj));
00032   set_mixin(mixinOop(nilObj));
00033 }
00034 
00035 oop Klass::allocateObject() {
00036   return markSymbol(vmSymbols::not_oops());
00037 }
00038 oop Klass::allocateObjectSize(int size) {
00039   return markSymbol(vmSymbols::not_oops());
00040 }
00041 
00042 void Klass::mark_for_schema_change() {
00043   set_mixin(NULL);
00044 }
00045 
00046 bool Klass::is_marked_for_schema_change() {
00047   return mixin() == NULL;
00048 }
00049 
00050 Klass::Format Klass::format_from_symbol(symbolOop format) {
00051   if (format->equals("Oops"))                               return mem_klass;
00052   if (format->equals("ExternalProxy"))                      return proxy_klass;
00053   // if (format->equals("Process"))                            return process_klass;
00054   if (format->equals("IndexedInstanceVariables"))           return objArray_klass;
00055   if (format->equals("IndexedByteInstanceVariables"))       return byteArray_klass;
00056   if (format->equals("IndexedDoubleByteInstanceVariables")) return doubleByteArray_klass;
00057   if (format->equals("IndexedNextOfKinInstanceVariables"))  return weakArray_klass;
00058   if (format->equals("Special"))                            return special_klass;
00059   return Klass::no_klass;
00060 }
00061 
00062 char* Klass::name_from_format(Format format) {
00063   switch (format) {
00064   case mem_klass:             return "Oops";
00065   case proxy_klass:           return "ExternalProxy";
00066   // case process_klass:         return "Process";
00067   case objArray_klass:        return "IndexedInstanceVariables";
00068   case byteArray_klass:       return "IndexedByteInstanceVariables";
00069   case doubleByteArray_klass: return "IndexedDoubleByteInstanceVariables";
00070   case weakArray_klass:       return "IndexedNextOfKinInstanceVariables";
00071   }
00072   return "Special";
00073 }
00074 
00075 
00076 
00077 bool Klass::has_same_layout_as(klassOop klass) {
00078   assert(klass->is_klass(), "argument must be klass");
00079   // Check equality
00080   if (as_klassOop() == klass) return true;
00081 
00082   // Check format
00083   if (format() != klass->klass_part()->format()) return false; 
00084 
00085   // Check instance size
00086   if (non_indexable_size() != klass->klass_part()->non_indexable_size()) return false;
00087 
00088   // Check instance variables
00089   for (int index = oop_header_size(); index < non_indexable_size(); index++) {
00090     if (inst_var_name_at(index) !=  klass->klass_part()->inst_var_name_at(index)) return false;
00091   }
00092   return true;
00093 }
00094 
00095 klassOop Klass::create_subclass(mixinOop mixin, Format format) {
00096   ShouldNotCallThis();
00097   return NULL;
00098 }
00099 
00100 klassOop Klass::create_generic_class(klassOop super_class, mixinOop mixin, int vtbl) {
00101   BlockScavenge bs;
00102 
00103   // Compute the class variables based on the instance side mixin class variable names
00104 
00105   assert(mixin->classVars()->is_objArray(),                "checking instance side class var names");
00106   assert(mixin->class_mixin()->classVars()->is_objArray(), "checking class side class var names");
00107   assert(mixin->class_mixin()->classVars()->length() == 0, "checking class side class var names");
00108 
00109   int length = mixin->number_of_classVars();
00110 
00111   objArrayOop class_vars = oopFactory::new_objArray(mixin->number_of_classVars());
00112   for (int index = 1; index <= length; index++) {
00113     associationOop assoc = oopFactory::new_association(mixin->classVar_at(index), nilObj, false);
00114     class_vars->obj_at_put(index, assoc);
00115   }
00116 
00117   // Meta class
00118   klassOop meta_klass = klassOop(super_class->klass()->klass()->klass_part()->allocateObject());
00119   Klass* mk = meta_klass->klass_part();
00120   mk->set_untagged_contents(false);
00121   mk->set_classVars(class_vars);
00122   mk->set_methods(oopFactory::new_objArray(0));
00123   mk->set_superKlass(super_class->klass());
00124   mk->set_mixin(mixin->class_mixin());
00125   mk->set_non_indexable_size(klassOopDesc::header_size() + mk->number_of_instance_variables());
00126   set_klassKlass_vtbl(mk);
00127 
00128   klassOop klass = klassOop(mk->allocateObject());
00129   Klass*   k     = klass->klass_part();
00130 
00131   k->set_untagged_contents(false);
00132   k->set_classVars(class_vars);
00133   k->set_methods(oopFactory::new_objArray(0));
00134   k->set_superKlass(super_class);
00135   k->set_mixin(mixin);
00136   k->set_vtbl_value(vtbl);
00137   k->set_non_indexable_size(k->oop_header_size() + k->number_of_instance_variables());
00138 
00139   return klass;
00140 }
00141 
00142 symbolOop Klass::inst_var_name_at(int offset) const {
00143   Klass* current_klass  = (Klass*) this;
00144   int   current_offset = non_indexable_size();
00145   do {
00146     mixinOop m = current_klass->mixin();
00147     for (int index = m->number_of_instVars(); index > 0; index--) {
00148       current_offset--;
00149       if (offset == current_offset) return m->instVar_at(index);
00150     } 
00151   } while(current_klass = (current_klass->superKlass() == nilObj ? NULL : current_klass->superKlass()->klass_part()));
00152   return NULL;
00153 }
00154 
00155 int Klass::lookup_inst_var(symbolOop name) const {
00156   int offset = mixin()->inst_var_offset(name, non_indexable_size());
00157   if (offset >= 0) return offset;
00158   return has_superKlass() ? superKlass()->klass_part()->lookup_inst_var(name) : -1;
00159 }
00160 
00161 int Klass::number_of_instance_variables() const {
00162   return mixin()->number_of_instVars() 
00163        + (has_superKlass() ? superKlass()->klass_part()->number_of_instance_variables() : 0);
00164 }
00165 
00166 // OPERATION FOR METHODS
00167 
00168 int Klass::number_of_methods() const {
00169   return methods()->length();
00170 }
00171 
00172 methodOop Klass::method_at(int index)  const {
00173   return methodOop(methods()->obj_at(index));
00174 }
00175 
00176 void Klass::add_method(methodOop method) {
00177   objArrayOop old_array = methods();
00178   symbolOop selector = method->selector();
00179   // Find out if a method with the same selector exists.
00180   for (int index = 1; index <= old_array->length(); index++) {
00181     assert(old_array->obj_at(index)->is_method(), "must be method");
00182     methodOop m = methodOop(old_array->obj_at(index));
00183     if (m->selector() == selector) {
00184       old_array->obj_at_put(index, method);
00185       return;
00186     }
00187   }
00188   // Extend the array
00189   set_methods(methods()->copy_add(method));
00190 }
00191 
00192 methodOop Klass::remove_method_at(int index) {
00193   methodOop method = method_at(index);
00194   set_methods(methods()->copy_remove(index));
00195   return method;
00196 }
00197 
00198 int Klass::number_of_classVars() const {
00199   return classVars()->length();
00200 }
00201 
00202 associationOop Klass::classVar_at(int index)  const {
00203   return associationOop(classVars()->obj_at(index));
00204 }
00205 
00206 void Klass::add_classVar(associationOop assoc) {
00207   objArrayOop array = classVars();
00208   // Find out if it already exists.
00209   for (int index = 1; index <= array->length(); index++) {
00210     assert(array->obj_at(index)->is_association(), "must be symbol");
00211     associationOop elem = associationOop(array->obj_at(index));
00212     if (elem->key() == assoc->key()) return;
00213   }
00214   // Extend the array
00215   set_classVars(array->copy_add(assoc));
00216 }
00217 
00218 associationOop Klass::remove_classVar_at(int index) {
00219   associationOop assoc = classVar_at(index);
00220   set_classVars(classVars()->copy_remove(index));
00221   return assoc;
00222 }
00223 
00224 bool Klass::includes_classVar(symbolOop name) {
00225   objArrayOop array = classVars();
00226   for (int index = 1; index <= array->length(); index++) {
00227     associationOop elem = associationOop(array->obj_at(index));
00228     if (elem->key() == name) return true;
00229   }
00230   return false;
00231 }
00232 
00233 associationOop Klass::local_lookup_class_var(symbolOop name) {
00234   objArrayOop array = classVars();
00235   for (int index = 1; index <= array->length(); index++) {
00236     assert(array->obj_at(index)->is_association(), "must be symbol");
00237     associationOop elem = associationOop(array->obj_at(index));
00238     if (elem->key() == name) return elem;
00239   }
00240   return NULL;
00241 }
00242 
00243 associationOop Klass::lookup_class_var(symbolOop name) {
00244   associationOop result = local_lookup_class_var(name);
00245   if (result) return result;
00246   result = (superKlass() == nilObj)
00247            ? NULL
00248            : superKlass()->klass_part()->lookup_class_var(name);
00249   return result;
00250 }
00251 
00252 
00253 inline methodOop Klass::local_lookup(symbolOop selector) {
00254   objArrayOop array;
00255   int         length;
00256   oop*        current;
00257 
00258   // Find out if there is a customized method matching the selector.
00259   array  = methods();
00260   length = array->length();
00261   if (length > 0) {
00262     current = array->objs(1);
00263     do {
00264       methodOop method = methodOop(*current++);
00265       assert(method->is_method(), "must be method");   
00266       if (method->selector() == selector)
00267         return method;
00268     } while (--length > 0);
00269   }
00270 
00271   assert(mixin()->is_mixin(), "mixin must exist");
00272 
00273   array   = mixin()->methods();
00274   length  = array->length();
00275   current = array->objs(1);
00276 
00277   while (length-- > 0) {
00278     methodOop method = methodOop(*current++);
00279     assert(method->is_method(), "must be method");   
00280     if (method->selector() == selector) {
00281       if (method->should_be_customized()) {
00282         if (as_klassOop() == mixin()->primary_invocation()){
00283           if (!method->is_customized()) method->customize_for(as_klassOop(), mixin());
00284           return method;
00285         } else {
00286           BlockScavenge bs;
00287           // Make customized version for klass
00288           methodOop new_method = method->copy_for_customization();
00289           new_method->customize_for(as_klassOop(), mixin());
00290           add_method(new_method);
00291           return new_method;
00292         }
00293       }
00294       return method;
00295     }
00296   }
00297   return NULL;
00298 }
00299 
00300 methodOop Klass::lookup(symbolOop selector) {
00301   Klass* current = this;
00302   while (true) {
00303     methodOop result = current->local_lookup(selector);
00304     if (result)                          return result;
00305     if (current->superKlass() == nilObj) return NULL;
00306     current = current->superKlass()->klass_part();
00307   }
00308   return NULL;
00309 }
00310 
00311 bool Klass::is_method_holder_for(methodOop method) {
00312   // Always use the home  of the method in case of a blockMethod  
00313   methodOop m = method->home();
00314 
00315   objArrayOop array = methods();
00316   // Find out if a method with the same selector exists.
00317   for (int index = 1; index <= array->length(); index++) {
00318     assert(array->obj_at(index)->is_method(), "must be method");
00319     if (methodOop(array->obj_at(index)) == m) return true;
00320   }
00321   // Try the mixin
00322   if (oop(mixin()) != nilObj) {
00323     assert(mixin()->is_mixin(), "must be mixin");
00324     array = mixin()->methods();
00325     for (int index = 1; index <= array->length(); index++) {
00326       assert(array->obj_at(index)->is_method(), "must be method");
00327       if (methodOop(array->obj_at(index)) == m) return true;
00328     }
00329   }
00330   return false;
00331 }
00332 
00333 klassOop Klass::lookup_method_holder_for(methodOop method) {
00334   if (is_method_holder_for(method)) return as_klassOop();
00335   return (superKlass() == nilObj)
00336          ? NULL
00337          : superKlass()->klass_part()->lookup_method_holder_for(method);
00338 }
00339 
00340 void Klass::flush_methods() {
00341   set_methods(oopFactory::new_objArray(0));
00342 }
00343 
00344 bool Klass::is_specialized_class() const {
00345   memOopKlass m;
00346   return name() == m.name();
00347 }
00348 
00349 bool Klass::is_named_class() const {
00350   return mixin()->primary_invocation() == as_klassOop();
00351 }
00352 
00353 void Klass::print_klass() {
00354   lprintf("%sKlass (%s)", name(), name_from_format(format()));
00355 }
00356 
00357 void Klass::print_name_on(outputStream* st) {
00358   int offset = as_klassOop()->blueprint()->lookup_inst_var(oopFactory::new_symbol("name"));
00359   symbolOop name = NULL;
00360   if (offset >= 0) {
00361     name = symbolOop(as_klassOop()->raw_at(offset));
00362     if (!name->is_symbol()) name = NULL;
00363   }
00364   if (name != NULL) name->print_symbol_on(st);
00365   else {
00366     bool meta;
00367     name = Universe::find_global_key_for(as_klassOop(), &meta);
00368     if (name) {
00369       name->print_symbol_on(st);
00370       if (meta) st->print(" class");
00371     } else {
00372       st->print("??");
00373     }
00374   }
00375 }
00376 
00377 int Klass::oop_scavenge_contents(oop obj) {
00378   fatal("should not call Klass::oop_scavenge_contents");
00379   return 0;
00380 }
00381 
00382 int Klass::oop_scavenge_tenured_contents(oop obj) {
00383   fatal("should not call Klass::oop_scavenge_promotion");
00384   return 0;
00385 }
00386 
00387 void Klass::oop_follow_contents(oop obj) {
00388   fatal("should not call Klass::oop_follow_contents");
00389 }
00390 
00391 void Klass::oop_layout_iterate(oop obj, ObjectLayoutClosure* blk) {
00392   fatal("should not call layout_iterate on Klass");
00393 }
00394 
00395 void Klass::oop_oop_iterate(oop obj, OopClosure *blk) {
00396   fatal("should not call oop_iterate on Klass");
00397 }
00398 
00399 void Klass::oop_print_on      (oop obj, outputStream* st) { fatal("should not call Klass::oop_print_on"); }
00400 void Klass::oop_print_value_on(oop obj, outputStream* st) { oop_print_on(obj, st); }
00401 void Klass::oop_short_print_on(oop obj, outputStream* st) { 
00402   if (obj == trueObj) {
00403     st->print("true");
00404   } else if (obj == falseObj) {
00405     st->print("false");
00406   } else if (obj == nilObj) {
00407      st->print("nil");
00408   } else {
00409     oop_print_value_on(obj, st); 
00410   }
00411 }
00412 
00413 bool Klass::oop_verify(oop obj) {
00414   // FIX LATER
00415   return true;
00416 }
00417 
00418 void Klass::bootstrap_klass_part_one(bootstrap* st) {
00419   st->read_oop((oop*)&_non_indexable_size);
00420   st->read_oop((oop*)&_has_untagged_contents);
00421 }
00422 
00423 void Klass::bootstrap_klass_part_two(bootstrap* st) {
00424   st->read_oop((oop*)&_classVars);
00425   st->read_oop((oop*)&_methods);
00426   st->read_oop((oop*)&_superKlass);
00427   st->read_oop((oop*)&_mixin);
00428 }  
00429 
00430 oop Klass::oop_primitive_allocate(oop obj) {
00431   return markSymbol(vmSymbols::not_klass()); }
00432 
00433 oop Klass::oop_primitive_allocate_size(oop obj, int size) {
00434   return markSymbol(vmSymbols::not_klass()); }
00435 
00436 oop Klass::oop_shallow_copy(oop obj, bool tenured) {
00437   return markSymbol(vmSymbols::not_oops()); }

Generated on Mon Oct 9 13:37:12 2006 for Strongtalk VM by  doxygen 1.4.7