Skip to content

Commit

Permalink
Use handle index in aux_word
Browse files Browse the repository at this point in the history
  • Loading branch information
dbussink committed Jun 5, 2012
1 parent c6eac13 commit 737cc57
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 14 deletions.
16 changes: 16 additions & 0 deletions vm/capi/handles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,22 @@ namespace rubinius {
return handle;
}

uintptr_t Handles::allocate_index(STATE, Object* obj) {
bool needs_gc = false;
uintptr_t handle_index = allocator_->allocate_index(&needs_gc);
Handle* handle = allocator_->from_index(handle_index);
handle->set_object(obj);
handle->validate();
if(needs_gc) {
state->memory()->collect_mature_now = true;
}
return handle_index;
}

Handle* Handles::find_index(STATE, uintptr_t index) {
return allocator_->from_index(index);
}

void Handles::deallocate_handles(std::list<Handle*>* cached, int mark, BakerGC* young) {

std::vector<bool> chunk_marks(allocator_->chunks_.size(), false);
Expand Down
4 changes: 2 additions & 2 deletions vm/capi/handles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ namespace rubinius {

Handle* allocate(STATE, Object* obj);

uint32_t allocate_index(STATE, Object* obj);
Handle* find_index(STATE, uint32_t index);
uintptr_t allocate_index(STATE, Object* obj);
Handle* find_index(STATE, uintptr_t index);

void deallocate_handles(std::list<Handle*>* cached, int mark, BakerGC* young);

Expand Down
1 change: 0 additions & 1 deletion vm/gc/baker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,6 @@ namespace rubinius {

if(!i->weak_p() && i->object()->young_object_p()) {
i->set_object(saw_object(i->object()));
assert(i->object()->inflated_header_p());

// Users manipulate values accessible from the data* within an
// RData without running a write barrier. Thusly if we see a mature
Expand Down
31 changes: 30 additions & 1 deletion vm/objectmemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,6 @@ namespace rubinius {
case eAuxWordHandle:
// Handle in use so inflate and update handle
ih = inflated_headers_->allocate(obj);
// TODO: update with proper handle
ih->set_handle(state, obj->handle(state));
break;
}
Expand Down Expand Up @@ -384,6 +383,10 @@ namespace rubinius {
ih = inflated_headers_->allocate(obj);
ih->set_object_id(orig.f.aux_word);
break;
case eAuxWordHandle:
ih = inflated_headers_->allocate(obj);
ih->set_handle(state, obj->handle(state));
break;
case eAuxWordLock:
// We have to be locking the object to inflate it, thats the law.
if(new_val.f.aux_word >> cAuxLockTIDShift != state->vm()->thread_id()) {
Expand Down Expand Up @@ -694,6 +697,7 @@ namespace rubinius {
}

InflatedHeader* header = inflated_headers_->allocate(obj);
header->set_handle(state, obj->handle(state));
header->set_object_id(id);

if(!obj->set_inflated_header(header)) {
Expand All @@ -708,6 +712,31 @@ namespace rubinius {

}

void ObjectMemory::inflate_for_handle(STATE, ObjectHeader* obj, capi::Handle* handle) {
SYNC(state);

HeaderWord orig = obj->header;

if(orig.f.inflated) {
rubinius::bug("Massive header state confusion detected. Call a doctor.");
}

InflatedHeader* header = inflated_headers_->allocate(obj);
header->set_handle(state, handle);
header->set_object_id(obj->object_id());

if(!obj->set_inflated_header(header)) {
if(obj->inflated_header_p()) {
obj->inflated_header()->set_handle(state, handle);
return;
}

// Now things are really in a weird state, just abort.
rubinius::bug("Massive header state confusion detected. Call a doctor.");
}

}

void ObjectMemory::prune_handles(capi::Handles* handles, std::list<capi::Handle*>* cached, BakerGC* young) {
handles->deallocate_handles(cached, mark(), young);
}
Expand Down
1 change: 1 addition & 0 deletions vm/objectmemory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ namespace rubinius {

InflatedHeader* inflate_header(STATE, ObjectHeader* obj);
void inflate_for_id(STATE, ObjectHeader* obj, uint32_t id);
void inflate_for_handle(STATE, ObjectHeader* obj, capi::Handle* handle);

void in_finalizer_thread(STATE);
void start_finalizer_thread(STATE);
Expand Down
60 changes: 60 additions & 0 deletions vm/oop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "builtin/class.hpp"
#include "builtin/exception.hpp"

#include "capi/handles.hpp"

#include "objectmemory.hpp"
#include "configuration.hpp"

Expand Down Expand Up @@ -132,6 +134,64 @@ namespace rubinius {
}
}

// Run only while om's lock is held.
void ObjectHeader::set_handle_index(STATE, uintptr_t handle_index) {
// Construct 2 new headers: one is the version we hope that
// is in use and the other is what we want it to be. The CAS
// the new one into place.
HeaderWord orig = header;

orig.f.inflated = 0;
orig.f.meaning = eAuxWordEmpty;
orig.f.aux_word = 0;

HeaderWord new_val = orig;

new_val.f.meaning = eAuxWordHandle;
new_val.f.aux_word = (uint32_t) handle_index;

if(handle_index < UINT32_MAX && header.atomic_set(orig, new_val)) return;

capi::Handle* handle = state->shared().global_handles()->find_index(state, handle_index);

orig = header;

if(orig.f.inflated) {
ObjectHeader::header_to_inflated_header(orig)->set_handle(state, handle);
return;
}

switch(orig.f.meaning) {
case eAuxWordEmpty:
case eAuxWordHandle:
assert(0);
case eAuxWordLock:
case eAuxWordObjID:
// not inflated, and the aux_word is being used for locking
// or a handle.
// Inflate!

state->memory()->inflate_for_handle(state, this, handle);
}
}

capi::Handle* ObjectHeader::handle(STATE) {
HeaderWord tmp = header;
if(tmp.f.inflated) {
return header_to_inflated_header(tmp)->handle(state);
}

capi::Handle* h = NULL;
switch(tmp.f.meaning) {
case eAuxWordHandle:
h = state->shared().global_handles()->find_index(state, tmp.f.aux_word);
assert(h->object() == this);
return h;
default:
return NULL;
}
}

LockStatus ObjectHeader::lock(STATE, GCToken gct, size_t us) {
// #1 Attempt to lock an unlocked object using CAS.

Expand Down
18 changes: 12 additions & 6 deletions vm/oop.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,12 +394,7 @@ Object* const cUndef = reinterpret_cast<Object*>(0x22L);
flags().obj_type = type;
}

capi::Handle* handle(STATE) {
if(inflated_header_p()) {
return inflated_header()->handle(state);
}
return NULL;
}
capi::Handle* handle(STATE);

void set_handle(STATE, capi::Handle* handle) {
assert(inflated_header_p());
Expand All @@ -411,9 +406,20 @@ Object* const cUndef = reinterpret_cast<Object*>(0x22L);
void clear_handle(STATE) {
if(inflated_header_p()) {
inflated_header()->set_handle(state, NULL);
} else {
HeaderWord orig = header;
orig.f.meaning = eAuxWordHandle;

HeaderWord new_val = orig;
new_val.f.meaning = eAuxWordEmpty;
new_val.f.aux_word = 0;

if(header.atomic_set(orig, new_val)) return;
}
}

void set_handle_index(STATE, uintptr_t handle_index);

public:

void initialize_copy(ObjectMemory* om, Object* other, unsigned int age);
Expand Down
9 changes: 5 additions & 4 deletions vm/shared_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,11 @@ namespace rubinius {

capi::Handle* SharedState::add_global_handle(STATE, Object* obj) {
SYNC(state);
InflatedHeader* ih = state->memory()->inflate_header(state, obj);
capi::Handle* handle = global_handles_->allocate(state, obj);
ih->set_handle(state, handle);
return handle;
//state->memory()->inflate_header(state, obj);
assert(obj->reference_p());
uintptr_t handle_index = global_handles_->allocate_index(state, obj);
obj->set_handle_index(state, handle_index);
return obj->handle(state);
}

void SharedState::make_handle_cached(STATE, capi::Handle* handle) {
Expand Down
12 changes: 12 additions & 0 deletions vm/util/allocator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,18 @@ namespace rubinius {
return t;
}

uintptr_t allocate_index(bool* needs_gc) {
if(!free_list_) allocate_chunk(needs_gc);

uintptr_t next_index = free_list_;
T* t = from_index(free_list_);
free_list_ = t->next();
t->clear();
in_use_++;

return next_index;
}

T* from_index(uintptr_t index) {
return chunks_[index / cChunkSize] + (index % cChunkSize);
}
Expand Down

0 comments on commit 737cc57

Please sign in to comment.