Commit b57d5cc9 authored by fqian@google.com's avatar fqian@google.com

Replace std::map, std::set by WTF::HashMap and WTF::HashSet.

WebKit gurus, please review the change carefully, WTF::HashMap interface is not well documented, so I have implement
customized hash functions and HashTraits in order to use StringKey as the hash key.

Review URL: http://codereview.chromium.org/100069

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@14995 0039d316-1c4b-4281-b951-d872f2087c98
parent 00b3428f
...@@ -26,21 +26,14 @@ ...@@ -26,21 +26,14 @@
#include "config.h" #include "config.h"
#include <map>
#include <set>
#include <string>
#include <v8.h>
#include "bindings/npruntime.h"
#include "NPV8Object.h" #include "NPV8Object.h"
#include "npruntime_priv.h" #include "npruntime_priv.h"
#include "V8NPObject.h" #include "V8NPObject.h"
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/Assertions.h> #include <wtf/Assertions.h>
using namespace v8;
// FIXME: Consider removing locks if we're singlethreaded already. // FIXME: Consider removing locks if we're singlethreaded already.
// The static initializer here should work okay, but we want to avoid // The static initializer here should work okay, but we want to avoid
// static initialization in general. // static initialization in general.
...@@ -53,25 +46,85 @@ namespace { ...@@ -53,25 +46,85 @@ namespace {
// We use StringKey here as the key-type to avoid a string copy to // We use StringKey here as the key-type to avoid a string copy to
// construct the map key and for faster comparisons than strcmp. // construct the map key and for faster comparisons than strcmp.
struct StringKey { class StringKey {
StringKey(const char* str) : string(str), length(strlen(str)) {} public:
const char* string; explicit StringKey(const char* str) : _string(str), _length(strlen(str)) {}
const size_t length; StringKey() : _string(0), _length(0) {}
explicit StringKey(WTF::HashTableDeletedValueType)
: _string(hashTableDeletedValue()), _length(0) { }
StringKey& operator=(const StringKey& other) {
this->_string = other._string;
this->_length = other._length;
return *this;
}
bool isHashTableDeletedValue() const {
return _string == hashTableDeletedValue();
}
const char* _string;
size_t _length;
private:
const char* hashTableDeletedValue() const {
return reinterpret_cast<const char*>(-1);
}
}; };
inline bool operator<(const StringKey& x, const StringKey& y) { inline bool operator==(const StringKey& x, const StringKey& y) {
// Shorter strings are less than longer strings, memcmp breaks ties. if (x._length != y._length) {
if (x.length < y.length)
return true;
else if (x.length > y.length)
return false; return false;
else } else if (x._string == y._string) {
return memcmp(x.string, y.string, y.length) < 0; return true;
} else {
ASSERT(!x.isHashTableDeletedValue() && !y.isHashTableDeletedValue());
return memcmp(x._string, y._string, y._length) == 0;
}
} }
// Implement WTF::DefaultHash<StringKey>::Hash interface.
struct StringKeyHash {
static unsigned hash(const StringKey& key) {
// Use the same string hash function as in V8.
unsigned hash = 0;
size_t len = key._length;
const char* str = key._string;
for (size_t i = 0; i < len; i++) {
char c = str[i];
hash += c;
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
if (hash == 0) {
hash = 27;
}
return hash;
}
static bool equal(const StringKey& x, const StringKey& y) {
return x == y;
}
static const bool safeToCompareToEmptyOrDeleted = true;
};
} // namespace } // namespace
typedef std::map<const StringKey, PrivateIdentifier*> StringIdentifierMap; // Implement HashTraits<StringKey>
struct StringKeyHashTraits : WTF::GenericHashTraits<StringKey> {
static void constructDeletedValue(StringKey& slot) {
new (&slot) StringKey(WTF::HashTableDeletedValue);
}
static bool isDeletedValue(const StringKey& value) {
return value.isHashTableDeletedValue();
}
};
typedef WTF::HashMap<StringKey, PrivateIdentifier*, \
StringKeyHash, StringKeyHashTraits> StringIdentifierMap;
static StringIdentifierMap* getStringIdentifierMap() { static StringIdentifierMap* getStringIdentifierMap() {
static StringIdentifierMap* stringIdentifierMap = 0; static StringIdentifierMap* stringIdentifierMap = 0;
...@@ -83,7 +136,7 @@ static StringIdentifierMap* getStringIdentifierMap() { ...@@ -83,7 +136,7 @@ static StringIdentifierMap* getStringIdentifierMap() {
// FIXME: Consider removing locks if we're singlethreaded already. // FIXME: Consider removing locks if we're singlethreaded already.
// static Lock IntIdentifierMapLock; // static Lock IntIdentifierMapLock;
typedef std::map<int, PrivateIdentifier*> IntIdentifierMap; typedef WTF::HashMap<int, PrivateIdentifier*> IntIdentifierMap;
static IntIdentifierMap* getIntIdentifierMap() { static IntIdentifierMap* getIntIdentifierMap() {
static IntIdentifierMap* intIdentifierMap = 0; static IntIdentifierMap* intIdentifierMap = 0;
...@@ -106,7 +159,7 @@ NPIdentifier NPN_GetStringIdentifier(const NPUTF8* name) { ...@@ -106,7 +159,7 @@ NPIdentifier NPN_GetStringIdentifier(const NPUTF8* name) {
if (iter != identMap->end()) if (iter != identMap->end())
return static_cast<NPIdentifier>(iter->second); return static_cast<NPIdentifier>(iter->second);
size_t nameLen = key.length; size_t nameLen = key._length;
// We never release identifiers, so this dictionary will grow. // We never release identifiers, so this dictionary will grow.
PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>( PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(
...@@ -115,8 +168,8 @@ NPIdentifier NPN_GetStringIdentifier(const NPUTF8* name) { ...@@ -115,8 +168,8 @@ NPIdentifier NPN_GetStringIdentifier(const NPUTF8* name) {
memcpy(nameStorage, name, nameLen + 1); memcpy(nameStorage, name, nameLen + 1);
identifier->isString = true; identifier->isString = true;
identifier->value.string = reinterpret_cast<NPUTF8*>(nameStorage); identifier->value.string = reinterpret_cast<NPUTF8*>(nameStorage);
key.string = nameStorage; key._string = nameStorage;
(*identMap)[key] = identifier; identMap->set(key, identifier);
return (NPIdentifier)identifier; return (NPIdentifier)identifier;
} }
...@@ -146,7 +199,7 @@ NPIdentifier NPN_GetIntIdentifier(int32_t intid) { ...@@ -146,7 +199,7 @@ NPIdentifier NPN_GetIntIdentifier(int32_t intid) {
malloc(sizeof(PrivateIdentifier))); malloc(sizeof(PrivateIdentifier)));
identifier->isString = false; identifier->isString = false;
identifier->value.number = intid; identifier->value.number = intid;
(*identMap)[intid] = identifier; identMap->set(intid, identifier);
return (NPIdentifier)identifier; return (NPIdentifier)identifier;
} }
...@@ -276,9 +329,9 @@ void _NPN_InitializeVariantWithStringCopy(NPVariant* variant, ...@@ -276,9 +329,9 @@ void _NPN_InitializeVariantWithStringCopy(NPVariant* variant,
// Frame teardown to deactivate all objects associated // Frame teardown to deactivate all objects associated
// with a particular plugin. // with a particular plugin.
typedef std::set<NPObject*> NPObjectSet; typedef WTF::HashSet<NPObject*> NPObjectSet;
typedef std::map<NPObject*, NPObject*> NPObjectMap; typedef WTF::HashMap<NPObject*, NPObject*> NPObjectMap;
typedef std::map<NPObject*, NPObjectSet*> NPRootObjectMap; typedef WTF::HashMap<NPObject*, NPObjectSet*> NPRootObjectMap;
// A map of live NPObjects with pointers to their Roots. // A map of live NPObjects with pointers to their Roots.
NPObjectMap g_live_objects; NPObjectMap g_live_objects;
...@@ -298,7 +351,7 @@ void _NPN_RegisterObject(NPObject* obj, NPObject* owner) { ...@@ -298,7 +351,7 @@ void _NPN_RegisterObject(NPObject* obj, NPObject* owner) {
if (!owner) { if (!owner) {
// Registering a new owner object. // Registering a new owner object.
ASSERT(g_root_objects.find(obj) == g_root_objects.end()); ASSERT(g_root_objects.find(obj) == g_root_objects.end());
g_root_objects[obj] = new NPObjectSet(); g_root_objects.set(obj, new NPObjectSet());
} else { } else {
// Always associate this object with it's top-most parent. // Always associate this object with it's top-most parent.
// Since we always flatten, we only have to look up one level. // Since we always flatten, we only have to look up one level.
...@@ -308,15 +361,15 @@ void _NPN_RegisterObject(NPObject* obj, NPObject* owner) { ...@@ -308,15 +361,15 @@ void _NPN_RegisterObject(NPObject* obj, NPObject* owner) {
parent = owner_entry->second; parent = owner_entry->second;
if (parent) { if (parent) {
owner = parent; owner = parent;
} }
ASSERT(g_root_objects.find(obj) == g_root_objects.end()); ASSERT(g_root_objects.find(obj) == g_root_objects.end());
if (g_root_objects.find(owner) != g_root_objects.end()) if (g_root_objects.find(owner) != g_root_objects.end())
(g_root_objects[owner])->insert(obj); g_root_objects.get(owner)->add(obj);
} }
ASSERT(g_live_objects.find(obj) == g_live_objects.end()); ASSERT(g_live_objects.find(obj) == g_live_objects.end());
g_live_objects[obj] = owner; g_live_objects.set(obj, owner);
} }
void _NPN_UnregisterObject(NPObject* obj) { void _NPN_UnregisterObject(NPObject* obj) {
...@@ -330,18 +383,18 @@ void _NPN_UnregisterObject(NPObject* obj) { ...@@ -330,18 +383,18 @@ void _NPN_UnregisterObject(NPObject* obj) {
if (owner == NULL) { if (owner == NULL) {
// Unregistering a owner object; also unregister it's descendants. // Unregistering a owner object; also unregister it's descendants.
ASSERT(g_root_objects.find(obj) != g_root_objects.end()); ASSERT(g_root_objects.find(obj) != g_root_objects.end());
NPObjectSet* set = g_root_objects[obj]; NPObjectSet* set = g_root_objects.get(obj);
while (set->size() > 0) { while (set->size() > 0) {
#ifndef NDEBUG #ifndef NDEBUG
size_t size = set->size(); int size = set->size();
#endif #endif
NPObject* sub_object = *(set->begin()); NPObject* sub_object = *(set->begin());
// The sub-object should not be a owner! // The sub-object should not be a owner!
ASSERT(g_root_objects.find(sub_object) == g_root_objects.end()); ASSERT(g_root_objects.find(sub_object) == g_root_objects.end());
// First, unregister the object. // First, unregister the object.
set->erase(sub_object); set->remove(sub_object);
g_live_objects.erase(sub_object); g_live_objects.remove(sub_object);
// Remove the JS references to the object. // Remove the JS references to the object.
ForgetV8ObjectForNPObject(sub_object); ForgetV8ObjectForNPObject(sub_object);
...@@ -349,18 +402,18 @@ void _NPN_UnregisterObject(NPObject* obj) { ...@@ -349,18 +402,18 @@ void _NPN_UnregisterObject(NPObject* obj) {
ASSERT(set->size() < size); ASSERT(set->size() < size);
} }
delete set; delete set;
g_root_objects.erase(obj); g_root_objects.remove(obj);
} else { } else {
NPRootObjectMap::iterator owner_entry = g_root_objects.find(owner); NPRootObjectMap::iterator owner_entry = g_root_objects.find(owner);
if (owner_entry != g_root_objects.end()) { if (owner_entry != g_root_objects.end()) {
NPObjectSet* list = owner_entry->second; NPObjectSet* list = owner_entry->second;
ASSERT(list->find(obj) != list->end()); ASSERT(list->find(obj) != list->end());
list->erase(obj); list->remove(obj);
} }
} }
ForgetV8ObjectForNPObject(obj); ForgetV8ObjectForNPObject(obj);
g_live_objects.erase(obj); g_live_objects.remove(obj);
} }
bool _NPN_IsAlive(NPObject* obj) { bool _NPN_IsAlive(NPObject* obj) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment