Skip to content

Unique function and method signature instances in metadata. #62

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
21 changes: 19 additions & 2 deletions src/Binary/binarySerializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::vector<::Meta::FFIType>, 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)
{

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

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

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.
Expand All @@ -15,6 +56,11 @@ 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.

std::unordered_map<std::vector<::Meta::FFIType>, 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);

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

virtual void visit(::Meta::MethodMeta* Meta) override;
};
}
}
24 changes: 23 additions & 1 deletion src/Meta/MetaEntities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ void Meta::MethodMeta::visit(MetaVisitor* visitor)
visitor->visit(this);
}

std::vector<Meta::FFIType> Meta::MethodMeta::getFFISignature()
{
std::vector<FFIType> 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);
Expand Down Expand Up @@ -67,6 +78,17 @@ void Meta::FunctionMeta::visit(MetaVisitor* visitor)
visitor->visit(this);
}

std::vector<Meta::FFIType> Meta::FunctionMeta::getFFISignature()
{
std::vector<FFIType> 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);
Expand All @@ -75,4 +97,4 @@ void Meta::EnumMeta::visit(MetaVisitor* visitor)
void Meta::VarMeta::visit(MetaVisitor* visitor)
{
visitor->visit(this);
}
}
6 changes: 5 additions & 1 deletion src/Meta/MetaEntities.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ class MethodMeta : public Meta {
std::string constructorTokens;

virtual void visit(MetaVisitor* visitor) override;

std::vector<FFIType>getFFISignature();
};

class PropertyMeta : public Meta {
Expand Down Expand Up @@ -227,6 +229,8 @@ class FunctionMeta : public Meta {
std::vector<Type*> signature;

virtual void visit(MetaVisitor* visitor) override;

std::vector<FFIType>getFFISignature();
};

class EnumConstantMeta : public Meta {
Expand Down Expand Up @@ -275,4 +279,4 @@ class VarMeta : public Meta {

virtual void visit(MetaVisitor* visitor) override;
};
}
}
2 changes: 1 addition & 1 deletion src/Meta/MetaFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -601,4 +601,4 @@ Version MetaFactory::convertVersion(clang::VersionTuple clangVersion)
};
return result;
}
}
}
60 changes: 60 additions & 0 deletions src/Meta/TypeEntities.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -157,6 +175,48 @@ class Type {
return visitor.visitTypeArgument(as<TypeArgumentType>());
}
}

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;
Expand Down