186 lines
9.2 KiB
Diff
186 lines
9.2 KiB
Diff
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
|
|
|