Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve performance of generating JS class from Metadata #1824

Merged
merged 10 commits into from
Jan 19, 2025
1 change: 1 addition & 0 deletions test-app/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ add_library(
src/main/cpp/MetadataNode.cpp
src/main/cpp/MetadataReader.cpp
src/main/cpp/MetadataTreeNode.cpp
src/main/cpp/MetadataEntry.cpp
src/main/cpp/MethodCache.cpp
src/main/cpp/ModuleBinding.cpp
src/main/cpp/ModuleInternal.cpp
Expand Down
21 changes: 11 additions & 10 deletions test-app/runtime/src/main/cpp/CallbackHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,8 @@ void CallbackHandlers::CallJavaMethod(const Local<Object> &caller, const string

auto isolate = args.GetIsolate();

if ((entry != nullptr) && entry->isResolved) {
if ((entry != nullptr) && entry->getIsResolved()) {
auto &entrySignature = entry->getSig();
isStatic = entry->isStatic;

if (entry->memberId == nullptr) {
Expand All @@ -236,14 +237,14 @@ void CallbackHandlers::CallJavaMethod(const Local<Object> &caller, const string
if (isFromInterface) {
auto methodAndClassPair = env.GetInterfaceStaticMethodIDAndJClass(className,
methodName,
entry->sig);
entrySignature);
entry->memberId = methodAndClassPair.first;
clazz = methodAndClassPair.second;
} else {
entry->memberId = env.GetStaticMethodID(clazz, methodName, entry->sig);
entry->memberId = env.GetStaticMethodID(clazz, methodName, entrySignature);
}
} else {
entry->memberId = env.GetMethodID(clazz, methodName, entry->sig);
entry->memberId = env.GetMethodID(clazz, methodName, entrySignature);
}

if (entry->memberId == nullptr) {
Expand All @@ -257,14 +258,14 @@ void CallbackHandlers::CallJavaMethod(const Local<Object> &caller, const string
if (isFromInterface) {
auto methodAndClassPair = env.GetInterfaceStaticMethodIDAndJClass(className,
methodName,
entry->sig);
entrySignature);
entry->memberId = methodAndClassPair.first;
clazz = methodAndClassPair.second;
} else {
entry->memberId = env.GetStaticMethodID(clazz, methodName, entry->sig);
entry->memberId = env.GetStaticMethodID(clazz, methodName, entrySignature);
}
} else {
entry->memberId = env.GetMethodID(clazz, methodName, entry->sig);
entry->memberId = env.GetMethodID(clazz, methodName, entrySignature);
}

if (entry->memberId == nullptr) {
Expand All @@ -279,9 +280,9 @@ void CallbackHandlers::CallJavaMethod(const Local<Object> &caller, const string

mid = reinterpret_cast<jmethodID>(entry->memberId);
clazz = entry->clazz;
sig = &entry->sig;
returnType = &entry->returnType;
retType = entry->retType;
sig = &entrySignature;
returnType = &entry->getReturnType();
retType = entry->getRetType();
} else {
DEBUG_WRITE("Resolving method: %s on className %s", methodName.c_str(), className.c_str());

Expand Down
33 changes: 19 additions & 14 deletions test-app/runtime/src/main/cpp/FieldAccessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ Local<Value> FieldAccessor::GetJavaField(Isolate* isolate, const Local<Object>&

JniLocalRef targetJavaObject;

const auto& fieldTypeName = fieldData->signature;
auto isStatic = fieldData->isStatic;
auto &fieldMetadata = fieldData->metadata;

const auto& fieldTypeName = fieldMetadata.getSig();
auto isStatic = fieldMetadata.isStatic;

auto isPrimitiveType = fieldTypeName.size() == 1;
auto isFieldArray = fieldTypeName[0] == '[';
Expand All @@ -35,11 +37,11 @@ Local<Value> FieldAccessor::GetJavaField(Isolate* isolate, const Local<Object>&
("L" + fieldTypeName + ";"));

if (isStatic) {
fieldData->clazz = env.FindClass(fieldData->declaringType);
fieldData->fid = env.GetStaticFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
fieldData->clazz = env.FindClass(fieldMetadata.getDeclaringType());
fieldData->fid = env.GetStaticFieldID(fieldData->clazz, fieldMetadata.name, fieldJniSig);
} else {
fieldData->clazz = env.FindClass(fieldData->declaringType);
fieldData->fid = env.GetFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
fieldData->clazz = env.FindClass(fieldMetadata.getDeclaringType());
fieldData->fid = env.GetFieldID(fieldData->clazz, fieldMetadata.name, fieldJniSig);
}
}

Expand All @@ -48,7 +50,7 @@ Local<Value> FieldAccessor::GetJavaField(Isolate* isolate, const Local<Object>&

if (targetJavaObject.IsNull()) {
stringstream ss;
ss << "Cannot access property '" << fieldData->name.c_str() << "' because there is no corresponding Java object";
ss << "Cannot access property '" << fieldMetadata.name.c_str() << "' because there is no corresponding Java object";
throw NativeScriptException(ss.str());
}
}
Expand Down Expand Up @@ -186,14 +188,17 @@ Local<Value> FieldAccessor::GetJavaField(Isolate* isolate, const Local<Object>&
void FieldAccessor::SetJavaField(Isolate* isolate, const Local<Object>& target, const Local<Value>& value, FieldCallbackData* fieldData) {
JEnv env;

auto &fieldMetadata = fieldData->metadata;

HandleScope handleScope(isolate);
auto runtime = Runtime::GetRuntime(isolate);
auto objectManager = runtime->GetObjectManager();

JniLocalRef targetJavaObject;

const auto& fieldTypeName = fieldData->signature;
auto isStatic = fieldData->isStatic;
const auto& fieldTypeName = fieldMetadata.getSig();
auto isStatic = fieldMetadata.isStatic;


auto isPrimitiveType = fieldTypeName.size() == 1;
auto isFieldArray = fieldTypeName[0] == '[';
Expand All @@ -208,14 +213,14 @@ void FieldAccessor::SetJavaField(Isolate* isolate, const Local<Object>& target,
("L" + fieldTypeName + ";"));

if (isStatic) {
fieldData->clazz = env.FindClass(fieldData->declaringType);
fieldData->clazz = env.FindClass(fieldMetadata.getDeclaringType());
assert(fieldData->clazz != nullptr);
fieldData->fid = env.GetStaticFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
fieldData->fid = env.GetStaticFieldID(fieldData->clazz, fieldMetadata.name, fieldJniSig);
assert(fieldData->fid != nullptr);
} else {
fieldData->clazz = env.FindClass(fieldData->declaringType);
fieldData->clazz = env.FindClass(fieldMetadata.getDeclaringType());
assert(fieldData->clazz != nullptr);
fieldData->fid = env.GetFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
fieldData->fid = env.GetFieldID(fieldData->clazz, fieldMetadata.name, fieldJniSig);
assert(fieldData->fid != nullptr);
}
}
Expand All @@ -225,7 +230,7 @@ void FieldAccessor::SetJavaField(Isolate* isolate, const Local<Object>& target,

if (targetJavaObject.IsNull()) {
stringstream ss;
ss << "Cannot access property '" << fieldData->name.c_str() << "' because there is no corresponding Java object";
ss << "Cannot access property '" << fieldMetadata.name.c_str() << "' because there is no corresponding Java object";
throw NativeScriptException(ss.str());
}
}
Expand Down
27 changes: 9 additions & 18 deletions test-app/runtime/src/main/cpp/FieldCallbackData.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,16 @@
#include "MetadataEntry.h"

namespace tns {
struct FieldCallbackData {
FieldCallbackData(const MetadataEntry& metadata)
:
fid(nullptr), clazz(nullptr) {
name = metadata.name;
signature = metadata.sig;
declaringType = metadata.declaringType;
isStatic = metadata.isStatic;
isFinal = metadata.isFinal;
}
struct FieldCallbackData {
FieldCallbackData(MetadataEntry metadata)
:
metadata(metadata), fid(nullptr), clazz(nullptr) {
}

std::string name;
std::string signature;
std::string declaringType;
bool isStatic;
bool isFinal;
jfieldID fid;
jclass clazz;
};
MetadataEntry metadata;
jfieldID fid;
jclass clazz;
};

}

Expand Down
4 changes: 2 additions & 2 deletions test-app/runtime/src/main/cpp/JsArgConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ JsArgConverter::JsArgConverter(const Local<Object> &caller,
m_argsLen = 1 + v8ProvidedArgumentsLength;

if (m_argsLen > 0) {
if ((entry != nullptr) && (entry->isResolved)) {
if ((entry != nullptr) && (entry->getIsResolved())) {
if (entry->parsedSig.empty()) {
JniSignatureParser parser(m_methodSignature);
entry->parsedSig = parser.Parse();
Expand Down Expand Up @@ -58,7 +58,7 @@ JsArgConverter::JsArgConverter(const v8::FunctionCallbackInfo<Value> &args,
m_argsLen = !hasImplementationObject ? args.Length() : args.Length() - 1;

if (m_argsLen > 0) {
if ((entry != nullptr) && (entry->isResolved)) {
if ((entry != nullptr) && (entry->getIsResolved())) {
if (entry->parsedSig.empty()) {
JniSignatureParser parser(m_methodSignature);
entry->parsedSig = parser.Parse();
Expand Down
135 changes: 135 additions & 0 deletions test-app/runtime/src/main/cpp/MetadataEntry.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#include "MetadataNode.h"
#include "MetadataEntry.h"
#include "MetadataMethodInfo.h"
#include "MetadataReader.h"

using namespace tns;

MetadataEntry::MetadataEntry(MetadataTreeNode *m_treeNode, NodeType nodeType) :
treeNode(m_treeNode), type(nodeType), isExtensionFunction(false), isStatic(false),
isTypeMember(false), memberId(nullptr), clazz(nullptr), mi(nullptr),fi(nullptr), sfi(nullptr),
retType(MethodReturnType::Unknown),
paramCount(-1), isFinal(false), isResolved(false), retTypeParsed(false),
isFinalSet(false), isResolvedSet(false) {}

std::string &MetadataEntry::getName() {
if (!name.empty()) return name;

auto reader = MetadataNode::getMetadataReader();

if (type == NodeType::Field) {
name = reader->ReadName(fi->nameOffset);
} else if (type == NodeType::StaticField) {
name = reader->ReadName(sfi->nameOffset);
} else if (type == NodeType::Method) {
name = mi.GetName();
}

return name;
}

std::string &MetadataEntry::getSig() {
if (!sig.empty()) return sig;

auto reader = MetadataNode::getMetadataReader();

if (type == NodeType::Field) {
sig = reader->ReadTypeName(fi->nodeId);
} else if (type == NodeType::StaticField) {
sig = reader->ReadTypeName(sfi->nodeId);
} else if (type == NodeType::Method) {
uint8_t sigLength = mi.GetSignatureLength();
if (sigLength > 0)
sig = mi.GetSignature();

}

return sig;
}

std::string &MetadataEntry::getReturnType() {
if (!returnType.empty()) return returnType;

auto reader = MetadataNode::getMetadataReader();

if (type == NodeType::Method) {
if (mi.GetSignatureLength() > 0) {
returnType = MetadataReader::ParseReturnType(this->getSig());
}
} else {
return returnType;
}

return returnType;
}

MethodReturnType MetadataEntry::getRetType() {
if (retTypeParsed) return retType;
auto reader = MetadataNode::getMetadataReader();

if (type == NodeType::Method && !this->getReturnType().empty()) {
retType = MetadataReader::GetReturnType(this->returnType);
}

retTypeParsed = true;

return retType;
}

std::string &MetadataEntry::getDeclaringType() {
if (!declaringType.empty()) return declaringType;

auto reader = MetadataNode::getMetadataReader();

if (type == NodeType::StaticField) {
declaringType = reader->ReadTypeName(sfi->declaringType);
} else if (type == NodeType::Method && isStatic) {
declaringType = mi.GetDeclaringType();
}

return declaringType;
}

int MetadataEntry::getParamCount() {
if (paramCount != -1) return paramCount;

auto reader = MetadataNode::getMetadataReader();

if (type == NodeType::Method) {
auto sigLength = mi.GetSignatureLength();
if (sigLength > 0) {
paramCount = sigLength - 1;
} else {
paramCount = 0;
}
}

return paramCount;
}

bool MetadataEntry::getIsFinal() {
if (isFinalSet) return isFinal;

if (type == NodeType::Field) {
isFinal = fi->finalModifier == MetadataTreeNode::FINAL;
} else if (type == NodeType::StaticField) {
isFinal = sfi->finalModifier == MetadataTreeNode::FINAL;
}

isFinalSet = true;

return isFinal;
}

bool MetadataEntry::getIsResolved() {
if (isResolvedSet) return isResolved;

auto reader = MetadataNode::getMetadataReader();
if (type == NodeType::Method) {
isResolved = mi.CheckIsResolved() == 1;
}

isResolvedSet = true;

return isResolved;
}
Loading
Loading