説明を見る。00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "v8.h"
00029
00030 #include "hashmap.h"
00031
00032 namespace v8 { namespace internal {
00033
00034
00035 static inline bool IsPowerOf2(uint32_t x) {
00036 ASSERT(x != 0);
00037 return (x & (x - 1)) == 0;
00038 }
00039
00040
00041 Allocator HashMap::DefaultAllocator;
00042
00043
00044 HashMap::HashMap() {
00045 allocator_ = NULL;
00046 match_ = NULL;
00047 }
00048
00049
00050 HashMap::HashMap(MatchFun match,
00051 Allocator* allocator,
00052 uint32_t initial_capacity) {
00053 allocator_ = allocator;
00054 match_ = match;
00055 Initialize(initial_capacity);
00056 }
00057
00058
00059 HashMap::~HashMap() {
00060 if (allocator_) {
00061 allocator_->Delete(map_);
00062 }
00063 }
00064
00065
00066 HashMap::Entry* HashMap::Lookup(void* key, uint32_t hash, bool insert) {
00067
00068 Entry* p = Probe(key, hash);
00069 if (p->key != NULL) {
00070 return p;
00071 }
00072
00073
00074 if (insert) {
00075 p->key = key;
00076 p->value = NULL;
00077 p->hash = hash;
00078 occupancy_++;
00079
00080
00081 if (occupancy_ + occupancy_/4 >= capacity_) {
00082 Resize();
00083 p = Probe(key, hash);
00084 }
00085
00086 return p;
00087 }
00088
00089
00090 return NULL;
00091 }
00092
00093
00094 void HashMap::Clear() {
00095
00096 const Entry* end = map_end();
00097 for (Entry* p = map_; p < end; p++) {
00098 p->key = NULL;
00099 }
00100 occupancy_ = 0;
00101 }
00102
00103
00104 HashMap::Entry* HashMap::Start() const {
00105 return Next(map_ - 1);
00106 }
00107
00108
00109 HashMap::Entry* HashMap::Next(Entry* p) const {
00110 const Entry* end = map_end();
00111 ASSERT(map_ - 1 <= p && p < end);
00112 for (p++; p < end; p++) {
00113 if (p->key != NULL) {
00114 return p;
00115 }
00116 }
00117 return NULL;
00118 }
00119
00120
00121 HashMap::Entry* HashMap::Probe(void* key, uint32_t hash) {
00122 ASSERT(key != NULL);
00123
00124 ASSERT(IsPowerOf2(capacity_));
00125 Entry* p = map_ + (hash & (capacity_ - 1));
00126 const Entry* end = map_end();
00127 ASSERT(map_ <= p && p < end);
00128
00129 ASSERT(occupancy_ < capacity_);
00130 while (p->key != NULL && (hash != p->hash || !match_(key, p->key))) {
00131 p++;
00132 if (p >= end) {
00133 p = map_;
00134 }
00135 }
00136
00137 return p;
00138 }
00139
00140
00141 void HashMap::Initialize(uint32_t capacity) {
00142 ASSERT(IsPowerOf2(capacity));
00143 map_ = reinterpret_cast<Entry*>(allocator_->New(capacity * sizeof(Entry)));
00144 if (map_ == NULL) V8::FatalProcessOutOfMemory("HashMap::Initialize");
00145 capacity_ = capacity;
00146 Clear();
00147 }
00148
00149
00150 void HashMap::Resize() {
00151 Entry* map = map_;
00152 uint32_t n = occupancy_;
00153
00154
00155 Initialize(capacity_ * 2);
00156
00157
00158 for (Entry* p = map; n > 0; p++) {
00159 if (p->key != NULL) {
00160 Lookup(p->key, p->hash, true)->value = p->value;
00161 n--;
00162 }
00163 }
00164
00165
00166 allocator_->Delete(map);
00167 }
00168
00169
00170 } }