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)