Skip to content

Commit f290ed2

Browse files
authored
perf: optimizations around generating JS classes from Metadata (#1824)
1 parent 3423e6f commit f290ed2

13 files changed

+694
-529
lines changed

test-app/runtime/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ add_library(
115115
src/main/cpp/MetadataNode.cpp
116116
src/main/cpp/MetadataReader.cpp
117117
src/main/cpp/MetadataTreeNode.cpp
118+
src/main/cpp/MetadataEntry.cpp
118119
src/main/cpp/MethodCache.cpp
119120
src/main/cpp/ModuleBinding.cpp
120121
src/main/cpp/ModuleInternal.cpp

test-app/runtime/src/main/cpp/CallbackHandlers.cpp

+11-10
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,8 @@ void CallbackHandlers::CallJavaMethod(const Local<Object> &caller, const string
213213

214214
auto isolate = args.GetIsolate();
215215

216-
if ((entry != nullptr) && entry->isResolved) {
216+
if ((entry != nullptr) && entry->getIsResolved()) {
217+
auto &entrySignature = entry->getSig();
217218
isStatic = entry->isStatic;
218219

219220
if (entry->memberId == nullptr) {
@@ -236,14 +237,14 @@ void CallbackHandlers::CallJavaMethod(const Local<Object> &caller, const string
236237
if (isFromInterface) {
237238
auto methodAndClassPair = env.GetInterfaceStaticMethodIDAndJClass(className,
238239
methodName,
239-
entry->sig);
240+
entrySignature);
240241
entry->memberId = methodAndClassPair.first;
241242
clazz = methodAndClassPair.second;
242243
} else {
243-
entry->memberId = env.GetStaticMethodID(clazz, methodName, entry->sig);
244+
entry->memberId = env.GetStaticMethodID(clazz, methodName, entrySignature);
244245
}
245246
} else {
246-
entry->memberId = env.GetMethodID(clazz, methodName, entry->sig);
247+
entry->memberId = env.GetMethodID(clazz, methodName, entrySignature);
247248
}
248249

249250
if (entry->memberId == nullptr) {
@@ -257,14 +258,14 @@ void CallbackHandlers::CallJavaMethod(const Local<Object> &caller, const string
257258
if (isFromInterface) {
258259
auto methodAndClassPair = env.GetInterfaceStaticMethodIDAndJClass(className,
259260
methodName,
260-
entry->sig);
261+
entrySignature);
261262
entry->memberId = methodAndClassPair.first;
262263
clazz = methodAndClassPair.second;
263264
} else {
264-
entry->memberId = env.GetStaticMethodID(clazz, methodName, entry->sig);
265+
entry->memberId = env.GetStaticMethodID(clazz, methodName, entrySignature);
265266
}
266267
} else {
267-
entry->memberId = env.GetMethodID(clazz, methodName, entry->sig);
268+
entry->memberId = env.GetMethodID(clazz, methodName, entrySignature);
268269
}
269270

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

280281
mid = reinterpret_cast<jmethodID>(entry->memberId);
281282
clazz = entry->clazz;
282-
sig = &entry->sig;
283-
returnType = &entry->returnType;
284-
retType = entry->retType;
283+
sig = &entrySignature;
284+
returnType = &entry->getReturnType();
285+
retType = entry->getRetType();
285286
} else {
286287
DEBUG_WRITE("Resolving method: %s on className %s", methodName.c_str(), className.c_str());
287288

test-app/runtime/src/main/cpp/FieldAccessor.cpp

+19-14
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ Local<Value> FieldAccessor::GetJavaField(Isolate* isolate, const Local<Object>&
1919

2020
JniLocalRef targetJavaObject;
2121

22-
const auto& fieldTypeName = fieldData->signature;
23-
auto isStatic = fieldData->isStatic;
22+
auto &fieldMetadata = fieldData->metadata;
23+
24+
const auto& fieldTypeName = fieldMetadata.getSig();
25+
auto isStatic = fieldMetadata.isStatic;
2426

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

3739
if (isStatic) {
38-
fieldData->clazz = env.FindClass(fieldData->declaringType);
39-
fieldData->fid = env.GetStaticFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
40+
fieldData->clazz = env.FindClass(fieldMetadata.getDeclaringType());
41+
fieldData->fid = env.GetStaticFieldID(fieldData->clazz, fieldMetadata.name, fieldJniSig);
4042
} else {
41-
fieldData->clazz = env.FindClass(fieldData->declaringType);
42-
fieldData->fid = env.GetFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
43+
fieldData->clazz = env.FindClass(fieldMetadata.getDeclaringType());
44+
fieldData->fid = env.GetFieldID(fieldData->clazz, fieldMetadata.name, fieldJniSig);
4345
}
4446
}
4547

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

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

191+
auto &fieldMetadata = fieldData->metadata;
192+
189193
HandleScope handleScope(isolate);
190194
auto runtime = Runtime::GetRuntime(isolate);
191195
auto objectManager = runtime->GetObjectManager();
192196

193197
JniLocalRef targetJavaObject;
194198

195-
const auto& fieldTypeName = fieldData->signature;
196-
auto isStatic = fieldData->isStatic;
199+
const auto& fieldTypeName = fieldMetadata.getSig();
200+
auto isStatic = fieldMetadata.isStatic;
201+
197202

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

210215
if (isStatic) {
211-
fieldData->clazz = env.FindClass(fieldData->declaringType);
216+
fieldData->clazz = env.FindClass(fieldMetadata.getDeclaringType());
212217
assert(fieldData->clazz != nullptr);
213-
fieldData->fid = env.GetStaticFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
218+
fieldData->fid = env.GetStaticFieldID(fieldData->clazz, fieldMetadata.name, fieldJniSig);
214219
assert(fieldData->fid != nullptr);
215220
} else {
216-
fieldData->clazz = env.FindClass(fieldData->declaringType);
221+
fieldData->clazz = env.FindClass(fieldMetadata.getDeclaringType());
217222
assert(fieldData->clazz != nullptr);
218-
fieldData->fid = env.GetFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
223+
fieldData->fid = env.GetFieldID(fieldData->clazz, fieldMetadata.name, fieldJniSig);
219224
assert(fieldData->fid != nullptr);
220225
}
221226
}
@@ -225,7 +230,7 @@ void FieldAccessor::SetJavaField(Isolate* isolate, const Local<Object>& target,
225230

226231
if (targetJavaObject.IsNull()) {
227232
stringstream ss;
228-
ss << "Cannot access property '" << fieldData->name.c_str() << "' because there is no corresponding Java object";
233+
ss << "Cannot access property '" << fieldMetadata.name.c_str() << "' because there is no corresponding Java object";
229234
throw NativeScriptException(ss.str());
230235
}
231236
}

test-app/runtime/src/main/cpp/FieldCallbackData.h

+9-18
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,16 @@
55
#include "MetadataEntry.h"
66

77
namespace tns {
8-
struct FieldCallbackData {
9-
FieldCallbackData(const MetadataEntry& metadata)
10-
:
11-
fid(nullptr), clazz(nullptr) {
12-
name = metadata.name;
13-
signature = metadata.sig;
14-
declaringType = metadata.declaringType;
15-
isStatic = metadata.isStatic;
16-
isFinal = metadata.isFinal;
17-
}
8+
struct FieldCallbackData {
9+
FieldCallbackData(MetadataEntry metadata)
10+
:
11+
metadata(metadata), fid(nullptr), clazz(nullptr) {
12+
}
1813

19-
std::string name;
20-
std::string signature;
21-
std::string declaringType;
22-
bool isStatic;
23-
bool isFinal;
24-
jfieldID fid;
25-
jclass clazz;
26-
};
14+
MetadataEntry metadata;
15+
jfieldID fid;
16+
jclass clazz;
17+
};
2718

2819
}
2920

test-app/runtime/src/main/cpp/JsArgConverter.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ JsArgConverter::JsArgConverter(const Local<Object> &caller,
2323
m_argsLen = 1 + v8ProvidedArgumentsLength;
2424

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

6060
if (m_argsLen > 0) {
61-
if ((entry != nullptr) && (entry->isResolved)) {
61+
if ((entry != nullptr) && (entry->getIsResolved())) {
6262
if (entry->parsedSig.empty()) {
6363
JniSignatureParser parser(m_methodSignature);
6464
entry->parsedSig = parser.Parse();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
#include "MetadataNode.h"
2+
#include "MetadataEntry.h"
3+
#include "MetadataMethodInfo.h"
4+
#include "MetadataReader.h"
5+
6+
using namespace tns;
7+
8+
MetadataEntry::MetadataEntry(MetadataTreeNode *m_treeNode, NodeType nodeType) :
9+
treeNode(m_treeNode), type(nodeType), isExtensionFunction(false), isStatic(false),
10+
isTypeMember(false), memberId(nullptr), clazz(nullptr), mi(nullptr),fi(nullptr), sfi(nullptr),
11+
retType(MethodReturnType::Unknown),
12+
paramCount(-1), isFinal(false), isResolved(false), retTypeParsed(false),
13+
isFinalSet(false), isResolvedSet(false) {}
14+
15+
std::string &MetadataEntry::getName() {
16+
if (!name.empty()) return name;
17+
18+
auto reader = MetadataNode::getMetadataReader();
19+
20+
if (type == NodeType::Field) {
21+
name = reader->ReadName(fi->nameOffset);
22+
} else if (type == NodeType::StaticField) {
23+
name = reader->ReadName(sfi->nameOffset);
24+
} else if (type == NodeType::Method) {
25+
name = mi.GetName();
26+
}
27+
28+
return name;
29+
}
30+
31+
std::string &MetadataEntry::getSig() {
32+
if (!sig.empty()) return sig;
33+
34+
auto reader = MetadataNode::getMetadataReader();
35+
36+
if (type == NodeType::Field) {
37+
sig = reader->ReadTypeName(fi->nodeId);
38+
} else if (type == NodeType::StaticField) {
39+
sig = reader->ReadTypeName(sfi->nodeId);
40+
} else if (type == NodeType::Method) {
41+
uint8_t sigLength = mi.GetSignatureLength();
42+
if (sigLength > 0)
43+
sig = mi.GetSignature();
44+
45+
}
46+
47+
return sig;
48+
}
49+
50+
std::string &MetadataEntry::getReturnType() {
51+
if (!returnType.empty()) return returnType;
52+
53+
auto reader = MetadataNode::getMetadataReader();
54+
55+
if (type == NodeType::Method) {
56+
if (mi.GetSignatureLength() > 0) {
57+
returnType = MetadataReader::ParseReturnType(this->getSig());
58+
}
59+
} else {
60+
return returnType;
61+
}
62+
63+
return returnType;
64+
}
65+
66+
MethodReturnType MetadataEntry::getRetType() {
67+
if (retTypeParsed) return retType;
68+
auto reader = MetadataNode::getMetadataReader();
69+
70+
if (type == NodeType::Method && !this->getReturnType().empty()) {
71+
retType = MetadataReader::GetReturnType(this->returnType);
72+
}
73+
74+
retTypeParsed = true;
75+
76+
return retType;
77+
}
78+
79+
std::string &MetadataEntry::getDeclaringType() {
80+
if (!declaringType.empty()) return declaringType;
81+
82+
auto reader = MetadataNode::getMetadataReader();
83+
84+
if (type == NodeType::StaticField) {
85+
declaringType = reader->ReadTypeName(sfi->declaringType);
86+
} else if (type == NodeType::Method && isStatic) {
87+
declaringType = mi.GetDeclaringType();
88+
}
89+
90+
return declaringType;
91+
}
92+
93+
int MetadataEntry::getParamCount() {
94+
if (paramCount != -1) return paramCount;
95+
96+
auto reader = MetadataNode::getMetadataReader();
97+
98+
if (type == NodeType::Method) {
99+
auto sigLength = mi.GetSignatureLength();
100+
if (sigLength > 0) {
101+
paramCount = sigLength - 1;
102+
} else {
103+
paramCount = 0;
104+
}
105+
}
106+
107+
return paramCount;
108+
}
109+
110+
bool MetadataEntry::getIsFinal() {
111+
if (isFinalSet) return isFinal;
112+
113+
if (type == NodeType::Field) {
114+
isFinal = fi->finalModifier == MetadataTreeNode::FINAL;
115+
} else if (type == NodeType::StaticField) {
116+
isFinal = sfi->finalModifier == MetadataTreeNode::FINAL;
117+
}
118+
119+
isFinalSet = true;
120+
121+
return isFinal;
122+
}
123+
124+
bool MetadataEntry::getIsResolved() {
125+
if (isResolvedSet) return isResolved;
126+
127+
auto reader = MetadataNode::getMetadataReader();
128+
if (type == NodeType::Method) {
129+
isResolved = mi.CheckIsResolved() == 1;
130+
}
131+
132+
isResolvedSet = true;
133+
134+
return isResolved;
135+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy