From 0f49e24d8ca722d4cf5bc9a28123cd98a20ce2d6 Mon Sep 17 00:00:00 2001 From: Teodor Dermendzhiev Date: Wed, 13 Sep 2017 13:41:46 +0300 Subject: [PATCH 1/2] Unique function and method signature instances in metadata. --- .gitignore | 2 + src/Binary/binarySerializer.cpp | 133 +++++++++++++++++++++++++++++++- src/Binary/binarySerializer.h | 32 +++++++- 3 files changed, 164 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 361d91e..558c6dc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ + +cmake-build/ # Mac .DS_Store #ignore thumbnails created by windows diff --git a/src/Binary/binarySerializer.cpp b/src/Binary/binarySerializer.cpp index dfad58b..eacd7b5 100644 --- a/src/Binary/binarySerializer.cpp +++ b/src/Binary/binarySerializer.cpp @@ -139,10 +139,138 @@ void binary::BinarySerializer::serializeMethod(::Meta::MethodMeta* meta, binary: if (meta->getFlags(::Meta::MetaFlags::MethodIsInitializer)) binaryMetaStruct._flags |= BinaryFlags::MethodIsInitializer; - binaryMetaStruct._encoding = this->typeEncodingSerializer.visit(meta->signature); + binaryMetaStruct._encoding = this->checkForExistingSignature(meta->signature); binaryMetaStruct._constructorTokens = this->heapWriter.push_string(meta->constructorTokens); } +binary::MetaFileOffset binary::BinarySerializer::checkForExistingSignature(std::vector<::Meta::Type*> signature) { + + for (size_t i = 0; i < this->cachedSignatures.size(); i++) { + if (this->cachedSignatures[i].types.size() != signature.size()) { + continue; + } else { + for (size_t x = 0; x < this->cachedSignatures[i].types.size(); x++) { + + + if ((this->cachedSignatures[i].types[x] == FFIVoid && signature[x]->getType() == ::Meta::TypeVoid) || + (this->cachedSignatures[i].types[x] == FFISint8 && signature[x]->getType() == ::Meta::TypeBool) || + (this->cachedSignatures[i].types[x] == FFISint16 && signature[x]->getType() == ::Meta::TypeShort) || + (this->cachedSignatures[i].types[x] == FFISint32 && (signature[x]->getType() == ::Meta::TypeInt || signature[x]->getType() == ::Meta::TypeLong)) || + (this->cachedSignatures[i].types[x] == FFISint64 && signature[x]->getType() == ::Meta::TypeLongLong) || + (this->cachedSignatures[i].types[x] == FFIUint16 && signature[x]->getType() == ::Meta::TypeUShort) || + (this->cachedSignatures[i].types[x] == FFIUint32 && (signature[x]->getType() == ::Meta::TypeUInt || signature[x]->getType() == ::Meta::TypeULong)) || + (this->cachedSignatures[i].types[x] == FFIFloat && signature[x]->getType() == ::Meta::TypeFloat) || + (this->cachedSignatures[i].types[x] == FFIDouble && signature[x]->getType() == ::Meta::TypeDouble) || + (this->cachedSignatures[i].types[x] == FFIStruct && signature[x]->getType() == ::Meta::TypeStruct) || + (this->cachedSignatures[i].types[x] == FFIPointer && (signature[x]->getType() == ::Meta::TypePointer || + signature[x]->getType() == ::Meta::TypeEnum || + signature[x]->getType() == ::Meta::TypeClass || + signature[x]->getType() == ::Meta::TypeId || + signature[x]->getType() == ::Meta::TypeBlock || + signature[x]->getType() == ::Meta::TypeUnion || + signature[x]->getType() == ::Meta::TypeStruct || + signature[x]->getType() == ::Meta::TypeSelector || + signature[x]->getType() == ::Meta::TypeProtocol || + signature[x]->getType() == ::Meta::TypeInterface || + signature[x]->getType() == ::Meta::TypeInstancetype || + signature[x]->getType() == ::Meta::TypeVaList || + signature[x]->getType() == ::Meta::TypeTypeArgument || + signature[x]->getType() == ::Meta::TypeConstantArray || + signature[x]->getType() == ::Meta::TypeFunctionPointer || + signature[x]->getType() == ::Meta::TypeBridgedInterface || + signature[x]->getType() == ::Meta::TypeCString))) { + if (x == cachedSignatures[i].types.size()-1) { + return cachedSignatures[i].offset; + } + } else { + break; + } + + } + } + } + + binary::MetaFileOffset newOffset = this->typeEncodingSerializer.visit(signature); + CachedSignature newSignature; + newSignature.offset = newOffset; + + for (size_t i = 0; i < signature.size(); i++) { + + switch (signature[i]->getType()) { + case ::Meta::TypeVoid: + newSignature.types.push_back(FFIVoid); + break; + + case ::Meta::TypeInt: + newSignature.types.push_back(FFISint32); + break; + + case ::Meta::TypeUInt: + newSignature.types.push_back(FFIUint32); + break; + + case ::Meta::TypeLong: + newSignature.types.push_back(FFISint32); + break; + + case ::Meta::TypeULong: + newSignature.types.push_back(FFIUint32); + break; + + case ::Meta::TypeLongLong: + newSignature.types.push_back(FFISint64); + break; + + case ::Meta::TypeULongLong: + newSignature.types.push_back(FFIUint64); + break; + + case ::Meta::TypeBool: + newSignature.types.push_back(FFISint8); + break; + + case ::Meta::TypeFloat: + newSignature.types.push_back(FFIFloat); + break; + + case ::Meta::TypeDouble: + newSignature.types.push_back(FFIDouble); + break; + + case ::Meta::TypeShort: + newSignature.types.push_back(FFISint16); + break; + + case ::Meta::TypeUShort: + newSignature.types.push_back(FFIUint16); + break; + + case ::Meta::TypeUnichar: + newSignature.types.push_back(FFIUshort); + break; + + case ::Meta::TypeSignedChar: + newSignature.types.push_back(FFIUshort); + break; + + case ::Meta::TypeUnsignedChar: + newSignature.types.push_back(FFIUshort); + break; + + case ::Meta::TypeStruct: + newSignature.types.push_back(FFIStruct); + break; + + default: + newSignature.types.push_back(FFIPointer); + break; + } + } + cachedSignatures.push_back(newSignature); + + return newOffset; +} + void binary::BinarySerializer::serializeProperty(::Meta::PropertyMeta* meta, binary::PropertyMeta& binaryMetaStruct) { @@ -318,7 +446,8 @@ void binary::BinarySerializer::visit(::Meta::FunctionMeta* meta) if (meta->getFlags(::Meta::MetaFlags::FunctionReturnsUnmanaged)) binaryStruct._flags |= BinaryFlags::FunctionReturnsUnmanaged; - binaryStruct._encoding = this->typeEncodingSerializer.visit(meta->signature); + binaryStruct._encoding = this->checkForExistingSignature(meta->signature); + this->file->registerInGlobalTable(meta->jsName, binaryStruct.save(this->heapWriter)); } diff --git a/src/Binary/binarySerializer.h b/src/Binary/binarySerializer.h index c4de320..5b71fee 100644 --- a/src/Binary/binarySerializer.h +++ b/src/Binary/binarySerializer.h @@ -6,6 +6,32 @@ #include namespace binary { + +enum FFIType : uint8_t { + FFIVoid, + FFIPointer, + FFISint8, + FFIUint8, + FFIUint16, + FFISint16, + FFIUint32, + FFISint32, + FFIUint64, + FFISint64, + FFIUshort, + FFIDouble, + FFIStruct, + FFIFloat +}; + +struct CachedSignature { + + MetaFileOffset offset; + std::vector types; + +}; + + /* * \class BinarySerializer * \brief Applies the Visitor pattern for serializing \c Meta::Meta objects in binary format. @@ -15,6 +41,10 @@ class BinarySerializer : public ::Meta::MetaVisitor { MetaFile* file; BinaryWriter heapWriter; BinaryTypeEncodingSerializer typeEncodingSerializer; + + std::vector cachedSignatures; + + binary::MetaFileOffset checkForExistingSignature(std::vector<::Meta::Type*> signature); void serializeBase(::Meta::Meta* Meta, binary::Meta& binaryMetaStruct); @@ -66,4 +96,4 @@ class BinarySerializer : public ::Meta::MetaVisitor { virtual void visit(::Meta::MethodMeta* Meta) override; }; -} \ No newline at end of file +} From c7962774d946273b3285d2ad9c3b38d6b4d05239 Mon Sep 17 00:00:00 2001 From: Teodor Dermendzhiev Date: Wed, 27 Sep 2017 10:54:21 +0300 Subject: [PATCH 2/2] Create hash function for FFITypes map --- src/Binary/binarySerializer.cpp | 136 +++----------------------------- src/Binary/binarySerializer.h | 56 ++++++++----- src/Meta/MetaEntities.cpp | 24 +++++- src/Meta/MetaEntities.h | 6 +- src/Meta/MetaFactory.cpp | 2 +- src/Meta/TypeEntities.h | 60 ++++++++++++++ 6 files changed, 137 insertions(+), 147 deletions(-) diff --git a/src/Binary/binarySerializer.cpp b/src/Binary/binarySerializer.cpp index eacd7b5..32e1d24 100644 --- a/src/Binary/binarySerializer.cpp +++ b/src/Binary/binarySerializer.cpp @@ -139,136 +139,24 @@ void binary::BinarySerializer::serializeMethod(::Meta::MethodMeta* meta, binary: if (meta->getFlags(::Meta::MetaFlags::MethodIsInitializer)) binaryMetaStruct._flags |= BinaryFlags::MethodIsInitializer; - binaryMetaStruct._encoding = this->checkForExistingSignature(meta->signature); + binaryMetaStruct._encoding = this->getOffset(meta->signature, meta->getFFISignature()); binaryMetaStruct._constructorTokens = this->heapWriter.push_string(meta->constructorTokens); } -binary::MetaFileOffset binary::BinarySerializer::checkForExistingSignature(std::vector<::Meta::Type*> signature) { - - for (size_t i = 0; i < this->cachedSignatures.size(); i++) { - if (this->cachedSignatures[i].types.size() != signature.size()) { - continue; - } else { - for (size_t x = 0; x < this->cachedSignatures[i].types.size(); x++) { - - - if ((this->cachedSignatures[i].types[x] == FFIVoid && signature[x]->getType() == ::Meta::TypeVoid) || - (this->cachedSignatures[i].types[x] == FFISint8 && signature[x]->getType() == ::Meta::TypeBool) || - (this->cachedSignatures[i].types[x] == FFISint16 && signature[x]->getType() == ::Meta::TypeShort) || - (this->cachedSignatures[i].types[x] == FFISint32 && (signature[x]->getType() == ::Meta::TypeInt || signature[x]->getType() == ::Meta::TypeLong)) || - (this->cachedSignatures[i].types[x] == FFISint64 && signature[x]->getType() == ::Meta::TypeLongLong) || - (this->cachedSignatures[i].types[x] == FFIUint16 && signature[x]->getType() == ::Meta::TypeUShort) || - (this->cachedSignatures[i].types[x] == FFIUint32 && (signature[x]->getType() == ::Meta::TypeUInt || signature[x]->getType() == ::Meta::TypeULong)) || - (this->cachedSignatures[i].types[x] == FFIFloat && signature[x]->getType() == ::Meta::TypeFloat) || - (this->cachedSignatures[i].types[x] == FFIDouble && signature[x]->getType() == ::Meta::TypeDouble) || - (this->cachedSignatures[i].types[x] == FFIStruct && signature[x]->getType() == ::Meta::TypeStruct) || - (this->cachedSignatures[i].types[x] == FFIPointer && (signature[x]->getType() == ::Meta::TypePointer || - signature[x]->getType() == ::Meta::TypeEnum || - signature[x]->getType() == ::Meta::TypeClass || - signature[x]->getType() == ::Meta::TypeId || - signature[x]->getType() == ::Meta::TypeBlock || - signature[x]->getType() == ::Meta::TypeUnion || - signature[x]->getType() == ::Meta::TypeStruct || - signature[x]->getType() == ::Meta::TypeSelector || - signature[x]->getType() == ::Meta::TypeProtocol || - signature[x]->getType() == ::Meta::TypeInterface || - signature[x]->getType() == ::Meta::TypeInstancetype || - signature[x]->getType() == ::Meta::TypeVaList || - signature[x]->getType() == ::Meta::TypeTypeArgument || - signature[x]->getType() == ::Meta::TypeConstantArray || - signature[x]->getType() == ::Meta::TypeFunctionPointer || - signature[x]->getType() == ::Meta::TypeBridgedInterface || - signature[x]->getType() == ::Meta::TypeCString))) { - if (x == cachedSignatures[i].types.size()-1) { - return cachedSignatures[i].offset; - } - } else { - break; - } - - } - } - } +binary::MetaFileOffset binary::BinarySerializer::getOffset(std::vector<::Meta::Type*> signature, std::vector<::Meta::FFIType> ffiSignature) { - binary::MetaFileOffset newOffset = this->typeEncodingSerializer.visit(signature); - CachedSignature newSignature; - newSignature.offset = newOffset; + static int invocations = 0; + std::unordered_map, MetaFileOffset, SignatureHash, SignatureEq>::const_iterator it = signatureCache.find(ffiSignature); - for (size_t i = 0; i < signature.size(); i++) { - - switch (signature[i]->getType()) { - case ::Meta::TypeVoid: - newSignature.types.push_back(FFIVoid); - break; - - case ::Meta::TypeInt: - newSignature.types.push_back(FFISint32); - break; - - case ::Meta::TypeUInt: - newSignature.types.push_back(FFIUint32); - break; - - case ::Meta::TypeLong: - newSignature.types.push_back(FFISint32); - break; - - case ::Meta::TypeULong: - newSignature.types.push_back(FFIUint32); - break; - - case ::Meta::TypeLongLong: - newSignature.types.push_back(FFISint64); - break; - - case ::Meta::TypeULongLong: - newSignature.types.push_back(FFIUint64); - break; - - case ::Meta::TypeBool: - newSignature.types.push_back(FFISint8); - break; - - case ::Meta::TypeFloat: - newSignature.types.push_back(FFIFloat); - break; - - case ::Meta::TypeDouble: - newSignature.types.push_back(FFIDouble); - break; - - case ::Meta::TypeShort: - newSignature.types.push_back(FFISint16); - break; - - case ::Meta::TypeUShort: - newSignature.types.push_back(FFIUint16); - break; - - case ::Meta::TypeUnichar: - newSignature.types.push_back(FFIUshort); - break; - - case ::Meta::TypeSignedChar: - newSignature.types.push_back(FFIUshort); - break; - - case ::Meta::TypeUnsignedChar: - newSignature.types.push_back(FFIUshort); - break; - - case ::Meta::TypeStruct: - newSignature.types.push_back(FFIStruct); - break; - - default: - newSignature.types.push_back(FFIPointer); - break; - } + if (it == signatureCache.end()) { + invocations += 1; + signatureCache[ffiSignature] = this->typeEncodingSerializer.visit(signature); } - cachedSignatures.push_back(newSignature); + + printf("%d\n", invocations); + + return signatureCache[ffiSignature]; - return newOffset; } void binary::BinarySerializer::serializeProperty(::Meta::PropertyMeta* meta, binary::PropertyMeta& binaryMetaStruct) @@ -446,7 +334,7 @@ void binary::BinarySerializer::visit(::Meta::FunctionMeta* meta) if (meta->getFlags(::Meta::MetaFlags::FunctionReturnsUnmanaged)) binaryStruct._flags |= BinaryFlags::FunctionReturnsUnmanaged; - binaryStruct._encoding = this->checkForExistingSignature(meta->signature); + binaryStruct._encoding = this->getOffset(meta->signature, meta->getFFISignature());; this->file->registerInGlobalTable(meta->jsName, binaryStruct.save(this->heapWriter)); } diff --git a/src/Binary/binarySerializer.h b/src/Binary/binarySerializer.h index 5b71fee..7d5aeb9 100644 --- a/src/Binary/binarySerializer.h +++ b/src/Binary/binarySerializer.h @@ -7,27 +7,42 @@ namespace binary { -enum FFIType : uint8_t { - FFIVoid, - FFIPointer, - FFISint8, - FFIUint8, - FFIUint16, - FFISint16, - FFIUint32, - FFISint32, - FFIUint64, - FFISint64, - FFIUshort, - FFIDouble, - FFIStruct, - FFIFloat -}; - struct CachedSignature { MetaFileOffset offset; - std::vector types; + std::vector<::Meta::FFIType> types; + +}; + +struct SignatureHash { + + std::size_t operator()(std::vector<::Meta::FFIType> signature) const { + std::size_t seed = 0; + for(size_t i = 0; i < signature.size(); i++) { + seed <<= 4; + seed |= signature[i]; + } + return seed; + } + +}; + +struct SignatureEq { + + bool operator() (const std::vector<::Meta::FFIType>& l, const std::vector<::Meta::FFIType>& r) const { + if (l.size() != r.size()) { + return false; + } else { + for (size_t i = 0; i < l.size(); i++) { + + if (l[i] != r[i]) { + return false; + } + + } + } + return true; + } }; @@ -43,8 +58,9 @@ class BinarySerializer : public ::Meta::MetaVisitor { BinaryTypeEncodingSerializer typeEncodingSerializer; std::vector cachedSignatures; - - binary::MetaFileOffset checkForExistingSignature(std::vector<::Meta::Type*> signature); + std::unordered_map, MetaFileOffset, SignatureHash, SignatureEq>signatureCache; + + binary::MetaFileOffset getOffset(std::vector<::Meta::Type*> signature, std::vector<::Meta::FFIType> ffiSignature); void serializeBase(::Meta::Meta* Meta, binary::Meta& binaryMetaStruct); diff --git a/src/Meta/MetaEntities.cpp b/src/Meta/MetaEntities.cpp index 70b0804..ed600cb 100644 --- a/src/Meta/MetaEntities.cpp +++ b/src/Meta/MetaEntities.cpp @@ -24,6 +24,17 @@ void Meta::MethodMeta::visit(MetaVisitor* visitor) visitor->visit(this); } +std::vector Meta::MethodMeta::getFFISignature() +{ + std::vector types; + + for (size_t i = 0; i < this->signature.size(); i++) { + types.push_back(signature[i]->toFFIType()); + } + + return types; +} + void Meta::PropertyMeta::visit(MetaVisitor* visitor) { visitor->visit(this); @@ -67,6 +78,17 @@ void Meta::FunctionMeta::visit(MetaVisitor* visitor) visitor->visit(this); } +std::vector Meta::FunctionMeta::getFFISignature() +{ + std::vector types; + + for (size_t i = 0; i < this->signature.size(); i++) { + types.push_back(signature[i]->toFFIType()); + } + + return types; +} + void Meta::EnumMeta::visit(MetaVisitor* visitor) { visitor->visit(this); @@ -75,4 +97,4 @@ void Meta::EnumMeta::visit(MetaVisitor* visitor) void Meta::VarMeta::visit(MetaVisitor* visitor) { visitor->visit(this); -} \ No newline at end of file +} diff --git a/src/Meta/MetaEntities.h b/src/Meta/MetaEntities.h index 49a17f0..66847cf 100644 --- a/src/Meta/MetaEntities.h +++ b/src/Meta/MetaEntities.h @@ -134,6 +134,8 @@ class MethodMeta : public Meta { std::string constructorTokens; virtual void visit(MetaVisitor* visitor) override; + + std::vectorgetFFISignature(); }; class PropertyMeta : public Meta { @@ -227,6 +229,8 @@ class FunctionMeta : public Meta { std::vector signature; virtual void visit(MetaVisitor* visitor) override; + + std::vectorgetFFISignature(); }; class EnumConstantMeta : public Meta { @@ -275,4 +279,4 @@ class VarMeta : public Meta { virtual void visit(MetaVisitor* visitor) override; }; -} \ No newline at end of file +} diff --git a/src/Meta/MetaFactory.cpp b/src/Meta/MetaFactory.cpp index 216bb0c..05330d9 100644 --- a/src/Meta/MetaFactory.cpp +++ b/src/Meta/MetaFactory.cpp @@ -601,4 +601,4 @@ Version MetaFactory::convertVersion(clang::VersionTuple clangVersion) }; return result; } -} \ No newline at end of file +} diff --git a/src/Meta/TypeEntities.h b/src/Meta/TypeEntities.h index 0c591eb..0572b68 100644 --- a/src/Meta/TypeEntities.h +++ b/src/Meta/TypeEntities.h @@ -11,6 +11,24 @@ class InterfaceMeta; class StructMeta; class UnionMeta; class EnumMeta; + + enum FFIType : uint8_t { + FFIVoid, + FFIPointer, + FFISint8, + FFIUint8, + FFIUint16, + FFISint16, + FFIUint32, + FFISint32, + FFIUint64, + FFISint64, + FFIUshort, + FFIDouble, + FFIStruct, + FFIFloat + }; + enum TypeType { TypeVoid, @@ -157,6 +175,48 @@ class Type { return visitor.visitTypeArgument(as()); } } + + FFIType toFFIType() const { + + switch (this->type) { + case TypeBool: + return FFIUint8; + case TypeULongLong: + return FFIUint64; + case TypeStruct: + return FFIStruct; + case TypeUnsignedChar: + return FFIUshort; + case TypeSignedChar: + return FFIUshort; + case TypeUnichar: + return FFIUshort; + case TypeUShort: + return FFIUint16; + case TypeShort: + return FFISint16; + case TypeDouble: + return FFIDouble; + case TypeFloat: + return FFIFloat; + case TypeLongLong: + return FFISint64; + case TypeULong: + return FFIUint32; + case TypeLong: + return FFISint32; + case TypeUInt: + return FFIUint32; + case TypeInt: + return FFISint32; + case TypeVoid: + return FFIVoid; + case TypeUnion: + return FFIStruct; + default: + return FFIPointer; + } + } protected: TypeType type;