--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/anonk.patch Tue Apr 15 01:22:23 2008 -0700
@@ -0,0 +1,903 @@
+diff --git a/src/share/vm/ci/ciEnv.cpp b/src/share/vm/ci/ciEnv.cpp
+--- a/src/share/vm/ci/ciEnv.cpp
++++ b/src/share/vm/ci/ciEnv.cpp
+@@ -484,7 +484,7 @@ ciConstant ciEnv::get_constant_by_index_
+ } else if (tag.is_double()) {
+ return ciConstant((jdouble)cpool->double_at(index));
+ } else if (tag.is_string() || tag.is_unresolved_string()) {
+- oop string = cpool->string_at(index, THREAD);
++ oop string = cpool->pseudo_string_at(index, THREAD);
+ if (HAS_PENDING_EXCEPTION) {
+ CLEAR_PENDING_EXCEPTION;
+ record_out_of_memory_failure();
+diff --git a/src/share/vm/classfile/classFileParser.cpp b/src/share/vm/classfile/classFileParser.cpp
+--- a/src/share/vm/classfile/classFileParser.cpp
++++ b/src/share/vm/classfile/classFileParser.cpp
+@@ -167,9 +167,21 @@ void ClassFileParser::parse_constant_poo
+ // Got utf8 string, guarantee utf8_length+1 bytes, set stream position forward.
+ cfs->guarantee_more(utf8_length+1, CHECK); // utf8 string, tag/access_flags
+ cfs->skip_u1_fast(utf8_length);
++
+ // Before storing the symbol, make sure it's legal
+ if (_need_verify) {
+ verify_legal_utf8((unsigned char*)utf8_buffer, utf8_length, CHECK);
++ }
++
++ if (has_cp_patch_at(index)) {
++ Handle patch = clear_cp_patch_at(index);
++ guarantee_property(java_lang_String::is_instance(patch()),
++ "Illegal utf8 patch at %d in class file %s",
++ index, CHECK);
++ char* str = java_lang_String::as_utf8_string(patch());
++ // (could use java_lang_String::as_symbol instead, but might as well batch them)
++ utf8_buffer = (u1*) str;
++ utf8_length = strlen(str);
+ }
+
+ unsigned int hash;
+@@ -300,7 +312,13 @@ constantPoolHandle ClassFileParser::pars
+ cp->tag_at(class_index).is_utf8(),
+ "Invalid constant pool index %u in class file %s",
+ class_index, CHECK_(nullHandle));
+- cp->unresolved_klass_at_put(index, cp->symbol_at(class_index));
++ symbolOop name = cp->symbol_at(class_index);
++ klassOop wkk = SystemDictionary::find_well_known_klass(name);
++ if (wkk != NULL) {
++ cp->klass_at_put(index, wkk); // eagerly resolve
++ } else {
++ cp->unresolved_klass_at_put(index, name);
++ }
+ }
+ break;
+ case JVM_CONSTANT_UnresolvedString :
+@@ -325,16 +343,45 @@ constantPoolHandle ClassFileParser::pars
+ } // end of switch
+ } // end of for
+
++ if (_cp_patches != NULL) {
++ // need to treat this_class specially...
++ int this_class_index;
++ {
++ cfs->guarantee_more(8, CHECK_(nullHandle)); // flags, this_class, super_class, infs_len
++ u1* mark = cfs->current();
++ u2 flags = cfs->get_u2_fast();
++ this_class_index = cfs->get_u2_fast();
++ cfs->set_current(mark); // revert to mark
++ }
++
++ for (index = 1; index < length; index++) { // Index 0 is unused
++ if (has_cp_patch_at(index)) {
++ guarantee_property(index != this_class_index,
++ "Illegal constant pool patch to self at %d in class file %s",
++ index, CHECK_(nullHandle));
++ patch_constant_pool(cp, index, cp_patch_at(index), CHECK_(nullHandle));
++ }
++ }
++ // Ensure that all the patches have been used.
++ for (index = 0; index < _cp_patches->length(); index++) {
++ guarantee_property(!has_cp_patch_at(index),
++ "Unused constant pool patch at %d in class file %s",
++ index, CHECK_(nullHandle));
++ }
++ }
++
+ if (!_need_verify) {
+ return cp;
+ }
+
+ // second verification pass - checks the strings are of the right format.
++ // but not yet to the other entries
+ for (index = 1; index < length; index++) {
+ jbyte tag = cp->tag_at(index).value();
+ switch (tag) {
+ case JVM_CONSTANT_UnresolvedClass: {
+ symbolHandle class_name(THREAD, cp->unresolved_klass_at(index));
++ // check the name, even if _cp_patches will overwrite it
+ verify_legal_class_name(class_name, CHECK_(nullHandle));
+ break;
+ }
+@@ -377,6 +424,71 @@ constantPoolHandle ClassFileParser::pars
+ }
+
+
++void ClassFileParser::patch_constant_pool(constantPoolHandle cp, int index, Handle patch, TRAPS) {
++ BasicType patch_type = T_VOID;
++ switch (cp->tag_at(index).value()) {
++
++ case JVM_CONSTANT_UnresolvedClass :
++ // Patching a class means pre-resolving it.
++ // The name in the constant pool is ignored.
++ if (java_lang_Class::is_instance(patch())) {
++ guarantee_property(!java_lang_Class::is_primitive(patch()),
++ "Illegal class patch at %d in class file %s",
++ index, CHECK);
++ cp->klass_at_put(index, java_lang_Class::as_klassOop(patch()));
++ } else {
++ guarantee_property(java_lang_String::is_instance(patch()),
++ "Illegal class patch at %d in class file %s",
++ index, CHECK);
++ symbolHandle name = java_lang_String::as_symbol(patch(), CHECK);
++ cp->unresolved_klass_at_put(index, name());
++ }
++ break;
++
++ case JVM_CONSTANT_UnresolvedString :
++ // Patching a string means pre-resolving it.
++ // The spelling in the constant pool is ignored.
++ // The constant reference may be any object whatever.
++ // If it is not a real string, the constant is referred to
++ // as a "pseudo-string".
++ cp->string_at_put(index, patch());
++ break;
++
++ case JVM_CONSTANT_Integer : patch_type = T_INT; goto patch_prim;
++ case JVM_CONSTANT_Float : patch_type = T_FLOAT; goto patch_prim;
++ case JVM_CONSTANT_Long : patch_type = T_LONG; goto patch_prim;
++ case JVM_CONSTANT_Double : patch_type = T_DOUBLE; goto patch_prim;
++ patch_prim:
++ {
++ jvalue value;
++ BasicType value_type = java_lang_boxing_object::get_value(patch(), &value);
++ guarantee_property(value_type == patch_type,
++ "Illegal primitive patch at %d in class file %s",
++ index, CHECK);
++ switch (value_type) {
++ case T_INT: cp->int_at_put(index, value.i); break;
++ case T_FLOAT: cp->float_at_put(index, value.f); break;
++ case T_LONG: cp->long_at_put(index, value.j); break;
++ case T_DOUBLE: cp->long_at_put(index, value.d); break;
++ default: assert(false, "");
++ }
++ }
++ break;
++
++ default:
++ // %%% TODO: put method handles into CONSTANT_InterfaceMethodref, etc.
++ guarantee_property(!has_cp_patch_at(index),
++ "Illegal unexpected patch at %d in class file %s",
++ index, CHECK);
++ return;
++ }
++
++ // On fall-through, mark the patch as used.
++ clear_cp_patch_at(index);
++}
++
++
++
+ class NameSigHash: public ResourceObj {
+ public:
+ symbolOop _name; // name
+@@ -447,25 +559,32 @@ objArrayHandle ClassFileParser::parse_in
+ int index;
+ for (index = 0; index < length; index++) {
+ u2 interface_index = cfs->get_u2(CHECK_(nullHandle));
++ KlassHandle interf;
+ check_property(
+ valid_cp_range(interface_index, cp->length()) &&
+- cp->tag_at(interface_index).is_unresolved_klass(),
++ cp->tag_at(interface_index).is_klass_reference(),
+ "Interface name has bad constant pool index %u in class file %s",
+ interface_index, CHECK_(nullHandle));
+- symbolHandle unresolved_klass (THREAD, cp->klass_name_at(interface_index));
+-
+- // Don't need to check legal name because it's checked when parsing constant pool.
+- // But need to make sure it's not an array type.
+- guarantee_property(unresolved_klass->byte_at(0) != JVM_SIGNATURE_ARRAY,
+- "Bad interface name in class file %s", CHECK_(nullHandle));
+-
+- vmtimer->suspend(); // do not count recursive loading twice
+- // Call resolve_super so classcircularity is checked
+- klassOop k = SystemDictionary::resolve_super_or_fail(class_name,
+- unresolved_klass, class_loader, protection_domain,
+- false, CHECK_(nullHandle));
+- KlassHandle interf (THREAD, k);
+- vmtimer->resume();
++ if (cp->tag_at(interface_index).is_klass()) {
++ interf = KlassHandle(THREAD, cp->resolved_klass_at(interface_index));
++ } else {
++ symbolHandle unresolved_klass (THREAD, cp->klass_name_at(interface_index));
++
++ // Don't need to check legal name because it's checked when parsing constant pool.
++ // But need to make sure it's not an array type.
++ guarantee_property(unresolved_klass->byte_at(0) != JVM_SIGNATURE_ARRAY,
++ "Bad interface name in class file %s", CHECK_(nullHandle));
++
++ vmtimer->suspend(); // do not count recursive loading twice
++ // Call resolve_super so classcircularity is checked
++ klassOop k = SystemDictionary::resolve_super_or_fail(class_name,
++ unresolved_klass, class_loader, protection_domain,
++ false, CHECK_(nullHandle));
++ interf = KlassHandle(THREAD, k);
++ vmtimer->resume();
++
++ cp->klass_at_put(interface_index, interf()); // eagerly resolve
++ }
+
+ if (!Klass::cast(interf())->is_interface()) {
+ THROW_MSG_(vmSymbols::java_lang_IncompatibleClassChangeError(), "Implementing class", nullHandle);
+@@ -876,8 +995,7 @@ typeArrayHandle ClassFileParser::parse_e
+ "Illegal exception table handler in class file %s", CHECK_(nullHandle));
+ if (catch_type_index != 0) {
+ guarantee_property(valid_cp_range(catch_type_index, cp->length()) &&
+- (cp->tag_at(catch_type_index).is_klass() ||
+- cp->tag_at(catch_type_index).is_unresolved_klass()),
++ cp->tag_at(catch_type_index).is_klass_reference(),
+ "Catch type in exception table has bad constant type in class file %s", CHECK_(nullHandle));
+ }
+ }
+@@ -1116,7 +1234,7 @@ void ClassFileParser::parse_type_array(u
+ } else if (tag == ITEM_Object) {
+ u2 class_index = u2_array[i2++] = cfs->get_u2(CHECK);
+ guarantee_property(valid_cp_range(class_index, cp->length()) &&
+- cp->tag_at(class_index).is_unresolved_klass(),
++ cp->tag_at(class_index).is_klass_reference(),
+ "Bad class index %u in StackMap in class file %s",
+ class_index, CHECK);
+ } else if (tag == ITEM_Uninitialized) {
+@@ -2339,6 +2457,7 @@ instanceKlassHandle ClassFileParser::par
+ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
+ Handle class_loader,
+ Handle protection_domain,
++ GrowableArray<Handle>* cp_patches,
+ symbolHandle& parsed_name,
+ TRAPS) {
+ // So that JVMTI can cache class file in the state before retransformable agents
+@@ -2370,6 +2489,7 @@ instanceKlassHandle ClassFileParser::par
+ }
+ }
+
++ _cp_patches = cp_patches;
+
+ instanceKlassHandle nullHandle;
+
+@@ -2500,14 +2620,22 @@ instanceKlassHandle ClassFileParser::par
+ CHECK_(nullHandle));
+ } else {
+ check_property(valid_cp_range(super_class_index, cp_size) &&
+- cp->tag_at(super_class_index).is_unresolved_klass(),
++ cp->tag_at(super_class_index).is_klass_reference(),
+ "Invalid superclass index %u in class file %s",
+ super_class_index,
+ CHECK_(nullHandle));
+ // The class name should be legal because it is checked when parsing constant pool.
+ // However, make sure it is not an array type.
++ bool is_array = false;
++ if (cp->tag_at(super_class_index).is_klass()) {
++ super_klass = instanceKlassHandle(THREAD, cp->resolved_klass_at(super_class_index));
++ if (_need_verify)
++ is_array = super_klass->oop_is_array();
++ } else if (_need_verify) {
++ is_array = (cp->unresolved_klass_at(super_class_index)->byte_at(0) == JVM_SIGNATURE_ARRAY);
++ }
+ if (_need_verify) {
+- guarantee_property(cp->unresolved_klass_at(super_class_index)->byte_at(0) != JVM_SIGNATURE_ARRAY,
++ guarantee_property(!is_array,
+ "Bad superclass name in class file %s", CHECK_(nullHandle));
+ }
+ }
+@@ -2547,7 +2675,7 @@ instanceKlassHandle ClassFileParser::par
+ objArrayHandle methods_default_annotations(THREAD, methods_default_annotations_oop);
+
+ // We check super class after class file is parsed and format is checked
+- if (super_class_index > 0) {
++ if (super_class_index > 0 && super_klass.is_null()) {
+ symbolHandle sk (THREAD, cp->klass_name_at(super_class_index));
+ if (access_flags.is_interface()) {
+ // Before attempting to resolve the superclass, check for class format
+@@ -2564,6 +2692,9 @@ instanceKlassHandle ClassFileParser::par
+ CHECK_(nullHandle));
+ KlassHandle kh (THREAD, k);
+ super_klass = instanceKlassHandle(THREAD, kh());
++ cp->klass_at_put(super_class_index, super_klass()); // eagerly resolve
++ }
++ if (super_klass.not_null()) {
+ if (super_klass->is_interface()) {
+ ResourceMark rm(THREAD);
+ Exceptions::fthrow(
+@@ -2973,6 +3104,7 @@ instanceKlassHandle ClassFileParser::par
+ this_klass->set_method_ordering(method_ordering());
+ this_klass->set_initial_method_idnum(methods->length());
+ this_klass->set_name(cp->klass_name_at(this_class_index));
++ cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
+ this_klass->set_protection_domain(protection_domain());
+ this_klass->set_fields_annotations(fields_annotations());
+ this_klass->set_methods_annotations(methods_annotations());
+diff --git a/src/share/vm/classfile/classFileParser.hpp b/src/share/vm/classfile/classFileParser.hpp
+--- a/src/share/vm/classfile/classFileParser.hpp
++++ b/src/share/vm/classfile/classFileParser.hpp
+@@ -33,6 +33,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SP
+ u2 _major_version;
+ u2 _minor_version;
+ symbolHandle _class_name;
++ GrowableArray<Handle>* _cp_patches; // overrides for CP entries
+
+ bool _has_finalizer;
+ bool _has_empty_finalizer;
+@@ -203,6 +204,24 @@ class ClassFileParser VALUE_OBJ_CLASS_SP
+ char* skip_over_field_name(char* name, bool slash_ok, unsigned int length);
+ char* skip_over_field_signature(char* signature, bool void_ok, unsigned int length, TRAPS);
+
++ bool has_cp_patch_at(int index) {
++ assert(index >= 0, "oob");
++ return (_cp_patches != NULL
++ && index < _cp_patches->length()
++ && _cp_patches->adr_at(index)->not_null());
++ }
++ Handle cp_patch_at(int index) {
++ assert(has_cp_patch_at(index), "oob");
++ return _cp_patches->at(index);
++ }
++ Handle clear_cp_patch_at(int index) {
++ Handle patch = cp_patch_at(index);
++ _cp_patches->at_put(index, Handle());
++ assert(!has_cp_patch_at(index), "");
++ return patch;
++ }
++ void patch_constant_pool(constantPoolHandle cp, int index, Handle patch, TRAPS);
++
+ public:
+ // Constructor
+ ClassFileParser(ClassFileStream* st) { set_stream(st); }
+@@ -218,6 +237,14 @@ class ClassFileParser VALUE_OBJ_CLASS_SP
+ Handle class_loader,
+ Handle protection_domain,
+ symbolHandle& parsed_name,
++ TRAPS) {
++ return parseClassFile(name, class_loader, protection_domain, NULL, parsed_name, THREAD);
++ }
++ instanceKlassHandle parseClassFile(symbolHandle name,
++ Handle class_loader,
++ Handle protection_domain,
++ GrowableArray<Handle>* cp_patches,
++ symbolHandle& parsed_name,
+ TRAPS);
+
+ // Verifier checks
+diff --git a/src/share/vm/classfile/systemDictionary.cpp b/src/share/vm/classfile/systemDictionary.cpp
+--- a/src/share/vm/classfile/systemDictionary.cpp
++++ b/src/share/vm/classfile/systemDictionary.cpp
+@@ -949,6 +949,8 @@ klassOop SystemDictionary::parse_stream(
+ Handle class_loader,
+ Handle protection_domain,
+ ClassFileStream* st,
++ KlassHandle host_klass,
++ GrowableArray<Handle>* cp_patches,
+ TRAPS) {
+ symbolHandle parsed_name;
+
+@@ -965,9 +967,9 @@ klassOop SystemDictionary::parse_stream(
+ instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name,
+ class_loader,
+ protection_domain,
++ cp_patches,
+ parsed_name,
+ THREAD);
+-
+
+ // We don't redefine the class, so we just need to clean up whether there
+ // was an error or not (don't want to modify any system dictionary
+@@ -982,6 +984,29 @@ klassOop SystemDictionary::parse_stream(
+ MutexLocker mu(SystemDictionary_lock, THREAD);
+ placeholders()->find_and_remove(p_index, p_hash, parsed_name, class_loader, THREAD);
+ SystemDictionary_lock->notify_all();
++ }
++ }
++
++ if (host_klass.not_null() && k.not_null()) {
++ // If it's anonymous, initialize it now, since nobody else will.
++ k->set_host_klass(host_klass());
++
++ {
++ MutexLocker mu_r(Compile_lock, THREAD);
++
++ // Add to class hierarchy, initialize vtables, and do possible
++ // deoptimizations.
++ add_to_hierarchy(k, CHECK_NULL); // No exception, but can block
++
++ // But, do not add to system dictionary.
++ }
++
++ k->eager_initialize(THREAD);
++
++ // notify jvmti
++ if (JvmtiExport::should_post_class_load()) {
++ assert(THREAD->is_Java_thread(), "thread->is_Java_thread()");
++ JvmtiExport::post_class_load((JavaThread *) THREAD, k());
+ }
+ }
+
+diff --git a/src/share/vm/classfile/systemDictionary.hpp b/src/share/vm/classfile/systemDictionary.hpp
+--- a/src/share/vm/classfile/systemDictionary.hpp
++++ b/src/share/vm/classfile/systemDictionary.hpp
+@@ -107,6 +107,16 @@ public:
+ Handle class_loader,
+ Handle protection_domain,
+ ClassFileStream* st,
++ TRAPS) {
++ KlassHandle nullHandle;
++ return parse_stream(class_name, class_loader, protection_domain, st, nullHandle, NULL, THREAD);
++ }
++ static klassOop parse_stream(symbolHandle class_name,
++ Handle class_loader,
++ Handle protection_domain,
++ ClassFileStream* st,
++ KlassHandle host_klass,
++ GrowableArray<Handle>* cp_patches,
+ TRAPS);
+
+ // Resolve from stream (called by jni_DefineClass and JVM_DefineClass)
+@@ -315,9 +325,13 @@ public:
+ static klassOop int_klass() { return check_klass(_int_klass); }
+ static klassOop long_klass() { return check_klass(_long_klass); }
+
++ // Return Integer for T_INT, etc.
++ // Return NULL if t is not a boxable primitive type, such as T_OBJECT or T_ILLEGAL.
+ static klassOop box_klass(BasicType t) {
+- assert((uint)t < T_VOID+1, "range check");
+- return check_klass(_box_klasses[t]);
++ if ((uint)t <= T_VOID)
++ return _box_klasses[t];
++ else
++ return NULL;
+ }
+ static BasicType box_klass_type(klassOop k); // inverse of box_klass
+
+diff --git a/src/share/vm/classfile/verifier.cpp b/src/share/vm/classfile/verifier.cpp
+--- a/src/share/vm/classfile/verifier.cpp
++++ b/src/share/vm/classfile/verifier.cpp
+@@ -1600,7 +1600,11 @@ void ClassVerifier::verify_ldc(
+ types = (1 << JVM_CONSTANT_Double) | (1 << JVM_CONSTANT_Long);
+ verify_cp_type(index, cp, types, CHECK_VERIFY(this));
+ }
+- if (tag.is_string() || tag.is_unresolved_string()) {
++ if (tag.is_string() && cp->is_pseudo_string_at(index)) {
++ current_frame->push_stack(
++ VerificationType::reference_type(
++ vmSymbols::java_lang_Object()), CHECK_VERIFY(this));
++ } else if (tag.is_string() || tag.is_unresolved_string()) {
+ current_frame->push_stack(
+ VerificationType::reference_type(
+ vmSymbols::java_lang_String()), CHECK_VERIFY(this));
+diff --git a/src/share/vm/oops/constantPoolKlass.cpp b/src/share/vm/oops/constantPoolKlass.cpp
+--- a/src/share/vm/oops/constantPoolKlass.cpp
++++ b/src/share/vm/oops/constantPoolKlass.cpp
+@@ -380,6 +380,7 @@ void constantPoolKlass::oop_verify_on(oo
+ guarantee((*base)->is_symbol() || (*base)->is_instance(),
+ "should be symbol or instance");
+ }
++ if (false) // @@@@ pseudo strings can be in non-perm
+ if (cp->tag_at(i).is_string()) {
+ guarantee((*base)->is_perm(), "should be in permspace");
+ guarantee((*base)->is_instance(), "should be instance");
+diff --git a/src/share/vm/oops/constantPoolOop.cpp b/src/share/vm/oops/constantPoolOop.cpp
+--- a/src/share/vm/oops/constantPoolOop.cpp
++++ b/src/share/vm/oops/constantPoolOop.cpp
+@@ -333,8 +333,11 @@ char* constantPoolOopDesc::string_at_nor
+ oop entry = *(obj_at_addr(which));
+ if (entry->is_symbol()) {
+ return ((symbolOop)entry)->as_C_string();
++ } else if (java_lang_String::is_instance(entry)) {
++ return java_lang_String::as_utf8_string(entry);
+ } else {
+- return java_lang_String::as_utf8_string(entry);
++ assert(false, "pseudo-string");
++ return (char*)"<pseudo-string>";
+ }
+ }
+
+@@ -366,7 +369,7 @@ void constantPoolOopDesc::resolve_string
+ }
+ }
+
+-oop constantPoolOopDesc::string_at_impl(constantPoolHandle this_oop, int which, TRAPS) {
++oop constantPoolOopDesc::string_at_impl(constantPoolHandle this_oop, int which, bool pseudo_ok, TRAPS) {
+ oop entry = *(this_oop->obj_at_addr(which));
+ if (entry->is_symbol()) {
+ ObjectLocker ol(this_oop, THREAD);
+@@ -380,8 +383,22 @@ oop constantPoolOopDesc::string_at_impl(
+ entry = this_oop->resolved_string_at(which);
+ }
+ }
+- assert(java_lang_String::is_instance(entry), "must be string");
++ if (!pseudo_ok)
++ assert(java_lang_String::is_instance(entry), "must be string");
+ return entry;
++}
++
++
++bool constantPoolOopDesc::is_pseudo_string_at(int which) {
++ oop entry = *(obj_at_addr(which));
++ if (entry->is_symbol())
++ // Not yet resolved, but it will resolve to a string.
++ return false;
++ else if (java_lang_String::is_instance(entry))
++ return false;
++ else
++ // truly pseudo
++ return true;
+ }
+
+
+diff --git a/src/share/vm/oops/constantPoolOop.hpp b/src/share/vm/oops/constantPoolOop.hpp
+--- a/src/share/vm/oops/constantPoolOop.hpp
++++ b/src/share/vm/oops/constantPoolOop.hpp
+@@ -268,7 +268,14 @@ class constantPoolOopDesc : public array
+
+ oop string_at(int which, TRAPS) {
+ constantPoolHandle h_this(THREAD, this);
+- return string_at_impl(h_this, which, CHECK_NULL);
++ return string_at_impl(h_this, which, false, CHECK_NULL);
++ }
++
++ bool is_pseudo_string_at(int which);
++
++ oop pseudo_string_at(int which, TRAPS) {
++ constantPoolHandle h_this(THREAD, this);
++ return string_at_impl(h_this, which, true, CHECK_NULL);
+ }
+
+ // only called when we are sure a string entry is already resolved (via an
+@@ -292,6 +299,7 @@ class constantPoolOopDesc : public array
+ // UTF8 char* representation was chosen to avoid conversion of
+ // java_lang_Strings at resolved entries into symbolOops
+ // or vice versa.
++ // Caller is responsible for checking for pseudo-strings.
+ char* string_at_noresolve(int which);
+
+ jint name_and_type_at(int which) {
+@@ -395,7 +403,7 @@ class constantPoolOopDesc : public array
+ // Implementation of methods that needs an exposed 'this' pointer, in order to
+ // handle GC while executing the method
+ static klassOop klass_at_impl(constantPoolHandle this_oop, int which, TRAPS);
+- static oop string_at_impl(constantPoolHandle this_oop, int which, TRAPS);
++ static oop string_at_impl(constantPoolHandle this_oop, int which, bool pseudo_ok, TRAPS);
+
+ // Resolve string constants (to prevent allocation during compilation)
+ static void resolve_string_constants_impl(constantPoolHandle this_oop, TRAPS);
+diff --git a/src/share/vm/oops/instanceKlass.hpp b/src/share/vm/oops/instanceKlass.hpp
+--- a/src/share/vm/oops/instanceKlass.hpp
++++ b/src/share/vm/oops/instanceKlass.hpp
+@@ -147,6 +147,8 @@ class instanceKlass: public Klass {
+ oop _class_loader;
+ // Protection domain.
+ oop _protection_domain;
++ // Host class, which shares access with this class
++ klassOop _host_klass;
+ // Class signers.
+ objArrayOop _signers;
+ // Name of source file containing this klass, NULL if not specified.
+@@ -370,6 +372,11 @@ class instanceKlass: public Klass {
+ oop protection_domain() { return _protection_domain; }
+ void set_protection_domain(oop pd) { oop_store((oop*) &_protection_domain, pd); }
+
++ // host class
++ oop host_klass() const { return _host_klass; }
++ void set_host_klass(oop host) { oop_store((oop*) &_host_klass, host); }
++ bool is_anonymous() const { return _host_klass != NULL; }
++
+ // signers
+ objArrayOop signers() const { return _signers; }
+ void set_signers(objArrayOop s) { oop_store((oop*) &_signers, oop(s)); }
+@@ -685,6 +692,7 @@ private:
+ oop* adr_constants() const { return (oop*)&this->_constants;}
+ oop* adr_class_loader() const { return (oop*)&this->_class_loader;}
+ oop* adr_protection_domain() const { return (oop*)&this->_protection_domain;}
++ oop* adr_host_klass() const { return (oop*)&this->_host_klass;}
+ oop* adr_signers() const { return (oop*)&this->_signers;}
+ oop* adr_source_file_name() const { return (oop*)&this->_source_file_name;}
+ oop* adr_source_debug_extension() const { return (oop*)&this->_source_debug_extension;}
+diff --git a/src/share/vm/oops/instanceKlassKlass.cpp b/src/share/vm/oops/instanceKlassKlass.cpp
+--- a/src/share/vm/oops/instanceKlassKlass.cpp
++++ b/src/share/vm/oops/instanceKlassKlass.cpp
+@@ -81,6 +81,7 @@ void instanceKlassKlass::oop_follow_cont
+ MarkSweep::mark_and_push(ik->adr_source_debug_extension());
+ MarkSweep::mark_and_push(ik->adr_inner_classes());
+ MarkSweep::mark_and_push(ik->adr_protection_domain());
++ MarkSweep::mark_and_push(ik->adr_host_klass());
+ MarkSweep::mark_and_push(ik->adr_signers());
+ MarkSweep::mark_and_push(ik->adr_generic_signature());
+ MarkSweep::mark_and_push(ik->adr_class_annotations());
+@@ -120,6 +121,7 @@ void instanceKlassKlass::oop_follow_cont
+ PSParallelCompact::mark_and_push(cm, ik->adr_source_debug_extension());
+ PSParallelCompact::mark_and_push(cm, ik->adr_inner_classes());
+ PSParallelCompact::mark_and_push(cm, ik->adr_protection_domain());
++ PSParallelCompact::mark_and_push(cm, ik->adr_host_klass());
+ PSParallelCompact::mark_and_push(cm, ik->adr_signers());
+ PSParallelCompact::mark_and_push(cm, ik->adr_generic_signature());
+ PSParallelCompact::mark_and_push(cm, ik->adr_class_annotations());
+@@ -159,6 +161,7 @@ int instanceKlassKlass::oop_oop_iterate(
+ blk->do_oop(ik->adr_constants());
+ blk->do_oop(ik->adr_class_loader());
+ blk->do_oop(ik->adr_protection_domain());
++ blk->do_oop(ik->adr_host_klass());
+ blk->do_oop(ik->adr_signers());
+ blk->do_oop(ik->adr_source_file_name());
+ blk->do_oop(ik->adr_source_debug_extension());
+@@ -210,6 +213,8 @@ int instanceKlassKlass::oop_oop_iterate_
+ adr = ik->adr_class_loader();
+ if (mr.contains(adr)) blk->do_oop(adr);
+ adr = ik->adr_protection_domain();
++ if (mr.contains(adr)) blk->do_oop(adr);
++ adr = ik->adr_host_klass();
+ if (mr.contains(adr)) blk->do_oop(adr);
+ adr = ik->adr_signers();
+ if (mr.contains(adr)) blk->do_oop(adr);
+@@ -260,6 +265,7 @@ int instanceKlassKlass::oop_adjust_point
+ MarkSweep::adjust_pointer(ik->adr_constants());
+ MarkSweep::adjust_pointer(ik->adr_class_loader());
+ MarkSweep::adjust_pointer(ik->adr_protection_domain());
++ MarkSweep::adjust_pointer(ik->adr_host_klass());
+ MarkSweep::adjust_pointer(ik->adr_signers());
+ MarkSweep::adjust_pointer(ik->adr_source_file_name());
+ MarkSweep::adjust_pointer(ik->adr_source_debug_extension());
+@@ -295,6 +301,11 @@ void instanceKlassKlass::oop_copy_conten
+ pm->claim_or_forward_breadth(pd_addr);
+ }
+
++ oop* hk_addr = ik->adr_host_klass();
++ if (PSScavenge::should_scavenge(*hk_addr)) {
++ pm->claim_or_forward_breadth(hk_addr);
++ }
++
+ oop* sg_addr = ik->adr_signers();
+ if (PSScavenge::should_scavenge(*sg_addr)) {
+ pm->claim_or_forward_breadth(sg_addr);
+@@ -316,6 +327,11 @@ void instanceKlassKlass::oop_push_conten
+ oop* pd_addr = ik->adr_protection_domain();
+ if (PSScavenge::should_scavenge(*pd_addr)) {
+ pm->claim_or_forward_depth(pd_addr);
++ }
++
++ oop* hk_addr = ik->adr_host_klass();
++ if (PSScavenge::should_scavenge(*hk_addr)) {
++ pm->claim_or_forward_depth(hk_addr);
+ }
+
+ oop* sg_addr = ik->adr_signers();
+@@ -421,6 +437,7 @@ klassOop instanceKlassKlass::allocate_in
+ ik->set_constants(NULL);
+ ik->set_class_loader(NULL);
+ ik->set_protection_domain(NULL);
++ ik->set_host_klass(NULL);
+ ik->set_signers(NULL);
+ ik->set_source_file_name(NULL);
+ ik->set_source_debug_extension(NULL);
+@@ -526,6 +543,7 @@ void instanceKlassKlass::oop_print_on(oo
+ st->print(" - constants: "); ik->constants()->print_value_on(st); st->cr();
+ st->print(" - class loader: "); ik->class_loader()->print_value_on(st); st->cr();
+ st->print(" - protection domain: "); ik->protection_domain()->print_value_on(st); st->cr();
++ st->print(" - host class: "); ik->host_klass()->print_value_on(st); st->cr();
+ st->print(" - signers: "); ik->signers()->print_value_on(st); st->cr();
+ if (ik->source_file_name() != NULL) {
+ st->print(" - source file: ");
+@@ -624,7 +642,7 @@ void instanceKlassKlass::oop_verify_on(o
+ ik->_verify_count = Universe::verify_count();
+ #endif
+ // Verify that klass is present in SystemDictionary
+- if (ik->is_loaded()) {
++ if (ik->is_loaded() && ik->host_klass() == NULL) { //@@@ !ik->is_anonymous()
+ symbolHandle h_name (thread, ik->name());
+ Handle h_loader (thread, ik->class_loader());
+ Handle h_obj(thread, obj);
+@@ -762,6 +780,9 @@ void instanceKlassKlass::oop_verify_on(o
+ if (ik->protection_domain() != NULL) {
+ guarantee(ik->protection_domain()->is_oop(), "should be oop");
+ }
++ if (ik->host_klass() != NULL) {
++ guarantee(ik->host_klass()->is_oop(), "should be oop");
++ }
+ if (ik->signers() != NULL) {
+ guarantee(ik->signers()->is_objArray(), "should be obj array");
+ }
+diff --git a/src/share/vm/oops/klass.cpp b/src/share/vm/oops/klass.cpp
+--- a/src/share/vm/oops/klass.cpp
++++ b/src/share/vm/oops/klass.cpp
+@@ -478,6 +478,23 @@ void Klass::with_array_klasses_do(void f
+
+
+ const char* Klass::external_name() const {
++ if (oop_is_instance()) {
++ instanceKlass* ik = (instanceKlass*) this;
++ if (ik->host_klass() != NULL) { // @@@ is_anonymous()
++ intptr_t hash = ik->java_mirror()->identity_hash();
++ char hash_buf[40];
++ sprintf(hash_buf, "/" UINTX_FORMAT, (uintx)hash);
++ int hash_len = strlen(hash_buf);
++
++ int result_len = name()->utf8_length();
++ char* result = NEW_RESOURCE_ARRAY(char, result_len + hash_len + 1);
++ name()->as_klass_external_name(result, result_len + 1);
++ assert(strlen(result) == result_len, "");
++ strcpy(result + result_len, hash_buf);
++ assert(strlen(result) == result_len + hash_len, "");
++ return result;
++ }
++ }
+ return name()->as_klass_external_name();
+ }
+
+diff --git a/src/share/vm/prims/jvm.cpp b/src/share/vm/prims/jvm.cpp
+--- a/src/share/vm/prims/jvm.cpp
++++ b/src/share/vm/prims/jvm.cpp
+@@ -708,6 +708,7 @@ static void is_lock_held_by_thread(Handl
+
+ // common code for JVM_DefineClass() and JVM_DefineClassWithSource()
+ static jclass jvm_define_class_common(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source, TRAPS) {
++ if (source == NULL) source = "__JVM_DefineClass__";
+
+ // Since exceptions can be thrown, class initialization can take place
+ // if name is NULL no check for class name in .class stream has to be made.
+@@ -746,7 +747,7 @@ JVM_ENTRY(jclass, JVM_DefineClass(JNIEnv
+ JVM_ENTRY(jclass, JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd))
+ JVMWrapper2("JVM_DefineClass %s", name);
+
+- return jvm_define_class_common(env, name, loader, buf, len, pd, "__JVM_DefineClass__", THREAD);
++ return jvm_define_class_common(env, name, loader, buf, len, pd, NULL, THREAD);
+ JVM_END
+
+
+diff --git a/src/share/vm/prims/jvm.h b/src/share/vm/prims/jvm.h
+--- a/src/share/vm/prims/jvm.h
++++ b/src/share/vm/prims/jvm.h
+@@ -410,6 +410,14 @@ JVM_DefineClassWithSource(JNIEnv *env, c
+ JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader,
+ const jbyte *buf, jsize len, jobject pd,
+ const char *source);
++
++/* Define a class with a source (MLVM) */
++JNIEXPORT jclass JNICALL
++JVM_DefineClassWithCP(JNIEnv *env, const char *name, jobject loader,
++ const jbyte *buf, jsize len, jobject pd,
++ const char *source,
++ // same args as JVM_DefineClassWithSource to this point
++ jobjectArray constants);
+
+ /*
+ * Reflection support functions
+diff --git a/src/share/vm/prims/unsafe.cpp b/src/share/vm/prims/unsafe.cpp
+--- a/src/share/vm/prims/unsafe.cpp
++++ b/src/share/vm/prims/unsafe.cpp
+@@ -792,6 +792,74 @@ UNSAFE_ENTRY(jclass, Unsafe_DefineClass1
+ }
+ UNSAFE_END
+
++#define DAC_Args CLS ADR"I["OBJ
++// define a class but do not make it known to the class loader or system dictionary
++// - host_class: supplies context for linkage, access control, protection domain, and class loader
++// - data: bytes of a class file, a raw memory address (length gives the number of bytes)
++// - cp_patches: where non-null entries exist, they replace corresponding CP entries in data
++UNSAFE_ENTRY(jclass, Unsafe_DefineAnonymousClass(JNIEnv *env, jobject unsafe, jclass host_class, jlong data, jint length, jobjectArray cp_patches_jh))
++{
++ UnsafeWrapper("Unsafe_DefineAnonymousClass");
++ ResourceMark rm(THREAD);
++
++ if (UsePerfData) {
++ ClassLoader::unsafe_defineClassCallCounter()->inc();
++ }
++
++ u1* class_bytes = (u1*) data;
++ int class_bytes_length = (int) length;
++ if (class_bytes_length < 0) class_bytes_length = 0;
++ if (class_bytes == NULL
++ || host_class == NULL
++ || length != class_bytes_length)
++ THROW_0(vmSymbols::java_lang_IllegalArgumentException());
++
++ objArrayHandle cp_patches_h;
++ if (cp_patches_jh != NULL) {
++ oop p = JNIHandles::resolve_non_null(cp_patches_jh);
++ if (!p->is_objArray())
++ THROW_0(vmSymbols::java_lang_IllegalArgumentException());
++ cp_patches_h = objArrayHandle(THREAD, (objArrayOop)p);
++ }
++
++ KlassHandle host_klass(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(host_class)));
++ const char* host_source = host_klass->external_name();
++ Handle host_loader(THREAD, host_klass->class_loader());
++ Handle host_domain(THREAD, host_klass->protection_domain());
++
++ GrowableArray<Handle>* cp_patches = NULL;
++ if (cp_patches_h.not_null()) {
++ int alen = cp_patches_h->length();
++ for (int i = alen-1; i >= 0; i--) {
++ oop p = cp_patches_h->obj_at(i);
++ if (p != NULL) {
++ Handle patch(THREAD, p);
++ if (cp_patches == NULL)
++ cp_patches = new GrowableArray<Handle>(i+1, i+1, Handle());
++ cp_patches->at_put(i, patch);
++ }
++ }
++ }
++
++ ClassFileStream st(class_bytes, class_bytes_length, (char*) host_source);
++
++ instanceKlassHandle anon_klass;
++ {
++ symbolHandle no_class_name;
++ klassOop anonk = SystemDictionary::parse_stream(no_class_name,
++ host_loader, host_domain,
++ &st, host_klass, cp_patches,
++ CHECK_NULL);
++ if (anonk == NULL) return NULL;
++ anon_klass = instanceKlassHandle(THREAD, anonk);
++ }
++
++ // let caller initialize it as needed...
++
++ return (jclass) JNIHandles::make_local(env, anon_klass->java_mirror());
++}
++UNSAFE_END
++
+
+ UNSAFE_ENTRY(void, Unsafe_MonitorEnter(JNIEnv *env, jobject unsafe, jobject jobj))
+ UnsafeWrapper("Unsafe_MonitorEnter");
+@@ -1246,6 +1314,9 @@ JNINativeMethod memcopy_methods_15[] = {
+ {CC"copyMemory", CC"("ADR ADR"J)V", FN_PTR(Unsafe_CopyMemory)}
+ };
+
++JNINativeMethod dynlang_methods[] = {
++ {CC"defineAnonymousClass", CC"("DAC_Args")"CLS, FN_PTR(Unsafe_DefineAnonymousClass)},
++};
+
+ #undef CC
+ #undef FN_PTR
+@@ -1308,6 +1379,15 @@ JVM_ENTRY(void, JVM_RegisterUnsafeMethod
+ }
+ }
+ }
++ {
++ env->RegisterNatives(unsafecls, dynlang_methods, sizeof(dynlang_methods)/sizeof(JNINativeMethod));
++ if (env->ExceptionOccurred()) {
++ if (PrintMiscellaneous && (Verbose || WizardMode)) {
++ tty->print_cr("Warning: SDK 1.7 Unsafe.defineClass (anonymous version) not found.");
++ }
++ env->ExceptionClear();
++ }
++ }
+ int status = env->RegisterNatives(unsafecls, methods, sizeof(methods)/sizeof(JNINativeMethod));
+ if (env->ExceptionOccurred()) {
+ if (PrintMiscellaneous && (Verbose || WizardMode)) {
+diff --git a/src/share/vm/runtime/reflection.cpp b/src/share/vm/runtime/reflection.cpp
+--- a/src/share/vm/runtime/reflection.cpp
++++ b/src/share/vm/runtime/reflection.cpp
+@@ -456,10 +456,26 @@ bool Reflection::verify_class_access(kla
+ return can_relax_access_check_for(current_class, new_class, classloader_only);
+ }
+
++static bool under_host_klass(instanceKlass* ik, klassOop host_klass) {
++ for (;;) {
++ klassOop hc = (klassOop) ik->host_klass();
++ if (hc == NULL) return false;
++ if (hc == host_klass) return true;
++ ik = instanceKlass::cast(hc);
++ }
++}
++
+ bool Reflection::can_relax_access_check_for(
+ klassOop accessor, klassOop accessee, bool classloader_only) {
+ instanceKlass* accessor_ik = instanceKlass::cast(accessor);
+ instanceKlass* accessee_ik = instanceKlass::cast(accessee);
++
++ // If either is on the other's host_klass chain, access is OK,
++ // because one is inside the other.
++ if (under_host_klass(accessor_ik, accessee) ||
++ under_host_klass(accessee_ik, accessor))
++ return true;
++
+ if (RelaxAccessControlCheck ||
+ (accessor_ik->major_version() < JAVA_1_5_VERSION &&
+ accessee_ik->major_version() < JAVA_1_5_VERSION)) {
+diff --git a/src/share/vm/utilities/constantTag.hpp b/src/share/vm/utilities/constantTag.hpp
+--- a/src/share/vm/utilities/constantTag.hpp
++++ b/src/share/vm/utilities/constantTag.hpp
+@@ -70,7 +70,7 @@ class constantTag VALUE_OBJ_CLASS_SPEC {
+ bool is_unresolved_string() const { return _tag == JVM_CONSTANT_UnresolvedString; }
+ bool is_string_index() const { return _tag == JVM_CONSTANT_StringIndex; }
+
+- bool is_klass_reference() const { return is_klass_index() || is_unresolved_klass(); }
++ bool is_klass_reference() const { return is_klass() || is_klass_index() || is_unresolved_klass(); }
+ bool is_field_or_method() const { return is_field() || is_method() || is_interface_method(); }
+ bool is_symbol() const { return is_utf8(); }
+