blob: 02ec90275bfd4e605dc7c03e17b1fed013593a89 [file] [log] [blame]
//===------- LockedMap.h - A thread-safe map implementation ---------------===//
//
// The VMKit project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines thread-safe maps that must be deallocated by the owning
// object. For example a class loader is responsible for deallocating the
// types stored in a TypeMap.
//
//===----------------------------------------------------------------------===//
#ifndef JNJVM_LOCKED_MAP_H
#define JNJVM_LOCKED_MAP_H
#include <map>
#include <cstring>
#include "types.h"
#include "mvm/Allocator.h"
#include "mvm/Threads/Locks.h"
#include "UTF8.h"
#include "JavaArray.h" // for comparing UTF8s
namespace j3 {
class JavaString;
class Signdef;
class Typedef;
class UserCommonClass;
class UserClassArray;
struct ltutf8
{
bool operator()(const UTF8* s1, const UTF8* s2) const
{
return s1->lessThan(s2);
}
};
struct ltarray16
{
bool operator()(const ArrayUInt16* s1, const ArrayUInt16* s2) const
{
if (s1->size < s2->size) return true;
else if (s1->size > s2->size) return false;
else return memcmp((const char*)s1->elements, (const char*)s2->elements,
s1->size * sizeof(uint16)) < 0;
}
};
class MapNoGC {
public:
static void gcroot(void* val, void* unused)
__attribute__ ((always_inline)) {}
};
class MapWithGC {
public:
static void gcroot(void* val, void* unused)
__attribute__ ((always_inline)) {
llvm_gcroot(val, unused);
}
};
template<class Key, class Container, class Compare, class Meta, class TLock,
class IsGC>
class LockedMap : public mvm::PermanentObject {
public:
typedef typename std::map<const Key, Container, Compare>::iterator iterator;
typedef Container (*funcCreate)(Key& V, Meta meta);
TLock lock;
std::map<const Key, Container, Compare,
gc_allocator<std::pair<const Key, Container> > > map;
inline Container lookupOrCreate(Key& V, Meta meta, funcCreate func) {
Container res = 0;
IsGC::gcroot(res, 0);
lock.lock();
iterator End = map.end();
iterator I = map.find(V);
if (I == End) {
Container res = func(V, meta);
map.insert(std::make_pair(V, res));
lock.unlock();
return res;
} else {
lock.unlock();
return ((Container)(I->second));
}
}
inline void remove(Key V) {
lock.lock();
map.erase(V);
lock.unlock();
}
inline void remove(Key V, Container C) {
IsGC::gcroot(C, 0);
lock.lock();
removeUnlocked(V, C);
lock.unlock();
}
inline void removeUnlocked(Key V, Container C) {
IsGC::gcroot(C, 0);
iterator End = map.end();
iterator I = map.find(V);
if (I != End && I->second == C)
map.erase(I);
}
inline Container lookup(Key V) {
lock.lock();
iterator End = map.end();
iterator I = map.find(V);
lock.unlock();
return I != End ? ((Container)(I->second)) : 0;
}
inline void hash(Key k, Container c) {
IsGC::gcroot(c, 0);
lock.lock();
map.insert(std::make_pair(k, c));
lock.unlock();
}
~LockedMap() {}
};
class ClassMap :
public LockedMap<const UTF8*, UserCommonClass*, ltutf8, JnjvmClassLoader*,
mvm::LockRecursive, MapNoGC > {
#ifdef USE_GC_BOEHM
public:
void* operator new(size_t sz, mvm::BumpPtrAllocator& allocator) {
return GC_MALLOC(sz);
}
#endif
};
class StringMap :
public LockedMap<const ArrayUInt16*, JavaString*, ltarray16, Jnjvm*,
mvm::LockNormal, MapWithGC> {
public:
void insert(JavaString* str);
};
class TypeMap : public mvm::PermanentObject {
public:
mvm::LockNormal lock;
std::map<const UTF8*, Typedef*, ltutf8> map;
typedef std::map<const UTF8*, Typedef*, ltutf8>::iterator iterator;
inline Typedef* lookup(const UTF8* V) {
iterator End = map.end();
iterator I = map.find(V);
return I != End ? I->second : 0;
}
inline void hash(const UTF8* k, Typedef* c) {
map.insert(std::make_pair(k, c));
}
};
class SignMap : public mvm::PermanentObject {
public:
mvm::LockNormal lock;
std::map<const UTF8*, Signdef*, ltutf8> map;
typedef std::map<const UTF8*, Signdef*, ltutf8>::iterator iterator;
inline Signdef* lookup(const UTF8* V) {
iterator End = map.end();
iterator I = map.find(V);
return I != End ? I->second : 0;
}
inline void hash(const UTF8* k, Signdef* c) {
map.insert(std::make_pair(k, c));
}
};
} // end namespace j3
#endif