Pack GlobalHandles::Node::state_ and three flags into uint8_t

TEST=test-api.cc (ApiObjectGroupsCycle, ApiObjectGroupsCycleForScavenger, IndependentWeakHandle)

Review URL: https://codereview.chromium.org/11875015
Patch from Kentaro Hara <haraken@chromium.org>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13383 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f15f2941
...@@ -46,7 +46,7 @@ class GlobalHandles::Node { ...@@ -46,7 +46,7 @@ class GlobalHandles::Node {
// State transition diagram: // State transition diagram:
// FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE } // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE }
enum State { enum State {
FREE, FREE = 0,
NORMAL, // Normal global handle. NORMAL, // Normal global handle.
WEAK, // Flagged as weak but not yet finalized. WEAK, // Flagged as weak but not yet finalized.
PENDING, // Has been recognized as only reachable by weak handles. PENDING, // Has been recognized as only reachable by weak handles.
...@@ -68,9 +68,9 @@ class GlobalHandles::Node { ...@@ -68,9 +68,9 @@ class GlobalHandles::Node {
object_ = NULL; object_ = NULL;
class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
index_ = 0; index_ = 0;
independent_ = false; set_independent(false);
partially_dependent_ = false; set_partially_dependent(false);
in_new_space_list_ = false; set_in_new_space_list(false);
parameter_or_next_free_.next_free = NULL; parameter_or_next_free_.next_free = NULL;
callback_ = NULL; callback_ = NULL;
} }
...@@ -79,33 +79,33 @@ class GlobalHandles::Node { ...@@ -79,33 +79,33 @@ class GlobalHandles::Node {
void Initialize(int index, Node** first_free) { void Initialize(int index, Node** first_free) {
index_ = static_cast<uint8_t>(index); index_ = static_cast<uint8_t>(index);
ASSERT(static_cast<int>(index_) == index); ASSERT(static_cast<int>(index_) == index);
state_ = FREE; set_state(FREE);
in_new_space_list_ = false; set_in_new_space_list(false);
parameter_or_next_free_.next_free = *first_free; parameter_or_next_free_.next_free = *first_free;
*first_free = this; *first_free = this;
} }
void Acquire(Object* object, GlobalHandles* global_handles) { void Acquire(Object* object, GlobalHandles* global_handles) {
ASSERT(state_ == FREE); ASSERT(state() == FREE);
object_ = object; object_ = object;
class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
independent_ = false; set_independent(false);
partially_dependent_ = false; set_partially_dependent(false);
state_ = NORMAL; set_state(NORMAL);
parameter_or_next_free_.parameter = NULL; parameter_or_next_free_.parameter = NULL;
callback_ = NULL; callback_ = NULL;
IncreaseBlockUses(global_handles); IncreaseBlockUses(global_handles);
} }
void Release(GlobalHandles* global_handles) { void Release(GlobalHandles* global_handles) {
ASSERT(state_ != FREE); ASSERT(state() != FREE);
if (IsWeakRetainer()) { if (IsWeakRetainer()) {
global_handles->number_of_weak_handles_--; global_handles->number_of_weak_handles_--;
if (object_->IsJSGlobalObject()) { if (object_->IsJSGlobalObject()) {
global_handles->number_of_global_object_weak_handles_--; global_handles->number_of_global_object_weak_handles_--;
} }
} }
state_ = FREE; set_state(FREE);
parameter_or_next_free_.next_free = global_handles->first_free_; parameter_or_next_free_.next_free = global_handles->first_free_;
global_handles->first_free_ = this; global_handles->first_free_ = this;
DecreaseBlockUses(global_handles); DecreaseBlockUses(global_handles);
...@@ -120,115 +120,134 @@ class GlobalHandles::Node { ...@@ -120,115 +120,134 @@ class GlobalHandles::Node {
bool has_wrapper_class_id() const { bool has_wrapper_class_id() const {
return class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId; return class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId;
} }
uint16_t wrapper_class_id() const { return class_id_; } uint16_t wrapper_class_id() const { return class_id_; }
void set_wrapper_class_id(uint16_t class_id) { void set_wrapper_class_id(uint16_t class_id) { class_id_ = class_id; }
class_id_ = class_id;
// State and flag accessors.
State state() const {
return NodeState::decode(flags_);
}
void set_state(State state) {
flags_ = NodeState::update(flags_, state);
}
bool is_independent() {
return IsIndependent::decode(flags_);
}
void set_independent(bool v) {
flags_ = IsIndependent::update(flags_, v);
} }
// State accessors. bool is_partially_dependent() {
return IsPartiallyDependent::decode(flags_);
}
void set_partially_dependent(bool v) {
flags_ = IsPartiallyDependent::update(flags_, v);
}
State state() const { return state_; } bool is_in_new_space_list() {
return IsInNewSpaceList::decode(flags_);
}
void set_in_new_space_list(bool v) {
flags_ = IsInNewSpaceList::update(flags_, v);
}
bool IsNearDeath() const { bool IsNearDeath() const {
// Check for PENDING to ensure correct answer when processing callbacks. // 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 { bool IsWeakRetainer() const {
return state_ == WEAK || state_ == PENDING || state_ == NEAR_DEATH; return state() == WEAK || state() == PENDING || state() == NEAR_DEATH;
} }
void MarkPending() { void MarkPending() {
ASSERT(state_ == WEAK); ASSERT(state() == WEAK);
state_ = PENDING; set_state(PENDING);
} }
// Independent flag accessors. // Independent flag accessors.
void MarkIndependent() { void MarkIndependent() {
ASSERT(state_ != FREE); ASSERT(state() != FREE);
independent_ = true; set_independent(true);
} }
bool is_independent() const { return independent_; }
void MarkPartiallyDependent(GlobalHandles* global_handles) { void MarkPartiallyDependent(GlobalHandles* global_handles) {
ASSERT(state_ != FREE); ASSERT(state() != FREE);
if (global_handles->isolate()->heap()->InNewSpace(object_)) { 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() { set_partially_dependent(false); }
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_; }
// Callback accessor. // Callback accessor.
WeakReferenceCallback callback() { return callback_; } WeakReferenceCallback callback() { return callback_; }
// Callback parameter accessors. // Callback parameter accessors.
void set_parameter(void* parameter) { void set_parameter(void* parameter) {
ASSERT(state_ != FREE); ASSERT(state() != FREE);
parameter_or_next_free_.parameter = parameter; parameter_or_next_free_.parameter = parameter;
} }
void* parameter() const { void* parameter() const {
ASSERT(state_ != FREE); ASSERT(state() != FREE);
return parameter_or_next_free_.parameter; return parameter_or_next_free_.parameter;
} }
// Accessors for next free node in the free list. // Accessors for next free node in the free list.
Node* next_free() { Node* next_free() {
ASSERT(state_ == FREE); ASSERT(state() == FREE);
return parameter_or_next_free_.next_free; return parameter_or_next_free_.next_free;
} }
void set_next_free(Node* value) { void set_next_free(Node* value) {
ASSERT(state_ == FREE); ASSERT(state() == FREE);
parameter_or_next_free_.next_free = value; parameter_or_next_free_.next_free = value;
} }
void MakeWeak(GlobalHandles* global_handles, void MakeWeak(GlobalHandles* global_handles,
void* parameter, void* parameter,
WeakReferenceCallback callback) { WeakReferenceCallback callback) {
ASSERT(state_ != FREE); ASSERT(state() != FREE);
if (!IsWeakRetainer()) { if (!IsWeakRetainer()) {
global_handles->number_of_weak_handles_++; global_handles->number_of_weak_handles_++;
if (object_->IsJSGlobalObject()) { if (object_->IsJSGlobalObject()) {
global_handles->number_of_global_object_weak_handles_++; global_handles->number_of_global_object_weak_handles_++;
} }
} }
state_ = WEAK; set_state(WEAK);
set_parameter(parameter); set_parameter(parameter);
callback_ = callback; callback_ = callback;
} }
void ClearWeakness(GlobalHandles* global_handles) { void ClearWeakness(GlobalHandles* global_handles) {
ASSERT(state_ != FREE); ASSERT(state() != FREE);
if (IsWeakRetainer()) { if (IsWeakRetainer()) {
global_handles->number_of_weak_handles_--; global_handles->number_of_weak_handles_--;
if (object_->IsJSGlobalObject()) { if (object_->IsJSGlobalObject()) {
global_handles->number_of_global_object_weak_handles_--; global_handles->number_of_global_object_weak_handles_--;
} }
} }
state_ = NORMAL; set_state(NORMAL);
set_parameter(NULL); set_parameter(NULL);
} }
bool PostGarbageCollectionProcessing(Isolate* isolate, bool PostGarbageCollectionProcessing(Isolate* isolate,
GlobalHandles* global_handles) { GlobalHandles* global_handles) {
if (state_ != Node::PENDING) return false; if (state() != Node::PENDING) return false;
WeakReferenceCallback func = callback(); WeakReferenceCallback func = callback();
if (func == NULL) { if (func == NULL) {
Release(global_handles); Release(global_handles);
return false; return false;
} }
void* par = parameter(); void* par = parameter();
state_ = NEAR_DEATH; set_state(NEAR_DEATH);
set_parameter(NULL); set_parameter(NULL);
v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle());
...@@ -245,7 +264,7 @@ class GlobalHandles::Node { ...@@ -245,7 +264,7 @@ class GlobalHandles::Node {
} }
// Absence of explicit cleanup or revival of weak handle // Absence of explicit cleanup or revival of weak handle
// in most of the cases would lead to memory leak. // in most of the cases would lead to memory leak.
ASSERT(state_ != NEAR_DEATH); ASSERT(state() != NEAR_DEATH);
return true; return true;
} }
...@@ -267,12 +286,14 @@ class GlobalHandles::Node { ...@@ -267,12 +286,14 @@ class GlobalHandles::Node {
// Index in the containing handle block. // Index in the containing handle block.
uint8_t index_; uint8_t index_;
// Need one more bit for MSVC as it treats enums as signed. // This stores three flags (independent, partially_dependent and
State state_ : 4; // in_new_space_list) and a State.
class NodeState: public BitField<State, 0, 4> {};
class IsIndependent: public BitField<bool, 4, 1> {};
class IsPartiallyDependent: public BitField<bool, 5, 1> {};
class IsInNewSpaceList: public BitField<bool, 6, 1> {};
bool independent_ : 1; uint8_t flags_;
bool partially_dependent_ : 1;
bool in_new_space_list_ : 1;
// Handle specific callback. // Handle specific callback.
WeakReferenceCallback callback_; WeakReferenceCallback callback_;
......
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