00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 # include "incls/_precompiled.incl"
00026 # include "incls/_reflection.cpp.incl"
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 class memConverter: public ResourceObj {
00040 protected:
00041 klassOop old_klass;
00042 klassOop new_klass;
00043 GrowableArray<int>* mapping;
00044
00045 void compute_mapping() {
00046 mapping = new GrowableArray<int>(20);
00047 int old_header_size = old_klass->klass_part()->oop_header_size();
00048 int new_header_size = new_klass->klass_part()->oop_header_size();
00049 int n = old_klass->klass_part()->number_of_instance_variables();
00050 for (int old_index = 0; old_index < n; old_index++) {
00051 symbolOop name = old_klass->klass_part()->inst_var_name_at(old_index + old_header_size);
00052 assert(name->is_symbol(), "instance variable name must be symbol");
00053 int new_index = new_klass->klass_part()->lookup_inst_var(name);
00054 if (new_index > 0) {
00055 if (TraceApplyChange) {
00056 std->print("map ");
00057 name->print_symbol_on(std);
00058 std->print_cr(" %d -> %d", old_index + old_header_size, new_index);
00059 }
00060
00061 mapping->push(old_index + old_header_size);
00062 mapping->push(new_index);
00063 }
00064 }
00065 }
00066
00067 public:
00068 memConverter(klassOop old_klass, klassOop new_klass) {
00069 this->old_klass = old_klass;
00070 this->new_klass = new_klass;
00071 compute_mapping();
00072 }
00073
00074 memOop convert(memOop src) {
00075 memOop dst = allocate(src);
00076
00077 transfer(src, dst);
00078 Reflection::forward(src, dst);
00079 return dst;
00080 }
00081
00082 virtual void transfer(memOop src, memOop dst) {
00083
00084 if (src->mark()->is_near_death())
00085 dst->mark_as_dying();
00086 dst->set_identity_hash(src->identity_hash());
00087
00088 for (int index = 0; index < mapping->length(); index += 2) {
00089 int from = mapping->at(index);
00090 int to = mapping->at(index+1);
00091 dst->raw_at_put(to, src->raw_at(from));
00092 }
00093 }
00094
00095 virtual memOop allocate(memOop src) {
00096 return memOop(new_klass->klass_part()->allocateObject());
00097 }
00098 };
00099
00100 class proxyConverter: public memConverter {
00101 private:
00102 bool source_is_proxy;
00103 public:
00104 proxyConverter(klassOop old_klass, klassOop new_klass)
00105 : memConverter(old_klass, new_klass){
00106 assert(new_klass->klass_part()->oop_is_proxy(), "new_klass must be a proxy klass");
00107 source_is_proxy = old_klass->klass_part()->oop_is_proxy();
00108 }
00109
00110 void transfer(memOop src, memOop dst) {
00111 if (source_is_proxy)
00112 proxyOop(dst)->set_pointer(proxyOop(src)->get_pointer());
00113 memConverter::transfer(src, dst);
00114 }
00115 };
00116
00117 class processConverter: public memConverter {
00118 private:
00119 bool source_is_process;
00120 public:
00121 processConverter(klassOop old_klass, klassOop new_klass)
00122 : memConverter(old_klass, new_klass){
00123 assert(new_klass->klass_part()->oop_is_process(), "new_klass must be a process klass");
00124 source_is_process = old_klass->klass_part()->oop_is_process();
00125 }
00126
00127 void transfer(memOop src, memOop dst) {
00128 if (source_is_process)
00129 processOop(dst)->set_process(processOop(src)->process());
00130 memConverter::transfer(src, dst);
00131 }
00132 };
00133
00134 class byteArrayConverter: public memConverter {
00135 private:
00136 bool source_is_byte_array;
00137 public:
00138 byteArrayConverter(klassOop old_klass, klassOop new_klass)
00139 : memConverter(old_klass, new_klass){
00140 assert(new_klass->klass_part()->oop_is_byteArray(), "new_klass must be a byteArray klass");
00141 source_is_byte_array = old_klass->klass_part()->oop_is_byteArray();
00142 }
00143
00144 void transfer(memOop src, memOop dst) {
00145 memConverter::transfer(src, dst);
00146 if (source_is_byte_array) {
00147 int length = byteArrayOop(src)->length();
00148 for (int index = 1; index <= length; index++)
00149 byteArrayOop(dst)->byte_at_put(index, byteArrayOop(src)->byte_at(index));
00150 }
00151 }
00152
00153 memOop allocate(memOop src) {
00154 int len = source_is_byte_array ? byteArrayOop(src)->length() : 0;
00155 return memOop(new_klass->klass_part()->allocateObjectSize(len));
00156 }
00157 };
00158
00159 class doubleByteArrayConverter: public memConverter {
00160 private:
00161 bool source_is_doubleByte_array;
00162 public:
00163 doubleByteArrayConverter(klassOop old_klass, klassOop new_klass)
00164 : memConverter(old_klass, new_klass){
00165 assert(new_klass->klass_part()->oop_is_doubleByteArray(), "new_klass must be a byteArray klass");
00166 source_is_doubleByte_array = old_klass->klass_part()->oop_is_doubleByteArray();
00167 }
00168
00169 void transfer(memOop src, memOop dst) {
00170 memConverter::transfer(src, dst);
00171 if (source_is_doubleByte_array) {
00172 int length = doubleByteArrayOop(src)->length();
00173 for (int index = 1; index <= length; index++)
00174 doubleByteArrayOop(dst)->doubleByte_at_put(index, doubleByteArrayOop(src)->doubleByte_at(index));
00175 }
00176 }
00177
00178 memOop allocate(memOop src) {
00179 int len = source_is_doubleByte_array ? doubleByteArrayOop(src)->length() : 0;
00180 return memOop(new_klass->klass_part()->allocateObjectSize(len));
00181 }
00182 };
00183
00184 class objArrayConverter: public memConverter {
00185 private:
00186 bool source_is_obj_array;
00187 public:
00188 objArrayConverter(klassOop old_klass, klassOop new_klass)
00189 : memConverter(old_klass, new_klass){
00190 assert(new_klass->klass_part()->oop_is_objArray(), "new_klass must be a objArray klass");
00191 source_is_obj_array = old_klass->klass_part()->oop_is_objArray();
00192 }
00193
00194 void transfer(memOop src, memOop dst) {
00195 memConverter::transfer(src, dst);
00196 if (source_is_obj_array) {
00197 int length = objArrayOop(src)->length();
00198 for (int index = 1; index <= length; index++)
00199 objArrayOop(dst)->obj_at_put(index, objArrayOop(src)->obj_at(index));
00200 }
00201 }
00202
00203 memOop allocate(memOop src) {
00204 int len = source_is_obj_array ? objArrayOop(src)->length() : 0;
00205 return memOop(new_klass->klass_part()->allocateObjectSize(len));
00206 }
00207 };
00208
00209 class doubleValueArrayConverter: public memConverter {
00210 private:
00211 bool source_is_obj_array;
00212 public:
00213 doubleValueArrayConverter(klassOop old_klass, klassOop new_klass)
00214 : memConverter(old_klass, new_klass){
00215 assert(new_klass->klass_part()->oop_is_doubleValueArray(), "new_klass must be a doubleValueArray klass");
00216 source_is_obj_array = old_klass->klass_part()->oop_is_doubleValueArray();
00217 }
00218
00219 void transfer(memOop src, memOop dst) {
00220 memConverter::transfer(src, dst);
00221 if (source_is_obj_array) {
00222 int length = doubleValueArrayOop(src)->length();
00223 for (int index = 1; index <= length; index++)
00224 doubleValueArrayOop(dst)->double_at_put(index, doubleValueArrayOop(src)->double_at(index));
00225 }
00226 }
00227
00228 memOop allocate(memOop src) {
00229 int len = source_is_obj_array ? doubleValueArrayOop(src)->length() : 0;
00230 return memOop(new_klass->klass_part()->allocateObjectSize(len));
00231 }
00232 };
00233
00234 class klassConverter: public memConverter {
00235 public:
00236 klassConverter(klassOop old_klass, klassOop new_klass)
00237 : memConverter(old_klass, new_klass){
00238 assert(old_klass->klass_part()->oop_is_klass(), "new_klass must be a klass klass");
00239 assert(new_klass->klass_part()->oop_is_klass(), "new_klass must be a klass klass");
00240 }
00241
00242 void transfer(memOop src, memOop dst) {
00243 memConverter::transfer(src, dst);
00244 }
00245
00246 memOop allocate(memOop src) {
00247 Unimplemented();
00248 return NULL;
00249 }
00250 };
00251
00252 class mixinConverter: public memConverter {
00253 public:
00254 mixinConverter(klassOop old_klass, klassOop new_klass)
00255 : memConverter(old_klass, new_klass){
00256 assert(old_klass->klass_part()->oop_is_mixin(), "new_klass must be a mixin klass");
00257 assert(new_klass->klass_part()->oop_is_mixin(), "new_klass must be a mixin klass");
00258 }
00259
00260 void transfer(memOop src, memOop dst) {
00261 Unimplemented();
00262 memConverter::transfer(src, dst);
00263 }
00264 };
00265
00266
00267 GrowableArray<ClassChange*>* Reflection::class_changes = NULL;
00268 GrowableArray<memOop>* Reflection::converted = NULL;
00269
00270 class ConvertClosure : public OopClosure {
00271 void do_oop(oop* o) {
00272 Reflection::convert(o);
00273 }
00274 };
00275
00276 class ConvertOopClosure : public ObjectClosure {
00277 public:
00278 void do_object(memOop obj) {
00279 if (obj->klass()->klass_part()->is_marked_for_schema_change()) return;
00280 ConvertClosure blk;
00281 obj->oop_iterate(&blk);
00282 }
00283 };
00284
00285 class ClassChange: public ResourceObj {
00286 private:
00287 klassOop _old_klass;
00288 mixinOop _new_mixin;
00289 Klass::Format _new_format;
00290 klassOop _new_klass;
00291 klassOop _new_super;
00292 memConverter* _converter;
00293 ClassChange* _super_change;
00294 bool _is_schema_change_computed;
00295 bool _needs_schema_change;
00296 char* _reason_for_schema_change;
00297
00298 public:
00299 ClassChange(klassOop old_klass, mixinOop new_mixin, Klass::Format new_format, klassOop new_super) {
00300 _old_klass = old_klass;
00301 _new_mixin = new_mixin;
00302 _new_format = new_format;
00303 _new_super = new_super;
00304 _new_klass = NULL;
00305 _converter = NULL;
00306 _super_change = NULL;
00307 _is_schema_change_computed = false;
00308 _reason_for_schema_change = "";
00309 }
00310
00311 ClassChange(klassOop old_klass, Klass::Format new_format) {
00312 _old_klass = old_klass;
00313 _new_mixin = old_klass->klass_part()->mixin();
00314 _new_format = new_format;
00315 _new_super = NULL;
00316 _new_klass = NULL;
00317 _converter = NULL;
00318 _super_change = NULL;
00319 _is_schema_change_computed = false;
00320 _reason_for_schema_change = "";
00321 }
00322 klassOop old_klass() const { return _old_klass; }
00323 mixinOop new_mixin() const { return _new_mixin; }
00324 Klass::Format new_format() const { return _new_format; }
00325 klassOop new_klass() const { return _new_klass; }
00326 klassOop new_super() const { return _new_super; }
00327 memConverter* converter() const { return _converter; }
00328 ClassChange* super_change() const { return _super_change; }
00329 mixinOop old_mixin() const { return _old_klass->klass_part()->mixin(); }
00330
00331
00332 char* reason_for_schema_change() { return _reason_for_schema_change; }
00333 void set_reason_for_schema_change(char* msg) { _reason_for_schema_change = msg; }
00334
00335 void set_super_change(ClassChange* change) {
00336 _super_change = change;
00337 }
00338
00339 void setup_schema_change();
00340 void recustomize_methods();
00341
00342 bool compute_needed_schema_change();
00343 bool needs_schema_change() {
00344 if (!_is_schema_change_computed)
00345 _needs_schema_change = compute_needed_schema_change();
00346 return _needs_schema_change;
00347 }
00348
00349 klassOop new_class_from(klassOop old_klass,
00350 klassOop new_super_klass,
00351 mixinOop new_mixin,
00352 Klass::Format new_format,
00353 mixinOop old_mixin);
00354
00355 memConverter* create_converter_for(klassOop old_class, klassOop new_class);
00356
00357 void transfer_misc(memOop src, memOop dst);
00358
00359
00360 void update_class(bool class_vars_changed,
00361 bool instance_methods_changed,
00362 bool class_methods_changed);
00363
00364 void update_class_vars();
00365 void update_methods(bool instance_side);
00366 };
00367
00368
00369 void ClassChange::recustomize_methods() {
00370 new_mixin()->customize_for(new_klass());
00371 new_mixin()->class_mixin()->customize_for(new_klass()->klass());
00372 }
00373
00374 klassOop ClassChange::new_class_from(klassOop old_klass,
00375 klassOop new_super_klass,
00376 mixinOop new_mixin,
00377 Klass::Format new_format,
00378 mixinOop old_mixin) {
00379
00380 Klass::Format format = (new_format != Klass::special_klass)
00381 ? new_format
00382 : old_klass->klass_part()->format();
00383
00384 klassOop result = new_super_klass->klass_part()->create_subclass(new_mixin, format);
00385 if (result == NULL) {
00386 fatal("class creation failed - internal error");
00387 }
00388
00389
00390 _new_klass = result;
00391
00392 if (old_klass->klass_part()->mixin()->primary_invocation() == old_klass) {
00393 recustomize_methods();
00394 new_mixin->set_primary_invocation(result);
00395 new_mixin->class_mixin()->set_primary_invocation(result->klass());
00396 }
00397
00398 new_mixin->set_installed(trueObj);
00399 new_mixin->class_mixin()->set_installed(trueObj);
00400
00401 transfer_misc(old_klass, result);
00402 transfer_misc(old_klass->klass(), result->klass());
00403
00404
00405 for (int index = old_klass->klass_part()->number_of_classVars(); index > 0; index--) {
00406 associationOop old_assoc = old_klass->klass_part()->classVar_at(index);
00407 associationOop new_assoc = result->klass_part()->local_lookup_class_var(old_assoc->key());
00408 if (new_assoc) {
00409 new_assoc->set_value(old_assoc->value());
00410 }
00411 }
00412 return result;
00413 }
00414
00415
00416 void ClassChange::transfer_misc(memOop src, memOop dst) {
00417 memConverter* c = new memConverter(src->klass(), dst->klass());
00418 c->transfer(src, dst);
00419 }
00420
00421 memConverter* ClassChange::create_converter_for(klassOop old_class, klassOop new_class) {
00422 switch (new_class->klass_part()->format()) {
00423 case Klass::mem_klass: return new memConverter(old_class, new_class);
00424 case Klass::byteArray_klass: return new byteArrayConverter(old_class, new_class);
00425 case Klass::doubleByteArray_klass: return new doubleByteArrayConverter(old_class, new_class);
00426 case Klass::doubleValueArray_klass: return new doubleValueArrayConverter(old_class, new_class);
00427 case Klass::klass_klass: return new klassConverter(old_class, new_class);
00428 case Klass::mixin_klass: return new mixinConverter(old_class, new_class);
00429 case Klass::objArray_klass: return new objArrayConverter(old_class, new_class);
00430 case Klass::weakArray_klass: return new objArrayConverter(old_class, new_class);
00431 case Klass::process_klass: return new processConverter(old_class, new_class);
00432 case Klass::proxy_klass: return new proxyConverter(old_class, new_class);
00433 }
00434 fatal("cannot create converter for type");
00435 return NULL;
00436 }
00437
00438 void ClassChange::update_class_vars() {
00439 if (TraceApplyChange) {
00440 std->print(" - updating class variables for: ");
00441 old_klass()->print_value();
00442 std->cr();
00443 }
00444
00445 Klass* k = old_klass()->klass_part();
00446
00447
00448 for (int index = k->number_of_classVars(); index > 0; index--) {
00449 associationOop assoc = k->classVar_at(index);
00450 if (!new_mixin()->includes_classVar(assoc->key())) {
00451 k->remove_classVar_at(index);
00452 }
00453 }
00454
00455 for (index = new_mixin()->number_of_classVars(); index > 0; index--) {
00456 symbolOop name = new_mixin()->classVar_at(index);
00457 if (!k->includes_classVar(name)) {
00458 k->add_classVar(oopFactory::new_association(name, nilObj, false));
00459 }
00460 }
00461
00462
00463 old_klass()->klass()->klass_part()->set_classVars(k->classVars());
00464
00465 old_mixin()->set_classVars(new_mixin()->classVars());
00466 old_mixin()->class_mixin()->set_classVars(new_mixin()->classVars());
00467 }
00468
00469 void ClassChange::update_methods(bool instance_side) {
00470 if (TraceApplyChange) {
00471 std->print(" updating %s-side methods for: ", instance_side ? "instance" : "class");
00472 old_klass()->print_value();
00473 std->cr();
00474 }
00475
00476 if (instance_side) {
00477 old_klass()->klass_part()->flush_methods();
00478 old_mixin()->set_methods(new_mixin()->methods());
00479 } else {
00480 old_klass()->klass()->klass_part()->flush_methods();
00481 old_mixin()->class_mixin()->set_methods(new_mixin()->class_mixin()->methods());
00482 }
00483 }
00484
00485 void ClassChange::update_class(bool class_vars_changed,
00486 bool instance_methods_changed,
00487 bool class_methods_changed) {
00488
00489
00490 if (old_mixin() == new_mixin()) return;
00491
00492
00493 if (class_vars_changed)
00494 update_class_vars();
00495 if (instance_methods_changed)
00496 update_methods(true);
00497 if (class_methods_changed)
00498 update_methods(false);
00499
00500 if (old_klass()->klass_part()->superKlass() != new_super()) {
00501 old_klass()->klass_part()->set_superKlass(new_super());
00502 }
00503 }
00504
00505 void ClassChange::setup_schema_change() {
00506
00507
00508 if (_super_change) {
00509 _new_super = super_change()->new_klass();
00510 assert(_new_super != NULL, "super class must exist");
00511 }
00512
00513
00514 _new_klass = new_class_from(old_klass(), new_super(), new_mixin(), new_format(), old_mixin());
00515
00516
00517 _converter = create_converter_for(old_klass(), new_klass());
00518
00519
00520 Reflection::forward(old_klass(), new_klass());
00521
00522
00523 Reflection::forward(old_klass()->klass(), new_klass()->klass());
00524
00525
00526 Reflection::forward(old_klass()->klass_part()->mixin(), new_klass()->klass_part()->mixin());
00527
00528
00529 Reflection::forward(old_klass()->klass()->klass_part()->mixin(), new_klass()->klass()->klass_part()->mixin());
00530 }
00531
00532 bool ClassChange::compute_needed_schema_change() {
00533
00534 if ( new_super()->is_klass()
00535 && !new_super()->klass_part()->has_same_layout_as(old_klass()->klass_part()->superKlass())) {
00536 set_reason_for_schema_change("super class has changed");
00537 return true;
00538 }
00539
00540
00541 if ( new_format() != Klass::special_klass
00542 && new_format() != old_klass()->klass_part()->format()) {
00543 set_reason_for_schema_change("format of class has changed");
00544 return true;
00545 }
00546
00547
00548 if (new_mixin()->number_of_instVars() != old_mixin()->number_of_instVars()) {
00549 set_reason_for_schema_change("number of instance variables have changed");
00550 return true;
00551 }
00552
00553 for (int index = new_mixin()->number_of_instVars(); index > 0; index--) {
00554 if (new_mixin()->instVar_at(index) != old_mixin()->instVar_at(index)) {
00555 set_reason_for_schema_change("instance variables have changed");
00556 return true;
00557 }
00558 }
00559 return false;
00560 }
00561
00562 bool Reflection::needs_schema_change() {
00563 bool result = false;
00564 for (int index = 0; index < class_changes->length(); index++) {
00565 bool sub_result = class_changes->at(index)->needs_schema_change();
00566 if (TraceApplyChange && sub_result) {
00567 class_changes->at(index)->old_klass()->print_value();
00568 std->cr();
00569 std->print_cr(" needs schema change because: %s.", class_changes->at(index)->reason_for_schema_change());
00570 }
00571 result = result || sub_result;
00572 }
00573 return result;
00574 }
00575
00576 void Reflection::forward(memOop old_obj, memOop new_obj) {
00577 if (old_obj == new_obj) return;
00578 if (old_obj->is_forwarded()) {
00579 if (old_obj->forwardee() != new_obj) {
00580 fatal("inconsistent forwarding");
00581 }
00582 return;
00583 }
00584 old_obj->forward_to(new_obj);
00585 converted->append(old_obj);
00586 }
00587
00588 bool Reflection::has_methods_changed(mixinOop new_mixin, mixinOop old_mixin) {
00589 if (new_mixin->number_of_methods() != old_mixin->number_of_methods())
00590 return true;
00591
00592 for (int index = 1; index <= new_mixin->number_of_methods(); index++) {
00593 if (!old_mixin->includes_method(new_mixin->method_at(index)))
00594 return true;
00595 }
00596 return false;
00597 }
00598
00599 bool Reflection::has_class_vars_changed(mixinOop new_mixin, mixinOop old_mixin) {
00600 if (new_mixin->number_of_classVars() != old_mixin->number_of_classVars())
00601 return true;
00602
00603 for (int index = 1; index <= new_mixin->number_of_classVars(); index++) {
00604 if (!old_mixin->includes_classVar(new_mixin->classVar_at(index)))
00605 return true;
00606 }
00607 return false;
00608 }
00609
00610
00611 ClassChange* Reflection::find_change_for(klassOop klass) {
00612 for (int index = 0; index < class_changes->length(); index++) {
00613 ClassChange* e = class_changes->at(index);
00614 if (e->old_klass() == klass) return e;
00615 }
00616 return NULL;
00617 }
00618
00619 void Reflection::register_class_changes(mixinOop new_mixin,
00620 objArrayOop invocations) {
00621
00622 class_changes = new GrowableArray<ClassChange*>(100);
00623 int length = invocations->length();
00624 for (int index = invocations_offset(); index <= length; index++) {
00625 objArrayOop invocation = objArrayOop(invocations->obj_at(index));
00626 assert(invocation->is_objArray(), "type check");
00627
00628
00629 ClassChange* change = new ClassChange(klassOop(invocation->obj_at(1)),
00630 new_mixin,
00631 Klass::format_from_symbol(symbolOop(invocation->obj_at(2))),
00632 klassOop(invocation->obj_at(3)));
00633 change->set_super_change(find_change_for(change->old_klass()->klass_part()->superKlass()));
00634 class_changes->append(change);
00635
00636 for (int j = 4; j <= invocation->length() - 1; j += 2) {
00637 klassOop old_klass = klassOop(invocation->obj_at(j));
00638 change = new ClassChange(old_klass,
00639 Klass::format_from_symbol(symbolOop(invocation->obj_at(j+1))));
00640 change->set_super_change(find_change_for(old_klass->klass_part()->superKlass()));
00641 class_changes->append(change);
00642 }
00643 }
00644 }
00645
00646 void Reflection::invalidate_classes(bool value) {
00647 for (int index = 0; index < class_changes->length(); index++) {
00648 klassOop old_klass = class_changes->at(index)->old_klass();
00649 old_klass->set_invalid(value);
00650 old_klass->klass()->set_invalid(value);
00651 }
00652 }
00653
00654 void Reflection::update_classes(bool class_vars_changed, bool instance_methods_changed, bool class_methods_changed) {
00655 for (int index = 0; index < class_changes->length(); index++) {
00656 class_changes->at(index)->update_class(class_vars_changed, instance_methods_changed, class_methods_changed);
00657 }
00658 }
00659
00660 void Reflection::setup_schema_change() {
00661 for (int index = 0; index < class_changes->length(); index++) {
00662 class_changes->at(index)->setup_schema_change();
00663 }
00664 for (index = 0; index < class_changes->length(); index++) {
00665
00666 class_changes->at(index)->old_klass()->klass_part()->mark_for_schema_change();
00667 }
00668 }
00669
00670 void Reflection::apply_change(mixinOop new_mixin,
00671 mixinOop old_mixin,
00672 objArrayOop invocations) {
00673 ResourceMark rm;
00674 if (TraceApplyChange) {
00675 std->print("Reflective change");
00676 std->print_cr("[new]");
00677 new_mixin->print();
00678 std->print_cr("[old]");
00679 old_mixin->print();
00680 std->print_cr("[invocations]");
00681 invocations->print();
00682 Universe::verify();
00683 }
00684
00685 register_class_changes(new_mixin, invocations);
00686
00687 invalidate_classes(true);
00688
00689
00690 Universe::code->mark_dependents_for_deoptimization();
00691 Processes::deoptimized_wrt_marked_nmethods();
00692 Universe::code->make_marked_nmethods_zombies();
00693
00694
00695 bool format_changed = needs_schema_change();
00696
00697 bool class_vars_changed = has_class_vars_changed(new_mixin, old_mixin);
00698 bool instance_methods_changed = has_methods_changed(new_mixin, old_mixin);
00699 bool class_methods_changed = has_methods_changed(new_mixin->class_mixin(), old_mixin->class_mixin());
00700
00701 if (format_changed) {
00702 if (TraceApplyChange) {
00703 std->print_cr(" - schema change is needed");
00704 }
00705
00706 converted = new GrowableArray<memOop> (100);
00707
00708 setup_schema_change();
00709
00710
00711 ConvertOopClosure blk;
00712 ConvertClosure bl;
00713 Universe::roots_do(&convert);
00714 Processes::oop_iterate(&bl);
00715
00716
00717 NewWaterMark eden_mark = Universe::new_gen.eden()->top_mark();
00718 OldWaterMark old_mark = Universe::old_gen.top_mark();
00719
00720 Universe::new_gen.object_iterate(&blk);
00721 Universe::old_gen.object_iterate(&blk);
00722
00723 while ( eden_mark != Universe::new_gen.eden()->top_mark()
00724 || old_mark != Universe::old_gen.top_mark()) {
00725 Universe::new_gen.eden()->object_iterate_from(&eden_mark, &blk);
00726 Universe::old_gen.object_iterate_from(&old_mark, &blk);
00727 }
00728
00729
00730
00731
00732 for (int j = 0; j < converted->length(); j++) {
00733 memOop obj = converted->at(j);
00734 if (TraceApplyChange) {
00735 std->print_cr("Old: 0x%lx, 0x%lx", obj, obj->mark());
00736 std->print_cr("New: 0x%lx, 0x%lx", obj->forwardee(), obj->forwardee()->mark());
00737 }
00738 obj->set_mark(obj->forwardee()->mark());
00739 }
00740
00741
00742 converted = NULL;
00743
00744 } else {
00745 if (TraceApplyChange) {
00746 std->print_cr(" - no schema change (%s%s%s)",
00747 class_vars_changed ? "class variables " : "",
00748 instance_methods_changed ? "instance methods " : "",
00749 class_methods_changed ? "class methods " : "");
00750 }
00751 update_classes(class_vars_changed, instance_methods_changed, class_methods_changed);
00752 }
00753
00754 invalidate_classes(false);
00755 class_changes = NULL;
00756
00757
00758 Universe::flush_inline_caches_in_methods();
00759 Universe::code->clear_inline_caches();
00760
00761 lookupCache::flush();
00762 DeltaCallCache::clearAll();
00763
00764 if (TraceApplyChange)
00765 Universe::verify();
00766 }
00767
00768 oop Reflection::apply_change(objArrayOop change) {
00769 TraceTime t("ApplyChange", TraceApplyChange);
00770
00771
00772
00773
00774
00775
00776 int length = change->length();
00777
00778 if (length < 3)
00779 return markSymbol(vmSymbols::argument_is_invalid());
00780
00781 mixinOop new_mixin = mixinOop(change->obj_at(1));
00782 if (!new_mixin->is_mixin())
00783 return markSymbol(vmSymbols::argument_is_invalid());
00784
00785 mixinOop old_mixin = mixinOop(change->obj_at(2));
00786 if (!old_mixin->is_mixin())
00787 return markSymbol(vmSymbols::argument_is_invalid());
00788
00789 for (int index = 3; index <= length; index++) {
00790 objArrayOop array = objArrayOop(change->obj_at(index));
00791
00792 if (!array->is_objArray())
00793 return markSymbol(vmSymbols::argument_is_invalid());
00794
00795 if (array->length() < 3)
00796 return markSymbol(vmSymbols::argument_is_invalid());
00797
00798 if (!array->obj_at(1)->is_klass())
00799 return markSymbol(vmSymbols::argument_is_invalid());
00800
00801 if (!array->obj_at(2)->is_symbol())
00802 return markSymbol(vmSymbols::argument_is_invalid());
00803
00804 if (!array->obj_at(3)->is_klass() && array->obj_at(3) != nilObj)
00805 return markSymbol(vmSymbols::argument_is_invalid());
00806
00807 for (int j = 4; j <= array->length() - 1; j += 2) {
00808 if (!array->obj_at(j)->is_klass())
00809 return markSymbol(vmSymbols::argument_is_invalid());
00810 if (!array->obj_at(j+1)->is_symbol())
00811 return markSymbol(vmSymbols::argument_is_invalid());
00812 }
00813 }
00814
00815 apply_change(new_mixin, old_mixin, change);
00816 return trueObj;
00817 }
00818
00819 void Reflection::convert(oop* p) {
00820 oop obj = *p;
00821
00822 if (!obj->is_mem())
00823 return;
00824
00825 if (memOop(obj)->is_forwarded()) {
00826 Universe::store(p, memOop(obj)->forwardee());
00827 return;
00828 }
00829
00830 if (memOop(obj)->klass()->klass_part()->is_marked_for_schema_change()) {
00831 Universe::store(p, convert_object(memOop(obj)));
00832 }
00833 }
00834
00835 memOop Reflection::convert_object(memOop obj) {
00836 assert(obj->klass()->klass_part()->is_marked_for_schema_change(), "just checking");
00837 ClassChange* change = find_change_for(obj->klass());
00838 assert(change, "change must be present");
00839 return change->converter()->convert(obj);
00840 }