Index: src/global-handles.cc |
diff --git a/src/global-handles.cc b/src/global-handles.cc |
index 392a1810bef62c46ec5a999682d89951e362c677..09704b16ccef336cda87c25bc06de516eec902d1 100644 |
--- a/src/global-handles.cc |
+++ b/src/global-handles.cc |
@@ -41,12 +41,21 @@ ObjectGroup::~ObjectGroup() { |
} |
+const uint8_t NodeIndependentFlag = 6; |
+const uint8_t NodePartiallyDependentFlag = 5; |
+const uint8_t NodeInNewSpaceListFlag = 4; |
+const uint8_t NodeIndependentFlagMask = 1 << NodeIndependentFlag; |
+const uint8_t NodePartiallyDependentFlagMask = 1 << NodePartiallyDependentFlag; |
+const uint8_t NodeInNewSpaceListFlagMask = 1 << NodeInNewSpaceListFlag; |
+const uint8_t NodeStateMask = 0xf; |
+ |
+ |
class GlobalHandles::Node { |
public: |
// State transition diagram: |
// FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE } |
enum State { |
- FREE, |
+ FREE = 0, |
NORMAL, // Normal global handle. |
WEAK, // Flagged as weak but not yet finalized. |
PENDING, // Has been recognized as only reachable by weak handles. |
@@ -68,9 +77,9 @@ class GlobalHandles::Node { |
object_ = NULL; |
class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
index_ = 0; |
- independent_ = false; |
- partially_dependent_ = false; |
- in_new_space_list_ = false; |
+ set_independent(false); |
+ set_partially_dependent_(false); |
+ set_in_new_space_list_(false); |
parameter_or_next_free_.next_free = NULL; |
callback_ = NULL; |
} |
@@ -79,33 +88,33 @@ class GlobalHandles::Node { |
void Initialize(int index, Node** first_free) { |
index_ = static_cast<uint8_t>(index); |
ASSERT(static_cast<int>(index_) == index); |
- state_ = FREE; |
- in_new_space_list_ = false; |
+ set_state(FREE); |
+ set_in_new_space_list(false); |
parameter_or_next_free_.next_free = *first_free; |
*first_free = this; |
} |
void Acquire(Object* object, GlobalHandles* global_handles) { |
- ASSERT(state_ == FREE); |
+ ASSERT(state() == FREE); |
object_ = object; |
class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
- independent_ = false; |
- partially_dependent_ = false; |
- state_ = NORMAL; |
+ set_independent(false); |
+ set_partially_dependent(false); |
+ set_state(NORMAL); |
parameter_or_next_free_.parameter = NULL; |
callback_ = NULL; |
IncreaseBlockUses(global_handles); |
} |
void Release(GlobalHandles* global_handles) { |
- ASSERT(state_ != FREE); |
+ ASSERT(state() != FREE); |
if (IsWeakRetainer()) { |
global_handles->number_of_weak_handles_--; |
if (object_->IsJSGlobalObject()) { |
global_handles->number_of_global_object_weak_handles_--; |
} |
} |
- state_ = FREE; |
+ set_state(FREE); |
parameter_or_next_free_.next_free = global_handles->first_free_; |
global_handles->first_free_ = this; |
DecreaseBlockUses(global_handles); |
@@ -120,115 +129,143 @@ class GlobalHandles::Node { |
bool has_wrapper_class_id() const { |
return class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId; |
} |
+ |
uint16_t wrapper_class_id() const { return class_id_; } |
void set_wrapper_class_id(uint16_t class_id) { |
- class_id_ = class_id; |
+ class_id_ = static_cast<uint8_t>(class_id); |
Michael Starzinger
2013/01/15 09:06:41
The class_id is a full 16 bit, we can drop this ca
haraken
2013/01/15 09:40:39
Done.
|
+ } |
+ |
+ // State and flag accessors. |
+ |
+ State state() const { |
+ return static_cast<State>(flags_and_state_ & NodeStateMask); |
Michael Starzinger
2013/01/15 09:06:41
Instead of using all of this hand-written magic, c
haraken
2013/01/15 09:40:39
Done.
|
+ } |
+ void set_state(State state) { |
+ flags_and_state_ = |
+ (flags_and_state_ & ~NodeStateMask) | state; |
+ } |
+ |
+ bool is_independent() { |
+ return flags_and_state_ & NodeIndependentFlagMask; |
+ } |
+ void set_independent(bool v) { |
+ flags_and_state_ = |
+ (flags_and_state_ & ~NodeIndependentFlagMask) | |
+ (static_cast<uint8_t>(v) << NodeIndependentFlag); |
} |
- // State accessors. |
+ bool is_partially_dependent() { |
+ return flags_and_state_ & NodePartiallyDependentFlagMask; |
+ } |
+ void set_partially_dependent(bool v) { |
+ flags_and_state_ = |
+ (flags_and_state_ & ~NodePartiallyDependentFlagMask) | |
+ (static_cast<uint8_t>(v) << NodePartiallyDependentFlag); |
+ } |
- State state() const { return state_; } |
+ bool is_in_new_space_list() { |
+ return flags_and_state_ & NodeInNewSpaceListFlagMask; |
+ } |
+ void set_in_new_space_list(bool v) { |
+ flags_and_state_ = |
+ (flags_and_state_ & ~NodeInNewSpaceListFlagMask) | |
+ (static_cast<uint8_t>(v) << NodeInNewSpaceListFlag); |
+ } |
bool IsNearDeath() const { |
// Check for PENDING to ensure correct answer when processing callbacks. |
- return state_ == PENDING || state_ == NEAR_DEATH; |
+ return state() == PENDING || state() == NEAR_DEATH; |
} |
- bool IsWeak() const { return state_ == WEAK; } |
+ bool IsWeak() const { return state() == WEAK; } |
- bool IsRetainer() const { return state_ != FREE; } |
+ bool IsRetainer() const { return state() != FREE; } |
- bool IsStrongRetainer() const { return state_ == NORMAL; } |
+ bool IsStrongRetainer() const { return state() == NORMAL; } |
bool IsWeakRetainer() const { |
- return state_ == WEAK || state_ == PENDING || state_ == NEAR_DEATH; |
+ return state() == WEAK || state() == PENDING || state() == NEAR_DEATH; |
} |
void MarkPending() { |
- ASSERT(state_ == WEAK); |
- state_ = PENDING; |
+ ASSERT(state() == WEAK); |
+ set_state(PENDING); |
} |
// Independent flag accessors. |
void MarkIndependent() { |
- ASSERT(state_ != FREE); |
- independent_ = true; |
+ ASSERT(state() != FREE); |
+ set_independent(true); |
} |
- bool is_independent() const { return independent_; } |
void MarkPartiallyDependent(GlobalHandles* global_handles) { |
- ASSERT(state_ != FREE); |
+ ASSERT(state() != FREE); |
if (global_handles->isolate()->heap()->InNewSpace(object_)) { |
- partially_dependent_ = true; |
+ set_partially_dependent(true); |
} |
} |
- bool is_partially_dependent() const { return partially_dependent_; } |
- void clear_partially_dependent() { partially_dependent_ = false; } |
- |
- // In-new-space-list flag accessors. |
- void set_in_new_space_list(bool v) { in_new_space_list_ = v; } |
- bool is_in_new_space_list() const { return in_new_space_list_; } |
+ void clear_partially_dependent() { set_partially_dependent(false); } |
// Callback accessor. |
WeakReferenceCallback callback() { return callback_; } |
// Callback parameter accessors. |
void set_parameter(void* parameter) { |
- ASSERT(state_ != FREE); |
+ ASSERT(state() != FREE); |
parameter_or_next_free_.parameter = parameter; |
} |
void* parameter() const { |
- ASSERT(state_ != FREE); |
+ ASSERT(state() != FREE); |
return parameter_or_next_free_.parameter; |
} |
// Accessors for next free node in the free list. |
Node* next_free() { |
- ASSERT(state_ == FREE); |
+ ASSERT(state() == FREE); |
return parameter_or_next_free_.next_free; |
} |
void set_next_free(Node* value) { |
- ASSERT(state_ == FREE); |
+ ASSERT(state() == FREE); |
parameter_or_next_free_.next_free = value; |
} |
void MakeWeak(GlobalHandles* global_handles, |
void* parameter, |
WeakReferenceCallback callback) { |
- ASSERT(state_ != FREE); |
+ ASSERT(state() != FREE); |
if (!IsWeakRetainer()) { |
global_handles->number_of_weak_handles_++; |
if (object_->IsJSGlobalObject()) { |
global_handles->number_of_global_object_weak_handles_++; |
} |
} |
- state_ = WEAK; |
+ set_state(WEAK); |
set_parameter(parameter); |
callback_ = callback; |
} |
void ClearWeakness(GlobalHandles* global_handles) { |
- ASSERT(state_ != FREE); |
+ ASSERT(state() != FREE); |
if (IsWeakRetainer()) { |
global_handles->number_of_weak_handles_--; |
if (object_->IsJSGlobalObject()) { |
global_handles->number_of_global_object_weak_handles_--; |
} |
} |
- state_ = NORMAL; |
+ set_state(NORMAL); |
set_parameter(NULL); |
} |
bool PostGarbageCollectionProcessing(Isolate* isolate, |
GlobalHandles* global_handles) { |
- if (state_ != Node::PENDING) return false; |
+ if (state() != Node::PENDING) return false; |
WeakReferenceCallback func = callback(); |
if (func == NULL) { |
Release(global_handles); |
return false; |
} |
void* par = parameter(); |
- state_ = NEAR_DEATH; |
+ set_state(NEAR_DEATH); |
set_parameter(NULL); |
v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); |
@@ -245,7 +282,7 @@ class GlobalHandles::Node { |
} |
// Absence of explicit cleanup or revival of weak handle |
// in most of the cases would lead to memory leak. |
- ASSERT(state_ != NEAR_DEATH); |
+ ASSERT(state() != NEAR_DEATH); |
return true; |
} |
@@ -267,12 +304,9 @@ class GlobalHandles::Node { |
// Index in the containing handle block. |
uint8_t index_; |
- // Need one more bit for MSVC as it treats enums as signed. |
- State state_ : 4; |
- |
- bool independent_ : 1; |
- bool partially_dependent_ : 1; |
- bool in_new_space_list_ : 1; |
+ // This stores three flags (independent, partially_dependent and |
+ // in_new_space_list) and a State. |
+ uint8_t flags_and_state_; |
Michael Starzinger
2013/01/15 09:06:41
Let's just call this field "flags_".
haraken
2013/01/15 09:40:39
Done.
|
// Handle specific callback. |
WeakReferenceCallback callback_; |