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..32e1d24 100644 --- a/src/Binary/binarySerializer.cpp +++ b/src/Binary/binarySerializer.cpp @@ -139,10 +139,26 @@ 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->getOffset(meta->signature, meta->getFFISignature()); binaryMetaStruct._constructorTokens = this->heapWriter.push_string(meta->constructorTokens); } +binary::MetaFileOffset binary::BinarySerializer::getOffset(std::vector<::Meta::Type*> signature, std::vector<::Meta::FFIType> ffiSignature) { + + static int invocations = 0; + std::unordered_map, MetaFileOffset, SignatureHash, SignatureEq>::const_iterator it = signatureCache.find(ffiSignature); + + if (it == signatureCache.end()) { + invocations += 1; + signatureCache[ffiSignature] = this->typeEncodingSerializer.visit(signature); + } + + printf("%d\n", invocations); + + return signatureCache[ffiSignature]; + +} + void binary::BinarySerializer::serializeProperty(::Meta::PropertyMeta* meta, binary::PropertyMeta& binaryMetaStruct) { @@ -318,7 +334,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->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 c4de320..7d5aeb9 100644 --- a/src/Binary/binarySerializer.h +++ b/src/Binary/binarySerializer.h @@ -6,6 +6,47 @@ #include namespace binary { + +struct CachedSignature { + + MetaFileOffset offset; + 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; + } + +}; + + /* * \class BinarySerializer * \brief Applies the Visitor pattern for serializing \c Meta::Meta objects in binary format. @@ -15,6 +56,11 @@ class BinarySerializer : public ::Meta::MetaVisitor { MetaFile* file; BinaryWriter heapWriter; BinaryTypeEncodingSerializer typeEncodingSerializer; + + std::vector cachedSignatures; + 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); @@ -66,4 +112,4 @@ class BinarySerializer : public ::Meta::MetaVisitor { virtual void visit(::Meta::MethodMeta* Meta) override; }; -} \ No newline at end of file +} 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;