Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@

cmake-build/
# Mac
.DS_Store
#ignore thumbnails created by windows
Expand Down
133 changes: 131 additions & 2 deletions src/Binary/binarySerializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are mapping Meta::Type objects to FFIType values for a second time in the same method I suggest extracting the mapping logic outside of the binary serialization. The mapping logic is not directly related to the binary serialization, it is a property of the Meta::Type itself. I suggest introducing an instance method of the Meta::Type structure, mapping the type to a FFIType:

FFIType toFFIType() const
{
    switch (this->type) {
        case TypeBool:
            return FFYTypeUInt8
        case TypeShort:
            ...
}

Then a MethodMeta can have a method that converts a vector of Meta::Types to vector of FFITypes e.g.:

std::vector<FFIType> getFFISignature() const
{
    ...
}

This way the mapping logic will not be extracted from the binary serializer and can be used in other modules without code repetition e.g. it is a good idea to print the FFI signature of a method in the Yaml output.


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)
{

Expand Down Expand Up @@ -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));
}

Expand Down
32 changes: 31 additions & 1 deletion src/Binary/binarySerializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,32 @@
#include <map>

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<FFIType> types;

};


/*
* \class BinarySerializer
* \brief Applies the Visitor pattern for serializing \c Meta::Meta objects in binary format.
Expand All @@ -15,6 +41,10 @@ class BinarySerializer : public ::Meta::MetaVisitor {
MetaFile* file;
BinaryWriter heapWriter;
BinaryTypeEncodingSerializer typeEncodingSerializer;

std::vector<CachedSignature> cachedSignatures;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be more efficient to use std::unordered_map<std::vector<FFIType>, MetaFileOffset> instead of vector? This way the lookup of a signature will be much faster, avoiding the need for iterating over the vector. However, this requires introducing hash and isEqualTo operations for std::vector<FFIType> which IMO should not be so difficult.


binary::MetaFileOffset checkForExistingSignature(std::vector<::Meta::Type*> signature);

void serializeBase(::Meta::Meta* Meta, binary::Meta& binaryMetaStruct);

Expand Down Expand Up @@ -66,4 +96,4 @@ class BinarySerializer : public ::Meta::MetaVisitor {

virtual void visit(::Meta::MethodMeta* Meta) override;
};
}
}