From 98a2ccbe9b39fdf0afff3ef0204f66d9e49a35d4 Mon Sep 17 00:00:00 2001 From: Ammar Ahmed Date: Mon, 7 Oct 2024 14:28:28 +0500 Subject: [PATCH] fix runtime class loading performance --- test-app/runtime/CMakeLists.txt | 3 +- .../runtime/src/main/cpp/CallbackHandlers.cpp | 21 +- .../runtime/src/main/cpp/FieldAccessor.cpp | 33 +- .../runtime/src/main/cpp/FieldCallbackData.h | 28 +- .../runtime/src/main/cpp/MetadataEntry.cpp | 133 +++++++ test-app/runtime/src/main/cpp/MetadataEntry.h | 117 +++--- .../src/main/cpp/MetadataMethodInfo.cpp | 65 ++-- .../runtime/src/main/cpp/MetadataMethodInfo.h | 32 +- .../runtime/src/main/cpp/MetadataNode.cpp | 360 ++++++++---------- test-app/runtime/src/main/cpp/MetadataNode.h | 28 +- .../runtime/src/main/cpp/MetadataReader.cpp | 199 +++------- .../runtime/src/main/cpp/MetadataReader.h | 164 +++++--- 12 files changed, 646 insertions(+), 537 deletions(-) create mode 100644 test-app/runtime/src/main/cpp/MetadataEntry.cpp diff --git a/test-app/runtime/CMakeLists.txt b/test-app/runtime/CMakeLists.txt index 14e93ea11..9b98ce512 100644 --- a/test-app/runtime/CMakeLists.txt +++ b/test-app/runtime/CMakeLists.txt @@ -18,7 +18,7 @@ endif (CCACHE_FOUND AND (USE_CCACHE)) # "-DANDROID_STL=c++_static" is just not enough for clang++ to find some libraries in the ndk MESSAGE(STATUS "## ANDROID_NDK_ROOT: " ${ANDROID_NDK_ROOT}) -set(COMMON_CMAKE_ARGUMENTS "-std=c++17 -Werror -Wno-unused-result -mstackrealign -fexceptions -fno-builtin-stpcpy -fno-rtti -DV8_31BIT_SMIS_ON_64BIT_ARCH -DV8_31BIT_SMIS_ON_64BIT_ARCH -DV8_ENABLE_REGEXP_INTERPRETER_THREADED_DISPATCH -DV8_EMBEDDED_BUILTINS") +set(COMMON_CMAKE_ARGUMENTS "-std=c++17 -Wno-unused-result -mstackrealign -fexceptions -fno-builtin-stpcpy -fno-rtti -DV8_31BIT_SMIS_ON_64BIT_ARCH -DV8_31BIT_SMIS_ON_64BIT_ARCH -DV8_ENABLE_REGEXP_INTERPRETER_THREADED_DISPATCH -DV8_EMBEDDED_BUILTINS") if("${ANDROID_ABI}" MATCHES "arm64-v8a$" OR "${ANDROID_ABI}" MATCHES "x86_64$") # Enable pointer compression on 64 bit platforms @@ -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 diff --git a/test-app/runtime/src/main/cpp/CallbackHandlers.cpp b/test-app/runtime/src/main/cpp/CallbackHandlers.cpp index 6f35d9698..95c1b4c1f 100644 --- a/test-app/runtime/src/main/cpp/CallbackHandlers.cpp +++ b/test-app/runtime/src/main/cpp/CallbackHandlers.cpp @@ -210,10 +210,11 @@ void CallbackHandlers::CallJavaMethod(const Local &caller, const string string *returnType = nullptr; auto retType = MethodReturnType::Unknown; MethodCache::CacheMethodInfo mi; + auto &entrySignature = entry->getSig(); auto isolate = args.GetIsolate(); - if ((entry != nullptr) && entry->isResolved) { + if ((entry != nullptr) && entry->getIsResolved()) { isStatic = entry->isStatic; if (entry->memberId == nullptr) { @@ -236,14 +237,14 @@ void CallbackHandlers::CallJavaMethod(const Local &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) { @@ -257,14 +258,14 @@ void CallbackHandlers::CallJavaMethod(const Local &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) { @@ -279,9 +280,9 @@ void CallbackHandlers::CallJavaMethod(const Local &caller, const string mid = reinterpret_cast(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()); diff --git a/test-app/runtime/src/main/cpp/FieldAccessor.cpp b/test-app/runtime/src/main/cpp/FieldAccessor.cpp index f8f7148c1..569894b3d 100644 --- a/test-app/runtime/src/main/cpp/FieldAccessor.cpp +++ b/test-app/runtime/src/main/cpp/FieldAccessor.cpp @@ -19,8 +19,10 @@ Local FieldAccessor::GetJavaField(Isolate* isolate, const Local& 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] == '['; @@ -35,11 +37,11 @@ Local FieldAccessor::GetJavaField(Isolate* isolate, const Local& ("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); } } @@ -48,7 +50,7 @@ Local FieldAccessor::GetJavaField(Isolate* isolate, const Local& 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()); } } @@ -186,14 +188,17 @@ Local FieldAccessor::GetJavaField(Isolate* isolate, const Local& void FieldAccessor::SetJavaField(Isolate* isolate, const Local& target, const Local& 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] == '['; @@ -208,14 +213,14 @@ void FieldAccessor::SetJavaField(Isolate* isolate, const Local& 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); } } @@ -225,7 +230,7 @@ void FieldAccessor::SetJavaField(Isolate* isolate, const Local& 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()); } } diff --git a/test-app/runtime/src/main/cpp/FieldCallbackData.h b/test-app/runtime/src/main/cpp/FieldCallbackData.h index 6712bba42..e22bff146 100644 --- a/test-app/runtime/src/main/cpp/FieldCallbackData.h +++ b/test-app/runtime/src/main/cpp/FieldCallbackData.h @@ -5,25 +5,17 @@ #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; + }; } diff --git a/test-app/runtime/src/main/cpp/MetadataEntry.cpp b/test-app/runtime/src/main/cpp/MetadataEntry.cpp new file mode 100644 index 000000000..3f7dc1f21 --- /dev/null +++ b/test-app/runtime/src/main/cpp/MetadataEntry.cpp @@ -0,0 +1,133 @@ +#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->getReturnType()); + } + + 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); + } + + 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; +} diff --git a/test-app/runtime/src/main/cpp/MetadataEntry.h b/test-app/runtime/src/main/cpp/MetadataEntry.h index fefa17666..ba80e8f21 100644 --- a/test-app/runtime/src/main/cpp/MetadataEntry.h +++ b/test-app/runtime/src/main/cpp/MetadataEntry.h @@ -4,56 +4,77 @@ #include #include "jni.h" #include "MetadataTreeNode.h" +#include "MetadataMethodInfo.h" +#include "MetadataFieldInfo.h" namespace tns { -enum class NodeType { - Package, - Class, - Interface, - Method, - Field, - StaticField -}; - -enum class MethodReturnType { - Unknown, - Void, - Byte, - Short, - Int, - Long, - Float, - Double, - Char, - Boolean, - String, - Object -}; - -struct MetadataEntry { - MetadataEntry() - : - isTypeMember(false), name(std::string()), treeNode(nullptr), sig(std::string()), returnType(std::string()), retType(MethodReturnType::Unknown), paramCount(0), - isStatic(false), isFinal(false), declaringType(std::string()), - isResolved(false), isExtensionFunction(false), memberId(nullptr), clazz(nullptr) { - } - MetadataTreeNode* treeNode; - NodeType type; - std::string name; - std::string sig; - std::string returnType; - MethodReturnType retType; - std::string declaringType; - int paramCount; - bool isStatic; - bool isFinal; - bool isTypeMember; - bool isResolved; - bool isExtensionFunction; - void* memberId; - jclass clazz; - std::vector parsedSig; -}; + enum class NodeType { + Package, + Class, + Interface, + Method, + Field, + StaticField + }; + + enum class MethodReturnType { + Unknown, + Void, + Byte, + Short, + Int, + Long, + Float, + Double, + Char, + Boolean, + String, + Object + }; + + class MetadataEntry { + public: + + MetadataEntry(MetadataTreeNode* m_treeNode, NodeType nodeType); + + std::string& getName(); + std::string& getSig(); + std::string& getReturnType(); + MethodReturnType getRetType(); + std::string& getDeclaringType(); + int getParamCount(); + bool getIsFinal(); + bool getIsResolved(); + + MetadataTreeNode* treeNode; + NodeType type; + bool isExtensionFunction; + bool isStatic; + bool isTypeMember; + void* memberId; + jclass clazz; + std::vector parsedSig; + + MethodInfo* mi; + FieldInfo* fi; + StaticFieldInfo* sfi; + + std::string name; + std::string sig; + std::string returnType; + MethodReturnType retType; + std::string declaringType; + int paramCount; + bool isFinal; + bool isResolved; + + private: + + bool retTypeParsed; + bool isFinalSet; + bool isResolvedSet; + + }; } #endif /* METADATAENTRY_H_ */ diff --git a/test-app/runtime/src/main/cpp/MetadataMethodInfo.cpp b/test-app/runtime/src/main/cpp/MetadataMethodInfo.cpp index bdd136e92..42289ab89 100644 --- a/test-app/runtime/src/main/cpp/MetadataMethodInfo.cpp +++ b/test-app/runtime/src/main/cpp/MetadataMethodInfo.cpp @@ -1,35 +1,28 @@ #include "MetadataMethodInfo.h" +#include "MetadataNode.h" + using namespace tns; std::string MethodInfo::GetName() { - uint32_t nameOfffset = *reinterpret_cast(m_pData); - string methodName = m_reader->ReadName(nameOfffset); - m_pData += sizeof(uint32_t); - + string methodName = MetadataNode::getMetadataReader()->ReadName(nameOffset); return methodName; } uint8_t MethodInfo::CheckIsResolved() { - auto resolvedData = *reinterpret_cast(m_pData); - m_pData += sizeof(uint8_t); - return resolvedData; } uint16_t MethodInfo::GetSignatureLength() { - m_signatureLength = *reinterpret_cast(m_pData); - m_pData += sizeof(uint16_t); - return m_signatureLength; } std::string MethodInfo::GetSignature() { //use nodeId's to read the whole signature - uint16_t* nodeIdPtr = reinterpret_cast(m_pData); + auto m_reader = MetadataNode::getMetadataReader(); string signature = "("; string ret; for (int i = 0; i < m_signatureLength; i++) { - uint16_t nodeId = *nodeIdPtr++; + uint16_t nodeId = nodeIds[i]; string curArgTypeName = m_reader->ReadTypeName(nodeId); MetadataTreeNode* node = m_reader->GetNodeById(nodeId); @@ -58,23 +51,49 @@ std::string MethodInfo::GetSignature() { //use nodeId's to read the whole signat } signature += ")" + ret; - int sizeofReadNodeIds = m_signatureLength * sizeof(uint16_t); - m_pData += sizeofReadNodeIds; - return signature; } std::string MethodInfo::GetDeclaringType() { - uint16_t* declaringTypePtr = reinterpret_cast(m_pData); - uint16_t nodeId = *declaringTypePtr; + auto m_reader = MetadataNode::getMetadataReader(); - string declTypeName = m_reader->ReadTypeName(nodeId); - - m_pData += sizeof(uint16_t); - - return declTypeName; + return m_reader->ReadTypeName(declaringNodeId); } int MethodInfo::GetSizeOfReadMethodInfo() { + + if (!sizeMeasured) { + sizeMeasured = true; + // name + nameOffset = *reinterpret_cast(m_pData); + m_pData += sizeof(uint32_t); + // resolved data + resolvedData = *reinterpret_cast(m_pData); + m_pData += sizeof(uint8_t); + // sig length + m_signatureLength = *reinterpret_cast(m_pData); + m_pData += sizeof(uint16_t); + + // signature + if (m_signatureLength > 0) { + uint16_t* nodeIdPtr = reinterpret_cast(m_pData); + nodeIds.resize(m_signatureLength); + for (int i = 0; i < m_signatureLength; i++) { + nodeIds[i] = *nodeIdPtr++; + } + m_pData += m_signatureLength * sizeof(uint16_t); + } + + // declaring type + if (isStatic) { + auto declaringTypePtr = reinterpret_cast(m_pData); + declaringNodeId = *declaringTypePtr; + m_pData += sizeof(uint16_t); + } + + + + } + return m_pData - m_pStartData; -} +} \ No newline at end of file diff --git a/test-app/runtime/src/main/cpp/MetadataMethodInfo.h b/test-app/runtime/src/main/cpp/MetadataMethodInfo.h index b3e61bcf1..e79dfb457 100644 --- a/test-app/runtime/src/main/cpp/MetadataMethodInfo.h +++ b/test-app/runtime/src/main/cpp/MetadataMethodInfo.h @@ -1,8 +1,6 @@ #ifndef METHODINFOSMARTPOINTER_H_ #define METHODINFOSMARTPOINTER_H_ -#include "MetadataReader.h" - #include #include #include @@ -10,26 +8,42 @@ using namespace std; namespace tns { -class MethodInfo { + class MethodInfo { public: - MethodInfo(uint8_t* pValue, MetadataReader* reader) - : m_pData(pValue), m_pStartData(pValue), m_reader(reader), m_signatureLength(0) { + + MethodInfo(uint8_t *pValue) + : isStatic(false), m_pData(pValue), m_pStartData(pValue), m_signatureLength(0), + sizeMeasured(false), nameOffset(0), resolvedData(0), + declaringNodeId(0){ } std::string GetName(); + uint8_t CheckIsResolved(); + uint16_t GetSignatureLength(); + std::string GetSignature(); + std::string GetDeclaringType(); //used only for static methods int GetSizeOfReadMethodInfo(); + bool isStatic; + private: - uint8_t* m_pData; //where we currently read - uint8_t* m_pStartData; // pointer to the beginning + uint8_t *m_pData; //where we currently read + uint8_t *m_pStartData; // pointer to the beginning uint16_t m_signatureLength; - MetadataReader* m_reader; -}; + bool sizeMeasured; + + uint32_t nameOffset; + uint8_t resolvedData; + uint16_t declaringNodeId; + std::vector nodeIds; + + + }; } #endif /* METHODINFOSMARTPOINTER_H_ */ diff --git a/test-app/runtime/src/main/cpp/MetadataNode.cpp b/test-app/runtime/src/main/cpp/MetadataNode.cpp index a01a5a1bf..e0caff1e1 100644 --- a/test-app/runtime/src/main/cpp/MetadataNode.cpp +++ b/test-app/runtime/src/main/cpp/MetadataNode.cpp @@ -327,10 +327,11 @@ void MetadataNode::FieldAccessorGetterCallback(Local property, const Prope try { auto thiz = info.This(); auto fieldCallbackData = reinterpret_cast(info.Data().As()->Value()); + auto fieldCallbackMetadata = fieldCallbackData->metadata; - if ((!fieldCallbackData->isStatic && thiz->StrictEquals(info.Holder())) + if ((!fieldCallbackMetadata->isStatic && thiz->StrictEquals(info.Holder())) // check whether there's a declaring type to get the class from it - || (fieldCallbackData->declaringType == "")) { + || (fieldCallbackMetadata->declaringType == "")) { info.GetReturnValue().SetUndefined(); return; } @@ -354,16 +355,17 @@ void MetadataNode::FieldAccessorSetterCallback(Local property, Local(info.Data().As()->Value()); + auto fieldCallbackMetadata = fieldCallbackData->metadata; - if (!fieldCallbackData->isStatic && thiz->StrictEquals(info.Holder())) { + if (!fieldCallbackMetadata->isStatic && thiz->StrictEquals(info.Holder())) { auto isolate = info.GetIsolate(); info.GetReturnValue().Set(v8::Undefined(isolate)); return; } - if (fieldCallbackData->isFinal) { + if (fieldCallbackMetadata->getIsFinal()) { stringstream ss; - ss << "You are trying to set \"" << fieldCallbackData->name << "\" which is a final field! Final fields can only be read."; + ss << "You are trying to set \"" << fieldCallbackMetadata->getName() << "\" which is a final field! Final fields can only be read."; string exceptionMessage = ss.str(); throw NativeScriptException(exceptionMessage); @@ -542,7 +544,7 @@ std::vector MetadataNode::SetInstanceMembers( PrototypeTemplateFiller& protoFiller, vector& instanceMethodsCallbackData, const vector& baseInstanceMethodsCallbackData, - MetadataTreeNode* treeNode) { + MetadataTreeNode* treeNode, uint8_t* &curPtr) { auto hasCustomMetadata = treeNode->metadata != nullptr; if (hasCustomMetadata) { @@ -551,10 +553,9 @@ std::vector MetadataNode::SetInstanceMembers( baseInstanceMethodsCallbackData, treeNode); } - SetInstanceFieldsFromStaticMetadata(isolate, protoFiller, treeNode); return SetInstanceMethodsFromStaticMetadata( isolate, ctorFuncTemplate, protoFiller, instanceMethodsCallbackData, - baseInstanceMethodsCallbackData, treeNode); + baseInstanceMethodsCallbackData, treeNode, curPtr); } vector MetadataNode::SetInstanceMethodsFromStaticMetadata( @@ -562,12 +563,12 @@ vector MetadataNode::SetInstanceMethodsFromS PrototypeTemplateFiller& protoFiller, vector &instanceMethodsCallbackData, const vector &baseInstanceMethodsCallbackData, - MetadataTreeNode *treeNode) { + MetadataTreeNode *treeNode, uint8_t* &curPtr) { SET_PROFILER_FRAME(); std::vector instanceMethodData; - uint8_t *curPtr = s_metadataReader.GetValueData() + treeNode->offsetValue + 1; + curPtr = s_metadataReader.GetValueData() + treeNode->offsetValue + 1; auto nodeType = s_metadataReader.GetNodeType(treeNode); @@ -584,24 +585,25 @@ vector MetadataNode::SetInstanceMethodsFromS auto context = isolate->GetCurrentContext(); - std::unordered_map collectedExtensionMethodDatas; + robin_hood::unordered_map collectedExtensionMethodDatas; auto extensionFunctionsCount = *reinterpret_cast(curPtr); curPtr += sizeof(uint16_t); for (auto i = 0; i < extensionFunctionsCount; i++) { - auto entry = s_metadataReader.ReadExtensionFunctionEntry(&curPtr); + auto entry = MetadataReader::ReadExtensionFunctionEntry(&curPtr); - if (entry.name != lastMethodName) { + auto &methodName = entry->getName(); + if (methodName!= lastMethodName) { // callbackData = tryGetExtensionMethodCallbackData(collectedExtensionMethodDatas, - entry.name); + methodName); if (callbackData == nullptr) { callbackData = new MethodCallbackData(this); - protoFiller.FillPrototypeMethod(isolate, entry.name, callbackData); + protoFiller.FillPrototypeMethod(isolate, methodName, callbackData); - lastMethodName = entry.name; - std::pair p(entry.name, callbackData); - collectedExtensionMethodDatas.insert(p); + lastMethodName = methodName; + std::pair p(methodName, callbackData); + collectedExtensionMethodDatas.emplace(p); } } callbackData->candidates.push_back(entry); @@ -613,19 +615,20 @@ vector MetadataNode::SetInstanceMethodsFromS curPtr += sizeof(uint16_t); for (auto i = 0; i < instanceMethodCount; i++) { - auto entry = s_metadataReader.ReadInstanceMethodEntry(&curPtr); + auto entry = MetadataReader::ReadInstanceMethodEntry(&curPtr); // attach a function to the prototype of a javascript Object - if (entry.name != lastMethodName) { + auto &methodName = entry->getName(); + if (methodName != lastMethodName) { // See if we have tracked the callback data before (meaning another version of entry.name exists with different parameters) callbackData = tryGetExtensionMethodCallbackData(collectedExtensionMethodDatas, - entry.name); + methodName); if (callbackData == nullptr) { callbackData = new MethodCallbackData(this); // If we have no tracking of this callback data, create tracking so that we can find it if need be for future itterations where the entry.name is the same... - std::pair p(entry.name, callbackData); - collectedExtensionMethodDatas.insert(p); + std::pair p(methodName, callbackData); + collectedExtensionMethodDatas.emplace(p); } instanceMethodData.push_back(callbackData); @@ -633,8 +636,8 @@ vector MetadataNode::SetInstanceMethodsFromS instanceMethodsCallbackData.push_back(callbackData); auto itBegin = baseInstanceMethodsCallbackData.begin(); auto itEnd = baseInstanceMethodsCallbackData.end(); - auto itFound = find_if(itBegin, itEnd, [&entry](MethodCallbackData *x) { - return x->candidates.front().name == entry.name; + auto itFound = find_if(itBegin, itEnd, [&methodName](MethodCallbackData *x) { + return x->candidates.front()->name == methodName; }); if (itFound != itEnd) { callbackData->parent = *itFound; @@ -645,88 +648,35 @@ vector MetadataNode::SetInstanceMethodsFromS Local funcTemplate = FunctionTemplate::New(isolate, MethodCallback, funcData); auto func = funcTemplate->GetFunction(context).ToLocalChecked(); std::string origin = Constants::APP_ROOT_FOLDER_PATH + GetOrCreateInternal(treeNode)->m_name; - Local wrapperFunc = Wrap(isolate, func, entry.name, origin, + Local wrapperFunc = Wrap(isolate, func, methodName, origin, false /* isCtorFunc */); Local ctorFunc = ctorFuncTemplate->GetFunction(context).ToLocalChecked(); Local protoVal; ctorFunc->Get(context, ArgConverter::ConvertToV8String(isolate, "prototype")).ToLocal( &protoVal); - Local funcName = ArgConverter::ConvertToV8String(isolate, entry.name); + Local funcName = ArgConverter::ConvertToV8String(isolate, methodName); if (!protoVal.IsEmpty() && !protoVal->IsUndefined() && !protoVal->IsNull()) { protoVal.As()->Set(context, funcName, wrapperFunc); } } else { - protoFiller.FillPrototypeMethod(isolate, entry.name, callbackData); + protoFiller.FillPrototypeMethod(isolate, methodName, callbackData); } - lastMethodName = entry.name; + lastMethodName = methodName; } callbackData->candidates.push_back(entry); } - return instanceMethodData; -} - -MetadataNode::MethodCallbackData *MetadataNode::tryGetExtensionMethodCallbackData( - std::unordered_map collectedMethodCallbackDatas, - std::string lookupName) { - - if (collectedMethodCallbackDatas.size() < 1) { - return nullptr; - } - - auto iter = collectedMethodCallbackDatas.find(lookupName); - - if (iter != collectedMethodCallbackDatas.end()) { - return iter->second; - } - - return nullptr; -} - -void MetadataNode::SetInstanceFieldsFromStaticMetadata( - Isolate* isolate, PrototypeTemplateFiller& prototypeTemplate, MetadataTreeNode* treeNode) { - SET_PROFILER_FRAME(); - - Local ctorFunction; - - uint8_t* curPtr = s_metadataReader.GetValueData() + treeNode->offsetValue + 1; - - auto nodeType = s_metadataReader.GetNodeType(treeNode); - - auto curType = s_metadataReader.ReadTypeName(treeNode); - - curPtr += sizeof(uint16_t /* baseClassId */); - - if (s_metadataReader.IsNodeTypeInterface(nodeType)) { - curPtr += sizeof(uint8_t) + sizeof(uint32_t); - } - - auto extensionFunctionsCount = *reinterpret_cast(curPtr); - curPtr += sizeof(uint16_t); - for (auto i = 0; i < extensionFunctionsCount; i++) { - auto entry = s_metadataReader.ReadExtensionFunctionEntry(&curPtr); - } - - //get candidates from instance methods metadata - auto instanceMethodCout = *reinterpret_cast(curPtr); - curPtr += sizeof(uint16_t); - - //skip metadata methods -- advance the pointer only - for (auto i = 0; i < instanceMethodCout; i++) { - auto entry = s_metadataReader.ReadInstanceMethodEntry(&curPtr); - } - //get candidates from instance fields metadata auto instanceFieldCout = *reinterpret_cast(curPtr); curPtr += sizeof(uint16_t); for (auto i = 0; i < instanceFieldCout; i++) { - auto entry = s_metadataReader.ReadInstanceFieldEntry(&curPtr); + auto entry = MetadataReader::ReadInstanceFieldEntry(&curPtr); auto fieldInfo = new FieldCallbackData(entry); - fieldInfo->declaringType = curType; - prototypeTemplate.FillPrototypeField(isolate, entry.name, fieldInfo); + fieldInfo->metadata->declaringType = curType; + protoFiller.FillPrototypeField(isolate, entry->getName(), fieldInfo); } auto kotlinPropertiesCount = *reinterpret_cast(curPtr); @@ -741,8 +691,8 @@ void MetadataNode::SetInstanceFieldsFromStaticMetadata( std::string getterMethodName = ""; if(hasGetter>=1){ - auto entry = s_metadataReader.ReadInstanceMethodEntry(&curPtr); - getterMethodName = entry.name; + auto entry = MetadataReader::ReadInstanceMethodEntry(&curPtr); + getterMethodName = entry->getName(); } auto hasSetter = *reinterpret_cast(curPtr); @@ -750,15 +700,35 @@ void MetadataNode::SetInstanceFieldsFromStaticMetadata( std::string setterMethodName = ""; if(hasSetter >= 1){ - auto entry = s_metadataReader.ReadInstanceMethodEntry(&curPtr); - setterMethodName = entry.name; + auto entry = MetadataReader::ReadInstanceMethodEntry(&curPtr); + setterMethodName = entry->getName(); } auto propertyInfo = new PropertyCallbackData(propertyName, getterMethodName, setterMethodName); - prototypeTemplate.FillPrototypeProperty(isolate, propertyName, propertyInfo); + protoFiller.FillPrototypeProperty(isolate, propertyName, propertyInfo); } + + return instanceMethodData; } +MetadataNode::MethodCallbackData *MetadataNode::tryGetExtensionMethodCallbackData( + const robin_hood::unordered_map &collectedMethodCallbackDatas, + const std::string &lookupName) { + + if (collectedMethodCallbackDatas.empty()) { + return nullptr; + } + + auto iter = collectedMethodCallbackDatas.find(lookupName); + + if (iter != collectedMethodCallbackDatas.end()) { + return iter->second; + } + + return nullptr; +} + + vector MetadataNode::SetInstanceMembersFromRuntimeMetadata( Isolate* isolate, PrototypeTemplateFiller& protoFiller, vector& instanceMethodsCallbackData, @@ -794,15 +764,16 @@ vector MetadataNode::SetInstanceMembersFromRu // method or field assert((chKind == 'M') || (chKind == 'F')); - MetadataEntry entry; - entry.name = name; - entry.sig = signature; - MetadataReader::FillReturnType(entry); - entry.paramCount = paramCount; - entry.isStatic = false; + auto entry = new MetadataEntry(nullptr, NodeType::Field); + + entry->name = name; + entry->sig = signature; +// MetadataReader::FillReturnType(entry); + entry->paramCount = paramCount; + entry->isStatic = false; if (chKind == 'M') { - if (entry.name != lastMethodName) { + if (entry->name != lastMethodName) { callbackData = new MethodCallbackData(this); instanceMethodData.push_back(callbackData); @@ -810,78 +781,31 @@ vector MetadataNode::SetInstanceMembersFromRu auto itBegin = baseInstanceMethodsCallbackData.begin(); auto itEnd = baseInstanceMethodsCallbackData.end(); auto itFound = find_if(itBegin, itEnd, [&entry] (MethodCallbackData *x) { - return x->candidates.front().name == entry.name; + return x->candidates.front()->name == entry->name; }); if (itFound != itEnd) { callbackData->parent = *itFound; } - protoFiller.FillPrototypeMethod(isolate, entry.name, callbackData); - lastMethodName = entry.name; + protoFiller.FillPrototypeMethod(isolate, entry->name, callbackData); + lastMethodName = entry->name; } callbackData->candidates.push_back(entry); } else if (chKind == 'F') { auto* fieldInfo = new FieldCallbackData(entry); - auto access = entry.isFinal ? AccessControl::ALL_CAN_READ : AccessControl::DEFAULT; - protoFiller.FillPrototypeField(isolate, entry.name, fieldInfo, access); + auto access = entry->isFinal ? AccessControl::ALL_CAN_READ : AccessControl::DEFAULT; + protoFiller.FillPrototypeField(isolate, entry->name, fieldInfo, access); } } return instanceMethodData; } -void MetadataNode::SetStaticMembers(Isolate* isolate, Local& ctorFunction, MetadataTreeNode* treeNode) { + +void MetadataNode::SetStaticMembers(Isolate* isolate, Local& ctorFunction, MetadataTreeNode* treeNode, uint8_t* &curPtr) { auto hasCustomMetadata = treeNode->metadata != nullptr; auto context = isolate->GetCurrentContext(); if (!hasCustomMetadata) { - uint8_t* curPtr = s_metadataReader.GetValueData() + treeNode->offsetValue + 1; - auto nodeType = s_metadataReader.GetNodeType(treeNode); - auto curType = s_metadataReader.ReadTypeName(treeNode); - curPtr += sizeof(uint16_t /* baseClassId */); - if (s_metadataReader.IsNodeTypeInterface(nodeType)) { - curPtr += sizeof(uint8_t) + sizeof(uint32_t); - } - - auto extensionFunctionsCount = *reinterpret_cast(curPtr); - curPtr += sizeof(uint16_t); - for (auto i = 0; i < extensionFunctionsCount; i++) { - auto entry = s_metadataReader.ReadExtensionFunctionEntry(&curPtr); - } - - auto instanceMethodCout = *reinterpret_cast(curPtr); - curPtr += sizeof(uint16_t); - for (auto i = 0; i < instanceMethodCout; i++) { - auto entry = s_metadataReader.ReadInstanceMethodEntry(&curPtr); - } - - auto instanceFieldCout = *reinterpret_cast(curPtr); - curPtr += sizeof(uint16_t); - for (auto i = 0; i < instanceFieldCout; i++) { - auto entry = s_metadataReader.ReadInstanceFieldEntry(&curPtr); - } - - auto kotlinPropertiesCount = *reinterpret_cast(curPtr); - curPtr += sizeof(uint16_t); - for (int i = 0; i < kotlinPropertiesCount; ++i) { - uint32_t nameOfffset = *reinterpret_cast(curPtr); - string propertyName = s_metadataReader.ReadName(nameOfffset); - curPtr += sizeof(uint32_t); - - auto hasGetter = *reinterpret_cast(curPtr); - curPtr += sizeof(uint16_t); - - if(hasGetter>=1){ - auto entry = s_metadataReader.ReadInstanceMethodEntry(&curPtr); - } - - auto hasSetter = *reinterpret_cast(curPtr); - curPtr += sizeof(uint16_t); - - if(hasSetter >= 1){ - auto entry = s_metadataReader.ReadInstanceMethodEntry(&curPtr); - } - } - string lastMethodName; MethodCallbackData* callbackData = nullptr; @@ -891,15 +815,16 @@ void MetadataNode::SetStaticMembers(Isolate* isolate, Local& ctorFunct auto staticMethodCout = *reinterpret_cast(curPtr); curPtr += sizeof(uint16_t); for (auto i = 0; i < staticMethodCout; i++) { - auto entry = s_metadataReader.ReadStaticMethodEntry(&curPtr); - if (entry.name != lastMethodName) { + auto entry = MetadataReader::ReadStaticMethodEntry(&curPtr); + auto &methodName = entry->getName(); + if (methodName != lastMethodName) { callbackData = new MethodCallbackData(this); auto funcData = External::New(isolate, callbackData); auto funcTemplate = FunctionTemplate::New(isolate, MethodCallback, funcData); auto func = funcTemplate->GetFunction(context).ToLocalChecked(); - auto funcName = ArgConverter::ConvertToV8String(isolate, entry.name); - ctorFunction->Set(context, funcName, Wrap(isolate, func, entry.name, origin, false /* isCtorFunc */)); - lastMethodName = entry.name; + auto funcName = ArgConverter::ConvertToV8String(isolate, methodName); + ctorFunction->Set(context, funcName, Wrap(isolate, func, methodName, origin, false /* isCtorFunc */)); + lastMethodName = methodName; } callbackData->candidates.push_back(entry); } @@ -913,9 +838,9 @@ void MetadataNode::SetStaticMembers(Isolate* isolate, Local& ctorFunct auto staticFieldCout = *reinterpret_cast(curPtr); curPtr += sizeof(uint16_t); for (auto i = 0; i < staticFieldCout; i++) { - auto entry = s_metadataReader.ReadStaticFieldEntry(&curPtr); + auto entry = MetadataReader::ReadStaticFieldEntry(&curPtr); - auto fieldName = ArgConverter::ConvertToV8String(isolate, entry.name); + auto fieldName = ArgConverter::ConvertToV8String(isolate, entry->getName()); auto fieldData = External::New(isolate, new FieldCallbackData(entry)); ctorFunction->SetAccessor(context, fieldName, FieldAccessorGetterCallback, FieldAccessorSetterCallback, fieldData, AccessControl::DEFAULT, PropertyAttribute::DontDelete); } @@ -929,30 +854,47 @@ void MetadataNode::SetStaticMembers(Isolate* isolate, Local& ctorFunct } } -void MetadataNode::SetInnerTypes(Isolate* isolate, Local& ctorFunction, MetadataTreeNode* treeNode) { - auto context = isolate->GetCurrentContext(); +void MetadataNode::SetInnerTypes(v8::Isolate* isolate, Local& ctorFunction, MetadataTreeNode *treeNode) { if (treeNode->children != nullptr) { - const auto& children = *treeNode->children; + auto context = isolate->GetCurrentContext(); + const auto &children = *treeNode->children; + for (auto curChild: children) { + ctorFunction->SetAccessor( + context, + v8::String::NewFromUtf8(isolate, curChild->name.c_str()).ToLocalChecked(), + InnerTypeAccessorGetterCallback, nullptr, v8::External::New(isolate, curChild) + ); + } + } +} - for (auto curChild : children) { - auto childNode = GetOrCreateInternal(curChild); +void MetadataNode::InnerTypeAccessorGetterCallback(v8::Local property, const v8::PropertyCallbackInfo& info) { + v8::Isolate* isolate = info.GetIsolate(); + v8::HandleScope handleScope(isolate); - // The call to GetConstructorFunctionTemplate bootstraps the ctor function for the childNode - auto innerTypeCtorFuncTemplate = childNode->GetConstructorFunctionTemplate(isolate, curChild); - if(innerTypeCtorFuncTemplate.IsEmpty()) { - // this class does not exist, so just ignore it - continue; - } - auto innerTypeCtorFunc = Local::New(isolate, *GetOrCreateInternal(curChild)->GetPersistentConstructorFunction(isolate)); - auto innerTypeName = ArgConverter::ConvertToV8String(isolate, curChild->name); - // TODO: remove this once we solve https://github.com/NativeScript/android/pull/1771 - // this avoids a crash, but the companion object is still unaccessible - TryCatch tc(isolate); - ctorFunction->Set(context, innerTypeName, innerTypeCtorFunc); - } + MetadataTreeNode* curChild = static_cast(v8::External::Cast(*info.Data())->Value()); + auto childNode = GetOrCreateInternal(curChild); + auto itFound = childNode->m_poCtorCachePerIsolate.find(isolate); + if (itFound != childNode->m_poCtorCachePerIsolate.end()) { + info.GetReturnValue().Set(itFound->second->Get(isolate)); + return; } + auto innerTypeCtorFuncTemplate= childNode->GetConstructorFunctionTemplate(isolate, curChild); + + if(innerTypeCtorFuncTemplate.IsEmpty()) { + info.GetReturnValue().Set(v8::Undefined(isolate)); + return; + } + + auto innerTypeCtorFunc = Local::New(isolate, *GetOrCreateInternal(curChild)->GetPersistentConstructorFunction(isolate)); + auto innerTypeName = ArgConverter::ConvertToV8String(isolate, curChild->name); + // TODO: remove this once we solve https://github.com/NativeScript/android/pull/1771 + // this avoids a crash, but the companion object is still unaccessible + TryCatch tc(isolate); + info.GetReturnValue().Set(innerTypeCtorFunc); } + Local MetadataNode::GetConstructorFunctionTemplate(Isolate* isolate, MetadataTreeNode* treeNode) { std::vector instanceMethodsCallbackData; @@ -1034,9 +976,11 @@ Local MetadataNode::GetConstructorFunctionTemplate(Isolate* is PrototypeTemplateFiller protoFiller{ctorFuncTemplate->PrototypeTemplate()}; + uint8_t* curPtr = nullptr; + auto instanceMethodData = node->SetInstanceMembers( isolate, ctorFuncTemplate, protoFiller, instanceMethodsCallbackData, - baseInstanceMethodsCallbackData, treeNode); + baseInstanceMethodsCallbackData, treeNode, curPtr); if (!skippedBaseTypes.empty()) { node->SetMissingBaseMethods(isolate, skippedBaseTypes, instanceMethodData, protoFiller); } @@ -1048,13 +992,13 @@ Local MetadataNode::GetConstructorFunctionTemplate(Isolate* is auto wrappedCtorFunc = Wrap(isolate, ctorFunc, node->m_treeNode->name, origin, true /* isCtorFunc */); - node->SetStaticMembers(isolate, wrappedCtorFunc, treeNode); + node->SetStaticMembers(isolate, wrappedCtorFunc, treeNode, curPtr); // insert isolate-specific persistent function handle node->m_poCtorCachePerIsolate.insert({isolate, new Persistent(isolate, wrappedCtorFunc)}); if (!baseCtorFunc.IsEmpty()) { - auto context = isolate->GetCurrentContext(); - wrappedCtorFunc->SetPrototype(context, baseCtorFunc); + auto currentContext = isolate->GetCurrentContext(); + wrappedCtorFunc->SetPrototype(currentContext, baseCtorFunc); } //cache "ctorFuncTemplate" @@ -1278,7 +1222,7 @@ void MetadataNode::MethodCallback(const v8::FunctionCallbackInfo& inf string* className; const auto& first = callbackData->candidates.front(); - const auto& methodName = first.name; + const auto& methodName = first->name; while ((callbackData != nullptr) && (entry == nullptr)) { auto& candidates = callbackData->candidates; @@ -1288,13 +1232,13 @@ void MetadataNode::MethodCallback(const v8::FunctionCallbackInfo& inf // Iterates through all methods and finds the best match based on the number of arguments auto found = false; for (auto& c : candidates) { - found = (!c.isExtensionFunction && c.paramCount == argLength) || ( - c.isExtensionFunction && c.paramCount == argLength + 1); + found = (!c->isExtensionFunction && c->getParamCount() == argLength) || ( + c->isExtensionFunction && c->getParamCount() == argLength + 1); if (found) { - if(c.isExtensionFunction){ - className = &c.declaringType; + if(c->isExtensionFunction){ + className = &c->getDeclaringType(); } - entry = &c; + entry = c; DEBUG_WRITE("MetaDataEntry Method %s's signature is: %s", entry->name.c_str(), entry->sig.c_str()); break; } @@ -1309,7 +1253,7 @@ void MetadataNode::MethodCallback(const v8::FunctionCallbackInfo& inf auto thiz = info.This(); auto isSuper = false; - if (!first.isStatic) { + if (!first->isStatic) { auto superValue = thiz->GetInternalField(static_cast(ObjectManager::MetadataNodeKeys::CallSuper)); isSuper = !superValue.IsEmpty() && superValue->IsTrue(); } @@ -1318,7 +1262,7 @@ void MetadataNode::MethodCallback(const v8::FunctionCallbackInfo& inf info.GetReturnValue().Set(thiz); } else { bool isFromInterface = initialCallbackData->node->IsNodeTypeInterface(); - CallbackHandlers::CallJavaMethod(thiz, *className, methodName, entry, isFromInterface, first.isStatic, isSuper, info); + CallbackHandlers::CallJavaMethod(thiz, *className, methodName, entry, isFromInterface, first->isStatic, isSuper, info); } } catch (NativeScriptException& e) { e.ReThrowToV8(); @@ -1446,9 +1390,9 @@ Local MetadataNode::GetImplementationObject(Isolate* isolate, const Loca //DEBUG_WRITE("GetImplementationObject not found since cycle parents reached abovePrototype:%d", (abovePrototype.IsEmpty() || abovePrototype.As().IsEmpty()) ? -1 : abovePrototype.As()->GetIdentityHash()); return Local(); } else { - Local hiddenVal; - V8GetPrivateValue(isolate, currentPrototype.As(), V8StringConstants::GetClassImplementationObject(isolate), hiddenVal); - auto value = hiddenVal; + Local _hiddenVal; + V8GetPrivateValue(isolate, currentPrototype.As(), V8StringConstants::GetClassImplementationObject(isolate), _hiddenVal); + auto value = _hiddenVal; if (!value.IsEmpty()) { implementationObject = currentPrototype.As(); @@ -1858,24 +1802,26 @@ MetadataNode* MetadataNode::GetNodeFromHandle(const Local& value) { return node; } -MetadataEntry MetadataNode::GetChildMetadataForPackage(MetadataNode* node, const string& propName) { - MetadataEntry child; - +MetadataEntry MetadataNode::GetChildMetadataForPackage(MetadataNode *node, std::string propName) { assert(node->m_treeNode->children != nullptr); - const auto& children = *node->m_treeNode->children; + MetadataEntry child(nullptr, NodeType::Class); - for (auto treeNodeChild : children) { + const auto &children = *node->m_treeNode->children; + + for (auto treeNodeChild: children) { if (propName == treeNodeChild->name) { child.name = propName; child.treeNode = treeNodeChild; + child.type = static_cast(s_metadataReader.GetNodeType(treeNodeChild)); - uint8_t childNodeType = s_metadataReader.GetNodeType(treeNodeChild); - if (s_metadataReader.IsNodeTypeInterface(childNodeType)) { + if (s_metadataReader.IsNodeTypeInterface((uint8_t) child.type)) { bool isPrefix; - string declaringType = s_metadataReader.ReadInterfaceImplementationTypeName(treeNodeChild, isPrefix); + string declaringType = s_metadataReader.ReadInterfaceImplementationTypeName( + treeNodeChild, isPrefix); child.declaringType = isPrefix - ? (declaringType + s_metadataReader.ReadTypeName(child.treeNode)) + ? (declaringType + + s_metadataReader.ReadTypeName(child.treeNode)) : declaringType; } } @@ -2158,15 +2104,15 @@ void MetadataNode::SetMissingBaseMethods( MethodCallbackData* callbackData = nullptr; for (auto i = 0; i < instanceMethodCount; i++) { - auto entry = s_metadataReader.ReadInstanceMethodEntry(&curPtr); + auto entry = MetadataReader::ReadInstanceMethodEntry(&curPtr); - auto isConstructor = entry.name == ""; + auto isConstructor = entry->getName() == ""; if (isConstructor) { continue; } for (auto data: instanceMethodData) { - if (data->candidates.front().name == entry.name) { + if (data->candidates.front()->getName() == entry->getName()) { callbackData = data; break; } @@ -2174,12 +2120,12 @@ void MetadataNode::SetMissingBaseMethods( if (callbackData == nullptr) { callbackData = new MethodCallbackData(this); - protoFiller.FillPrototypeMethod(isolate, entry.name, callbackData); + protoFiller.FillPrototypeMethod(isolate, entry->getName(), callbackData); } bool foundSameSig = false; for (auto m: callbackData->candidates) { - foundSameSig = m.sig == entry.sig; + foundSameSig = m->sig == entry->getSig(); if (foundSameSig) { break; } @@ -2291,6 +2237,10 @@ void MetadataNode::onDisposeIsolate(Isolate* isolate) { } } +MetadataReader* MetadataNode::getMetadataReader() { + return &MetadataNode::s_metadataReader; +} + string MetadataNode::TNS_PREFIX = "com/tns/gen/"; MetadataReader MetadataNode::s_metadataReader; robin_hood::unordered_map MetadataNode::s_name2NodeCache; diff --git a/test-app/runtime/src/main/cpp/MetadataNode.h b/test-app/runtime/src/main/cpp/MetadataNode.h index ea8a18ec7..c92d4f6a7 100644 --- a/test-app/runtime/src/main/cpp/MetadataNode.h +++ b/test-app/runtime/src/main/cpp/MetadataNode.h @@ -60,6 +60,8 @@ class MetadataNode { static std::string GetTypeMetadataName(v8::Isolate* isolate, v8::Local& value); static void onDisposeIsolate(v8::Isolate* isolate); + + static MetadataReader* getMetadataReader(); private: struct MethodCallbackData; @@ -81,23 +83,23 @@ class MetadataNode { v8::Local GetConstructorFunctionTemplate(v8::Isolate* isolate, MetadataTreeNode* treeNode); v8::Local GetConstructorFunctionTemplate(v8::Isolate* isolate, MetadataTreeNode* treeNode, std::vector& instanceMethodsCallbackData); v8::Persistent* GetPersistentConstructorFunction(v8::Isolate* isolate); - v8::Local GetOrCreateArrayObjectTemplate(v8::Isolate* isolate); + static v8::Local GetOrCreateArrayObjectTemplate(v8::Isolate* isolate); std::vector SetInstanceMembers( v8::Isolate* isolate, v8::Local& ctorFuncTemplate, PrototypeTemplateFiller& protoFiller, std::vector& instanceMethodsCallbackData, const std::vector& baseInstanceMethodsCallbackData, - MetadataTreeNode* treeNode); + MetadataTreeNode* treeNode, uint8_t* &curPtr); std::vector SetInstanceMethodsFromStaticMetadata( v8::Isolate* isolate, v8::Local& ctorFuncTemplate, PrototypeTemplateFiller& protoFiller, std::vector& instanceMethodsCallbackData, const std::vector& baseInstanceMethodsCallbackData, - MetadataTreeNode* treeNode); - MethodCallbackData* tryGetExtensionMethodCallbackData( - std::unordered_map collectedMethodCallbackDatas, - std::string lookupName); + MetadataTreeNode* treeNode, uint8_t* &curPtr); + static MethodCallbackData* tryGetExtensionMethodCallbackData( + const robin_hood::unordered_map &collectedMethodCallbackDatas, + const std::string &lookupName); void SetInstanceFieldsFromStaticMetadata( v8::Isolate* isolate, PrototypeTemplateFiller& protoFiller, MetadataTreeNode* treeNode); @@ -106,8 +108,10 @@ class MetadataNode { std::vector& instanceMethodsCallbackData, const std::vector& baseInstanceMethodsCallbackData, MetadataTreeNode* treeNode); - void SetStaticMembers(v8::Isolate* isolate, v8::Local& ctorFunction, MetadataTreeNode* treeNode); - void SetInnerTypes(v8::Isolate* isolate, v8::Local& ctorFunction, MetadataTreeNode* treeNode); + + void SetStaticMembers(v8::Isolate* isolate, v8::Local& ctorFunction, MetadataTreeNode* treeNode, uint8_t* &curPtr); + static void InnerTypeAccessorGetterCallback(v8::Local property, const v8::PropertyCallbackInfo& info); + static void SetInnerTypes(v8::Isolate* isolate, v8::Local& ctorFunction, MetadataTreeNode* treeNode); static void BuildMetadata(uint32_t nodesLength, uint8_t* nodeData, uint32_t nameLength, uint8_t* nameData, uint32_t valueLength, uint8_t* valueData); @@ -117,7 +121,7 @@ class MetadataNode { static MetadataTreeNode* GetOrCreateTreeNodeByName(const std::string& className); - static MetadataEntry GetChildMetadataForPackage(MetadataNode* node, const std::string& propName); + static MetadataEntry GetChildMetadataForPackage(MetadataNode *node, std::string propName); static MetadataNode* GetInstanceMetadata(v8::Isolate* isolate, const v8::Local& value); @@ -161,9 +165,9 @@ class MetadataNode { static void SymbolHasInstanceCallback(const v8::FunctionCallbackInfo& info); static std::string GetJniClassName(MetadataEntry entry); - v8::Local Wrap(v8::Isolate* isolate, const v8::Local& function, const std::string& name, const std::string& origin, bool isCtorFunc); + static v8::Local Wrap(v8::Isolate* isolate, const v8::Local& function, const std::string& name, const std::string& origin, bool isCtorFunc); - bool CheckClassHierarchy(JEnv& env, jclass currentClass, MetadataTreeNode* curentTreeNode, MetadataTreeNode* baseTreeNode, std::vector& skippedBaseTypes); + static bool CheckClassHierarchy(JEnv& env, jclass currentClass, MetadataTreeNode* curentTreeNode, MetadataTreeNode* baseTreeNode, std::vector& skippedBaseTypes); void SetMissingBaseMethods(v8::Isolate* isolate, const std::vector& skippedBaseTypes, const std::vector& instanceMethodData, @@ -195,7 +199,7 @@ class MetadataNode { node(_node), parent(nullptr), isSuper(false) { } - std::vector candidates; + std::vector candidates; MetadataNode* node; MethodCallbackData* parent; bool isSuper; diff --git a/test-app/runtime/src/main/cpp/MetadataReader.cpp b/test-app/runtime/src/main/cpp/MetadataReader.cpp index 5c37dfdcb..3ee9e202c 100644 --- a/test-app/runtime/src/main/cpp/MetadataReader.cpp +++ b/test-app/runtime/src/main/cpp/MetadataReader.cpp @@ -2,22 +2,27 @@ #include "MetadataMethodInfo.h" #include "Util.h" #include -#include using namespace std; using namespace tns; -MetadataReader::MetadataReader() - : - m_nodesLength(0), m_nodeData(nullptr), m_nameLength(0), m_nameData(nullptr), m_valueLength(0), m_valueData(nullptr), m_root(nullptr), m_getTypeMetadataCallback(nullptr) { -} - -MetadataReader::MetadataReader(uint32_t nodesLength, uint8_t* nodeData, uint32_t nameLength, uint8_t* nameData, uint32_t valueLength, uint8_t* valueData, GetTypeMetadataCallback getTypeMetadataCallback) - : - m_nodesLength(nodesLength), m_nodeData(nodeData), m_nameLength(nameLength), m_nameData(nameData), m_valueLength(valueLength), m_valueData(valueData), m_getTypeMetadataCallback(getTypeMetadataCallback) { +MetadataReader::MetadataReader() : m_root(nullptr), m_nodesLength(0), m_nameLength(0), + m_valueLength(0), + m_nodeData(nullptr), m_nameData(nullptr), m_valueData(nullptr), + m_getTypeMetadataCallback(nullptr) {} + +MetadataReader::MetadataReader(uint32_t nodesLength, uint8_t *nodeData, uint32_t nameLength, + uint8_t *nameData, uint32_t valueLength, uint8_t *valueData, + GetTypeMetadataCallback getTypeMetadataCallback) + : + m_nodesLength(nodesLength), m_nodeData(nodeData), m_nameLength(nameLength), + m_nameData(nameData), m_valueLength(valueLength), m_valueData(valueData), + m_getTypeMetadataCallback(getTypeMetadataCallback) { m_root = BuildTree(); } + + // helper debug function when need to convert a metadata node to its full name //std::string toFullName(MetadataTreeNode* p) { // std::string final = p->name; @@ -28,18 +33,18 @@ MetadataReader::MetadataReader(uint32_t nodesLength, uint8_t* nodeData, uint32_t //} MetadataTreeNode* MetadataReader::BuildTree() { - MetadataTreeNodeRawData* rootNodeData = reinterpret_cast(m_nodeData); + MetadataTreeNodeRawData *rootNodeData = reinterpret_cast(m_nodeData); - MetadataTreeNodeRawData* curNodeData = rootNodeData; + MetadataTreeNodeRawData *curNodeData = rootNodeData; int len = m_nodesLength / sizeof(MetadataTreeNodeRawData); m_v.resize(len + 1000); - MetadataTreeNode* emptyNode = nullptr; + MetadataTreeNode * emptyNode = nullptr; fill(m_v.begin(), m_v.end(), emptyNode); for (int i = 0; i < len; i++) { - MetadataTreeNode* node = GetNodeById(i); + MetadataTreeNode * node = GetNodeById(i); if (nullptr == node) { node = new MetadataTreeNode; node->name = ReadName(curNodeData->offsetName); @@ -50,33 +55,25 @@ MetadataTreeNode* MetadataReader::BuildTree() { uint16_t curNodeDataId = curNodeData - rootNodeData; if (curNodeDataId != curNodeData->firstChildId) { - node->children = new vector; - MetadataTreeNodeRawData* childNodeData = rootNodeData + curNodeData->firstChildId; + node->children = new vector; + MetadataTreeNodeRawData *childNodeData = rootNodeData + curNodeData->firstChildId; while (true) { uint16_t childNodeDataId = childNodeData - rootNodeData; - - MetadataTreeNode* childNode; // node (and its next siblings) already visited, so we don't need to visit it again if (m_v[childNodeDataId] != emptyNode) { - childNode = m_v[childNodeDataId]; - __android_log_print(ANDROID_LOG_ERROR, "TNS.error", "Consistency error in metadata. A child should never have been visited before its parent. Parent: %s Child: %s. Child metadata id: %u", node->name.c_str(), childNode->name.c_str(), childNodeDataId); break; - } else { - childNode = new MetadataTreeNode; - childNode->name = ReadName(childNodeData->offsetName); - childNode->offsetValue = childNodeData->offsetValue; } + + MetadataTreeNode * childNode = new MetadataTreeNode; childNode->parent = node; + childNode->name = ReadName(childNodeData->offsetName); + childNode->offsetValue = childNodeData->offsetValue; node->children->push_back(childNode); m_v[childNodeDataId] = childNode; - if (childNodeDataId == childNodeData->nextSiblingId) { - break; - } - childNodeData = rootNodeData + childNodeData->nextSiblingId; } } @@ -87,97 +84,13 @@ MetadataTreeNode* MetadataReader::BuildTree() { return GetNodeById(0); } -void MetadataReader::FillEntryWithFiedldInfo(FieldInfo* fi, MetadataEntry& entry) { - entry.isTypeMember = true; - entry.name = ReadName(fi->nameOffset); - entry.sig = ReadTypeName(fi->nodeId); - entry.isFinal = fi->finalModifier == MetadataTreeNode::FINAL; -} - -void MetadataReader::FillEntryWithMethodInfo(MethodInfo& mi, MetadataEntry& entry) { - entry.type = NodeType::Method; - entry.isTypeMember = true; - entry.name = mi.GetName(); - entry.isResolved = mi.CheckIsResolved() == 1; - uint16_t sigLength = mi.GetSignatureLength(); - assert(sigLength > 0); - entry.paramCount = sigLength - 1; - entry.sig = mi.GetSignature(); - FillReturnType(entry); -} - - -MetadataEntry MetadataReader::ReadInstanceFieldEntry(uint8_t** data) { - FieldInfo* fi = *reinterpret_cast(data); - - MetadataEntry entry; - FillEntryWithFiedldInfo(fi, entry); - entry.isStatic = false; - entry.type = NodeType::Field; - - *data += sizeof(FieldInfo); - - return entry; -} - -MetadataEntry MetadataReader::ReadStaticFieldEntry(uint8_t** data) { - StaticFieldInfo* sfi = *reinterpret_cast(data); - MetadataEntry entry; - FillEntryWithFiedldInfo(sfi, entry); - entry.isStatic = true; - entry.type = NodeType::StaticField; - entry.declaringType = ReadTypeName(sfi->declaringType); - - *data += sizeof(StaticFieldInfo); - - return entry; -} - -MetadataEntry MetadataReader::ReadInstanceMethodEntry(uint8_t** data) { - MetadataEntry entry; - MethodInfo mip(*data, this); //method info pointer+ - - FillEntryWithMethodInfo(mip, entry); - - *data += mip.GetSizeOfReadMethodInfo(); - - return entry; -} - -MetadataTreeNode* MetadataReader::GetNodeById(uint16_t nodeId) { +MetadataTreeNode *MetadataReader::GetNodeById(uint16_t nodeId) { return m_v[nodeId]; } -MetadataEntry MetadataReader::ReadStaticMethodEntry(uint8_t** data) { - MetadataEntry entry; - MethodInfo smip(*data, this); //static method info pointer - - FillEntryWithMethodInfo(smip, entry); - entry.isStatic = true; - entry.declaringType = smip.GetDeclaringType(); - - *data += smip.GetSizeOfReadMethodInfo(); - - return entry; -} - -MetadataEntry MetadataReader::ReadExtensionFunctionEntry(uint8_t** data) { - MetadataEntry entry; - MethodInfo smip(*data, this); //static method info pointer - - FillEntryWithMethodInfo(smip, entry); - entry.isStatic = true; - entry.declaringType = smip.GetDeclaringType(); - entry.isExtensionFunction = true; - - *data += smip.GetSizeOfReadMethodInfo(); - - return entry; -} - -string MetadataReader::ReadTypeName(MetadataTreeNode* treeNode) { +string MetadataReader::ReadTypeName(MetadataTreeNode *treeNode) { string name; auto itFound = m_typeNameCache.find(treeNode); @@ -193,7 +106,7 @@ string MetadataReader::ReadTypeName(MetadataTreeNode* treeNode) { return name; } -string MetadataReader::ReadTypeNameInternal(MetadataTreeNode* treeNode) { +string MetadataReader::ReadTypeNameInternal(MetadataTreeNode *treeNode) { string name; uint8_t prevNodeType; @@ -205,7 +118,7 @@ string MetadataReader::ReadTypeNameInternal(MetadataTreeNode* treeNode) { if (isArrayElement) { uint16_t forwardNodeId = treeNode->offsetValue - ARRAY_OFFSET; - MetadataTreeNode* forwardNode = GetNodeById(forwardNodeId); + MetadataTreeNode * forwardNode = GetNodeById(forwardNodeId); name = ReadTypeName(forwardNode); uint8_t forwardNodeType = GetNodeType(forwardNode); if (IsNodeTypeInterface(forwardNodeType) || IsNodeTypeClass(forwardNodeType)) { @@ -215,7 +128,7 @@ string MetadataReader::ReadTypeNameInternal(MetadataTreeNode* treeNode) { if (!name.empty()) { if (!IsNodeTypeArray(curNodeType)) { if ((IsNodeTypeClass(prevNodeType) || IsNodeTypeInterface(prevNodeType)) - && (IsNodeTypeClass(curNodeType) || IsNodeTypeInterface(curNodeType))) { + && (IsNodeTypeClass(curNodeType) || IsNodeTypeInterface(curNodeType))) { name = "$" + name; } else { name = "/" + name; @@ -234,11 +147,11 @@ string MetadataReader::ReadTypeNameInternal(MetadataTreeNode* treeNode) { return name; } -uint8_t* MetadataReader::GetValueData() const { +uint8_t *MetadataReader::GetValueData() const { return m_valueData; } -uint16_t MetadataReader::GetNodeId(MetadataTreeNode* treeNode) { +uint16_t MetadataReader::GetNodeId(MetadataTreeNode *treeNode) { auto itFound = find(m_v.begin(), m_v.end(), treeNode); assert(itFound != m_v.end()); uint16_t nodeId = itFound - m_v.begin(); @@ -246,11 +159,11 @@ uint16_t MetadataReader::GetNodeId(MetadataTreeNode* treeNode) { return nodeId; } -MetadataTreeNode* MetadataReader::GetRoot() const { +MetadataTreeNode *MetadataReader::GetRoot() const { return m_root; } -uint8_t MetadataReader::GetNodeType(MetadataTreeNode* treeNode) { +uint8_t MetadataReader::GetNodeType(MetadataTreeNode *treeNode) { if (treeNode->type == MetadataTreeNode::INVALID_TYPE) { uint8_t nodeType; @@ -264,7 +177,7 @@ uint8_t MetadataReader::GetNodeType(MetadataTreeNode* treeNode) { nodeType = MetadataTreeNode::ARRAY; } else { uint16_t nodeId = offsetValue - ARRAY_OFFSET; - MetadataTreeNode* arrElemNode = GetNodeById(nodeId); + MetadataTreeNode * arrElemNode = GetNodeById(nodeId); nodeType = *(m_valueData + arrElemNode->offsetValue); } @@ -274,19 +187,19 @@ uint8_t MetadataReader::GetNodeType(MetadataTreeNode* treeNode) { return treeNode->type; } -MetadataTreeNode* MetadataReader::GetOrCreateTreeNodeByName(const string& className) { - MetadataTreeNode* treeNode = GetRoot(); +MetadataTreeNode *MetadataReader::GetOrCreateTreeNodeByName(const string &className) { + MetadataTreeNode * treeNode = GetRoot(); int arrayIdx = -1; string arrayName = "["; while (className[++arrayIdx] == '[') { - MetadataTreeNode* child = treeNode->GetChild(arrayName); + MetadataTreeNode * child = treeNode->GetChild(arrayName); if (child == nullptr) { - vector* children = treeNode->children; + vector *children = treeNode->children; if (children == nullptr) { - children = treeNode->children = new vector; + children = treeNode->children = new vector; } child = new MetadataTreeNode; @@ -310,19 +223,19 @@ MetadataTreeNode* MetadataReader::GetOrCreateTreeNodeByName(const string& classN } } - vector < string > names; + vector names; Util::SplitString(cn, "/$", names); if (arrayIdx > 0) { bool found = false; - MetadataTreeNode* forwardedNode = GetOrCreateTreeNodeByName(cn); + MetadataTreeNode * forwardedNode = GetOrCreateTreeNodeByName(cn); uint16_t forwardedNodeId = GetNodeId(forwardedNode); if (treeNode->children == nullptr) { - treeNode->children = new vector(); + treeNode->children = new vector(); } - vector& children = *treeNode->children; - for (auto childNode : children) { + vector &children = *treeNode->children; + for (auto childNode: children) { uint32_t childNodeId = (childNode->offsetValue >= ARRAY_OFFSET) ? (childNode->offsetValue - ARRAY_OFFSET) : @@ -336,7 +249,7 @@ MetadataTreeNode* MetadataReader::GetOrCreateTreeNodeByName(const string& classN } if (!found) { - MetadataTreeNode* forwardNode = new MetadataTreeNode; + MetadataTreeNode * forwardNode = new MetadataTreeNode; forwardNode->offsetValue = forwardedNodeId + ARRAY_OFFSET; forwardNode->parent = treeNode; @@ -351,15 +264,15 @@ MetadataTreeNode* MetadataReader::GetOrCreateTreeNodeByName(const string& classN int curIdx = 0; for (auto it = names.begin(); it != names.end(); ++it) { - MetadataTreeNode* child = treeNode->GetChild(*it); + MetadataTreeNode * child = treeNode->GetChild(*it); if (child == nullptr) { - vector < string > api = m_getTypeMetadataCallback(cn, curIdx); + vector api = m_getTypeMetadataCallback(cn, curIdx); - for (const auto& part : api) { - vector* children = treeNode->children; + for (const auto &part: api) { + vector *children = treeNode->children; if (children == nullptr) { - children = treeNode->children = new vector; + children = treeNode->children = new vector; } child = new MetadataTreeNode; @@ -381,7 +294,8 @@ MetadataTreeNode* MetadataReader::GetOrCreateTreeNodeByName(const string& classN if ((cKind == 'C') || (cKind == 'I')) { child->metadata = new string(part); - child->type = (cKind == 'C') ? MetadataTreeNode::CLASS : MetadataTreeNode::INTERFACE; + child->type = (cKind == 'C') ? MetadataTreeNode::CLASS + : MetadataTreeNode::INTERFACE; if (name == "S") { child->type |= MetadataTreeNode::STATIC; } @@ -397,7 +311,7 @@ MetadataTreeNode* MetadataReader::GetOrCreateTreeNodeByName(const string& classN child->offsetValue = m_valueLength; m_valueData[m_valueLength++] = child->type; - *reinterpret_cast(m_valueData + m_valueLength) = baseClassNodeId; + *reinterpret_cast(m_valueData + m_valueLength) = baseClassNodeId; m_valueLength += sizeof(uint16_t); } else { child->type = MetadataTreeNode::PACKAGE; @@ -419,11 +333,12 @@ MetadataTreeNode* MetadataReader::GetOrCreateTreeNodeByName(const string& classN return treeNode; } -MetadataTreeNode* MetadataReader::GetBaseClassNode(MetadataTreeNode* treeNode) { - MetadataTreeNode* baseClassNode = nullptr; +MetadataTreeNode *MetadataReader::GetBaseClassNode(MetadataTreeNode *treeNode) { + MetadataTreeNode * baseClassNode = nullptr; if (treeNode != nullptr) { - uint16_t baseClassNodeId = *reinterpret_cast(m_valueData + treeNode->offsetValue + 1); + uint16_t baseClassNodeId = *reinterpret_cast(m_valueData + + treeNode->offsetValue + 1); size_t nodeCount = m_v.size(); diff --git a/test-app/runtime/src/main/cpp/MetadataReader.h b/test-app/runtime/src/main/cpp/MetadataReader.h index 1f3706994..b15288ac8 100644 --- a/test-app/runtime/src/main/cpp/MetadataReader.h +++ b/test-app/runtime/src/main/cpp/MetadataReader.h @@ -7,74 +7,127 @@ #include #include #include "robin_hood.h" -namespace tns { -typedef std::vector (*GetTypeMetadataCallback)(const std::string& classname, int index); -class MethodInfo; +namespace tns { + typedef std::vector (*GetTypeMetadataCallback)(const std::string &classname, + int index); -class MetadataReader { + class MetadataReader { public: MetadataReader(); - MetadataReader(uint32_t nodesLength, uint8_t* nodeData, uint32_t nameLength, uint8_t* nameData, uint32_t valueLength, uint8_t* valueData, GetTypeMetadataCallback getTypeMetadataCallack); + MetadataReader(uint32_t nodesLength, uint8_t *nodeData, uint32_t nameLength, + uint8_t *nameData, uint32_t valueLength, uint8_t *valueData, + GetTypeMetadataCallback getTypeMetadataCallack); + + inline static MetadataEntry* ReadInstanceFieldEntry(uint8_t **data) { + auto entry = new MetadataEntry(nullptr, NodeType::Field); + entry->fi = *reinterpret_cast(data); + entry->isTypeMember = true; + + *data += sizeof(FieldInfo); + + return entry; + } + + inline static MetadataEntry* ReadStaticFieldEntry(uint8_t **data) { + auto entry = new MetadataEntry(nullptr, NodeType::StaticField); + entry->sfi = *reinterpret_cast(data); + entry->isStatic = true; + entry->isTypeMember = false; + + *data += sizeof(StaticFieldInfo); + + return entry; + } + + inline static MetadataEntry* ReadInstanceMethodEntry(uint8_t **data) { + auto entry = new MetadataEntry(nullptr, NodeType::Method); + entry->isTypeMember = true; + + entry->mi = new MethodInfo(*data); //method info pointer+ + *data += entry->mi->GetSizeOfReadMethodInfo(); - MetadataEntry ReadInstanceMethodEntry(uint8_t** data); + return entry; + } + + + inline static MetadataEntry* ReadStaticMethodEntry(uint8_t **data) { + auto entry = new MetadataEntry(nullptr, NodeType::Method); + entry->isTypeMember = true; + entry->mi = new MethodInfo(*data); + entry->mi->isStatic = true; + entry->isStatic = true; + + *data += entry->mi->GetSizeOfReadMethodInfo(); + + return entry; + } - MetadataEntry ReadStaticMethodEntry(uint8_t** data); + inline static MetadataEntry* ReadExtensionFunctionEntry(uint8_t **data) { + auto entry = new MetadataEntry(nullptr, NodeType::Method); - MetadataEntry ReadExtensionFunctionEntry(uint8_t** data); + entry->mi = new MethodInfo(*data); //static method info pointer - MetadataEntry ReadInstanceFieldEntry(uint8_t** data); + entry->mi->isStatic = true; + entry->isExtensionFunction = true; + entry->isStatic = true; - MetadataEntry ReadStaticFieldEntry(uint8_t** data); + *data += entry->mi->GetSizeOfReadMethodInfo(); - inline std::string ReadTypeName(uint16_t nodeId){ - MetadataTreeNode* treeNode = GetNodeById(nodeId); + return entry; + } + + inline std::string ReadTypeName(uint16_t nodeId) { + MetadataTreeNode *treeNode = GetNodeById(nodeId); - return ReadTypeName(treeNode); - } + return ReadTypeName(treeNode); + } - std::string ReadTypeName(MetadataTreeNode* treeNode); + std::string ReadTypeName(MetadataTreeNode *treeNode); - inline std::string ReadName(uint32_t offset) { - uint16_t length = *reinterpret_cast(m_nameData + offset); + inline std::string ReadName(uint32_t offset) { + uint16_t length = *reinterpret_cast(m_nameData + offset); - std::string name(reinterpret_cast(m_nameData + offset + sizeof(uint16_t)), length); + std::string name(reinterpret_cast(m_nameData + offset + sizeof(uint16_t)), + length); - return name; - } + return name; + } - inline std::string ReadInterfaceImplementationTypeName(MetadataTreeNode* treeNode, bool& isPrefix) { - uint8_t* data = m_valueData + treeNode->offsetValue + sizeof(uint8_t) + sizeof(uint16_t); + inline std::string + ReadInterfaceImplementationTypeName(MetadataTreeNode *treeNode, bool &isPrefix) { + uint8_t *data = + m_valueData + treeNode->offsetValue + sizeof(uint8_t) + sizeof(uint16_t); - isPrefix = *data == 1; + isPrefix = *data == 1; - uint32_t pos = *reinterpret_cast(data + sizeof(uint8_t)); + uint32_t pos = *reinterpret_cast(data + sizeof(uint8_t)); - uint16_t len = *reinterpret_cast(m_nameData + pos); + uint16_t len = *reinterpret_cast(m_nameData + pos); - char* ptr = reinterpret_cast(m_nameData + pos + sizeof(uint16_t)); + char *ptr = reinterpret_cast(m_nameData + pos + sizeof(uint16_t)); - std::string name(ptr, len); + std::string name(ptr, len); - assert(name.length() == len); + assert(name.length() == len); - return name; - } + return name; + } - uint8_t* GetValueData() const; + uint8_t *GetValueData() const; - uint8_t GetNodeType(MetadataTreeNode* treeNode); + uint8_t GetNodeType(MetadataTreeNode *treeNode); - uint16_t GetNodeId(MetadataTreeNode* treeNode); + uint16_t GetNodeId(MetadataTreeNode *treeNode); - MetadataTreeNode* GetRoot() const; + MetadataTreeNode *GetRoot() const; - MetadataTreeNode* GetOrCreateTreeNodeByName(const std::string& className); + MetadataTreeNode *GetOrCreateTreeNodeByName(const std::string &className); - MetadataTreeNode* GetBaseClassNode(MetadataTreeNode* treeNode); + MetadataTreeNode *GetBaseClassNode(MetadataTreeNode *treeNode); - MetadataTreeNode* GetNodeById(uint16_t nodeId); + MetadataTreeNode *GetNodeById(uint16_t nodeId); inline bool IsNodeTypeArray(uint8_t type) { bool isArray = (((type & MetadataTreeNode::PRIMITIVE) == 0) @@ -98,7 +151,8 @@ class MetadataReader { inline bool IsNodeTypeInterface(uint8_t type) { bool isInterface = (((type & MetadataTreeNode::PRIMITIVE) == 0) - && ((type & MetadataTreeNode::INTERFACE) == MetadataTreeNode::INTERFACE)); + && ((type & MetadataTreeNode::INTERFACE) == + MetadataTreeNode::INTERFACE)); return isInterface; } @@ -109,18 +163,18 @@ class MetadataReader { return isPackage; } - inline static void FillReturnType(MetadataEntry& entry) { - entry.returnType = ParseReturnType(entry.sig); - entry.retType = GetReturnType(entry.returnType); - } +// inline static void FillReturnType(MetadataEntry* entry) { +// entry->returnType = ParseReturnType(entry->getSig()); +// entry->retType = GetReturnType(entry->getReturnType()); +// } - inline static std::string ParseReturnType(const std::string& signature) { + inline static std::string ParseReturnType(const std::string &signature) { int idx = signature.find(')'); auto returnType = signature.substr(idx + 1); return returnType; } - inline static MethodReturnType GetReturnType(const std::string& returnType) { + inline static MethodReturnType GetReturnType(const std::string &returnType) { MethodReturnType retType; char retTypePrefix = returnType[0]; switch (retTypePrefix) { @@ -169,26 +223,26 @@ class MetadataReader { static const uint32_t ARRAY_OFFSET = 1000000000; - MetadataTreeNode* BuildTree(); + MetadataTreeNode *BuildTree(); - std::string ReadTypeNameInternal(MetadataTreeNode* treeNode); + std::string ReadTypeNameInternal(MetadataTreeNode *treeNode); - void FillEntryWithFiedldInfo(FieldInfo* fi, MetadataEntry& entry); + void FillEntryWithFiedldInfo(FieldInfo *fi, MetadataEntry &entry); - void FillEntryWithMethodInfo(MethodInfo& mi, MetadataEntry& entry); + void FillEntryWithMethodInfo(MethodInfo &mi, MetadataEntry &entry); - MetadataTreeNode* m_root; + MetadataTreeNode *m_root; uint32_t m_nodesLength; uint32_t m_nameLength; uint32_t m_valueLength; - uint8_t* m_nodeData; - uint8_t* m_nameData; - uint8_t* m_valueData; - std::vector m_v; + uint8_t *m_nodeData; + uint8_t *m_nameData; + uint8_t *m_valueData; + std::vector m_v; GetTypeMetadataCallback m_getTypeMetadataCallback; - robin_hood::unordered_map m_typeNameCache; -}; + robin_hood::unordered_map m_typeNameCache; + }; } #endif /* METADATAREADER_H_ */