説明を見る。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 "api.h"
00031 #include "global-handles.h"
00032
00033 namespace v8 { namespace internal {
00034
00035 class GlobalHandles::Node : public Malloced {
00036 public:
00037
00038 void Initialize(Object* object) {
00039
00040 object_ = object;
00041 state_ = NORMAL;
00042 parameter_or_next_free_.parameter = NULL;
00043 callback_ = NULL;
00044 }
00045
00046 explicit Node(Object* object) {
00047 Initialize(object);
00048
00049 next_ = NULL;
00050 }
00051
00052 ~Node() {
00053 if (state_ != DESTROYED) Destroy();
00054 #ifdef DEBUG
00055
00056 object_ = NULL;
00057 next_ = NULL;
00058 parameter_or_next_free_.next_free = NULL;
00059 #endif
00060 }
00061
00062 void Destroy() {
00063 if (state_ == WEAK || IsNearDeath()) {
00064 GlobalHandles::number_of_weak_handles_--;
00065 if (object_->IsJSGlobalObject()) {
00066 GlobalHandles::number_of_global_object_weak_handles_--;
00067 }
00068 }
00069 state_ = DESTROYED;
00070 }
00071
00072
00073 Node* next() { return next_; }
00074 void set_next(Node* value) { next_ = value; }
00075 Node** next_addr() { return &next_; }
00076
00077
00078 Node* next_free() {
00079 ASSERT(state_ == DESTROYED);
00080 return parameter_or_next_free_.next_free;
00081 }
00082 void set_next_free(Node* value) {
00083 ASSERT(state_ == DESTROYED);
00084 parameter_or_next_free_.next_free = value;
00085 }
00086
00087
00088 static Node* FromLocation(Object** location) {
00089 ASSERT(OFFSET_OF(Node, object_) == 0);
00090 return reinterpret_cast<Node*>(location);
00091 }
00092
00093
00094 Handle<Object> handle() { return Handle<Object>(&object_); }
00095
00096
00097 void MakeWeak(void* parameter, WeakReferenceCallback callback) {
00098 LOG(HandleEvent("GlobalHandle::MakeWeak", handle().location()));
00099 if (state_ != WEAK && !IsNearDeath()) {
00100 GlobalHandles::number_of_weak_handles_++;
00101 if (object_->IsJSGlobalObject()) {
00102 GlobalHandles::number_of_global_object_weak_handles_++;
00103 }
00104 }
00105 state_ = WEAK;
00106 set_parameter(parameter);
00107 callback_ = callback;
00108 }
00109
00110 void ClearWeakness() {
00111 LOG(HandleEvent("GlobalHandle::ClearWeakness", handle().location()));
00112 if (state_ == WEAK || IsNearDeath()) {
00113 GlobalHandles::number_of_weak_handles_--;
00114 if (object_->IsJSGlobalObject()) {
00115 GlobalHandles::number_of_global_object_weak_handles_--;
00116 }
00117 }
00118 state_ = NORMAL;
00119 set_parameter(NULL);
00120 }
00121
00122 bool IsNearDeath() {
00123
00124 return state_ == PENDING || state_ == NEAR_DEATH;
00125 }
00126
00127 bool IsWeak() {
00128 return state_ == WEAK;
00129 }
00130
00131
00132 void set_parameter(void* parameter) {
00133 ASSERT(state_ != DESTROYED);
00134 parameter_or_next_free_.parameter = parameter;
00135 }
00136 void* parameter() {
00137 ASSERT(state_ != DESTROYED);
00138 return parameter_or_next_free_.parameter;
00139 }
00140
00141
00142 WeakReferenceCallback callback() { return callback_; }
00143
00144 void PostGarbageCollectionProcessing() {
00145 if (state_ != Node::PENDING) return;
00146 LOG(HandleEvent("GlobalHandle::Processing", handle().location()));
00147 void* par = parameter();
00148 state_ = NEAR_DEATH;
00149 set_parameter(NULL);
00150
00151
00152 WeakReferenceCallback func = callback();
00153 if (func != NULL) {
00154 func(v8::Persistent<v8::Object>(ToApi<v8::Object>(handle())), par);
00155 }
00156 }
00157
00158
00159 Object* object_;
00160
00161
00162
00163 enum State {
00164 NORMAL,
00165 WEAK,
00166 PENDING,
00167 NEAR_DEATH,
00168 DESTROYED
00169 };
00170 State state_;
00171
00172 private:
00173
00174 WeakReferenceCallback callback_;
00175
00176
00177 union {
00178 void* parameter;
00179 Node* next_free;
00180 } parameter_or_next_free_;
00181
00182
00183 Node* next_;
00184
00185 public:
00186 TRACK_MEMORY("GlobalHandles::Node")
00187 };
00188
00189
00190 Handle<Object> GlobalHandles::Create(Object* value) {
00191 Counters::global_handles.Increment();
00192 Node* result;
00193 if (first_free() == NULL) {
00194
00195 result = new Node(value);
00196 result->set_next(head());
00197 set_head(result);
00198 } else {
00199
00200 result = first_free();
00201 set_first_free(result->next_free());
00202 result->Initialize(value);
00203 }
00204 return result->handle();
00205 }
00206
00207
00208 void GlobalHandles::Destroy(Object** location) {
00209 Counters::global_handles.Decrement();
00210 if (location == NULL) return;
00211 Node* node = Node::FromLocation(location);
00212 node->Destroy();
00213
00214 node->set_next_free(first_free());
00215 set_first_free(node);
00216 }
00217
00218
00219 void GlobalHandles::MakeWeak(Object** location, void* parameter,
00220 WeakReferenceCallback callback) {
00221 ASSERT(callback != NULL);
00222 Node::FromLocation(location)->MakeWeak(parameter, callback);
00223 }
00224
00225
00226 void GlobalHandles::ClearWeakness(Object** location) {
00227 Node::FromLocation(location)->ClearWeakness();
00228 }
00229
00230
00231 bool GlobalHandles::IsNearDeath(Object** location) {
00232 return Node::FromLocation(location)->IsNearDeath();
00233 }
00234
00235
00236 bool GlobalHandles::IsWeak(Object** location) {
00237 return Node::FromLocation(location)->IsWeak();
00238 }
00239
00240
00241 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) {
00242
00243
00244 for (Node* current = head_; current != NULL; current = current->next()) {
00245 if (current->state_ == Node::WEAK
00246 || current->state_ == Node::PENDING
00247 || current->state_ == Node::NEAR_DEATH) {
00248 v->VisitPointer(¤t->object_);
00249 }
00250 }
00251 }
00252
00253
00254 void GlobalHandles::MarkWeakRoots(WeakSlotCallback f) {
00255 for (Node* current = head_; current != NULL; current = current->next()) {
00256 if (current->state_ == Node::WEAK) {
00257 if (f(¤t->object_)) {
00258 current->state_ = Node::PENDING;
00259 LOG(HandleEvent("GlobalHandle::Pending", current->handle().location()));
00260 }
00261 }
00262 }
00263 }
00264
00265
00266 void GlobalHandles::PostGarbageCollectionProcessing() {
00267
00268
00269
00270
00271 ASSERT(Heap::gc_state() == Heap::NOT_IN_GC);
00272 Node** p = &head_;
00273 while (*p != NULL) {
00274 (*p)->PostGarbageCollectionProcessing();
00275 if ((*p)->state_ == Node::DESTROYED) {
00276
00277 Node* node = *p;
00278 *p = node->next();
00279 delete node;
00280 } else {
00281 p = (*p)->next_addr();
00282 }
00283 }
00284 set_first_free(NULL);
00285 }
00286
00287
00288 void GlobalHandles::IterateRoots(ObjectVisitor* v) {
00289
00290 for (Node* current = head_; current != NULL; current = current->next()) {
00291 if (current->state_ == Node::NORMAL) {
00292 v->VisitPointer(¤t->object_);
00293 }
00294 }
00295 }
00296
00297 void GlobalHandles::TearDown() {
00298
00299 Node* current = head_;
00300 while (current != NULL) {
00301 Node* n = current;
00302 current = current->next();
00303 delete n;
00304 }
00305
00306 set_head(NULL);
00307 set_first_free(NULL);
00308 }
00309
00310
00311 int GlobalHandles::number_of_weak_handles_ = 0;
00312 int GlobalHandles::number_of_global_object_weak_handles_ = 0;
00313
00314 GlobalHandles::Node* GlobalHandles::head_ = NULL;
00315 GlobalHandles::Node* GlobalHandles::first_free_ = NULL;
00316
00317 #ifdef DEBUG
00318
00319 void GlobalHandles::PrintStats() {
00320 int total = 0;
00321 int weak = 0;
00322 int pending = 0;
00323 int near_death = 0;
00324 int destroyed = 0;
00325
00326 for (Node* current = head_; current != NULL; current = current->next()) {
00327 total++;
00328 if (current->state_ == Node::WEAK) weak++;
00329 if (current->state_ == Node::PENDING) pending++;
00330 if (current->state_ == Node::NEAR_DEATH) near_death++;
00331 if (current->state_ == Node::DESTROYED) destroyed++;
00332 }
00333
00334 PrintF("Global Handle Statistics:\n");
00335 PrintF(" allocated memory = %dB\n", sizeof(Node) * total);
00336 PrintF(" # weak = %d\n", weak);
00337 PrintF(" # pending = %d\n", pending);
00338 PrintF(" # near_death = %d\n", near_death);
00339 PrintF(" # destroyed = %d\n", destroyed);
00340 PrintF(" # total = %d\n", total);
00341 }
00342
00343 void GlobalHandles::Print() {
00344 PrintF("Global handles:\n");
00345 for (Node* current = head_; current != NULL; current = current->next()) {
00346 PrintF(" handle %p to %p (weak=%d)\n", current->handle().location(),
00347 *current->handle(), current->state_ == Node::WEAK);
00348 }
00349 }
00350
00351 #endif
00352
00353 List<ObjectGroup*> GlobalHandles::object_groups_(4);
00354
00355 void GlobalHandles::AddToGroup(void* id, Object** handle) {
00356 for (int i = 0; i < object_groups_.length(); i++) {
00357 ObjectGroup* entry = object_groups_[i];
00358 if (entry->id_ == id) {
00359 entry->objects_.Add(handle);
00360 return;
00361 }
00362 }
00363
00364
00365 ObjectGroup* new_entry = new ObjectGroup(id);
00366 new_entry->objects_.Add(handle);
00367 object_groups_.Add(new_entry);
00368 }
00369
00370
00371 void GlobalHandles::RemoveObjectGroups() {
00372 for (int i = 0; i< object_groups_.length(); i++) {
00373 delete object_groups_[i];
00374 }
00375 object_groups_.Clear();
00376 }
00377
00378
00379 } }