Skip to content

Commit 014d14a

Browse files
committed
Implement typed-gc
Signed-off-by: Seonghyun Kim <[email protected]>
1 parent 3138a80 commit 014d14a

File tree

7 files changed

+111
-63
lines changed

7 files changed

+111
-63
lines changed

escargotshim.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
'-Wno-unused-result',
9090
'-fexceptions',
9191
'-fvisibility=hidden',
92+
'-Wno-invalid-offsetof',
9293
],
9394
'direct_dependent_settings': {
9495
'defines': [

src/api/engine.cc

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -115,18 +115,18 @@ void GCHeap::acquire(void* address, Kind kind, void* data) {
115115

116116
auto iter = persistents_.find(GC_WRAP_PERSISTENT_POINTER(address));
117117
if (iter != persistents_.end()) {
118-
if (kind == STRONG) iter->second.strong++;
119-
if (kind == WEAK) iter->second.weak++;
118+
if (kind == STRONG) iter.value().strong++;
119+
if (kind == WEAK) iter.value().weak++;
120120
} else {
121121
auto iter = weakPhantoms_.find(GC_WRAP_WEAK_POINTER(address));
122122
if (iter != weakPhantoms_.end()) {
123-
AddressInfo info = iter->second;
123+
AddressInfo info = iter.value();
124124

125125
LWNODE_CHECK(info.strong == 0);
126126
LWNODE_CHECK(info.weak != 0);
127127

128-
if (kind == STRONG) iter->second.strong++;
129-
if (kind == WEAK) iter->second.weak++;
128+
if (kind == STRONG) iter.value().strong++;
129+
if (kind == WEAK) iter.value().weak++;
130130

131131
persistents_.emplace(GC_WRAP_PERSISTENT_POINTER(address), info);
132132
weakPhantoms_.erase(iter);
@@ -147,16 +147,16 @@ void GCHeap::release(void* address, Kind kind) {
147147

148148
auto iter = persistents_.find(GC_WRAP_PERSISTENT_POINTER(address));
149149
if (iter != persistents_.end()) {
150-
if (kind == STRONG) iter->second.strong--;
151-
if (kind == WEAK) iter->second.weak--;
150+
if (kind == STRONG) iter.value().strong--;
151+
if (kind == WEAK) iter.value().weak--;
152152

153-
iter->second.strong = std::max(iter->second.strong, 0);
154-
iter->second.weak = std::max(iter->second.weak, 0);
153+
iter.value().strong = std::max(iter.value().strong, 0);
154+
iter.value().weak = std::max(iter.value().weak, 0);
155155

156156
// progress handling weak phantoms
157157
if (iter->second.strong == 0) {
158158
if (iter->second.weak > 0) {
159-
weakPhantoms_.emplace(GC_WRAP_WEAK_POINTER(address), iter->second);
159+
weakPhantoms_.emplace(GC_WRAP_WEAK_POINTER(address), iter.value());
160160
}
161161
persistents_.erase(iter);
162162
}

src/api/global-handles.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ void GlobalHandles::create(ValueWrap* lwValue) {
6969
if (iter == persistentValues_.end()) {
7070
persistentValues_.emplace(lwValue, 1);
7171
} else {
72-
++iter->second;
72+
++iter.value();
7373
// TODO:
7474
LWNODE_CALL_TRACE_ID(GLOBALHANDLES,
7575
"Persistent value was created multiple times: %p",
@@ -83,7 +83,7 @@ bool GlobalHandles::destroy(ValueWrap* lwValue) {
8383
if (iter->second == 1) {
8484
persistentValues_.erase(iter);
8585
} else {
86-
--iter->second;
86+
--iter.value();
8787
}
8888
return true;
8989
}

src/api/isolate.cc

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ namespace internal {
2929

3030
using namespace EscargotShim;
3131

32+
void Isolate::fillGCDescriptor(GC_word* desc) {
33+
GC_set_bit(desc, GC_WORD_OFFSET(Isolate, scheduled_exception_));
34+
GC_set_bit(desc, GC_WORD_OFFSET(Isolate, global_handles_));
35+
GC_set_bit(desc, GC_WORD_OFFSET(Isolate, try_catch_handler_));
36+
GC_set_bit(desc, GC_WORD_OFFSET(Isolate, pending_exception_));
37+
GC_set_bit(desc, GC_WORD_OFFSET(Isolate, pending_message_obj_));
38+
GC_set_bit(desc, GC_WORD_OFFSET(Isolate, prepareStackTraceRecursion_));
39+
}
40+
3241
// 'exception_' is of type ValueWrap*. Ref: api-exception.cc
3342
void Isolate::SetTerminationOnExternalTryCatch() {
3443
LWNODE_CALL_TRACE_ID(TRYCATCH, "try_catch_handler_: %p", try_catch_handler_);
@@ -269,6 +278,39 @@ namespace EscargotShim {
269278
LWNODE_EXPORT THREAD_LOCAL IsolateWrap* IsolateWrap::s_currentIsolate;
270279
LWNODE_EXPORT THREAD_LOCAL IsolateWrap* IsolateWrap::s_previousIsolate;
271280

281+
void IsolateWrap::fillGCDescriptor(GC_word* desc) {
282+
Isolate::fillGCDescriptor(desc);
283+
GC_set_bit(desc, GC_WORD_OFFSET(IsolateWrap, eternals_));
284+
markHashSet(desc, GC_WORD_OFFSET(IsolateWrap, backingStoreCounter_));
285+
GC_set_bit(desc, GC_WORD_OFFSET(IsolateWrap, handleScopes_));
286+
GC_set_bit(desc, GC_WORD_OFFSET(IsolateWrap, contextScopes_));
287+
288+
GC_set_bit(desc, GC_WORD_OFFSET(IsolateWrap, privateValuesSymbol_));
289+
GC_set_bit(desc, GC_WORD_OFFSET(IsolateWrap, apiSymbols_));
290+
GC_set_bit(desc, GC_WORD_OFFSET(IsolateWrap, apiPrivateSymbols_));
291+
292+
GC_set_bit(desc, GC_WORD_OFFSET(IsolateWrap, vmInstance_));
293+
294+
GC_set_bit(desc, GC_WORD_OFFSET(IsolateWrap, release_lock_));
295+
for (size_t i = 0; i < internal::Internals::kRootIndexSize; i++) {
296+
GC_set_bit(desc, GC_WORD_OFFSET(IsolateWrap, globalSlot_) + i);
297+
}
298+
299+
GC_set_bit(desc, GC_WORD_OFFSET(IsolateWrap, threadManager_));
300+
}
301+
302+
void* IsolateWrap::operator new(size_t size) {
303+
static bool typeInited = false;
304+
static GC_descr descr;
305+
if (!typeInited) {
306+
GC_word desc[GC_BITMAP_SIZE(IsolateWrap)] = {0};
307+
fillGCDescriptor(desc);
308+
descr = GC_make_descriptor(desc, GC_WORD_LEN(IsolateWrap));
309+
typeInited = true;
310+
}
311+
return GC_MALLOC_EXPLICITLY_TYPED(size, descr);
312+
}
313+
272314
IsolateWrap::IsolateWrap() {
273315
LWNODE_CALL_TRACE_ID(ISOWRAP, "malc: %p", this);
274316

@@ -552,7 +594,7 @@ void IsolateWrap::addEternal(GCManagedObject* value) {
552594
void IsolateWrap::addBackingStore(BackingStoreRef* value) {
553595
auto itr = backingStoreCounter_.find(value);
554596
if (itr != backingStoreCounter_.end()) {
555-
++itr->second;
597+
itr.value() = itr.value() + 1;
556598
} else {
557599
backingStoreCounter_.insert(std::make_pair(value, 1));
558600
}
@@ -564,7 +606,7 @@ void IsolateWrap::removeBackingStore(BackingStoreRef* value) {
564606
if (itr->second == 1) {
565607
backingStoreCounter_.erase(itr);
566608
} else {
567-
--itr->second;
609+
itr.value() = itr.value() - 1;
568610
}
569611
} else {
570612
LWNODE_CHECK_MSG(false, "increment/decrement count do not match");

src/api/isolate.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ class Isolate : public gc {
110110
EscargotShim::GlobalHandles* global_handles() { return global_handles_; }
111111

112112
protected:
113+
static void fillGCDescriptor(GC_word* desc);
113114
void set_pending_exception(Escargot::ValueRef* exception_obj);
114115
void set_pending_message_obj(Escargot::ValueRef* message_obj);
115116
void clear_pending_exception();
@@ -149,12 +150,6 @@ class ContextWrap;
149150

150151
typedef gc GCManagedObject;
151152

152-
struct BackingStoreComparator {
153-
bool operator()(const BackingStoreRef* a, const BackingStoreRef* b) const {
154-
return a < b;
155-
}
156-
};
157-
158153
class IsolateWrap final : public v8::internal::Isolate {
159154
public:
160155
enum class State { None, Active, Disposed };
@@ -279,13 +274,17 @@ class IsolateWrap final : public v8::internal::Isolate {
279274

280275
State getState() { return state_; }
281276

277+
void* operator new(size_t size);
278+
282279
private:
280+
static void fillGCDescriptor(GC_word* desc);
283281
IsolateWrap();
284282

285283
void InitializeGlobalSlots();
286284

287285
GCVector<GCManagedObject*> eternals_;
288-
GCMap<BackingStoreRef*, int, BackingStoreComparator> backingStoreCounter_;
286+
GCUnorderedMap<BackingStoreRef*, StorePositiveNumberAsOddNumber>
287+
backingStoreCounter_;
289288

290289
GCVector<HandleScopeWrap*> handleScopes_;
291290
GCVector<ContextWrap*> contextScopes_;

src/api/utils/gc-util.h

Lines changed: 46 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,23 @@
2525
#include "gc-container.h"
2626
#include "sf-vector.h"
2727

28+
// from deps/escargot/src/api
29+
#include "../../third_party/robin_map/include/tsl/robin_map.h"
30+
#include "../../third_party/robin_map/include/tsl/robin_set.h"
31+
32+
class StorePositiveNumberAsOddNumber {
33+
public:
34+
StorePositiveNumberAsOddNumber(const size_t& src = 0) {
35+
// ASSERT(src < std::numeric_limits<size_t>::max() / 2);
36+
m_data = (src << 1) | 0x1;
37+
}
38+
39+
operator size_t() const { return m_data >> 1; }
40+
41+
private:
42+
size_t m_data;
43+
};
44+
2845
#include <string>
2946

3047
// typedef of GC-aware vector
@@ -47,19 +64,15 @@ class GCVector : public GCVectorT<T, isEraseStrategyStrict, Allocator>,
4764
public gc {};
4865
#endif
4966

50-
// typedef of GC-aware list
51-
template <typename T, typename Allocator = GCUtil::gc_malloc_allocator<T>>
52-
using GCListT = std::list<T, Allocator>;
53-
54-
template <typename T, typename Allocator = GCUtil::gc_malloc_allocator<T>>
55-
class GCList : public GCListT<T, Allocator>, public gc {};
56-
57-
// typedef of GC-aware deque
58-
template <typename T, typename Allocator = GCUtil::gc_malloc_allocator<T>>
59-
using GCDequeT = std::deque<T, Allocator>;
60-
61-
template <typename T, typename Allocator = GCUtil::gc_malloc_allocator<T>>
62-
class GCDeque : public GCDequeT<T, Allocator>, public gc {};
67+
template <class Key,
68+
class T,
69+
class Hash = std::hash<Key>,
70+
class KeyEqual = std::equal_to<Key>,
71+
class Allocator = std::allocator<std::pair<Key, T>>,
72+
bool StoreHash = false,
73+
class GrowthPolicy = tsl::rh::power_of_two_growth_policy<2>>
74+
using HashMap =
75+
tsl::robin_map<Key, T, Hash, KeyEqual, Allocator, StoreHash, GrowthPolicy>;
6376

6477
// typedef of GC-aware unordered_map
6578
template <typename Key,
@@ -68,8 +81,7 @@ template <typename Key,
6881
typename Predicate = std::equal_to<Key>,
6982
typename Allocator =
7083
GCUtil::gc_malloc_allocator<std::pair<Key const, Value>>>
71-
using GCUnorderedMapT =
72-
std::unordered_map<Key, Value, Hasher, Predicate, Allocator>;
84+
using GCUnorderedMapT = HashMap<Key, Value, Hasher, Predicate, Allocator>;
7385

7486
template <typename Key,
7587
typename Value,
@@ -86,49 +98,41 @@ template <typename Key,
8698
typename Hasher = std::hash<Key>,
8799
typename Predicate = std::equal_to<Key>,
88100
typename Allocator =
89-
GCUtil::gc_malloc_allocator<std::pair<Key const, Value>>>
90-
using GCUnorderedMultiMapT =
91-
std::unordered_multimap<Key, Value, Hasher, Predicate, Allocator>;
101+
GCUtil::gc_malloc_atomic_allocator<std::pair<Key const, Value>>>
102+
using GCAtomicUnorderedMapT = HashMap<Key, Value, Hasher, Predicate, Allocator>;
92103

93104
template <typename Key,
94105
typename Value,
95106
typename Hasher = std::hash<Key>,
96107
typename Predicate = std::equal_to<Key>,
97108
typename Allocator =
98-
GCUtil::gc_malloc_allocator<std::pair<Key const, Value>>>
99-
class GCUnorderedMultiMap
100-
: public GCUnorderedMultiMapT<Key, Value, Hasher, Predicate, Allocator>,
109+
GCUtil::gc_malloc_atomic_allocator<std::pair<Key const, Value>>>
110+
class GCAtomicUnorderedMap
111+
: public GCAtomicUnorderedMapT<Key, Value, Hasher, Predicate, Allocator>,
101112
public gc {};
102113

103-
// typedef of GC-aware map
104-
template <typename Key,
105-
typename Value,
106-
typename Comparator,
107-
typename Allocator =
108-
GCUtil::gc_malloc_allocator<std::pair<Key const, Value>>>
109-
using GCMapT = std::map<Key, Value, Comparator, Allocator>;
110-
111-
template <typename Key,
112-
typename Value,
113-
typename Comparator,
114-
typename Allocator =
115-
GCUtil::gc_malloc_allocator<std::pair<Key const, Value>>>
116-
class GCMap : public GCMapT<Key, Value, Comparator, Allocator>, public gc {};
114+
template <class Key,
115+
class Hash = std::hash<Key>,
116+
class KeyEqual = std::equal_to<Key>,
117+
class Allocator = std::allocator<Key>,
118+
bool StoreHash = false,
119+
class GrowthPolicy = tsl::rh::power_of_two_growth_policy<2>>
120+
using HashSet =
121+
tsl::robin_set<Key, Hash, KeyEqual, Allocator, StoreHash, GrowthPolicy>;
117122

118123
// typedef of GC-aware unordered_set
119124
template <typename T,
120125
typename Hasher = std::hash<T>,
121126
typename Predicate = std::equal_to<T>,
122127
typename Allocator = GCUtil::gc_malloc_allocator<T>>
123-
using GCUnorderedSetT = std::unordered_set<T, Hasher, Predicate, Allocator>;
124-
125-
template <typename T,
126-
typename Hasher = std::hash<T>,
127-
typename Predicate = std::equal_to<T>,
128-
typename Allocator = GCUtil::gc_malloc_allocator<T>>
129-
class GCUnorderedSet : public GCUnorderedSetT<T, Hasher, Predicate, Allocator>,
128+
class GCUnorderedSet : public HashSet<T, Hasher, Predicate, Allocator>,
130129
public gc {};
131130

131+
inline void markHashSet(GC_word* desc, size_t base) {
132+
GC_set_bit(desc, base + 1); // m_ht.m_buckets_data
133+
GC_set_bit(desc, base + 4); // m_ht.m_buckets
134+
}
135+
132136
namespace Escargot {
133137
class ValueRef;
134138
class ObjectRef;

src/execution/v8threads.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ class ThreadManager : public gc {
3636

3737
bool IsLockedByCurrentThread() const;
3838

39+
void* operator new(size_t size) { return GC_MALLOC_ATOMIC(size); }
40+
3941
std::mutex mutex_;
4042
std::atomic<std::thread::id> mutex_owner_;
4143
};

0 commit comments

Comments
 (0)