Date: Fri, 9 Jun 2023 10:29:38 +0800
Subject: Reuse translet in XSLTC for XML

---
 .../share/vm/classfile/classFileParser.cpp    | 52 +++++++++++-
 .../share/vm/classfile/classFileParser.hpp    |  2 +-
 hotspot/src/share/vm/classfile/vmSymbols.hpp  |  4 +-
 hotspot/src/share/vm/runtime/arguments.cpp    |  2 +
 hotspot/src/share/vm/runtime/arguments.hpp    |  3 +
 .../src/share/vm/utilities/accessFlags.hpp    |  1 +
 7 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp
index d8e99e622..b9fde38dc 100644
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp
@@ -59,12 +59,13 @@
 #include "runtime/reflection.hpp"
 #include "runtime/signature.hpp"
 #include "runtime/timer.hpp"
+#include "runtime/arguments.hpp"
 #include "services/classLoadingService.hpp"
 #include "services/threadService.hpp"
 #include "utilities/array.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/ostream.hpp"
-
+#include "interpreter/bytecodeStream.hpp"
 // We generally try to create the oops directly when parsing, rather than
 // allocating temporary data structures and copying the bytes twice. A
 // temporary area is only needed when parsing utf8 entries in the constant
@@ -2556,6 +2557,7 @@ Array<Method*>* ClassFileParser::parse_methods(bool is_interface,
   ClassFileStream* cfs = stream();
   cfs->guarantee_more(2, CHECK_NULL);  // length
   u2 length = cfs->get_u2_fast();
+  Method* initializerMethod = NULL;
   if (length == 0) {
     _methods = Universe::the_empty_method_array();
   } else {
@@ -2570,6 +2572,9 @@ Array<Method*>* ClassFileParser::parse_methods(bool is_interface,
       if (method->is_final()) {
         *has_final_method = true;
       }
+      if (method->name()== vmSymbols::object_initializer_name()) {
+        initializerMethod = method();
+      }
       // declares_default_methods: declares concrete instance methods, any access flags
       // used for interface initialization, and default method inheritance analysis
       if (is_interface && !(*declares_default_methods)
@@ -2606,6 +2611,11 @@ Array<Method*>* ClassFileParser::parse_methods(bool is_interface,
                               name->as_C_string(), sig->as_klass_external_name(), CHECK_NULL);
       }
     }
+
+    if (Arguments::transletEnhance()) {
+      bool isClassMatched = (_class_name == vmSymbols::transformerFactoryImpl_class_name());
+      if(isClassMatched) modify_fields_value(initializerMethod, vmSymbols::transformer_generateTranslet_field_name(), vmSymbols::transformer_autoTranslet_field_name(), Bytecodes::_iconst_1, CHECK_NULL);
+    }
   }
   return _methods;
 }
@@ -5421,6 +5431,46 @@ char* ClassFileParser::skip_over_field_signature(char* signature,
   return NULL;
 }
 
+// This function sets the class's specific fields to a fixed value, ie: targetFieldName1 and targetFieldName2.
+// initializerMethod is the class's "<init>" method, should not be NULL.
+// For performance, two fields can be set at the same time. You can also set only one field, just set targetFieldName2 to NULL.
+// Bytecodes::Code can be bytecode between iconst_0 and dconst_0, range is 0x03 ~ 0x0f.
+void ClassFileParser::modify_fields_value(Method* initializerMethod, Symbol* targetFieldName1, Symbol* targetFieldName2, Bytecodes::Code targetCode, TRAPS) {
+  assert(initializerMethod != NULL, "The method can't be NULL.");
+  assert(initializerMethod->name() == vmSymbols::object_initializer_name(), "The method must be <init>.");
+  assert(targetFieldName1 != NULL, "At least targetFieldName1 can't be NULL.");
+  assert(targetCode >= Bytecodes::_iconst_0 && targetCode <= Bytecodes::_dconst_1, "The primitive constant's value range is 0x03 ~ 0x0f.");
+
+  ResourceMark rm(THREAD);
+  methodHandle mh(initializerMethod);
+  BytecodeStream bcs(mh);
+  while (!bcs.is_last_bytecode()) {
+    Bytecodes::Code code = bcs.next();
+    if (code == Bytecodes::_putfield) {
+      address p = bcs.bcp();
+      // get field index
+      int index = Bytes::get_Java_u2(p + 1);
+      Symbol *name = _cp->name_ref_at(index);
+      if (name == targetFieldName1) {
+        p = p - 1;
+        *(u1 *) p = (u1) targetCode;
+      }
+      if ((targetFieldName2 != NULL) && (name == targetFieldName2)) {
+        p = p - 1;
+        *(u1 *) p = (u1) targetCode;
+      }
+    }
+  }
+  _has_vanilla_constructor = false;
+  AccessFlags flags = mh()->access_flags();
+  flags.clear_has_vanilla_constructor();
+  if (mh->is_vanilla_constructor()) {
+    _has_vanilla_constructor = true;
+    flags.set_has_vanilla_constructor();
+  }
+  mh()->set_access_flags(flags);
+}
+
 #if INCLUDE_JFR
 
 // Caller responsible for ResourceMark
diff --git a/hotspot/src/share/vm/classfile/classFileParser.hpp b/hotspot/src/share/vm/classfile/classFileParser.hpp
index dfb56c990..1900f0abf 100644
--- a/hotspot/src/share/vm/classfile/classFileParser.hpp
+++ b/hotspot/src/share/vm/classfile/classFileParser.hpp
@@ -391,7 +391,7 @@ PRAGMA_DIAG_POP
   bool verify_unqualified_name(char* name, unsigned int length, int type);
   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);
-
+  void modify_fields_value(Method* initializerMethod, Symbol* targetFieldName1, Symbol* targetFieldName2, Bytecodes::Code targetCode, TRAPS);
   bool is_anonymous() {
     assert(EnableInvokeDynamic || _host_klass.is_null(), "");
     return _host_klass.not_null();
diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp
index 5f2a9a720..494fd9bdf 100644
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp
@@ -422,7 +422,9 @@
   template(resolved_references_name,                  "<resolved_references>")                    \
   template(referencequeue_null_name,                  "NULL")                                     \
   template(referencequeue_enqueued_name,              "ENQUEUED")                                 \
-                                                                                                  \
+  template(transformerFactoryImpl_class_name,         "com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl") \
+  template(transformer_generateTranslet_field_name,   "_generateTranslet")                        \
+  template(transformer_autoTranslet_field_name,       "_autoTranslet")                            \
   /* non-intrinsic name/signature pairs: */                                                       \
   template(register_method_name,                      "register")                                 \
   do_alias(register_method_signature,         object_void_signature)                              \
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
index 43fdd0b49..0c8a4012a 100644
--- a/hotspot/src/share/vm/runtime/arguments.cpp
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
@@ -149,6 +149,8 @@ SystemProperty *Arguments::_sun_boot_class_path = NULL;
 char* Arguments::_meta_index_path = NULL;
 char* Arguments::_meta_index_dir = NULL;
 
+bool Arguments::_transletEnhance = false;
+
 // Check if head of 'option' matches 'name', and sets 'tail' remaining part of option string
 
 static bool match_option(const JavaVMOption *option, const char* name,
diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp
index 88741e8c3..4f7232e48 100644
--- a/hotspot/src/share/vm/runtime/arguments.hpp
+++ b/hotspot/src/share/vm/runtime/arguments.hpp
@@ -267,6 +267,7 @@ class Arguments : AllStatic {
   static char* _meta_index_path;
   static char* _meta_index_dir;
 
+  static bool _transletEnhance;
   // java.vendor.url.bug, bug reporting URL for fatal errors.
   static const char* _java_vendor_url_bug;
 
@@ -633,6 +634,8 @@ class Arguments : AllStatic {
   static Mode mode()                { return _mode; }
   static bool is_interpreter_only() { return mode() == _int; }
 
+  static void set_transletEnhance(bool arg) { _transletEnhance = arg; }
+  static bool transletEnhance() { return _transletEnhance; }
 
   // Utility: copies src into buf, replacing "%%" with "%" and "%p" with pid.
   static bool copy_expand_pid(const char* src, size_t srclen, char* buf, size_t buflen);
diff --git a/hotspot/src/share/vm/utilities/accessFlags.hpp b/hotspot/src/share/vm/utilities/accessFlags.hpp
index bc56262d1..b20f0f740 100644
--- a/hotspot/src/share/vm/utilities/accessFlags.hpp
+++ b/hotspot/src/share/vm/utilities/accessFlags.hpp
@@ -209,6 +209,7 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC {
   void clear_not_c2_osr_compilable()   { atomic_clear_bits(JVM_ACC_NOT_C2_OSR_COMPILABLE);   }
   // Klass* flags
   void set_has_vanilla_constructor()   { atomic_set_bits(JVM_ACC_HAS_VANILLA_CONSTRUCTOR); }
+  void clear_has_vanilla_constructor()  { atomic_clear_bits(JVM_ACC_HAS_VANILLA_CONSTRUCTOR); }
   void set_has_finalizer()             { atomic_set_bits(JVM_ACC_HAS_FINALIZER);           }
   void set_has_final_method()          { atomic_set_bits(JVM_ACC_HAS_FINAL_METHOD);        }
   void set_is_cloneable()              { atomic_set_bits(JVM_ACC_IS_CLONEABLE);            }
-- 
2.22.0

