1
2
3
4
5
6 #include <cmajor/rt/Classes.hpp>
7 #include <cmajor/rt/Statics.hpp>
8 #include <cmajor/rt/Error.hpp>
9 #include <cmajor/rt/Io.hpp>
10 #include <soulng/util/System.hpp>
11 #include <soulng/util/BinaryReader.hpp>
12 #include <soulng/util/Path.hpp>
13 #include <soulng/util/Prime.hpp>
14 #include <soulng/util/Uuid.hpp>
15 #include <boost/filesystem.hpp>
16 #include <boost/uuid/uuid_io.hpp>
17 #include <boost/functional/hash.hpp>
18 #include <unordered_map>
19 #include <mutex>
20 #include <sstream>
21
22 namespace cmajor { namespace rt {
23
24 using namespace soulng::util;
25
26 class ClassIdMap
27 {
28 public:
29 static void Init();
30 static void Done();
31 static ClassIdMap& Instance() { return *instance; }
32 void SetClassId(const boost::uuids::uuid& typeId, const boost::multiprecision::uint128_t& classId);
33 boost::multiprecision::uint128_t GetClassId(const boost::uuids::uuid& typeId) const;
34 private:
35 static std::unique_ptr<ClassIdMap> instance;
36 std::unordered_map<boost::uuids::uuid, boost::multiprecision::uint128_t, boost::boost::hash<boost::uuids::uuid>>classIdMap;
37 };
38
39 std::unique_ptr<ClassIdMap> ClassIdMap::instance;
40
41 void ClassIdMap::Init()
42 {
43 instance.reset(new ClassIdMap());
44 }
45
46 void ClassIdMap::Done()
47 {
48 instance.reset();
49 }
50
51 void ClassIdMap::SetClassId(const boost::uuids::uuid& typeId, const boost::multiprecision::uint128_t& classId)
52 {
53 classIdMap[typeId] = classId;
54 }
55
56 boost::multiprecision::uint128_t ClassIdMap::GetClassId(const boost::uuids::uuid& typeId) const
57 {
58 auto it = classIdMap.find(typeId);
59 if (it != classIdMap.cend())
60 {
61 return it->second;
62 }
63 else
64 {
65 std::stringstream s;
66 s << "internal error : class id for type id " << typeId << " not found.\n";
67 std::string str = s.str();
68 int32_t errorStringHandle = -1;
69 void* stdError = RtOpenStdFile(2, errorStringHandle);
70 RtWrite(stdError, reinterpret_cast<const uint8_t*>(str.c_str()), str.length(), errorStringHandle);
71 RtFlush(stdError, errorStringHandle);
72 exit(exitCodeInternalError);
73 }
74 }
75
76 boost::multiprecision::uint128_t GetClassId(const boost::uuids::uuid& typeId)
77 {
78 return ClassIdMap::Instance().GetClassId(typeId);
79 }
80
81 void InitClasses(int64_t numberOfPolymorphicClassIds, const uint64_t* polymorphicClassIdArray, int64_t numberOfStaticClassIds, const uint64_t* staticClassIdArray)
82 {
83 try
84 {
85 ClassIdMap::Init();
86 boost::uuids::uuid dynamicTypeId;
87 for (int64_t i = 0; i < numberOfPolymorphicClassIds; ++i)
88 {
89 uint64_t typeId1 = polymorphicClassIdArray[4 * i];
90 uint64_t typeId2 = polymorphicClassIdArray[4 * i + 1];
91 boost::multiprecision::uint128_t classId = boost::multiprecision::uint128_t(polymorphicClassIdArray[4 * i + 2]) << 64 | polymorphicClassIdArray[4 * i + 3];
92 IntsToUuid(typeId1, typeId2, dynamicTypeId);
93 ClassIdMap::Instance().SetClassId(dynamicTypeId, classId);
94 }
95 boost::uuids::uuid staticTypeId;
96 std::vector<boost::uuids::uuid> staticClassIds;
97 for (int64_t i = 0; i < numberOfStaticClassIds; ++i)
98 {
99 uint64_t typeId1 = staticClassIdArray[2 * i];
100 uint64_t typeId2 = staticClassIdArray[2 * i + 1];
101 IntsToUuid(typeId1, typeId2, staticTypeId);
102 staticClassIds.push_back(staticTypeId);
103 }
104 AllocateMutexes(staticClassIds);
105 }
106 catch (const std::exception& ex;)
107 {
108 std::stringstream s;
109 s << "internal error in program initialization: " << ex.what() << "\n";
110 std::string str = s.str();
111 int32_t errorStringHandle = -1;
112 void* stdError = RtOpenStdFile(2, errorStringHandle);
113 RtWrite(stdError, reinterpret_cast<const uint8_t*>(str.c_str()), str.length(), errorStringHandle);
114 RtFlush(stdError, errorStringHandle);
115 exit(exitCodeInternalError);
116 }
117 }
118
119 std::mutex dynamicInitVmtMutex;
120
121 bool DynamicInitVmtsAndCompare(void* vmt1, void* vmt2)
122 {
123 std::lock_guard<std::mutex> lock(dynamicInitVmtMutex);
124 uint64_t* vmt1Header = reinterpret_cast<uint64_t*>(vmt1);
125 boost::multiprecision::uint128_t classId1(boost::multiprecision::uint128_t(vmt1Header[0]) << 64 | vmt1Header[1]);
126 if (classId1 == 0)
127 {
128 uint64_t typeId1 = vmt1Header[2];
129 uint64_t typeId2 = vmt1Header[3];
130 boost::uuids::uuid typeId;
131 IntsToUuid(typeId1, typeId2, typeId);
132 classId1 = ClassIdMap::Instance().GetClassId(typeId);
133 vmt1Header[0] = static_cast<uint64_t>(classId1 >> 64);
134 vmt1Header[1] = static_cast<uint64_t>(classId1);
135 }
136 uint64_t* vmt2Header = reinterpret_cast<uint64_t*>(vmt2);
137 boost::multiprecision::uint128_t classId2(boost::multiprecision::uint128_t(vmt2Header[0]) << 64 | vmt2Header[1]);
138 if (classId2 == 0)
139 {
140 uint64_t typeId1 = vmt2Header[2];
141 uint64_t typeId2 = vmt2Header[3];
142 boost::uuids::uuid typeId;
143 IntsToUuid(typeId1, typeId2, typeId);
144 classId2 = ClassIdMap::Instance().GetClassId(typeId);
145 vmt2Header[0] = static_cast<uint64_t>(classId2 >> 64);
146 vmt2Header[1] = static_cast<uint64_t>(classId2);
147 }
148 return classId1 % classId2 == 0;
149 }
150
151 void DoneClasses()
152 {
153 ClassIdMap::Done();
154 }
155
156 } }