From bde0453b997dd621a8a521b1c0353678d7ef7ee6 Mon Sep 17 00:00:00 2001 From: Brian Shirai Date: Mon, 26 Feb 2018 17:15:35 -0800 Subject: [PATCH] Switch to new MemoryHeader. --- build/scripts/field_extract.rb | 2 +- core/rubinius.rb | 15 +- core/tuple.rb | 36 +- core/vm.rb | 5 - machine/call_frame.cpp | 6 +- machine/capi/array.cpp | 294 ++---- machine/capi/bignum.cpp | 26 +- machine/capi/capi.cpp | 222 ++-- machine/capi/capi.hpp | 32 +- machine/capi/class.cpp | 53 +- machine/capi/data.cpp | 108 +- machine/capi/encoding.cpp | 37 +- machine/capi/exception.cpp | 4 +- machine/capi/file.cpp | 33 +- machine/capi/fixnum.cpp | 8 +- machine/capi/float.cpp | 58 +- machine/capi/gc.cpp | 18 +- machine/capi/globals.cpp | 29 +- machine/capi/handle.cpp | 153 --- machine/capi/handle.hpp | 290 ----- machine/capi/handles.cpp | 161 --- machine/capi/handles.hpp | 58 - machine/capi/hash.cpp | 2 +- machine/capi/integer.cpp | 6 +- machine/capi/io.cpp | 199 ++-- machine/capi/kernel.cpp | 11 +- machine/capi/module.cpp | 51 +- machine/capi/numeric.cpp | 64 +- machine/capi/object.cpp | 51 +- machine/capi/proc.cpp | 4 +- machine/capi/regexp.cpp | 3 +- machine/capi/string.cpp | 262 ++--- machine/capi/struct.cpp | 4 +- machine/capi/symbol.cpp | 2 +- machine/capi/thread.cpp | 24 +- machine/capi/time.cpp | 18 +- machine/capi/util.cpp | 8 +- machine/capi/value.hpp | 10 - machine/class/access_variable.cpp | 4 +- machine/class/array.cpp | 28 +- machine/class/array.hpp | 71 +- machine/class/block_environment.cpp | 2 +- machine/class/call_site.cpp | 5 - machine/class/call_site.hpp | 5 +- machine/class/channel.cpp | 6 +- machine/class/class.cpp | 12 +- machine/class/data.cpp | 39 +- machine/class/find_object.cpp | 2 +- machine/class/heap_dump.cpp | 400 ------- machine/class/io.cpp | 11 +- machine/class/location.cpp | 8 +- machine/class/native_method.cpp | 483 +++------ machine/class/native_method.hpp | 71 +- machine/class/object.cpp | 97 +- machine/class/object.hpp | 99 +- machine/class/pack.cpp | 7 +- machine/class/string.cpp | 22 +- machine/class/string.hpp | 49 +- machine/class/system.cpp | 78 +- machine/class/system.hpp | 12 +- machine/class/thread.cpp | 29 +- machine/class/thread.hpp | 4 - machine/class/tuple.cpp | 87 +- machine/class/tuple.hpp | 49 +- machine/class/unpack.cpp | 1 + machine/class/weakref.cpp | 24 +- machine/class/weakref.hpp | 11 +- machine/defines.hpp | 12 - machine/diagnostics.hpp | 2 +- machine/diagnostics/memory.hpp | 6 +- machine/globals.hpp | 3 +- machine/include/capi/capi_oop.h | 6 +- machine/include/capi/ruby/ruby.h | 7 +- machine/instructions.hpp | 2 +- machine/instructions/check_frozen.hpp | 2 +- machine/instructions/set_ivar.hpp | 2 +- machine/instructions/store_my_field.hpp | 2 +- machine/instructions/string_build.hpp | 4 +- machine/interpreter.cpp | 7 +- machine/machine_code.cpp | 29 +- machine/memory.cpp | 515 +-------- machine/memory.hpp | 100 +- machine/memory/finalizer.cpp | 4 +- machine/memory/gc.cpp | 93 +- machine/memory/gc.hpp | 54 +- machine/memory/header.cpp | 1292 +++++------------------ machine/memory/header.hpp | 1164 ++++++++++---------- machine/memory/immix_collector.cpp | 224 ++-- machine/memory/immix_collector.hpp | 2 +- machine/memory/inflated_headers.cpp | 72 -- machine/memory/inflated_headers.hpp | 50 - machine/memory/managed.hpp | 27 - machine/memory/mark_sweep.cpp | 23 +- machine/memory/object_mark.cpp | 7 + machine/memory/object_mark.hpp | 1 + machine/memory/walker.cpp | 6 - machine/memory/write_barrier.cpp | 21 +- machine/memory/write_barrier.hpp | 13 +- machine/object_utils.hpp | 68 +- machine/ontology.cpp | 1 + machine/shared_state.cpp | 6 +- machine/shared_state.hpp | 30 +- machine/signal.cpp | 6 +- machine/test/test_memory_header.hpp | 67 +- machine/test/test_native_method.hpp | 26 +- machine/test/test_object.hpp | 42 +- machine/test/test_object_memory.hpp | 14 +- machine/test/test_pointer.hpp | 20 +- machine/test/test_vm.hpp | 39 - machine/thread_nexus.cpp | 27 +- machine/thread_nexus.hpp | 15 + machine/thread_phase.hpp | 12 +- machine/type_info.hpp | 1 + machine/vm.cpp | 16 +- spec/ruby/core/kernel/taint_spec.rb | 16 +- spec/ruby/core/kernel/untrusted_spec.rb | 36 +- 116 files changed, 2657 insertions(+), 5620 deletions(-) delete mode 100644 machine/capi/handle.cpp delete mode 100644 machine/capi/handle.hpp delete mode 100644 machine/capi/handles.cpp delete mode 100644 machine/capi/handles.hpp delete mode 100644 machine/capi/value.hpp delete mode 100644 machine/class/heap_dump.cpp delete mode 100644 machine/memory/inflated_headers.cpp delete mode 100644 machine/memory/inflated_headers.hpp diff --git a/build/scripts/field_extract.rb b/build/scripts/field_extract.rb index a7c2634c1d..e4e924ddde 100644 --- a/build/scripts/field_extract.rb +++ b/build/scripts/field_extract.rb @@ -683,7 +683,7 @@ def strip_and_map(type, map) def parse_stream(f) class_pattern = /class\s+([^\s]+)\s*:\s*public\s+([^\s]+)/ - slot_pattern = %r!^\s*(\w+)\*?\s+\*?(\w+)_\s*;\s*//\s*slot(.*)! + slot_pattern = %r!^\s*(\w+)\*?\s+\*?_(\w+)_\s*;\s*//\s*slot(.*)! accessor_pattern = %r!^\s*attr_(accessor|reader|writer)\((\w+),\s*(\w+)\)! primitive_pattern = %r%^\s*//\s+Rubinius.primitive([?!\+])?\s+:(.*)\s*$% prototype_pattern = %r!\s*(static\s+)?([\w\*]+)\s+([\w]+)\((.*)\)! diff --git a/core/rubinius.rb b/core/rubinius.rb index c27eebbac2..445fb5330e 100644 --- a/core/rubinius.rb +++ b/core/rubinius.rb @@ -161,16 +161,6 @@ def self.lock(obj) raise PrimitiveFailure, "Rubinius.lock primitive failed" end - def self.uninterrupted_lock(obj) - Rubinius.primitive :vm_object_uninterrupted_lock - raise PrimitiveFailure, "Rubinius.uninterrupted_lock primitive failed" - end - - def self.lock_timed(obj, duration) - Rubinius.primitive :vm_object_lock_timed - raise PrimitiveFailure, "Rubinius.lock_timed primitive failed" - end - def self.try_lock(obj) Rubinius.primitive :vm_object_trylock raise PrimitiveFailure, "Rubinius.try_lock primitive failed" @@ -181,6 +171,11 @@ def self.locked?(obj) raise PrimitiveFailure, "Rubinius.locked? primitive failed" end + def self.lock_owned?(obj) + Rubinius.primitive :vm_object_lock_owned_p + raise PrimitiveFailure, "Rubinius.lock_owned? primitive failed" + end + def self.unlock(obj) Rubinius.primitive :vm_object_unlock raise PrimitiveFailure, "Rubinius.unlock primitive failed" diff --git a/core/tuple.rb b/core/tuple.rb index fa9b4bfe10..3f78ff13a7 100644 --- a/core/tuple.rb +++ b/core/tuple.rb @@ -2,10 +2,6 @@ module Rubinius class Tuple include Enumerable - def self.allocate - raise TypeError, "Tuple cannot be created via allocate()" - end - def self.new(cnt) Rubinius.primitive :tuple_allocate raise PrimitiveFailure, "Tuple.new primitive failed" @@ -324,4 +320,36 @@ def self._load(str) return t end end + + class RTuple < Tuple + include Enumerable + + def self.new(cnt) + Rubinius.primitive :rtuple_allocate + raise PrimitiveFailure, "RTuple.new primitive failed" + end + + def [](idx) + Rubinius.primitive :rtuple_at + + unless idx.kind_of? Fixnum + raise TypeError, "Only Fixnums valid for RTuple indices" + end + + raise PrimitiveFailure, "RTuple#[] primitive failed" + end + + alias_method :at, :[] + + def []=(idx, val) + Rubinius.primitive :rtuple_put + + unless idx.kind_of? Fixnum + raise TypeError, "Only Fixnums valid for RTuple indices" + end + raise PrimitiveFailure, "RTuple#[]= primitive failed" + end + + alias_method :put, :[]= + end end diff --git a/core/vm.rb b/core/vm.rb index 760d69e189..f496607ab4 100644 --- a/core/vm.rb +++ b/core/vm.rb @@ -14,11 +14,6 @@ def self.stats raise PrimitiveFailure, "Rubinius::VM.stats primitive failed" end - def self.dump_heap(path) - Rubinius.primitive :vm_dump_heap - raise PrimitiveFailure, "Rubinius::VM.dump_heap primitive failed" - end - def self.load_library(path, name) Rubinius.primitive :load_library raise PrimitiveFailure, "Rubinius::VM.load_library primitive failed" diff --git a/machine/call_frame.cpp b/machine/call_frame.cpp index b5b6691f96..95fb82bf5c 100644 --- a/machine/call_frame.cpp +++ b/machine/call_frame.cpp @@ -14,6 +14,8 @@ #include "class/variable_scope.hpp" #include "class/unwind_site.hpp" +#include "capi/capi.hpp" + #include "diagnostics/machine.hpp" #include @@ -72,7 +74,7 @@ namespace rubinius { if(NativeMethodFrame* nmf = cf->native_method_frame()) { stream << static_cast(cf) << ": "; - NativeMethod* nm = try_as(nmf->get_object(nmf->method())); + NativeMethod* nm = MemoryHandle::try_as(nmf->method()); if(nm && nm->name()->symbol_p()) { stream << "capi:" << nm->name()->debug_str(state) << " at "; stream << nm->file()->c_str(state); @@ -110,7 +112,7 @@ namespace rubinius { stream << "MAIN."; } else { stream << "#<" << obj->class_object(state)->debug_str(state) << - ":" << (void*)obj->id(state)->to_native() << ">."; + ":" << (void*)obj->object_id(state)->to_native() << ">."; } } } else if(IncludedModule* im = try_as(cf->module())) { diff --git a/machine/capi/array.cpp b/machine/capi/array.cpp index 4ea530d576..1514dc9ecc 100644 --- a/machine/capi/array.cpp +++ b/machine/capi/array.cpp @@ -1,14 +1,16 @@ #include "class/array.hpp" #include "class/fixnum.hpp" +#include "class/lookup_table.hpp" #include "class/object.hpp" #include "class/proc.hpp" #include "class/thread.hpp" -#include "class/lookup_table.hpp" -#include "memory.hpp" +#include "class/tuple.hpp" #include "arguments.hpp" #include "dispatch.hpp" #include "exception_point.hpp" +#include "memory.hpp" +#include "object_utils.hpp" #include "capi/capi.hpp" #include "capi/ruby.h" @@ -19,170 +21,94 @@ using namespace rubinius; using namespace rubinius::capi; namespace rubinius { - namespace capi { - - Array* capi_get_array(NativeMethodEnvironment* env, VALUE val) { - Handle* handle = Handle::from(val); - Array* array = c_as(handle->object()); - handle->flush(env); - - return array; + /* It is possible to create an Array in MRI whose capacity exceeds its + * current length (eg rb_ary_new2(long length)). The same is true in + * Rubinius where Array has a size() attribute and is backed by an + * instance of Tuple, whose size will always be gte Array::size(). The + * RArray structure in MRI accounts for this and we must as well when + * updating and syncing the cached values. For example: + * + * for(i = 0; i < len; i++) { + * RARRAY(ary)->ptr[i] = obj + * } + * RARRAY(ary)->len = len + */ + + RArray* MemoryHandle::get_rarray(STATE) { + if(rarray_p()) { + return reinterpret_cast(data()); + } else if(unknown_type_p()) { + Array* array = c_as(object());; + array->set_type_specific(Array::eRArray); + + RTuple* rtuple = RTuple::from(state, array->tuple()); + + native_int size = array->size(); + VALUE* ptr = reinterpret_cast(rtuple->field + array->offset()); + + RArray* rarray = new RArray; + + rarray->dmwmb = rarray->ptr = ptr; + rarray->len = size; + rarray->aux.capa = size; + rarray->aux.shared = Qfalse; + + set_rarray(rarray); + return rarray; + } else { + Exception::raise_runtime_error(state, "C-API handle invalid reference as RArray"); } + } - void capi_update_array(NativeMethodEnvironment* env, VALUE array) { - Handle::from(array)->update(env); - } + void MemoryHandle::read_rarray(STATE) { + if(rarray_p()) { + Array* array = as(object()); + RArray* rarray = reinterpret_cast(data()); - /* We were in C-land and now we are returning to Ruby-land. Since the C - * program can freely assign to RArray.len and RArray.ptr, we account - * for that when updating the Ruby Array with the C structure contents. - * - * Note that we must copy the total elements in the cached C array - * regardless of the value of the len parameter because the C array - * contents can be changed indepedently from the len parameter. - * - * See Handle::as_rarray below. - */ - void flush_cached_rarray(NativeMethodEnvironment* env, Handle* handle) { - if(handle->is_rarray()) { - Array* array = c_as(handle->object()); - Tuple* tuple = array->tuple(); - RArray* rarray = handle->as_rarray(env); - - native_int size = tuple->num_fields(); - native_int num = 0; - - if(rarray->ptr != rarray->dmwmb) { - // This is a very bad C extension. Assume len is valid. - num = rarray->len; + if(array->size() != rarray->len) { + if(rarray->len <= array->tuple()->num_fields() - array->offset()) { + array->total(Fixnum::from(rarray->len)); } else { - num = rarray->aux.capa; - } - - if(num > size) { - tuple = Tuple::create(env->state(), rarray->aux.capa); - array->tuple(env->state(), tuple); - } - - array->start(env->state(), Fixnum::from(0)); - array->total(env->state(), Fixnum::from(rarray->len)); - - for(native_int i = 0; i < num; i++) { - tuple->put(env->state(), i, env->get_object(rarray->ptr[i])); + // TODO: MemoryHeader raise error rarray->len set beyond capa } } } + } - /* We were in Ruby-land and we are heading to C-land. In Ruby-land, we - * may have updated the existing Array elements, appended new elements, - * or shifted off elements. We account for this when updating the C - * structure contents. - * - * We are potentially writing into a C structure that exists and that - * may have been changed in C-land. It is possible for C code to change - * both the len and ptr values of an RArray. We DO NOT EVER encourage - * doing this, but we must account for it. The C code may also merely - * change the contents of the array pointed to by ptr. Updating that - * array with the current elements in the Ruby Array is the purpose of - * this code. - */ - void update_cached_rarray(NativeMethodEnvironment* env, Handle* handle) { - if(handle->is_rarray()) { - Array* array = c_as(handle->object()); - Tuple* tuple = array->tuple(); - RArray* rarray = handle->as_rarray(env); - - native_int size = tuple->num_fields(); - native_int start = array->start()->to_native(); - native_int num = 0; - - if(rarray->ptr != rarray->dmwmb) { - // This is a very bad C extension. Assume len is valid - // and do not change its value. - num = rarray->len; - } else { - env->shared().capi_ds_lock().lock(); - - if(rarray->aux.capa < size) { - delete[] rarray->dmwmb; - rarray->dmwmb = rarray->ptr = new VALUE[size]; - rarray->aux.capa = size; - } - num = rarray->aux.capa; - rarray->len = array->size(); + void MemoryHandle::write_rarray(STATE) { + if(rarray_p()) { + Array* array = as(object()); + RArray* rarray = reinterpret_cast(data()); - env->shared().capi_ds_lock().unlock(); - } + RTuple* rtuple; - for(native_int i = 0, j = start; i < num && j < size; i++, j++) { - rarray->ptr[i] = env->get_handle(tuple->at(j)); - } + if(array->tuple()->type_id() == RTupleType) { + rtuple = reinterpret_cast(array->tuple()); + } else { + rtuple = RTuple::from(state, array->tuple()); } - } - - /* It is possible to create an Array in MRI whose capacity exceeds its - * current length (eg rb_ary_new2(long length)). The same is true in - * Rubinius where Array has a size() attribute and is backed by an - * instance of Tuple, whose size will always be gte Array::size(). The - * RArray structure in MRI accounts for this and we must as well when - * updating and syncing the cached values. For example: - * - * for(i = 0; i < len; i++) { - * RARRAY(ary)->ptr[i] = obj - * } - * RARRAY(ary)->len = len - */ - RArray* Handle::as_rarray(NativeMethodEnvironment* env) { - if(type_ != cRArray) { - env->shared().capi_ds_lock().lock(); - - // Gotta double check since we're now lock and it might - // have changed since we asked for the lock. - if(type_ != cRArray) { - Array* array = c_as(object()); - native_int size = array->tuple()->num_fields(); - - RArray* ary = new RArray; - VALUE* ptr = new VALUE[size]; - for(native_int i = 0; i < size; i++) { - ptr[i] = env->get_handle(array->get(env->state(), i)); - } - - ary->dmwmb = ary->ptr = ptr; - ary->len = array->size(); - ary->aux.capa = size; - ary->aux.shared = Qfalse; - - type_ = cRArray; - as_.rarray = ary; - - flush_ = flush_cached_rarray; - update_ = update_cached_rarray; - - env->state()->memory()->make_capi_handle_cached(env->state(), this); - } - env->shared().capi_ds_lock().unlock(); - } + native_int size = array->size(); + VALUE* ptr = reinterpret_cast(rtuple->field + array->offset()); - return as_.rarray; + rarray->dmwmb = rarray->ptr = ptr; + rarray->len = array->size(); + rarray->aux.capa = size; + rarray->aux.shared = Qfalse; } } } extern "C" { - struct RArray* capi_rarray_struct(VALUE val) { + struct RArray* capi_rarray_struct(VALUE value) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Handle* h = Handle::from(val); - - env->check_tracked_handle(h); - return h->as_rarray(env); + return MemoryHandle::from(value)->get_rarray(env->state()); } VALUE rb_Array(VALUE object) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Object* obj = env->get_object(object); + Object* obj = MemoryHandle::object(object); if(kind_of(obj)) { return object; @@ -196,7 +122,7 @@ extern "C" { Array* array = Array::create(env->state(), 1); array->set(env->state(), 0, obj); - return env->get_handle(array); + return MemoryHandle::value(array); } VALUE rb_ary_clear(VALUE self) { @@ -219,16 +145,17 @@ extern "C" { VALUE rb_ary_entry(VALUE self, long index) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Array* array = capi_get_array(env, self); - return env->get_handle(array->aref(env->state(), Fixnum::from(index))); + Array* array = MemoryHandle::object(self); + return MemoryHandle::value(array->aref(env->state(), Fixnum::from(index))); } VALUE rb_ary_each(VALUE self) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Array* array = capi_get_array(env, self); + Array* array = MemoryHandle::object(self); + for(native_int i = 0; i < array->size(); i++) { - rb_yield(env->get_handle(array->get(env->state(), i))); + rb_yield(MemoryHandle::value(array->get(env->state(), i))); } return self; @@ -253,7 +180,7 @@ extern "C" { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Array* array = Array::create(env->state(), cCApiArrayDefaultCapacity); - return env->get_handle(array); + return MemoryHandle::value(array); } VALUE rb_ary_new2(unsigned long length) { @@ -261,7 +188,7 @@ extern "C" { Array* array = Array::create(env->state(), length); - return env->get_handle(array); + return MemoryHandle::value(array); } VALUE rb_ary_new3(unsigned long length, ...) { @@ -277,13 +204,13 @@ extern "C" { for(unsigned long i = 0; i < length; ++i) { // @todo determine if we need to check these objects for whether // they are arrays and flush any caches - Object* object = env->get_object(va_arg(args, VALUE)); + Object* object = MemoryHandle::object(va_arg(args, VALUE)); array->set(env->state(), i, object); } va_end(args); - return env->get_handle(array); + return MemoryHandle::value(array); } VALUE rb_ary_new4(unsigned long length, const VALUE* objects) { @@ -297,30 +224,28 @@ extern "C" { for(std::size_t i = 0; i < length; ++i) { // @todo determine if we need to check these objects for whether // they are arrays and flush any caches - Object* object = env->get_object(objects[i]); + Object* object = MemoryHandle::object(objects[i]); array->set(env->state(), i, object); } } - return env->get_handle(array); + return MemoryHandle::value(array); } VALUE rb_ary_pop(VALUE self) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Array* array = capi_get_array(env, self); + Array* array = MemoryHandle::object(self); Object* obj = array->pop(env->state()); - capi_update_array(env, self); - return env->get_handle(obj); + return MemoryHandle::value(obj); } VALUE rb_ary_push(VALUE self, VALUE object) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Array* array = capi_get_array(env, self); - array->append(env->state(), env->get_object(object)); - capi_update_array(env, self); + Array* array = MemoryHandle::object(self); + array->append(env->state(), MemoryHandle::object(object)); return self; } @@ -332,23 +257,20 @@ extern "C" { VALUE rb_ary_shift(VALUE self) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Array* array = capi_get_array(env, self); + Array* array = MemoryHandle::object(self); Object* obj = array->shift(env->state()); - capi_update_array(env, self); - return env->get_handle(obj); + return MemoryHandle::value(obj); } long rb_ary_size(VALUE self) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - return capi_get_array(env, self)->size(); + return MemoryHandle::object(self)->size(); } void rb_ary_store(VALUE self, long int index, VALUE object) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Array* array = capi_get_array(env, self); + Array* array = MemoryHandle::object(self); native_int total = array->size(); if(index < 0) { @@ -359,17 +281,16 @@ extern "C" { rb_raise(rb_eIndexError, "Index %li out of range", index - total); } - array->set(env->state(), index, env->get_object(object)); - capi_update_array(env, self); + array->set(env->state(), index, MemoryHandle::object(object)); } VALUE rb_ary_concat(VALUE self, VALUE second) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Array* array = capi_get_array(env, self); - Array* other = capi_get_array(env, second); + Array* array = MemoryHandle::object(self); + Array* other = MemoryHandle::object(second); array->concat(env->state(), other); - capi_update_array(env, self); + return self; } @@ -380,9 +301,8 @@ extern "C" { VALUE rb_ary_unshift(VALUE self, VALUE object) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Array* array = capi_get_array(env, self); - array->unshift(env->state(), env->get_object(object)); - capi_update_array(env, self); + Array* array = MemoryHandle::object(self); + array->unshift(env->state(), MemoryHandle::object(object)); return self; } @@ -405,7 +325,7 @@ extern "C" { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); // Minor optimization. - if(ifunc == rb_each && kind_of(env->get_object(ary))) { + if(ifunc == rb_each && kind_of(MemoryHandle::object(ary))) { for(long i = 0; i < rb_ary_size(ary); i++) { (*cb)(rb_ary_entry(ary, i), cb_data, Qnil); } @@ -415,7 +335,7 @@ extern "C" { Proc* prc = capi::wrap_c_function((void*)cb, cb_data, ITERATE_BLOCK); - env->set_outgoing_block(env->get_handle(prc)); + env->set_outgoing_block(MemoryHandle::value(prc)); return (*ifunc)(ary); } @@ -433,9 +353,9 @@ extern "C" { Thread* thr = Thread::current(state); LookupTable* rectbl = thr->recursive_objects(); - Object* obj = env->get_object(h_obj); + Object* obj = MemoryHandle::object(h_obj); - Object* id = obj->id(state); + Object* id = obj->object_id(state); bool found = false; rectbl->fetch(state, id, &found); @@ -464,8 +384,8 @@ extern "C" { // Get the thread and table again, the GC might have fun. thr = Thread::current(state); rectbl = thr->recursive_objects(); - obj = env->get_object(h_obj); - id = obj->id(state); + obj = MemoryHandle::object(h_obj); + id = obj->object_id(state); rectbl->remove(state, id); @@ -481,9 +401,9 @@ extern "C" { Thread* thr = Thread::current(state); LookupTable* rectbl = thr->recursive_objects(); - Object* obj = env->get_object(h_obj); + Object* obj = MemoryHandle::object(h_obj); - Object* id = obj->id(state); + Object* id = obj->object_id(state); bool found = false; rectbl->fetch(state, id, &found); @@ -499,7 +419,7 @@ extern "C" { VALUE rb_ary_to_ary(VALUE object) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Object* obj = env->get_object(object); + Object* obj = MemoryHandle::object(object); if(kind_of(obj)) { return object; @@ -511,9 +431,9 @@ extern "C" { return rb_funcall(object, to_ary_id, 0); } else { Array* array = Array::create(env->state(), 1); - array->set(env->state(), 0, env->get_object(object)); + array->set(env->state(), 0, MemoryHandle::object(object)); - return env->get_handle(array); + return MemoryHandle::value(array); } } @@ -527,7 +447,7 @@ extern "C" { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Array* array = c_as(env->get_object(ary)); - return env->get_handle(array->new_range(env->state(), Fixnum::from(beg), Fixnum::from(len))); + Array* array = MemoryHandle::object(ary); + return MemoryHandle::value(array->new_range(env->state(), Fixnum::from(beg), Fixnum::from(len))); } } diff --git a/machine/capi/bignum.cpp b/machine/capi/bignum.cpp index 0d37f3ef6e..2e6b11c3d4 100644 --- a/machine/capi/bignum.cpp +++ b/machine/capi/bignum.cpp @@ -17,9 +17,7 @@ extern "C" { } long rb_big2long(VALUE obj) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - Object* object = env->get_object(obj); + Object* object = MemoryHandle::object(obj); if(object->nil_p()) { rb_raise(rb_eTypeError, "no implicit conversion from nil to long"); @@ -42,9 +40,7 @@ extern "C" { } unsigned long rb_big2ulong(VALUE obj) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - Object* object = env->get_object(obj); + Object* object = MemoryHandle::object(obj); if(object->nil_p()) { rb_raise(rb_eTypeError, "no implicit conversion from nil to unsigned long"); @@ -72,9 +68,7 @@ extern "C" { } long long rb_big2ll(VALUE obj) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - Object* object = env->get_object(obj); + Object* object = MemoryHandle::object(obj); if(object->nil_p()) { rb_raise(rb_eTypeError, "no implicit conversion from nil to unsigned long"); @@ -93,9 +87,7 @@ extern "C" { } unsigned long long rb_big2ull(VALUE obj) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - Object* object = env->get_object(obj); + Object* object = MemoryHandle::object(obj); if(object->nil_p()) { rb_raise(rb_eTypeError, "no implicit conversion from nil to unsigned long"); @@ -117,7 +109,7 @@ extern "C" { double rb_big2dbl(VALUE obj) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Bignum* big = c_as(env->get_object(obj)); + Bignum* big = MemoryHandle::object(obj); double d = big->to_double(env->state()); if(isinf(d)) { if(big->mp_val()->sign == MP_NEG) { @@ -143,21 +135,19 @@ extern "C" { Integer* bignum = Bignum::from_double(env->state(), num); - return env->get_handle(bignum); + return MemoryHandle::value(bignum); } int rb_big_bytes_used(VALUE obj) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Bignum* big = c_as(env->get_object(obj)); + Bignum* big = MemoryHandle::object(obj); return big->size(env->state())->to_native(); } int rb_big_sign(VALUE obj) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - Bignum* big = c_as(env->get_object(obj)); + Bignum* big = MemoryHandle::object(obj); return big->mp_val()->sign != MP_NEG; } diff --git a/machine/capi/capi.cpp b/machine/capi/capi.cpp index dbfe4d1427..0f8eaf8d7c 100644 --- a/machine/capi/capi.cpp +++ b/machine/capi/capi.cpp @@ -16,6 +16,7 @@ #include "class/proc.hpp" #include "class/exception.hpp" +#include "bug.hpp" #include "call_frame.hpp" #include "configuration.hpp" #include "lookup_data.hpp" @@ -30,8 +31,72 @@ #include "capi/ruby.h" namespace rubinius { - namespace capi { + using namespace capi; + + NORETURN(static void abort_memory_handle_error(const char* error)); + + static void abort_memory_handle_error(const char* error) { + /* This is one of the rare cases where aborting with rubinius::bug is + * acceptable. We MUST be able to do the conversions performed by the + * functions that may call this abort function. We CANNOT raise exceptions + * inside components like the GC because certain state invariants must be + * maintained and those operations cannot be interrupted. + */ + rubinius::bug(error); + } + + MemoryHandle* MemoryHandle::from(VALUE value) { + if(REFERENCE_P(value)) { + return reinterpret_cast(STRIP_HANDLE_TAG(value)); + } + + abort_memory_handle_error("MemoryHandle requested for unknown VALUE type"); + } + + Object* MemoryHandle::object(VALUE value) { + if(REFERENCE_P(value)) { + MemoryHandle* handle = MemoryHandle::from(value); + + return handle->object(); + } else if(FIXNUM_P(value) || SYMBOL_P(value)) { + return reinterpret_cast(value); + } else if(TRUE_P(value)) { + return cTrue; + } else if(FALSE_P(value)) { + return cFalse; + } else if(NIL_P(value)) { + return cNil; + } else if(UNDEF_P(value)) { + return cUndef; + } + + abort_memory_handle_error("Object reference requested for unknown VALUE type"); + } + + VALUE MemoryHandle::value(Object* object) { + if(object->reference_p()) { + NativeMethodEnvironment* env = NativeMethodEnvironment::get(); + + MemoryHandle* handle = object->get_handle(env->state()); + handle->access(); + return handle->as_value(); + } else if(object->fixnum_p() || object->symbol_p()) { + return reinterpret_cast(object); + } else if(object->true_p()) { + return Qtrue; + } else if(object->false_p()) { + return Qfalse; + } else if(object->nil_p()) { + return Qnil; + } else if(object->undef_p()) { + return Qundef; + } + + abort_memory_handle_error("VALUE requested for unknown Object type"); + } + + namespace capi { /** * This looks like a complicated scheme but there is a reason for * doing it this way. In MRI, rb_cObject, etc. are all global data. @@ -42,7 +107,7 @@ namespace rubinius { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); if(type < 0 || type >= cCApiMaxConstant) { - rb_raise(env->get_handle(env->state()->globals().exception.get()), + rb_raise(MemoryHandle::value(env->state()->globals().exception.get()), "C-API: invalid constant index"); } @@ -72,21 +137,20 @@ namespace rubinius { size_t arg_count, VALUE* arg_array) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - env->flush_cached_data(); Array* args = Array::create(env->state(), arg_count); for(size_t i = 0; i < arg_count; i++) { - args->set(env->state(), i, env->get_object(arg_array[i])); + args->set(env->state(), i, MemoryHandle::object(arg_array[i])); } Object* blk = cNil; if(VALUE blk_handle = env->outgoing_block()) { - blk = env->get_object(blk_handle); + blk = MemoryHandle::object(blk_handle); env->set_outgoing_block(0); } - Object* recv = env->get_object(receiver); + Object* recv = MemoryHandle::object(receiver); // Unlock, we're leaving extension code. LEAVE_CAPI(env->state()); @@ -97,13 +161,11 @@ namespace rubinius { // We need to get the handle for the return value before getting // the GEL so that ret isn't accidentally GCd while we wait. VALUE ret_handle = 0; - if(ret) ret_handle = env->get_handle(ret); + if(ret) ret_handle = MemoryHandle::value(ret); // Re-entering extension code ENTER_CAPI(env->state()); - env->update_cached_data(); - // An exception occurred if(!ret) env->current_ep()->return_to(env); @@ -121,8 +183,6 @@ namespace rubinius { env->current_ep()->return_to(env); } - env->flush_cached_data(); - // Unlock, we're leaving extension code. LEAVE_CAPI(env->state()); @@ -147,13 +207,11 @@ namespace rubinius { // We need to get the handle for the return value before getting // the GEL so that ret isn't accidentally GCd while we wait. VALUE ret_handle = 0; - if(ret) ret_handle = env->get_handle(ret); + if(ret) ret_handle = MemoryHandle::value(ret); // Re-entering extension code ENTER_CAPI(env->state()); - env->update_cached_data(); - // An exception occurred if(!ret) env->current_ep()->return_to(env); @@ -169,7 +227,7 @@ namespace rubinius { Object* args[arg_count]; for(int i = 0; i < arg_count; i++) { - args[i] = env->get_object(va_arg(varargs, VALUE)); + args[i] = MemoryHandle::object(va_arg(varargs, VALUE)); } va_end(varargs); @@ -177,7 +235,7 @@ namespace rubinius { // Unlock, we're leaving extension code. LEAVE_CAPI(env->state()); - Object* recv = env->get_object(receiver); + Object* recv = MemoryHandle::object(receiver); Symbol* method = (Symbol*)method_name; Object* ret = cNil; @@ -194,7 +252,7 @@ namespace rubinius { // We need to get the handle for the return value before getting // the GEL so that ret isn't accidentally GCd while we wait. VALUE ret_handle = 0; - if(ret) ret_handle = env->get_handle(ret); + if(ret) ret_handle = MemoryHandle::value(ret); // Re-entering extension code ENTER_CAPI(env->state()); @@ -213,8 +271,6 @@ namespace rubinius { env->current_ep()->return_to(env); } - env->flush_cached_data(); - // Unlock, we're leaving extension code. LEAVE_CAPI(env->state()); @@ -242,13 +298,11 @@ namespace rubinius { // We need to get the handle for the return value before getting // the GEL so that ret isn't accidentally GCd while we wait. VALUE ret_handle = 0; - if(ret) ret_handle = env->get_handle(ret); + if(ret) ret_handle = MemoryHandle::value(ret); // Re-entering extension code ENTER_CAPI(env->state()); - env->update_cached_data(); - // An exception occurred if(!ret) env->current_ep()->return_to(env); @@ -262,13 +316,11 @@ namespace rubinius { env->current_ep()->return_to(env); } - env->flush_cached_data(); - NativeMethodFrame* frame = NativeMethodFrame::current(); - Object* recv = env->get_object(frame->receiver()); - Module* mod = c_as(env->get_object(frame->module())); - Symbol* name = c_as(env->get_object(frame->method()))->name(); + Object* recv = MemoryHandle::object(frame->receiver()); + Module* mod = MemoryHandle::object(frame->module()); + Symbol* name = MemoryHandle::object(frame->method())->name(); // Unlock, we're leaving extension code. LEAVE_CAPI(env->state()); @@ -287,13 +339,11 @@ namespace rubinius { // We need to get the handle for the return value before getting // the GEL so that ret isn't accidentally GCd while we wait. VALUE ret_handle = 0; - if(ret) ret_handle = env->get_handle(ret); + if(ret) ret_handle = MemoryHandle::value(ret); // Re-entering extension code ENTER_CAPI(env->state()); - env->update_cached_data(); - // An exception occurred if(!ret) env->current_ep()->return_to(env); @@ -361,21 +411,21 @@ namespace rubinius { } void capi_raise_backend(VALUE exception) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Exception *exc = capi::c_as(env->get_object(exception)); + Exception *exc = MemoryHandle::object(exception); capi_raise_backend(exc); } void capi_raise_backend(VALUE klass, const char* reason) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Class* cls = c_as(env->get_object(klass)); + Class* cls = MemoryHandle::object(klass); Exception* exc = Exception::make_exception(env->state(), cls, reason); capi_raise_backend(exc); } void capi_raise_break(VALUE obj) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - env->state()->vm()->thread_state()->raise_break(env->get_object(obj), env->scope()->parent()); + env->state()->vm()->thread_state()->raise_break( + MemoryHandle::object(obj), env->scope()->parent()); env->current_ep()->return_to(env); } @@ -387,7 +437,7 @@ namespace rubinius { Fixnum::from(arity), 0); nm->set_ivar(env->state(), env->state()->symbol("cb_data"), - env->get_object(cb_data)); + MemoryHandle::object(cb_data)); Object* current_block = env->block(); if(!current_block->nil_p()) { @@ -412,23 +462,29 @@ extern "C" { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); env->shared().capi_constant_lock().lock(); - CApiConstantHandleMap& map = env->state()->shared().capi_constant_handle_map(); + CApiConstantHandleMap& map = env->state()->shared().capi_constant_map(); + + VALUE value; CApiConstantHandleMap::iterator entry = map.find(type); if(entry == map.end()) { std::string constant_name = capi_get_constant_name(type); - VALUE val = rb_path2class(constant_name.c_str()); - capi::Handle* hdl = capi::Handle::from(val); - hdl->ref(); // Extra ref, since we save it in the map - map[type] = hdl; - env->shared().capi_constant_lock().unlock(); - return val; + value = rb_path2class(constant_name.c_str()); + MemoryHandle* handle = MemoryHandle::from(value); + Object* object = handle->object(); + + if(object->reference_p()) { + object->add_reference(env->state()); + } + + map[type] = handle; } else { - VALUE val = entry->second->as_value(); - env->shared().capi_constant_lock().unlock(); - return val; + value = entry->second->as_value(); } + + env->shared().capi_constant_lock().unlock(); + return value; } VALUE rb_call_super(int argc, const VALUE *argv) { @@ -436,7 +492,7 @@ extern "C" { Object* args[argc]; for(int i = 0; i < argc; i++) { - args[i] = env->get_object(argv[i]); + args[i] = MemoryHandle::object(argv[i]); } return capi_call_super_native(env, argc, args); @@ -451,7 +507,7 @@ extern "C" { Object* args[arg_count]; for(int i = 0; i < arg_count; i++) { - args[i] = env->get_object(va_arg(varargs, VALUE)); + args[i] = MemoryHandle::object(va_arg(varargs, VALUE)); } va_end(varargs); @@ -459,12 +515,12 @@ extern "C" { Object* blk = cNil; if(VALUE blk_handle = env->outgoing_block()) { - blk = env->get_object(blk_handle); + blk = MemoryHandle::object(blk_handle); env->set_outgoing_block(0); } return capi_funcall_backend_native(env, "", 0, - env->get_object(receiver), + MemoryHandle::object(receiver), reinterpret_cast(method_name), arg_count, args, blk, true); } @@ -475,18 +531,18 @@ extern "C" { Object* args[arg_count]; for(int i = 0; i < arg_count; i++) { - args[i] = env->get_object(v_args[i]); + args[i] = MemoryHandle::object(v_args[i]); } Object* blk = cNil; if(VALUE blk_handle = env->outgoing_block()) { - blk = env->get_object(blk_handle); + blk = MemoryHandle::object(blk_handle); env->set_outgoing_block(0); } return capi_funcall_backend_native(env, "", 0, - env->get_object(receiver), + MemoryHandle::object(receiver), reinterpret_cast(method_name), arg_count, args, blk, true); } @@ -497,18 +553,18 @@ extern "C" { Object* args[arg_count]; for(int i = 0; i < arg_count; i++) { - args[i] = env->get_object(v_args[i]); + args[i] = MemoryHandle::object(v_args[i]); } Object* blk = cNil; if(VALUE blk_handle = env->outgoing_block()) { - blk = env->get_object(blk_handle); + blk = MemoryHandle::object(blk_handle); env->set_outgoing_block(0); } return capi_funcall_backend_native(env, "", 0, - env->get_object(receiver), + MemoryHandle::object(receiver), reinterpret_cast(method_name), arg_count, args, blk, false); } @@ -521,13 +577,13 @@ extern "C" { Object* args[arg_count]; for(int i = 0; i < arg_count; i++) { - args[i] = env->get_object(v_args[i]); + args[i] = MemoryHandle::object(v_args[i]); } return capi_funcall_backend_native(env, "", 0, - env->get_object(receiver), + MemoryHandle::object(receiver), reinterpret_cast(method_name), - arg_count, args, env->get_object(block), allow_private); + arg_count, args, MemoryHandle::object(block), allow_private); } VALUE rb_funcall2b(VALUE receiver, ID method_name, int arg_count, @@ -551,7 +607,7 @@ extern "C" { rb_raise(rb_eLocalJumpError, "no block given", 0); } - Object* arg = env->get_object(argument_handle); + Object* arg = MemoryHandle::object(argument_handle); return capi_yield_backend(env, blk, 1, &arg); } @@ -575,7 +631,7 @@ extern "C" { va_start(args, n); for(int i = 0; i < n; ++i) { - vars[i] = env->get_object(va_arg(args, VALUE)); + vars[i] = MemoryHandle::object(va_arg(args, VALUE)); } va_end(args); @@ -592,7 +648,7 @@ extern "C" { rb_raise(rb_eLocalJumpError, "no block given", 0); } - if(Array* ary = try_as(env->get_object(array_handle))) { + if(Array* ary = MemoryHandle::try_as(array_handle)) { int count = ary->size(); Object* vars[count]; @@ -623,9 +679,9 @@ extern "C" { if(cb) { Proc* prc = capi::wrap_c_function((void*)cb, cb_data, C_BLOCK_CALL); - env->set_outgoing_block(env->get_handle(prc)); + env->set_outgoing_block(MemoryHandle::value(prc)); } else { - env->set_outgoing_block(env->get_handle(env->block())); + env->set_outgoing_block(MemoryHandle::value(env->block())); } return rb_funcall2(obj, meth, argc, argv); @@ -633,11 +689,10 @@ extern "C" { VALUE rb_apply(VALUE recv, ID mid, VALUE args) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - env->flush_cached_data(); - Array* ary = capi::c_as(env->get_object(args)); + Array* ary = MemoryHandle::object(args); - Object* obj = env->get_object(recv); + Object* obj = MemoryHandle::object(recv); // Unlock, we're leaving extension code. LEAVE_CAPI(env->state()); @@ -647,47 +702,40 @@ extern "C" { // We need to get the handle for the return value before getting // the GEL so that ret isn't accidentally GCd while we wait. VALUE ret_handle = 0; - if(ret) ret_handle = env->get_handle(ret); + if(ret) ret_handle = MemoryHandle::value(ret); // Re-entering extension code ENTER_CAPI(env->state()); - env->update_cached_data(); - // An exception occurred if(!ret) env->current_ep()->return_to(env); return ret_handle; } - void capi_infect(VALUE h, VALUE s) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Object* host = env->get_object(h); - Object* source = env->get_object(s); + Object* host = MemoryHandle::object(h); + Object* source = MemoryHandle::object(s); source->infect(env->state(), host); } int capi_nil_p(VALUE expression_result) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - return env->get_object(expression_result)->nil_p(); + return MemoryHandle::object(expression_result)->nil_p(); } void capi_taint(VALUE obj) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - env->get_object(obj)->taint(env->state()); + MemoryHandle::object(obj)->taint(env->state()); } - int rb_obj_tainted(VALUE obj) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - Object* tainted = env->get_object(obj)->tainted_p(env->state()); + int rb_obj_tainted(VALUE value) { + Object* obj = MemoryHandle::object(value); - return tainted->true_p() ? 1 : 0; + return obj->reference_p() && obj->tainted_p(); } void capi_define_method(const char* file, VALUE target, @@ -702,9 +750,9 @@ extern "C" { Module* module = NULL; if(kind == cCApiSingletonMethod) { - module = c_as(env->get_object(target)->singleton_class(env->state())); + module = c_as(MemoryHandle::object(target)->singleton_class(env->state())); } else { - module = c_as(env->get_object(target)); + module = MemoryHandle::object(target); } NativeMethod* method = NULL; @@ -734,9 +782,7 @@ extern "C" { } VALUE capi_class_superclass(VALUE class_handle) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - Module* module = c_as(env->get_object(class_handle)); + Module* module = MemoryHandle::object(class_handle); Module* super = module->superclass(); if(super->nil_p()) { @@ -745,7 +791,7 @@ extern "C" { */ return 0; } else { - return env->get_handle(super); + return MemoryHandle::value(super); } } @@ -753,7 +799,7 @@ extern "C" { void __show_subtend__(VALUE obj_handle) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Object* object = env->get_object(obj_handle); + Object* object = MemoryHandle::object(obj_handle); if(!object) { std::cout << "the object is NULL, check if an exception was raised." << std::endl; return; diff --git a/machine/capi/capi.hpp b/machine/capi/capi.hpp index 8c0c5817e0..3f37dc9025 100644 --- a/machine/capi/capi.hpp +++ b/machine/capi/capi.hpp @@ -8,6 +8,8 @@ #include #include +#include "memory/header.hpp" + #include "class/native_method.hpp" #include "object_utils.hpp" @@ -50,24 +52,6 @@ namespace rubinius { void capi_raise_break(VALUE obj); - /** Get an Array object for a handle ensuring that any RARRAY data has - * been flushed. */ - Array* capi_get_array(NativeMethodEnvironment* env, VALUE ary_handle); - - /** Update the RARRAY cache if one exists for this handle. */ - void capi_update_array(NativeMethodEnvironment* env, VALUE ary_handle); - - /** Get a String object for a handle ensuring that any RSTRING data has - * been flushed. */ - String* capi_get_string(NativeMethodEnvironment* env, VALUE str_handle); - - /** Update the RSTRING cache if one exists for this handle. */ - void capi_update_string(NativeMethodEnvironment* env, VALUE str_handle); - - /** Get a Float object for a handle ensuring that RFLOAT data has - * been flushed. */ - Float* capi_get_float(NativeMethodEnvironment* env, VALUE float_handle); - /** Wrap a C function in a Proc */ Proc* wrap_c_function(void* func, VALUE cb, int arity); @@ -78,7 +62,7 @@ namespace rubinius { template VALUE capi_native2num(NativeType number) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - return env->get_handle(Integer::from(env->state(), number)); + return MemoryHandle::value(Integer::from(env->state(), number)); } /** @@ -129,6 +113,16 @@ namespace rubinius { return obj; } } + + template + T* MemoryHandle::object(VALUE value) { + return capi::c_as(MemoryHandle::object(value)); + } + + template + T* MemoryHandle::try_as(VALUE value) { + return rubinius::try_as(MemoryHandle::object(value)); + } } #endif diff --git a/machine/capi/class.cpp b/machine/capi/class.cpp index e8993e5c7d..4f823b423b 100644 --- a/machine/capi/class.cpp +++ b/machine/capi/class.cpp @@ -23,20 +23,19 @@ extern "C" { VALUE rb_class_of(VALUE object_handle) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Class* class_object = env->get_object(object_handle)->class_object(env->state()); - return env->get_handle(class_object); + Class* class_object = MemoryHandle::object(object_handle)->class_object(env->state()); + return MemoryHandle::value(class_object); } - VALUE rb_class_real(VALUE object_handle) { - if(object_handle == 0) return 0; + VALUE rb_class_real(VALUE value) { + if(value == 0) return 0; NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Object* object = env->get_object(object_handle); - if(Class* cls = try_as(object)) { - return env->get_handle(Class::real_class(env->state(), cls)); + if(Class* cls = MemoryHandle::try_as(value)) { + return MemoryHandle::value(Class::real_class(env->state(), cls)); } else { - return object_handle; + return value; } } @@ -47,20 +46,20 @@ extern "C" { // MUST return the immediate object in the class field, not the real class! VALUE CLASS_OF(VALUE object_handle) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Class* class_object = env->get_object(object_handle)->direct_class(env->state()); - return env->get_handle(class_object); + Class* class_object = MemoryHandle::object(object_handle)->direct_class(env->state()); + return MemoryHandle::value(class_object); } VALUE rb_class_name(VALUE class_handle) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); State* state = env->state(); - Class* class_object = c_as(env->get_object(class_handle)); + Class* class_object = MemoryHandle::object(class_handle); String* str = class_object->get_name(state); if(str->nil_p()) { std::string desc = class_object->to_string(state); str = String::create(state, desc.c_str(), desc.size()); } - return env->get_handle(str); + return MemoryHandle::value(str); } VALUE rb_class_inherited(VALUE super_handle, VALUE class_handle) @@ -76,13 +75,13 @@ extern "C" { rb_raise(rb_eTypeError, "can't make subclass of Class"); } - if(try_as(env->get_object(super_handle))) { + if(MemoryHandle::try_as(super_handle)) { rb_raise(rb_eTypeError, "can't make subclass of virtual class"); } - Class* klass = Class::create(env->state(), c_as(env->get_object(super_handle))); + Class* klass = Class::create(env->state(), MemoryHandle::object(super_handle)); - return env->get_handle(klass); + return MemoryHandle::value(klass); } VALUE rb_path2class(const char* path) { @@ -109,9 +108,9 @@ extern "C" { } if(Autoload* autoload = try_as(val)) { - VALUE m = capi_fast_call(env->get_handle(autoload), - rb_intern("call"), 1, env->get_handle(mod)); - val = env->get_object(m); + VALUE m = capi_fast_call(MemoryHandle::value(autoload), + rb_intern("call"), 1, MemoryHandle::value(mod)); + val = MemoryHandle::object(m); } if(!(mod = try_as(val))) { @@ -122,7 +121,7 @@ extern "C" { free(pathd); - return env->get_handle(mod); + return MemoryHandle::value(mod); } VALUE rb_cv_get(VALUE module_handle, const char* name) { @@ -150,7 +149,7 @@ extern "C" { return rb_funcall(module_handle, rb_intern("class_variable_get"), 1, - env->get_handle(prefixed_by(env->state(), "@@", 2, name))); + MemoryHandle::value(prefixed_by(env->state(), "@@", 2, name))); } VALUE rb_cvar_set_internal(VALUE module_handle, ID name, VALUE value) { @@ -158,7 +157,7 @@ extern "C" { return rb_funcall(module_handle, rb_intern("class_variable_set"), 2, - env->get_handle(prefixed_by(env->state(), "@@", 2, name)), + MemoryHandle::value(prefixed_by(env->state(), "@@", 2, name)), value); } @@ -175,8 +174,8 @@ extern "C" { VALUE rb_define_class_id_under(VALUE outer, ID name, VALUE super) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Module* module = c_as(env->get_object(outer)); - Class* superclass = c_as(env->get_object(super ? super : rb_cObject)); + Module* module = MemoryHandle::object(outer); + Class* superclass = MemoryHandle::object(super ? super : rb_cObject); Symbol* constant = reinterpret_cast(name); bool created = false; @@ -201,7 +200,7 @@ extern "C" { // code. The problem otherwise can be that the GC runs and // the opened_class is GC'ed. - VALUE klass = env->get_handle(opened_class); + VALUE klass = MemoryHandle::value(opened_class); ENTER_CAPI(env->state()); if(super) rb_funcall(super, rb_intern("inherited"), 1, klass); @@ -228,13 +227,13 @@ extern "C" { VALUE rb_singleton_class(VALUE object_handle) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Class* sc = env->get_object(object_handle)->singleton_class(env->state()); - return env->get_handle(sc); + Class* sc = MemoryHandle::object(object_handle)->singleton_class(env->state()); + return MemoryHandle::value(sc); } VALUE rb_path_to_class(VALUE str) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - String* string = c_as(env->get_object(str)); + String* string = MemoryHandle::object(str); return rb_path2class(string->c_str(env->state())); } diff --git a/machine/capi/data.cpp b/machine/capi/data.cpp index d723b6ca6c..74684666fa 100644 --- a/machine/capi/data.cpp +++ b/machine/capi/data.cpp @@ -10,51 +10,35 @@ using namespace rubinius; using namespace rubinius::capi; namespace rubinius { - namespace capi { - RData* Handle::as_rdata(NativeMethodEnvironment* env) { - Data* data = c_as(object_); - - if(data->freed_p()) { - rb_raise(rb_eArgError, "Data object has already been freed"); - } - - if(type_ == cRData) { - return as_.rdata; - } else { - type_ = cRData; - - RData* rdata = new RData; - rdata->data = 0; - rdata->dmark = 0; - rdata->dfree = 0; - - as_.rdata = rdata; - - return rdata; - } + RData* MemoryHandle::get_rdata(STATE) { + if(rdata_p()) { + return reinterpret_cast(data()); + } else if(unknown_type_p()) { + RData* rdata = new RData; + rdata->data = 0; + rdata->dmark = 0; + rdata->dfree = 0; + + set_rdata(rdata); + return rdata; + } else { + Exception::raise_runtime_error(state, "C-API handle invalid reference as RData"); } + } - RTypedData* Handle::as_rtypeddata(NativeMethodEnvironment* env) { - Data* data = c_as(object_); - - if(data->freed_p()) { - rb_raise(rb_eArgError, "TypedData object has already been freed"); - } - - if(type_ == cRData) { - return as_.rtypeddata; - } else { - type_ = cRData; - - RTypedData* rtypeddata = new RTypedData; - rtypeddata->data = 0; - rtypeddata->type = 0; - rtypeddata->typed_flag = 1; - - as_.rtypeddata = rtypeddata; - - return rtypeddata; - } + RTypedData* MemoryHandle::get_rtypeddata(STATE) { + if(rtypeddata_p()) { + return reinterpret_cast(data()); + } else if(unknown_type_p()) { + RTypedData* rtypeddata = new RTypedData; + rtypeddata->data = 0; + rtypeddata->type = 0; + rtypeddata->typed_flag = 1; + + set_rtypeddata(rtypeddata); + return rtypeddata; + } else { + Exception::raise_runtime_error(state, "C-API handle invalid reference as RData"); } } } @@ -63,10 +47,16 @@ extern "C" { struct RData* capi_rdata_struct(VALUE data_handle) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Handle* handle = Handle::from(data_handle); - env->check_tracked_handle(handle, false); + MemoryHandle* handle = MemoryHandle::from(data_handle); - return handle->as_rdata(env); + if(RData* rdata = handle->get_rdata(env->state())) { + return rdata; + } else { + // TODO: MemoryHandle + rdata = new RData(); + handle->set_rdata(rdata); + return rdata; + } } VALUE rb_data_object_alloc(VALUE klass, void* ptr, @@ -75,22 +65,28 @@ extern "C" { if(!klass) klass = rb_cObject; - Class* data_klass = c_as(env->get_object(klass)); + Class* data_klass = MemoryHandle::object(klass); Data* data = Data::create(env->state(), ptr, mark, free); data->klass(env->state(), data_klass); - return env->get_handle(data); + return MemoryHandle::value(data); } struct RTypedData* capi_rtypeddata_struct(VALUE data_handle) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Handle* handle = Handle::from(data_handle); - env->check_tracked_handle(handle, false); + MemoryHandle* handle = MemoryHandle::from(data_handle); - return handle->as_rtypeddata(env); + if(RTypedData* rdata = handle->get_rtypeddata(env->state())) { + return rdata; + } else { + // TODO: MemoryHandle + rdata = new RTypedData(); + handle->set_rtypeddata(rdata); + return rdata; + } } VALUE rb_data_typed_object_alloc(VALUE klass, void* ptr, const rb_data_type_t* type) { @@ -98,13 +94,13 @@ extern "C" { if(!klass) klass = rb_cObject; - Class* data_klass = c_as(env->get_object(klass)); + Class* data_klass = MemoryHandle::object(klass); Data* data = Data::create_typed(env->state(), ptr, reinterpret_cast(type)); data->klass(env->state(), data_klass); - return env->get_handle(data); + return MemoryHandle::value(data); } int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent) { @@ -116,9 +112,8 @@ extern "C" { } void* rb_check_typeddata(VALUE obj, const rb_data_type_t* data_type) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); const char* mesg = "wrong argument type %s (expected %s)"; - Data* data = c_as(env->get_object(obj)); + Data* data = MemoryHandle::object(obj); if(!data->typed()) { rb_raise(rb_eTypeError, mesg, rb_obj_classname(obj), data_type->wrap_struct_name); } @@ -132,8 +127,7 @@ extern "C" { } int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Data* data = try_as(env->get_object(obj)); + Data* data = MemoryHandle::try_as(obj); if(!data || !data->typed()) return 0; return rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type); } diff --git a/machine/capi/encoding.cpp b/machine/capi/encoding.cpp index 83d0f4256c..e980091ace 100644 --- a/machine/capi/encoding.cpp +++ b/machine/capi/encoding.cpp @@ -20,12 +20,10 @@ using namespace rubinius; using namespace rubinius::capi; extern "C" { - int rb_enc_coderange_asciionly_p(VALUE obj) { + int rb_enc_coderange_asciionly_p(VALUE value) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Object* val = env->get_object(obj); - - if(String* str = try_as(val)) { + if(String* str = MemoryHandle::try_as(value)) { if(CBOOL(str->ascii_only_p(env->state()))) return Qtrue; } else { rb_raise(rb_eArgError, "ENC_CODERANGE_ASCIIONLY is only defined for String"); @@ -120,31 +118,34 @@ extern "C" { } } - rb_encoding* rb_enc_get(VALUE obj) { + rb_encoding* rb_enc_get(VALUE value) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Object* val = env->get_object(obj); - if(!val->reference_p() && !val->symbol_p()) return 0; - Encoding* enc = Encoding::get_object_encoding(env->state(), val); + Object* name = MemoryHandle::object(value); + + if(!name->reference_p() && !name->symbol_p()) return 0; + Encoding* enc = Encoding::get_object_encoding(env->state(), name); if(enc->nil_p()) return 0; + return enc->encoding(); } VALUE rb_obj_encoding(VALUE obj) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Object* val = env->get_object(obj); + Object* val = MemoryHandle::object(obj); Encoding* enc = Encoding::get_object_encoding(env->state(), val); - return env->get_handle(enc); + return MemoryHandle::value(enc); } - int rb_enc_get_index(VALUE obj) { + int rb_enc_get_index(VALUE value) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Object* val = env->get_object(obj); - if(!val->reference_p() && !val->symbol_p()) return -1; + Object* name = MemoryHandle::object(value); - Encoding* enc = Encoding::get_object_encoding(env->state(), val); + if(!name->reference_p() && !name->symbol_p()) return -1; + + Encoding* enc = Encoding::get_object_encoding(env->state(), name); if(enc->nil_p()) return 0; @@ -155,7 +156,7 @@ extern "C" { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Encoding* enc = Encoding::from_index(env->state(), index); - Object* val = env->get_object(obj); + Object* val = MemoryHandle::object(obj); Encoding::set_object_encoding(env->state(), val, enc); } @@ -188,7 +189,7 @@ extern "C" { switch(TYPE(obj)) { case T_ENCODING: - enc = c_as(env->get_object(obj)); + enc = MemoryHandle::object(obj); break; case T_STRING: enc = Encoding::find(env->state(), RSTRING_PTR(obj)); @@ -219,7 +220,7 @@ extern "C" { if(!enc) return obj; - Object* val = env->get_object(obj); + Object* val = MemoryHandle::object(obj); if(String* str = try_as(val)) { str->encoding(env->state(), enc); @@ -276,7 +277,7 @@ extern "C" { VALUE rb_enc_from_encoding(rb_encoding *enc) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - return env->get_handle(Encoding::find(env->state(), enc->name)); + return MemoryHandle::value(Encoding::find(env->state(), enc->name)); } int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc) { diff --git a/machine/capi/exception.cpp b/machine/capi/exception.cpp index eb0cf38a4c..765e087bb2 100644 --- a/machine/capi/exception.cpp +++ b/machine/capi/exception.cpp @@ -30,14 +30,14 @@ extern "C" { VALUE rb_errinfo() { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - return env->get_handle(env->state()->thread_state()->current_exception()); + return MemoryHandle::value(env->state()->thread_state()->current_exception()); } void rb_set_errinfo(VALUE err) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Exception* exc = 0; - Object* object = env->get_object(err); + Object* object = MemoryHandle::object(err); if(object->nil_p()) { exc = nil(); diff --git a/machine/capi/file.cpp b/machine/capi/file.cpp index 26263df1e0..8e73dbf084 100644 --- a/machine/capi/file.cpp +++ b/machine/capi/file.cpp @@ -6,18 +6,15 @@ using namespace rubinius; using namespace rubinius::capi; namespace rubinius { - namespace capi { - RFile* Handle::as_rfile(NativeMethodEnvironment* env) { - if(type_ != cRFile) { - RFile* rfile = new RFile; - rfile->handle = as_value(); - rfile->fptr = as_rio(env); - - type_ = cRFile; - as_.rfile = rfile; - } - - return as_.rfile; + RFile* MemoryHandle::get_rfile(STATE) { + if(rfile_p()) { + return reinterpret_cast(data()); + } else if(unknown_type_p()) { + RFile* rfile = new RFile(); + set_rfile(rfile); + return rfile; + } else { + Exception::raise_runtime_error(state, "C-API handle invalid reference as RFile"); } } } @@ -25,7 +22,7 @@ namespace rubinius { extern "C" { struct RFile* capi_rfile_struct(VALUE file) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - return Handle::from(file)->as_rfile(env); + return MemoryHandle::from(file)->get_rfile(env->state()); } int rb_cloexec_dup(int fd) { @@ -34,8 +31,8 @@ extern "C" { VALUE rb_file_open(const char* name, const char* mode) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - VALUE n = env->get_handle(String::create(env->state(), name)); - VALUE m = env->get_handle(String::create(env->state(), mode)); + VALUE n = MemoryHandle::value(String::create(env->state(), name)); + VALUE m = MemoryHandle::value(String::create(env->state(), mode)); return rb_funcall(rb_cFile, rb_intern("open"), 2, n, m); } @@ -48,8 +45,8 @@ extern "C" { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); STATE = env->state(); - if(!kind_of(env->get_object(*obj))) { - *obj = rb_funcall(env->get_handle(G(type)), rb_intern("coerce_to_path"), 1, *obj); + if(!MemoryHandle::try_as(*obj)) { + *obj = rb_funcall(MemoryHandle::value(G(type)), rb_intern("coerce_to_path"), 1, *obj); } return *obj; @@ -57,7 +54,7 @@ extern "C" { VALUE rb_file_open_str(VALUE name, const char* mode) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - VALUE m = env->get_handle(String::create(env->state(), mode)); + VALUE m = MemoryHandle::value(String::create(env->state(), mode)); FilePathValue(name); return rb_funcall(rb_cFile, rb_intern("open"), 2, name, m); diff --git a/machine/capi/fixnum.cpp b/machine/capi/fixnum.cpp index 024b0120c1..4319ed8d30 100644 --- a/machine/capi/fixnum.cpp +++ b/machine/capi/fixnum.cpp @@ -39,15 +39,15 @@ extern "C" { Integer* exp = Integer::from(state, y); if(Fixnum* base_fix = try_as(base)) { if(Fixnum* exp_fix = try_as(exp)) { - return env->get_handle(base_fix->pow(state, exp_fix)); + return MemoryHandle::value(base_fix->pow(state, exp_fix)); } else { - return env->get_handle(base_fix->pow(state, as(exp))); + return MemoryHandle::value(base_fix->pow(state, as(exp))); } } else { if(Fixnum* exp_fix = try_as(exp)) { - return env->get_handle(as(base)->pow(state, exp_fix)); + return MemoryHandle::value(as(base)->pow(state, exp_fix)); } else { - return env->get_handle(as(base)->pow(state, as(exp))); + return MemoryHandle::value(as(base)->pow(state, as(exp))); } } } diff --git a/machine/capi/float.cpp b/machine/capi/float.cpp index 0badbe5c98..32654e1b2e 100644 --- a/machine/capi/float.cpp +++ b/machine/capi/float.cpp @@ -8,62 +8,38 @@ using namespace rubinius; using namespace rubinius::capi; namespace rubinius { - namespace capi { - - Float* capi_get_float(NativeMethodEnvironment* env, VALUE float_handle) { - Handle* handle = Handle::from(float_handle); - handle->flush(env); - return c_as(handle->object()); - } - - void flush_cached_rfloat(NativeMethodEnvironment* env, Handle* handle) { - if(handle->is_rfloat()) { - Float* obj = c_as(handle->object()); - RFloat* rfloat = handle->as_rfloat(env); - obj->value(rfloat->value); - } - } - - RFloat* Handle::as_rfloat(NativeMethodEnvironment* env) { - if(type_ != cRFloat) { - Float* float_obj = c_as(object()); - - RFloat* f = new RFloat; - f->value = float_obj->value(); - - type_ = cRFloat; - as_.rfloat = f; - - flush_ = flush_cached_rfloat; - - env->state()->memory()->make_capi_handle_cached(env->state(), this); - } - - return as_.rfloat; + RFloat* MemoryHandle::get_rfloat(STATE) { + if(rfloat_p()) { + RFloat* rfloat = reinterpret_cast(data()); + rfloat->value = c_as(object())->value(); + return rfloat; + } else if(unknown_type_p()) { + RFloat* rfloat = new RFloat(); + rfloat->value = c_as(object())->value(); + set_rfloat(rfloat); + return rfloat; + } else { + Exception::raise_runtime_error(state, "C-API handle invalid reference as RFloat"); } } } extern "C" { - struct RFloat* capi_rfloat_struct(VALUE flt) { + struct RFloat* capi_rfloat_struct(VALUE value) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Handle* handle = Handle::from(flt); - env->check_tracked_handle(handle); - - return handle->as_rfloat(env); + return MemoryHandle::from(value)->get_rfloat(env->state()); } - double capi_rfloat_value(VALUE flt) { + double capi_rfloat_value(VALUE value) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Handle* handle = Handle::from(flt); - Float* f = c_as(handle->object()); + Float* f = MemoryHandle::object(value); return f->to_double(env->state()); } VALUE rb_float_new(double val) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - return env->get_handle(Float::create(env->state(), val)); + return MemoryHandle::value(Float::create(env->state(), val)); } } diff --git a/machine/capi/gc.cpp b/machine/capi/gc.cpp index 6568c29133..124c9b655a 100644 --- a/machine/capi/gc.cpp +++ b/machine/capi/gc.cpp @@ -39,11 +39,12 @@ extern "C" { } void rb_gc_mark(VALUE ptr) { - Handle* handle = Handle::from(ptr); - if(REFERENCE_P(handle) && handle->object()->reference_p()) { - Object* res = capi::current_mark()->call(handle->object()); - if(res) { - handle->set_object(res); + if(REFERENCE_P(ptr)) { + MemoryHandle* handle = MemoryHandle::from(ptr); + Object* obj = handle->object(); + if(obj->reference_p()) { + obj = capi::current_mark()->call(obj); + if(obj) handle->object(obj); } } } @@ -59,12 +60,7 @@ extern "C" { * to be in the heap. */ void rb_gc_mark_maybe(VALUE ptr) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Handle* handle = Handle::from(ptr); - - if(capi::Handle::valid_handle_p(env->state(), handle)) { - rb_gc_mark(ptr); - } + rb_gc_mark(ptr); } void rb_memerror() { diff --git a/machine/capi/globals.cpp b/machine/capi/globals.cpp index 2b464647b5..19a1df2b95 100644 --- a/machine/capi/globals.cpp +++ b/machine/capi/globals.cpp @@ -60,23 +60,22 @@ extern "C" { return rb_thread_local_aref(rb_thread_current(), rb_intern("$_")); } - void rb_free_global(VALUE global_handle) { - capi::Handle* handle = capi::Handle::from(global_handle); - if(REFERENCE_P(handle) && handle->object()->reference_p()) { - handle->deref(); - } - } - void capi_gc_register_address(VALUE* address, const char* file, int line) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - capi::Handle** loc = reinterpret_cast(address); - env->state()->memory()->add_global_capi_handle_location(env->state(), loc, file, line); + Object* object = MemoryHandle::object(*address); + + if(object->reference_p()) { + object->add_reference(env->state()); + } } void rb_gc_unregister_address(VALUE* address) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - capi::Handle** loc = reinterpret_cast(address); - env->state()->memory()->del_global_capi_handle_location(env->state(), loc); + Object* object = MemoryHandle::object(*address); + + if(object->reference_p()) { + object->sub_reference(env->state()); + } } VALUE rb_gv_get(const char* name) { @@ -86,7 +85,7 @@ extern "C" { len = strlen(name); if((len == 1 && name[0] == '~') || (len == 2 && name[0] == '$' && name[1] == '~')) { - return env->get_handle(Regexp::last_match_result(env->state(), + return MemoryHandle::value(Regexp::last_match_result(env->state(), Fixnum::from(0), Fixnum::from(0))); } VALUE Globals = rb_const_get(rb_mRubinius, rb_intern("Globals")); @@ -94,7 +93,7 @@ extern "C" { return rb_funcall(Globals, rb_intern("[]"), 1, - env->get_handle(prefixed_by(env->state(), '$', rb_intern(name)))); + MemoryHandle::value(prefixed_by(env->state(), '$', rb_intern(name)))); } VALUE rb_gv_set(const char* name, VALUE value) { @@ -105,7 +104,7 @@ extern "C" { return rb_funcall(Globals, rb_intern("[]="), 2, - env->get_handle(prefixed_by(env->state(), '$', rb_intern(name))), + MemoryHandle::value(prefixed_by(env->state(), '$', rb_intern(name))), value); } @@ -118,6 +117,6 @@ extern "C" { VALUE Globals = rb_const_get(rb_mRubinius, rb_intern("Globals")); NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - rb_funcall(Globals, rb_intern("read_only"), 1, env->get_handle(prefixed_by(env->state(), '$', rb_intern(name)))); + rb_funcall(Globals, rb_intern("read_only"), 1, MemoryHandle::value(prefixed_by(env->state(), '$', rb_intern(name)))); } } diff --git a/machine/capi/handle.cpp b/machine/capi/handle.cpp deleted file mode 100644 index 0083d77327..0000000000 --- a/machine/capi/handle.cpp +++ /dev/null @@ -1,153 +0,0 @@ -#include "class/native_method.hpp" - -#include "memory.hpp" - -#include "memory/gc.hpp" - -#include "memory/allocator.hpp" - -#include "capi/capi.hpp" -#include "capi/handle.hpp" -#include "capi/handles.hpp" -#include "capi/ruby.h" - -namespace rubinius { - namespace capi { - - bool Handle::valid_handle_p(STATE, Handle* handle) { - Handles* capi_handles = state->memory()->capi_handles(); - return capi_handles->validate(handle); - } - - void Handle::free_data() { - if(as_.cache_data) { - switch(type_) { - case cRArray: - delete[] as_.rarray->dmwmb; - delete as_.rarray; - break; - case cRString: - delete as_.rstring; - break; - case cRFloat: - delete as_.rfloat; - break; - case cRIO: - // When the IO is finalized, the FILE* is closed. - delete as_.rio; - break; - case cRFile: - delete as_.rfile; - break; - case cRData: - delete as_.rdata; - break; - default: - break; - } - as_.cache_data = 0; - } - - type_ = cUnknown; - } - - void Handle::debug_print() { - std::cerr << std::endl << "Invalid handle usage detected!" << std::endl; - std::cerr << " handle: " << this << std::endl; - std::cerr << " checksum: 0x" << std::hex << checksum_ << std::endl; - std::cerr << " references: " << references_ << std::endl; - std::cerr << " type: " << type_ << std::endl; - std::cerr << " object: " << object_ << std::endl; - } - - HandleSet::HandleSet() - : slow_(0) - { - for(int i = 0; i < cFastHashSize; i++) { - table_[i] = 0; - } - } - - void HandleSet::deref_all() { - for(int i = 0; i < cFastHashSize; i++) { - if(table_[i]) table_[i]->deref(); - } - - if(slow_) { - for(SlowHandleSet::iterator i = slow_->begin(); - i != slow_->end(); - ++i) { - Handle* handle = *i; - handle->deref(); - } - } - } - - void HandleSet::flush_all(NativeMethodEnvironment* env) { - for(int i = 0; i < cFastHashSize; i++) { - if(table_[i]) table_[i]->flush(env); - } - - if(slow_) { - for(SlowHandleSet::iterator i = slow_->begin(); - i != slow_->end(); - ++i) { - Handle* handle = *i; - handle->flush(env); - } - } - } - - void HandleSet::update_all(NativeMethodEnvironment* env) { - for(int i = 0; i < cFastHashSize; i++) { - if(table_[i]) table_[i]->update(env); - } - - if(slow_) { - for(SlowHandleSet::iterator i = slow_->begin(); - i != slow_->end(); - ++i) { - Handle* handle = *i; - handle->update(env); - } - } - } - - void HandleSet::gc_scan(memory::GarbageCollector* gc) { - for(int i = 0; i < cFastHashSize; i++) { - if(Handle* handle = table_[i]) { - handle->set_object(gc->mark_object(handle->object())); - } - } - - if(slow_) { - for(SlowHandleSet::iterator i = slow_->begin(); - i != slow_->end(); - ++i) { - Handle* handle = *i; - handle->set_object(gc->mark_object(handle->object())); - } - } - } - - bool HandleSet::slow_add_if_absent(Handle* handle) { - for(int i = 0; i < cFastHashSize; i++) { - if(table_[i] == handle) return false; - } - - std::pair ret = slow_->insert(handle); - - if(ret.second) { - handle->ref(); - } - return ret.second; - } - - void HandleSet::make_slow_and_add(Handle* handle) { - // Inflate it to the slow set. - slow_ = new SlowHandleSet; - slow_->insert(handle); - handle->ref(); - } - } -} diff --git a/machine/capi/handle.hpp b/machine/capi/handle.hpp deleted file mode 100644 index c5ec706d6b..0000000000 --- a/machine/capi/handle.hpp +++ /dev/null @@ -1,290 +0,0 @@ -#ifndef RBX_CAPI_HANDLE_HPP -#define RBX_CAPI_HANDLE_HPP - -#include "detection.hpp" - -#if defined(__APPLE__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070 -#ifndef RBX_HAVE_TR1_HASH -#include "missing/leopard_hashtable.hpp" -#endif -#endif - -#include "vm.hpp" -#include "state.hpp" -#include "memory/root.hpp" - -#include "capi/value.hpp" - -#include - -#ifndef RIO -#define RIO rb_io_t -#endif - -struct RArray; -struct RString; -struct RData; -struct RTypedData; -struct RFloat; -struct RIO; -struct RFile; - -namespace rubinius { - class NativeMethodEnvironment; - - namespace capi { - - enum HandleType { - cUnknown, - cRArray, - cRString, - cRData, - cRFloat, - cRIO, - cRFile - }; - - class Handle { - Object* object_; - HandleType type_; - int references_; - unsigned int checksum_; - - typedef void (*CApiCacheFlusher)(NativeMethodEnvironment* env, Handle* handle); - typedef void (*CApiCacheUpdater)(NativeMethodEnvironment* env, Handle* handle); - - CApiCacheFlusher flush_; - CApiCacheUpdater update_; - - union { - RArray* rarray; - RString* rstring; - RData* rdata; - RTypedData* rtypeddata; - RFloat* rfloat; - RIO* rio; - RFile* rfile; - uintptr_t next_index_; - intptr_t cache_data; - } as_; - - public: - Handle() - : object_(NULL) - , type_(cUnknown) - , references_(0) - , checksum_(0) - , flush_(0) - , update_(0) - { - as_.cache_data = 0; - } - - static bool valid_handle_p(STATE, Handle* handle); - - void flush(NativeMethodEnvironment* env) { - if(flush_) (*flush_)(env, this); - } - - void update(NativeMethodEnvironment* env) { - if(update_) (*update_)(env, this); - } - -#define RBX_CAPI_HANDLE_CHECKSUM 0xffff - - bool valid_p() const { - return checksum_ == RBX_CAPI_HANDLE_CHECKSUM; - } - - void validate() { - checksum_ = RBX_CAPI_HANDLE_CHECKSUM; - } - - void invalidate() { - checksum_ = 0; - } - - Object* object() const { - return object_; - } - - bool in_use_p() const { - return object_ != 0; - } - - void set_object(Object* obj) { - object_ = obj; - } - - bool weak_p() const { - return references_ == 0; - } - - void ref() { - references_++; - } - - void deref() { - references_--; - } - - void debug_print(); - - // Explict conversion functions, to keep the code clean. - VALUE as_value() const { - return reinterpret_cast(this); - } - - static Handle* from(VALUE val) { - return reinterpret_cast(val); - } - - bool is_rarray() const { - return type_ == cRArray; - } - - bool is_rdata() const { - return type_ == cRData; - } - - bool is_rstring() const { - return type_ == cRString; - } - - bool is_rfloat() const { - return type_ == cRFloat; - } - - bool is_rio() const { - return type_ == cRIO; - } - - bool is_rfile() const { - return type_ == cRFile; - } - - HandleType type() const { - return type_; - } - - void clear() { - forget_object(); - type_ = cUnknown; - references_ = 0; - flush_ = 0; - update_ = 0; - } - - void forget_object() { - free_data(); - invalidate(); - object_ = 0; - } - - RString* get_rstring() const { - return as_.rstring; - } - - uintptr_t next() const { - return as_.next_index_; - } - - void set_next(uintptr_t next_index) { - as_.next_index_ = next_index; - } - - RData* as_rdata(NativeMethodEnvironment* env); - RTypedData* as_rtypeddata(NativeMethodEnvironment* env); - RArray* as_rarray(NativeMethodEnvironment* env); - RString* as_rstring(NativeMethodEnvironment* env, int cache_level); - RFloat* as_rfloat(NativeMethodEnvironment* env); - RIO* as_rio(NativeMethodEnvironment* env); - RFile* as_rfile(NativeMethodEnvironment* env); - - void free_data(); - bool rio_close(); - }; - - class GlobalHandle { - private: - Handle** handle_; - const char* file_; - int line_; - - public: - GlobalHandle(Handle** handle, const char* file, int line) - : handle_(handle) - , file_(file) - , line_(line) - {} - - GlobalHandle(Handle** handle) - : handle_(handle) - , file_(NULL) - , line_(0) - {} - - Handle** handle() { - return handle_; - } - - const char* file() { - return file_; - } - - int line() { - return line_; - } - }; - - typedef std::set SlowHandleSet; - - class HandleSet { - public: - const static int cFastHashSize = 16; - - private: - SlowHandleSet* slow_; - Handle* table_[cFastHashSize]; - - public: - HandleSet(); - ~HandleSet() { - if(slow_) delete slow_; - } - - void deref_all(); - void flush_all(NativeMethodEnvironment* env); - void update_all(NativeMethodEnvironment* env); - void gc_scan(memory::GarbageCollector* gc); - - bool add_if_absent(Handle* handle) { - // ref() ONLY if it's not already in there! - // otherwise the refcount is wrong and we leak handles. - - if(unlikely(slow_)) { - return slow_add_if_absent(handle); - } else { - for(int i = 0; i < cFastHashSize; i++) { - if(!table_[i]) { - table_[i] = handle; - handle->ref(); - - return true; - } - if(table_[i] == handle) return false; - } - - make_slow_and_add(handle); - return true; - } - } - - private: - void make_slow_and_add(Handle* handle); - bool slow_add_if_absent(Handle* handle); - }; - } -} - -#endif diff --git a/machine/capi/handles.cpp b/machine/capi/handles.cpp deleted file mode 100644 index 9a05e5ac7d..0000000000 --- a/machine/capi/handles.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include "class/native_method.hpp" - -#include "memory.hpp" -#include "logger.hpp" - -#include "memory/gc.hpp" - -#include "capi/capi.hpp" -#include "capi/handles.hpp" - -#include "diagnostics/gc.hpp" -#include "diagnostics/memory.hpp" - -namespace rubinius { - namespace capi { - Handles::Handles() - : allocator_(new memory::Allocator()) - , diagnostic_(new diagnostics::Handles()) - {} - - Handles::~Handles() { - for(std::vector::size_type i = 0; i < allocator_->chunks_.size(); ++i) { - Handle* chunk = allocator_->chunks_[i]; - - for(size_t j = 0; j < allocator_->cChunkSize; j++) { - Handle* handle = &chunk[j]; - if(handle->in_use_p()) { - handle->clear(); - } - } - } - - delete allocator_; - - if(diagnostic_) { - delete diagnostic_; - diagnostic_ = nullptr; - } - } - - Handle* Handles::allocate(STATE, Object* obj) { - bool needs_gc = false; - Handle* handle = allocator_->allocate(&needs_gc); - handle->set_object(obj); - handle->validate(); - if(needs_gc) { - diagnostic()->collections++; - state->memory()->schedule_full_collection( - "CAPI handles", - state->shared().gc_metrics()->handles_set); - } - atomic::memory_barrier(); - return handle; - } - - uintptr_t Handles::allocate_index(STATE, Object* obj) { - bool needs_gc = false; - uintptr_t handle_index = allocator_->allocate_index(&needs_gc); - - if(handle_index > UINT32_MAX) { - rubinius::bug("Rubinius can allocate maximum 2^32 C-API handles"); - } - - Handle* handle = allocator_->from_index(handle_index); - handle->set_object(obj); - handle->validate(); - if(needs_gc) { - diagnostic()->collections++; - state->memory()->schedule_full_collection( - "CAPI handles", - state->shared().gc_metrics()->handles_set); - } - atomic::memory_barrier(); - - return handle_index; - } - - bool Handles::validate(Handle* handle) { - return allocator_->validate(handle); - } - - void Handles::deallocate_handles(std::list* cached, - unsigned int mark, /* BakerGC */ void* young) - { - std::vector chunk_marks(allocator_->chunks_.size(), false); - - diagnostic()->objects = 0; - - for(std::vector::size_type i = 0; i < allocator_->chunks_.size(); ++i) { - Handle* chunk = allocator_->chunks_[i]; - - for(size_t j = 0; j < allocator_->cChunkSize; j++) { - Handle* handle = &chunk[j]; - - Object* obj = handle->object(); - - if(!handle->in_use_p()) { - continue; - } - - // Strong references will already have been updated. - if(!handle->weak_p()) { - chunk_marks[i] = true; - diagnostic()->objects++; - continue; - } - - if(young) { - /* - if(obj->young_object_p()) { - // A weakref pointing to a valid young object - // - // TODO this only works because we run prune_handles right after - // a collection. In this state, valid objects are only in current. - if(young->in_current_p(obj)) { - chunk_marks[i] = true; - diagnostic()->objects++; - // A weakref pointing to a forwarded young object - } else if(obj->forwarded_p()) { - handle->set_object(obj->forward()); - chunk_marks[i] = true; - diagnostic()->objects++; - // A weakref pointing to a dead young object - } else { - handle->clear(); - } - } else { - // Not a young object, so won't be GC'd so mark - // chunk as still active - chunk_marks[i] = true; - diagnostic()->objects++; - } - */ - - // A weakref pointing to a dead mature object - } else if(!obj->marked_p(mark)) { - handle->clear(); - } else { - chunk_marks[i] = true; - diagnostic()->objects++; - } - } - } - - // Cleanup cached handles - for(std::list::iterator it = cached->begin(); it != cached->end();) { - Handle* handle = *it; - - if(handle->in_use_p()) { - ++it; - } else { - it = cached->erase(it); - } - } - - allocator_->rebuild_freelist(&chunk_marks); - - diagnostic()->bytes = allocator_->in_use_ * sizeof(Handle); - } - } -} diff --git a/machine/capi/handles.hpp b/machine/capi/handles.hpp deleted file mode 100644 index 2211e4eddb..0000000000 --- a/machine/capi/handles.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef RBX_CAPI_HANDLES_HPP -#define RBX_CAPI_HANDLES_HPP - -#include "vm.hpp" -#include "state.hpp" - -#include "memory/root.hpp" -#include "memory/allocator.hpp" - -#include "capi/handle.hpp" - -#include "diagnostics.hpp" - -#include -#include - -namespace rubinius { - namespace capi { - class Handles { - memory::Allocator* allocator_; - - diagnostics::Handles* diagnostic_; - - public: - - Handles(); - ~Handles(); - - Handle* allocate(STATE, Object* obj); - - uintptr_t allocate_index(STATE, Object* obj); - - Handle* find_index(uintptr_t index) { - return allocator_->from_index(index); - } - - bool validate(Handle* handle); - - void deallocate_handles(std::list* cached, unsigned int mark, /* BakerGC */ void* young); - - void flush_all(NativeMethodEnvironment* env); - - memory::Allocator* allocator() const { - return allocator_; - } - - int size() const { - return allocator_->in_use_; - } - - diagnostics::Handles* diagnostic() { - return diagnostic_; - } - }; - } -} - -#endif diff --git a/machine/capi/hash.cpp b/machine/capi/hash.cpp index bbf8bb7d0f..71ba23ef1e 100644 --- a/machine/capi/hash.cpp +++ b/machine/capi/hash.cpp @@ -37,7 +37,7 @@ extern "C" { VALUE rb_hash_delete_if(VALUE self) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - VALUE block_handle = env->get_handle(env->block()); + VALUE block_handle = MemoryHandle::value(env->block()); return rb_funcall2b(self, rb_intern("delete_if"), 0, 0, block_handle); } diff --git a/machine/capi/integer.cpp b/machine/capi/integer.cpp index 34a890370f..e244a60986 100644 --- a/machine/capi/integer.cpp +++ b/machine/capi/integer.cpp @@ -25,7 +25,7 @@ extern "C" { size = FIXNUM_MIN_WIDTH; } } else if(RB_TYPE_P(value, T_BIGNUM)) { - Bignum* big = c_as(env->get_object(value)); + Bignum* big = MemoryHandle::object(value); size = big->size(env->state())->to_native(); } @@ -56,7 +56,7 @@ extern "C" { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - if(Fixnum* f = try_as(env->get_object(value))) { + if(Fixnum* f = MemoryHandle::try_as(value)) { native_int v = f->to_native(); if(v == 0) return 0; @@ -81,7 +81,7 @@ extern "C" { memset(bytes->byte_address(), 0, numbytes); VALUE result = rb_funcall(rb_mCAPI, rb_intern("rb_integer_pack"), 6, - value, env->get_handle(bytes), INT2FIX(numwords), INT2FIX(wordsize), + value, MemoryHandle::value(bytes), INT2FIX(numwords), INT2FIX(wordsize), INT2FIX(nails), INT2FIX(flags)); memcpy(words, bytes->byte_address(), numbytes); diff --git a/machine/capi/io.cpp b/machine/capi/io.cpp index 6112e5d6be..51677ba6c0 100644 --- a/machine/capi/io.cpp +++ b/machine/capi/io.cpp @@ -22,130 +22,115 @@ using namespace rubinius; using namespace rubinius::capi; namespace rubinius { - namespace capi { - - IO* capi_get_io(NativeMethodEnvironment* env, VALUE io_handle) { - Handle* handle = Handle::from(io_handle); - handle->flush(env); - env->check_tracked_handle(handle, false); - return c_as(handle->object()); - } - - static const char* flags_modestr(int oflags) - { + static const char* flags_modestr(int oflags) + { #ifdef O_BINARY # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a)) #else # define MODE_BINARY(a,b) (a) #endif - int accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR); - if(oflags & O_APPEND) { - if(accmode == O_WRONLY) { - return MODE_BINARY("a", "ab"); - } - if(accmode == O_RDWR) { - return MODE_BINARY("a+", "ab+"); - } + int accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR); + if(oflags & O_APPEND) { + if(accmode == O_WRONLY) { + return MODE_BINARY("a", "ab"); } - switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) { - case O_RDONLY: - return MODE_BINARY("r", "rb"); - case O_WRONLY: - return MODE_BINARY("w", "wb"); - case O_RDWR: - return MODE_BINARY("r+", "rb+"); + if(accmode == O_RDWR) { + return MODE_BINARY("a+", "ab+"); } - return NULL; } + switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) { + case O_RDONLY: + return MODE_BINARY("r", "rb"); + case O_WRONLY: + return MODE_BINARY("w", "wb"); + case O_RDWR: + return MODE_BINARY("r+", "rb+"); + } + return NULL; + } - RIO* Handle::as_rio(NativeMethodEnvironment* env) { - IO* io_obj = c_as(object()); - ID id_descriptor = rb_intern("descriptor"); - ID id_mode = rb_intern("mode"); - VALUE jobj = env->get_handle(io_obj); - - if(type_ != cRIO) { - env->shared().capi_ds_lock().lock(); - - if(type_ != cRIO) { - native_int fd = -1; - VALUE fileno = rb_funcall(jobj, id_descriptor, 0); - Fixnum* tmp_fd = try_as(env->get_object(fileno)); - - if(tmp_fd) { - fd = tmp_fd->to_native(); - } + RIO* MemoryHandle::get_rio(STATE) { + ID id_descriptor = rb_intern("descriptor"); + ID id_mode = rb_intern("mode"); + VALUE jobj = as_value(); - env->shared().capi_ds_lock().unlock(); + if(rio_p()) { + return reinterpret_cast(data()); + } else if(unknown_type_p()) { + native_int fd = -1; + VALUE fileno = rb_funcall(jobj, id_descriptor, 0); + Fixnum* tmp_fd = MemoryHandle::try_as(fileno); - if(fd == -1) { - char buf[RBX_STRERROR_BUFSIZE]; - char* err = RBX_STRERROR(errno, buf, RBX_STRERROR_BUFSIZE); - rb_raise(rb_eIOError, "%s (%d)", err, errno); - } + if(tmp_fd) { + fd = tmp_fd->to_native(); + } - FILE* f = fdopen(fd, flags_modestr(try_as(env->get_object(rb_funcall(jobj, id_mode, 0)))->to_native())); + if(fd == -1) { + char buf[RBX_STRERROR_BUFSIZE]; + char* err = RBX_STRERROR(errno, buf, RBX_STRERROR_BUFSIZE); + rb_raise(rb_eIOError, "%s (%d)", err, errno); + } - if(!f) { - char buf[RBX_STRERROR_BUFSIZE]; - char* err = RBX_STRERROR(errno, buf, RBX_STRERROR_BUFSIZE); - std::cerr << "Error convert fd (" << fd << ") to lowlevel IO: " - << err << " (" << errno << ")" << std::endl; + VALUE mode = rb_funcall(jobj, id_mode, 0); + Fixnum* oflags = MemoryHandle::try_as(mode); + FILE* f = fdopen(fd, flags_modestr(oflags ? oflags->to_native() : 0)); - env->shared().capi_ds_lock().unlock(); + if(!f) { + char buf[RBX_STRERROR_BUFSIZE]; + char* err = RBX_STRERROR(errno, buf, RBX_STRERROR_BUFSIZE); + std::cerr << "Error convert fd (" << fd << ") to lowlevel IO: " + << err << " (" << errno << ")" << std::endl; - rb_raise(rb_eTypeError, - "unable to convert fd (%d) to lowlevel IO: %s (%d)", - fd, err, errno); - } + rb_raise(rb_eTypeError, + "unable to convert fd (%d) to lowlevel IO: %s (%d)", + fd, err, errno); + } - RIO* rf = new RIO; - rf->handle = as_value(); - rf->fd = fd; - rf->f = f; - rf->f2 = NULL; - rf->stdio_file = NULL; - rf->finalize = NULL; + RIO* rf = new RIO; + rf->handle = as_value(); + rf->fd = fd; + rf->f = f; + rf->f2 = NULL; + rf->stdio_file = NULL; + rf->finalize = NULL; - // Disable all buffering so that it doesn't get out of sync with - // the normal IO buffer. - setvbuf(rf->f, 0, _IONBF, 0); + // Disable all buffering so that it doesn't get out of sync with + // the normal IO buffer. + setvbuf(rf->f, 0, _IONBF, 0); - type_ = cRIO; - as_.rio = rf; - } + set_rio(rf); - env->shared().capi_ds_lock().unlock(); - } - - return as_.rio; + return rf; + } else { + Exception::raise_runtime_error(state, "C-API handle invalid reference as RIO"); } + } - bool Handle::rio_close() { - if(type_ != cRIO) return true; - - RIO* rio = as_.rio; + bool MemoryHandle::rio_close(STATE) { + if(!rio_p()) return true; - if(rio->finalize) rio->finalize(rio, true); + RIO* rio = reinterpret_cast(data()); - bool ok = true; + if(rio->finalize) rio->finalize(rio, true); - /* This field is publicly accessible in the C-API structure so we need - * to guard against the possibility that it is NULL; - */ - if(rio->f) { - ok = (fclose(rio->f) == 0); - rio->f = NULL; - } + bool ok = true; - return ok; + /* This field is publicly accessible in the C-API structure so we need + * to guard against the possibility that it is NULL; + */ + if(rio->f) { + ok = (fclose(rio->f) == 0); + rio->f = NULL; } + + return ok; } } + extern "C" { - struct RIO* capi_rio_struct(VALUE io_handle) { + RIO* capi_rio_struct(VALUE io_handle) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - return Handle::from(io_handle)->as_rio(env); + return MemoryHandle::from(io_handle)->get_rio(env->state()); } void rb_eof_error() { @@ -182,9 +167,8 @@ extern "C" { } int rb_io_fd(VALUE io_handle) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - return c_as(env->get_object(rb_funcall(io_handle, rb_intern("fileno"), 0)))->to_native(); + return MemoryHandle::object( + rb_funcall(io_handle, rb_intern("fileno"), 0))->to_native(); } long rb_io_fread(char* ptr, int len, FILE* f) { @@ -385,17 +369,16 @@ extern "C" { void rb_io_check_closed(rb_io_t* iot) { VALUE io_handle = iot->handle; - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - if(c_as(env->get_object(rb_funcall(io_handle, rb_intern("fileno"), 0)))->to_native() == -1) { + if(MemoryHandle::object( + rb_funcall(io_handle, rb_intern("fileno"), 0))->to_native() == -1) { rb_raise(rb_eIOError, "closed stream"); } } void rb_io_check_readable(rb_io_t* iot) { VALUE io_handle = iot->handle; - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - int io_mode = c_as(env->get_object(rb_funcall(io_handle, rb_intern("mode"), 0)))->to_native() & O_ACCMODE; + int io_mode = MemoryHandle::object( + rb_funcall(io_handle, rb_intern("mode"), 0))->to_native() & O_ACCMODE; if(!(O_RDONLY == io_mode || O_RDWR == io_mode)) { rb_raise(rb_eIOError, "not opened for reading"); } @@ -403,8 +386,8 @@ extern "C" { void rb_io_check_writable(rb_io_t* iot) { VALUE io_handle = iot->handle; - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - int io_mode = c_as(env->get_object(rb_funcall(io_handle, rb_intern("mode"), 0)))->to_native() & O_ACCMODE; + int io_mode = MemoryHandle::object( + rb_funcall(io_handle, rb_intern("mode"), 0))->to_native() & O_ACCMODE; if(!(O_WRONLY == io_mode || O_RDWR == io_mode)) { rb_raise(rb_eIOError, "not opened for writing"); } @@ -414,8 +397,8 @@ extern "C" { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); State *state = env->state(); Object* fd_object = G(io)->get_const(env->state(), "FileDescriptor"); - VALUE fd_class = env->get_handle(fd_object); - VALUE descriptor = env->get_handle(Fixnum::from(fd)); + VALUE fd_class = MemoryHandle::value(fd_object); + VALUE descriptor = MemoryHandle::value(Fixnum::from(fd)); rb_funcall(fd_class, rb_intern("update_max_fd"), 1, descriptor); } @@ -424,8 +407,8 @@ extern "C" { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); State *state = env->state(); Object* fd_object = G(io)->get_const(env->state(), "FileDescriptor"); - VALUE fd_class = env->get_handle(fd_object); - VALUE descriptor = env->get_handle(Fixnum::from(fd)); + VALUE fd_class = MemoryHandle::value(fd_object); + VALUE descriptor = MemoryHandle::value(Fixnum::from(fd)); rb_funcall(fd_class, rb_intern("new_open_fd"), 1, descriptor); } diff --git a/machine/capi/kernel.cpp b/machine/capi/kernel.cpp index 5dc394b921..2b7bea091b 100644 --- a/machine/capi/kernel.cpp +++ b/machine/capi/kernel.cpp @@ -65,7 +65,7 @@ extern "C" { env->current_ep()->return_to(env); } - VALUE exc_handle = env->get_handle(env->state()->thread_state()->current_exception()); + VALUE exc_handle = MemoryHandle::value(env->state()->thread_state()->current_exception()); bool handle_exc = false; va_start(exc_classes, arg2); @@ -208,7 +208,7 @@ extern "C" { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); String* string = String::create(env->state(), msg); - rb_funcall(rb_mKernel, rb_intern("warn"), 1, env->get_handle(string)); + rb_funcall(rb_mKernel, rb_intern("warn"), 1, MemoryHandle::value(string)); } void rb_warning(const char* fmt, ...) { @@ -221,7 +221,7 @@ extern "C" { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); String* string = String::create(env->state(), msg); - rb_funcall(rb_mKernel, rb_intern("warning"), 1, env->get_handle(string)); + rb_funcall(rb_mKernel, rb_intern("warning"), 1, MemoryHandle::value(string)); } VALUE rb_require(const char* name) { @@ -252,7 +252,7 @@ extern "C" { VALUE rb_block_proc() { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); return rb_funcall(rb_mCAPI, rb_intern("rb_block_proc"), 1, - env->get_handle(env->block())); + MemoryHandle::value(env->block())); } // Hoisted from 1.8.7 @@ -352,8 +352,7 @@ extern "C" { } void rb_set_end_proc(void* cb, VALUE cb_data) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - VALUE prc = env->get_handle( + VALUE prc = MemoryHandle::value( capi::wrap_c_function(cb, cb_data, C_CALLBACK)); rb_funcall(rb_mKernel, rb_intern("at_exit"), 1, prc); } diff --git a/machine/capi/module.cpp b/machine/capi/module.cpp index 91405f2564..a4cf34fcc6 100644 --- a/machine/capi/module.cpp +++ b/machine/capi/module.cpp @@ -41,7 +41,7 @@ extern "C" { if(CallFrame* frame = env->state()->vm()->get_ruby_frame(1)) { Symbol* name = frame->name(); - if(!name->nil_p()) return env->get_handle(name); + if(!name->nil_p()) return MemoryHandle::value(name); } return rb_intern(""); @@ -55,7 +55,7 @@ extern "C" { if(name->nil_p()) return rb_intern(""); - return env->get_handle(name); + return MemoryHandle::value(name); } static VALUE const_missing(VALUE klass, ID id) { @@ -67,7 +67,7 @@ extern "C" { State* state = env->state(); Symbol* name = reinterpret_cast(id_name); - Module* module = c_as(env->get_object(module_handle)); + Module* module = MemoryHandle::object(module_handle); ConstantMissingReason reason = vNonExistent; Object* val = module->get_const(state, name, G(sym_private), &reason); @@ -75,11 +75,11 @@ extern "C" { if(reason != vFound) return const_missing(module_handle, id_name); if(Autoload* autoload = try_as(val)) { - return capi_fast_call(env->get_handle(autoload), + return capi_fast_call(MemoryHandle::value(autoload), rb_intern("call"), 1, module_handle); } - return env->get_handle(val); + return MemoryHandle::value(val); } VALUE rb_const_get_from(VALUE module_handle, ID id_name) { @@ -87,18 +87,18 @@ extern "C" { State* state = env->state(); Symbol* name = reinterpret_cast(id_name); - Module* module = c_as(env->get_object(module_handle)); + Module* module = MemoryHandle::object(module_handle); ConstantMissingReason reason = vNonExistent; while(!module->nil_p()) { Object* val = module->get_const(state, name, G(sym_private), &reason); if(reason == vFound) { if(Autoload* autoload = try_as(val)) { - return capi_fast_call(env->get_handle(autoload), + return capi_fast_call(MemoryHandle::value(autoload), rb_intern("call"), 1, module_handle); } - return env->get_handle(val); + return MemoryHandle::value(val); } module = module->superclass(); @@ -112,18 +112,18 @@ extern "C" { State* state = env->state(); Symbol* name = reinterpret_cast(id_name); - Module* module = c_as(env->get_object(module_handle)); + Module* module = MemoryHandle::object(module_handle); ConstantMissingReason reason = vNonExistent; while(!module->nil_p()) { Object* val = module->get_const(state, name, G(sym_private), &reason); if(reason == vFound) { if(Autoload* autoload = try_as(val)) { - return capi_fast_call(env->get_handle(autoload), - rb_intern("call"), 1, env->get_handle(module)); + return capi_fast_call(MemoryHandle::value(autoload), + rb_intern("call"), 1, MemoryHandle::value(module)); } - return env->get_handle(val); + return MemoryHandle::value(val); } module = module->superclass(); @@ -136,11 +136,11 @@ extern "C" { Object* val = module->get_const(state, name, G(sym_private), &reason); if(reason == vFound) { if(Autoload* autoload = try_as(val)) { - return capi_fast_call(env->get_handle(autoload), - rb_intern("call"), 1, env->get_handle(module)); + return capi_fast_call(MemoryHandle::value(autoload), + rb_intern("call"), 1, MemoryHandle::value(module)); } - return env->get_handle(val); + return MemoryHandle::value(val); } module = module->superclass(); @@ -152,8 +152,8 @@ extern "C" { void rb_const_set(VALUE module_handle, ID name, VALUE obj_handle) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Module* module = c_as(env->get_object(module_handle)); - Object* object = env->get_object(obj_handle); + Module* module = MemoryHandle::object(module_handle); + Object* object = MemoryHandle::object(obj_handle); module->set_const(env->state(), reinterpret_cast(name), object); } @@ -176,7 +176,8 @@ extern "C" { void rb_undef_alloc_func(VALUE class_handle) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); rb_undef_method( - env->get_handle(env->get_object(class_handle)->singleton_class(env->state())), + MemoryHandle::value( + MemoryHandle::object(class_handle)->singleton_class(env->state())), "allocate"); } @@ -193,8 +194,8 @@ extern "C" { void rb_define_const(VALUE module_handle, const char* name, VALUE obj_handle) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Module* module = c_as(env->get_object(module_handle)); - Object* object = env->get_object(obj_handle); + Module* module = c_as(MemoryHandle::object(module_handle)); + Object* object = MemoryHandle::object(obj_handle); module->set_const(env->state(), name, object); } @@ -221,7 +222,7 @@ extern "C" { VALUE rb_define_module_under(VALUE parent_handle, const char* name) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Module* parent = c_as(env->get_object(parent_handle)); + Module* parent = c_as(MemoryHandle::object(parent_handle)); Symbol* constant = env->state()->symbol(name); LEAVE_CAPI(env->state()); @@ -242,7 +243,7 @@ extern "C" { // Grab the module handle before grabbing the lock // so the Module isn't accidentally GC'ed. - VALUE module_handle = env->get_handle(module); + VALUE module_handle = MemoryHandle::value(module); ENTER_CAPI(env->state()); return module_handle; @@ -277,7 +278,7 @@ extern "C" { VALUE rb_mod_remove_const(VALUE mod, VALUE name) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Module* module = c_as(env->get_object(mod)); + Module* module = c_as(MemoryHandle::object(mod)); module->del_const(env->state(), reinterpret_cast(name)); return Qnil; } @@ -285,13 +286,13 @@ extern "C" { const char* rb_class2name(VALUE module_handle) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); State* state = env->state(); - Module* module_object = c_as(env->get_object(module_handle)); + Module* module_object = c_as(MemoryHandle::object(module_handle)); String* str = module_object->get_name(state); if(str->nil_p()) { std::string desc = module_object->to_string(state); str = String::create(state, desc.c_str(), desc.size()); } - return RSTRING_PTR(env->get_handle(str)); + return RSTRING_PTR(MemoryHandle::value(str)); } } diff --git a/machine/capi/numeric.cpp b/machine/capi/numeric.cpp index 0e18b080f5..6e51aaaa66 100644 --- a/machine/capi/numeric.cpp +++ b/machine/capi/numeric.cpp @@ -17,7 +17,7 @@ extern "C" { char rb_num2chr(VALUE obj) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Object* object = env->get_object(obj); + Object* object = MemoryHandle::object(obj); String* str; char chr; @@ -39,19 +39,19 @@ extern "C" { return num; } - long rb_num2long(VALUE obj) { + long rb_num2long(VALUE value) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Object* object = env->get_object(obj); + Object* object = MemoryHandle::object(value); if(object->nil_p()) { rb_raise(rb_eTypeError, "no implicit conversion from nil to Integer"); } else if(Fixnum* fix = try_as(object)) { return fix->to_long(); } else if(try_as(object)) { - return rb_big2long(obj); + return rb_big2long(value); } else if(try_as(object)) { - return (long)capi_get_float(env, obj)->value(); + return (long)MemoryHandle::from(value)->get_rfloat(env->state())->value; } else if(object->true_p()) { rb_raise(rb_eTypeError, "can't convert true to Integer"); } else if(object->false_p()) { @@ -60,14 +60,14 @@ extern "C" { ID to_int_id = rb_intern("to_int"); - if(!rb_respond_to(obj, to_int_id)) { + if(!rb_respond_to(value, to_int_id)) { rb_raise(rb_eTypeError, "can't convert %s into Integer", - rb_obj_classname(obj)); + rb_obj_classname(value)); } - obj = rb_funcall(obj, to_int_id, 0); + value = rb_funcall(value, to_int_id, 0); - return rb_num2long(obj); + return rb_num2long(value); } unsigned long rb_num2uint(VALUE obj) { @@ -87,40 +87,28 @@ extern "C" { return num; } - unsigned long rb_num2ulong(VALUE obj) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - Object* object = env->get_object(obj); - - if(try_as(object)) { - return rb_big2ulong(obj); + unsigned long rb_num2ulong(VALUE value) { + if(MemoryHandle::try_as(value)) { + return rb_big2ulong(value); } - return (unsigned long)rb_num2long(obj); + return (unsigned long)rb_num2long(value); } - long long rb_num2ll(VALUE obj) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - Object* object = env->get_object(obj); - - if(Bignum* big = try_as(object)) { + long long rb_num2ll(VALUE value) { + if(Bignum* big = MemoryHandle::try_as(value)) { return big->to_long_long(); } - return (long long)rb_num2long(obj); + return (long long)rb_num2long(value); } - unsigned long long rb_num2ull(VALUE obj) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - Object* object = env->get_object(obj); - - if(Bignum* big = try_as(object)) { + unsigned long long rb_num2ull(VALUE value) { + if(Bignum* big = MemoryHandle::try_as(value)) { return big->to_ulong_long(); } - return (unsigned long long)rb_num2long(obj); + return (unsigned long long)rb_num2long(value); } VALUE rb_int2big(long number) { @@ -166,17 +154,17 @@ extern "C" { if(i->nil_p()) { rb_raise(rb_eArgError, "invalid string for Integer"); } - return env->get_handle(i); + return MemoryHandle::value(i); } VALUE rb_ll2inum(long long val) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - return env->get_handle(Integer::from(env->state(), val)); + return MemoryHandle::value(Integer::from(env->state(), val)); } VALUE rb_ull2inum(unsigned long long val) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - return env->get_handle(Integer::from(env->state(), val)); + return MemoryHandle::value(Integer::from(env->state(), val)); } VALUE rb_num_coerce_bin(VALUE x, VALUE y, ID func) { @@ -191,20 +179,20 @@ extern "C" { return rb_funcall(rb_mCAPI, rb_intern("rb_num_coerce_relop"), 3, x, y, ID2SYM(func)); } - double rb_num2dbl(VALUE val) { + double rb_num2dbl(VALUE value) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Object* object = env->get_object(val); + Object* object = MemoryHandle::object(value); if(object->nil_p()) { rb_raise(rb_eTypeError, "no implicit conversion from nil to Float"); } else if(try_as(object)) { rb_raise(rb_eTypeError, "no implicit conversion from String to Float"); } else if(!try_as(object)) { - val = rb_Float(val); + value = rb_Float(value); } - return capi_get_float(env, val)->value(); + return MemoryHandle::from(value)->get_rfloat(env->state())->value; } // Imported from MRI diff --git a/machine/capi/object.cpp b/machine/capi/object.cpp index 6d86d6a402..c746d04ca4 100644 --- a/machine/capi/object.cpp +++ b/machine/capi/object.cpp @@ -13,18 +13,12 @@ using namespace rubinius; using namespace rubinius::capi; extern "C" { - void rb_error_frozen(const char* what) { rb_raise(rb_eRuntimeError, "can't modify frozen %s", what); } VALUE rb_obj_frozen_p(VALUE obj) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - if(CBOOL(env->get_object(obj)->frozen_p(env->state()))) { - return Qtrue; - } - - return Qfalse; + return MemoryHandle::object(obj)->frozen_p() ? Qtrue : Qfalse; } void rb_check_frozen(VALUE obj_handle) { @@ -36,7 +30,7 @@ extern "C" { VALUE rb_obj_freeze(VALUE hndl) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - env->get_object(hndl)->freeze(env->state()); + MemoryHandle::object(hndl)->freeze(env->state()); return hndl; } @@ -110,19 +104,19 @@ extern "C" { VALUE rb_check_array_type(VALUE object_handle) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - return rb_funcall(env->get_handle(env->state()->globals().type.get()), rb_intern("try_convert"), 3, object_handle, rb_cArray, rb_intern("to_ary")); + return rb_funcall(MemoryHandle::value(env->state()->globals().type.get()), rb_intern("try_convert"), 3, object_handle, rb_cArray, rb_intern("to_ary")); } VALUE rb_check_string_type(VALUE object_handle) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - return rb_funcall(env->get_handle(env->state()->globals().type.get()), rb_intern("try_convert"), 3, object_handle, rb_cString, rb_intern("to_str")); + return rb_funcall(MemoryHandle::value(env->state()->globals().type.get()), rb_intern("try_convert"), 3, object_handle, rb_cString, rb_intern("to_str")); } static VALUE convert_type(VALUE object, const char* type_name, const char* method_name, bool raise=false) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - VALUE name = env->get_handle(String::create(env->state(), method_name)); + VALUE name = MemoryHandle::value(String::create(env->state(), method_name)); if(RTEST(rb_funcall(object, rb_intern("respond_to?"), 1, name)) ) { return rb_funcall2(object, rb_intern(method_name), 0, NULL); @@ -209,7 +203,7 @@ extern "C" { if(obj == Qundef) return T_UNDEF; if(SYMBOL_P(obj)) return T_SYMBOL; - capi::Handle* handle = capi::Handle::from(obj); + MemoryHandle* handle = MemoryHandle::from(obj); Object* object = handle->object(); switch(object->type_id()) { case ArrayType: @@ -261,11 +255,7 @@ extern "C" { } VALUE rb_obj_as_string(VALUE obj_handle) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - Object* object = env->get_object(obj_handle); - - if(kind_of(object)) { + if(MemoryHandle::try_as(obj_handle)) { return obj_handle; } @@ -273,9 +263,6 @@ extern "C" { } VALUE rb_obj_clone(VALUE obj_handle) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - env->flush_cached_data(); return rb_funcall(obj_handle, rb_intern("clone"), 0); } @@ -322,7 +309,7 @@ extern "C" { ID rb_intern_str(VALUE str) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - String* string = capi_get_string(env, str); + String* string = MemoryHandle::object(str); return reinterpret_cast(string->to_sym(env->state())); } @@ -337,20 +324,20 @@ extern "C" { VALUE rb_ivar_get(VALUE self_handle, ID ivar_name) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Object* object = env->get_object(self_handle); + Object* object = MemoryHandle::object(self_handle); Symbol* sym = reinterpret_cast(ivar_name); - return env->get_handle(object->get_ivar(env->state(), sym)); + return MemoryHandle::value(object->get_ivar(env->state(), sym)); } VALUE rb_ivar_set(VALUE self_handle, ID ivar_name, VALUE value) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Object* receiver = env->get_object(self_handle); + Object* receiver = MemoryHandle::object(self_handle); Symbol* sym = reinterpret_cast(ivar_name); receiver->set_ivar(env->state(), sym, - env->get_object(value)); + MemoryHandle::object(value)); return value; } @@ -359,10 +346,10 @@ extern "C" { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Symbol* ivar = reinterpret_cast(ivar_name); - Object* obj = env->get_object(obj_handle); + Object* obj = MemoryHandle::object(obj_handle); Object* ret = obj->ivar_defined(env->state(), ivar); - return env->get_handle(ret); + return MemoryHandle::value(ret); } VALUE rb_attr_get(VALUE obj_handle, ID attr_name) { @@ -410,7 +397,7 @@ extern "C" { VALUE rb_obj_instance_eval(int argc, VALUE* argv, VALUE self) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - VALUE block = env->get_handle(env->block()); + VALUE block = MemoryHandle::value(env->block()); return rb_funcall2b(self, rb_intern("instance_eval"), argc, (const VALUE*)argv, block); @@ -421,18 +408,16 @@ extern "C" { } VALUE rb_hash(VALUE obj) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - Object* hash = env->get_object(rb_funcall(obj, rb_intern("hash"), 0)); + Object* hash = MemoryHandle::object(rb_funcall(obj, rb_intern("hash"), 0)); retry: if(try_as(hash)) { - return env->get_handle(hash); + return MemoryHandle::value(hash); } else if(Bignum* big = try_as(hash)) { return LONG2FIX(big->to_native()); } else { - hash = env->get_object(rb_to_int(env->get_handle(hash))); + hash = MemoryHandle::object(rb_to_int(MemoryHandle::value(hash))); goto retry; } } diff --git a/machine/capi/proc.cpp b/machine/capi/proc.cpp index 74faf40330..cb48c9e349 100644 --- a/machine/capi/proc.cpp +++ b/machine/capi/proc.cpp @@ -11,11 +11,9 @@ using namespace rubinius::capi; extern "C" { VALUE rb_proc_new(VALUE (*func)(ANYARGS), VALUE val) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - int arity = ITERATE_BLOCK; Proc* prc = capi::wrap_c_function((void*)func, val, arity); - return env->get_handle(prc); + return MemoryHandle::value(prc); } } diff --git a/machine/capi/regexp.cpp b/machine/capi/regexp.cpp index 3fc56ca6b0..57bde1effd 100644 --- a/machine/capi/regexp.cpp +++ b/machine/capi/regexp.cpp @@ -23,7 +23,8 @@ extern "C" { VALUE rb_reg_new(const char *source, long len, int options) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); String *pat = String::create(env->state(), source, len); - return rb_funcall(rb_cRegexp, rb_intern("new"), 2, env->get_handle(pat), Fixnum::from(options)); + return rb_funcall(rb_cRegexp, rb_intern("new"), 2, + MemoryHandle::value(pat), Fixnum::from(options)); } VALUE rb_reg_nth_match(long nth, VALUE match_data) { diff --git a/machine/capi/string.cpp b/machine/capi/string.cpp index b98cb473f2..5c6d76a6c1 100644 --- a/machine/capi/string.cpp +++ b/machine/capi/string.cpp @@ -22,139 +22,62 @@ using namespace rubinius; using namespace rubinius::capi; namespace rubinius { - namespace capi { - String* capi_get_string(NativeMethodEnvironment* env, VALUE string) { - Handle* handle = Handle::from(string); - String* str = c_as(handle->object()); - handle->flush(env); + RString* MemoryHandle::get_rstring(STATE) { + if(rstring_p()) { + return reinterpret_cast(data()); + } else if(unknown_type_p()) { + String* string = c_as(object()); + string->set_type_specific(String::eRString); + string->unshare(state); - return str; - } + ByteArray* byte_array = string->data(); + byte_array->set_pinned(); - void capi_update_string(NativeMethodEnvironment* env, VALUE string) { - Handle* handle = Handle::from(string); - handle->update(env); - } - - /* We use the garbage collector's feature to "pin" an Object at a - * particular memory location to allow C code to write directly into the - * contets of a Ruby String (actually, a ByteArray, which provides the - * storage for String). Since any method on String that mutates self may - * cause a new ByteArray to be created, we always check whether the - * String is pinned and update the RString structure unconditionally. - */ - void ensure_pinned(NativeMethodEnvironment* env, String* string, RString* rstring) { - ByteArray* ba = string->data(); - size_t byte_size = ba->size(); - - if(!ba->pinned_p()) { - ByteArray* nba = ByteArray::create_pinned(env->state(), byte_size); - memcpy(nba->raw_bytes(), ba->raw_bytes(), byte_size); - string->data(env->state(), nba); - ba = nba; - } + char* ptr = reinterpret_cast(byte_array->raw_bytes()); - char* ptr = reinterpret_cast(ba->raw_bytes()); + RString* rstring = new RString; - ptr[byte_size-1] = 0; rstring->dmwmb = rstring->ptr = ptr; rstring->len = string->byte_size(); - rstring->aux.capa = byte_size; + rstring->aux.capa = byte_array->size(); rstring->aux.shared = Qfalse; - } - /* We are in C-land returning to Ruby-land. The value of RString.len - * may have changed. We raise an exception if the value of len exceeds - * the capacity of the underlying ByteArray or if the value of ptr has - * changed. - */ - void flush_cached_rstring(NativeMethodEnvironment* env, Handle* handle) { - if(handle->is_rstring()) { - String* string = c_as(handle->object()); - RString* rstring = handle->get_rstring(); - - if(rstring->ptr != rstring->dmwmb) { - rb_raise(rb_eRuntimeError, - "changing the value of RSTRING(obj)->ptr is not supported"); - } - - if(rstring->len > c_as(string->data())->size()) { - rb_raise(rb_eRuntimeError, - "RSTRING(obj)->len must be <= capacity of the String"); - } else if(rstring->len != string->num_bytes()->to_native()) { - // TODO: encoding support will need to define whether ->len - // means bytes or characters. - string->num_bytes(env->state(), Fixnum::from(rstring->len)); - string->hash_value(env->state(), nil()); - } - } + rstring->ptr[string->byte_size()] = 0; + + set_rstring(rstring); + return rstring; + } else { + Exception::raise_runtime_error(state, "C-API handle invalid reference as RString"); } + } + + void MemoryHandle::read_rstring(STATE) { + if(rstring_p()) { + String* string = as(object()); + RString* rstring = reinterpret_cast(data()); - /* We were in Ruby-land and we are heading into C-land. In Ruby-land, we - * may have updated the existing String bytes, appended more, shifted the - * start of the String, or replaced the ByteArray so we ensure that the - * RString structure contents are update. - */ - void update_cached_rstring(NativeMethodEnvironment* env, Handle* handle) { - if(handle->is_rstring()) { - String* string = c_as(handle->object()); - RString* rstring = handle->get_rstring(); - - ensure_pinned(env, string, rstring); + if(string->get_byte_size() != rstring->len) { + string->num_bytes(Fixnum::from(rstring->len)); } } + } - RString* Handle::as_rstring(NativeMethodEnvironment* env, int cache_level) { - String* string = c_as(object()); - bool unset = type_ != cRString; - - if(unset) { - env->shared().capi_ds_lock().lock(); - - // Gotta double check since we're now lock and it might - // have changed since we asked for the lock. - - unset = type_ != cRString; - if(unset) { - - string->unshare(env->state()); - - RString* str = new RString; - as_.rstring = str; - - if(cache_level == RSTRING_CACHE_UNSAFE) { - flush_ = flush_cached_rstring; - update_ = update_cached_rstring; - env->check_tracked_handle(this, true); - } else { - env->check_tracked_handle(this, false); - } - // The underlying String may have changed since we last got the - // associated RString structure. - ensure_pinned(env, string, as_.rstring); - - atomic::memory_barrier(); - type_ = cRString; - } - - env->shared().capi_ds_lock().unlock(); - } else { - // The underlying String may have changed since we last got the - // associated RString structure. - ensure_pinned(env, string, as_.rstring); - } + void MemoryHandle::write_rstring(STATE) { + if(rstring_p()) { + String* string = as(object()); + RString* rstring = reinterpret_cast(data()); + + ByteArray* byte_array = string->data(); + if(!byte_array->pinned_p()) byte_array->set_pinned(); - /* In Ruby, regardless of the contents in the ByteArray for a String, - * the String's size is the authority on the length of the String. - * However, for the C-API, we cannot assume this because C code may be - * writing to the cache behind our backs, so we faithfully keep the full - * contents of the ByteArray and the C cache in sync. If there has never - * been a cache created for a string, however, we must set put a null - * byte in the cache based on the String size. - */ - if(unset) as_.rstring->ptr[string->byte_size()] = 0; - - return as_.rstring; + char* ptr = reinterpret_cast(byte_array->raw_bytes()); + + rstring->dmwmb = rstring->ptr = ptr; + rstring->len = string->get_byte_size(); + rstring->aux.capa = byte_array->size(); + rstring->aux.shared = Qfalse; + + rstring->ptr[string->get_byte_size()] = 0; } } } @@ -163,15 +86,13 @@ extern "C" { struct RString* capi_rstring_struct(VALUE string, int cache_level) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Handle* handle = Handle::from(string); - - return handle->as_rstring(env, cache_level); + return MemoryHandle::from(string)->get_rstring(env->state()); } void* rb_alloc_tmp_buffer(VALUE* store, long len) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - VALUE s = env->get_handle(String::create_pinned(env->state(), Fixnum::from(len))); + VALUE s = MemoryHandle::value(String::create_pinned(env->state(), Fixnum::from(len))); *store = s; return RSTRING_PTR(s); @@ -184,7 +105,7 @@ extern "C" { VALUE s = *store; *store = 0; - String* str = c_as(env->get_object(s)); + String* str = MemoryHandle::object(s); str->num_bytes(env->state(), Fixnum::from(0)); str->data(env->state(), ByteArray::create(env->state(), 1)); } @@ -196,7 +117,7 @@ extern "C" { void rb_str_modify(VALUE self) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - String* string = capi_get_string(env, self); + String* string = MemoryHandle::object(self); string->unshare(env->state()); } @@ -208,9 +129,9 @@ extern "C" { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); StringValue(other); - String* string = capi_get_string(env, self); - string->append(env->state(), capi_get_string(env, other)); - capi_update_string(env, self); + String* string = MemoryHandle::object(self); + String* another = MemoryHandle::object(other); + string->append(env->state(), another); return self; } @@ -221,7 +142,7 @@ extern "C" { String* str = String::create(env->state(), Fixnum::from(capacity)); str->num_bytes(env->state(), Fixnum::from(0)); - return env->get_handle(str); + return MemoryHandle::value(str); } VALUE rb_str_buf_new2(const char* string) { @@ -235,9 +156,8 @@ extern "C" { VALUE rb_str_buf_cat(VALUE self, const char* other, size_t size) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - String* string = capi_get_string(env, self); + String* string = MemoryHandle::object(self); string->append(env->state(), other, size); - capi_update_string(env, self); return self; } @@ -249,9 +169,8 @@ extern "C" { VALUE rb_str_cat(VALUE self, const char* other, size_t length) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - String* string = capi_get_string(env, self); + String* string = MemoryHandle::object(self); string->append(env->state(), other, length); - capi_update_string(env, self); return self; } @@ -265,12 +184,8 @@ extern "C" { } VALUE rb_str_concat(VALUE self, VALUE other) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - Object* object = env->get_object(other); - /* Could be a character code. Only up to 256 supported. */ - if(Fixnum* character = try_as(object)) { + if(Fixnum* character = MemoryHandle::try_as(other)) { char byte = character->to_uint(); return rb_str_cat(self, &byte, 1); @@ -282,8 +197,8 @@ extern "C" { VALUE rb_str_dup(VALUE self) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - String* string = capi_get_string(env, self); - return env->get_handle(string->string_dup(env->state())); + String* string = MemoryHandle::object(self); + return MemoryHandle::value(string->string_dup(env->state())); } VALUE rb_str_inspect(VALUE self) { @@ -298,7 +213,7 @@ extern "C" { if(length < 0) rb_raise(rb_eArgError, "invalid string size"); NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - return env->get_handle(String::create(env->state(), string, length)); + return MemoryHandle::value(String::create(env->state(), string, length)); } VALUE rb_str_new2(const char* string) { @@ -332,8 +247,8 @@ extern "C" { VALUE str = rb_str_new(ptr, len); - String* new_string = capi_get_string(env, str); - String* template_string = capi_get_string(env, object); + String* new_string = MemoryHandle::object(str); + String* template_string = MemoryHandle::object(object); new_string->klass(env->state(), template_string->klass()); @@ -347,7 +262,7 @@ extern "C" { VALUE rb_str_resize(VALUE self, size_t len) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - String* string = capi_get_string(env, self); + String* string = MemoryHandle::object(self); size_t capacity = c_as(string->data())->size(); // We make sure we have at least a byte for a trailing NULL @@ -359,7 +274,6 @@ extern "C" { string->hash_value(env->state(), nil()); string->num_bytes(env->state(), Fixnum::from(len)); - capi_update_string(env, self); return self; } @@ -390,9 +304,7 @@ extern "C" { } VALUE rb_string_value(volatile VALUE* object_variable) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - if(!kind_of(env->get_object(*object_variable))) { + if(!MemoryHandle::try_as(*object_variable)) { *object_variable = rb_str_to_str(*object_variable); } @@ -400,11 +312,7 @@ extern "C" { } char* rb_string_value_ptr(volatile VALUE* object_variable) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - VALUE str = rb_string_value(object_variable); - // Type check. - (void)c_as(env->get_object(str)); return RSTRING_PTR(str); } @@ -413,7 +321,7 @@ extern "C" { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); VALUE str = rb_string_value(object_variable); - String* string = capi_get_string(env, str); + String* string = MemoryHandle::object(str); if(string->byte_size() != (native_int)strlen(string->c_str(env->state()))) { rb_raise(rb_eArgError, "string contains NULL byte"); @@ -436,14 +344,12 @@ extern "C" { String* str = String::create(env->state(), string, size); str->taint(env->state()); - return env->get_handle(str); + return MemoryHandle::value(str); } char* rb_str2cstr(VALUE string, long* len) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - StringValue(string); - String* str = capi_get_string(env, string); + String* str = MemoryHandle::object(string); char *ptr = RSTRING_PTR(string); if(len) { *len = str->byte_size(); @@ -454,16 +360,13 @@ extern "C" { char* rb_str_ptr(VALUE self) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Handle* handle = Handle::from(self); - RString* rstring = handle->as_rstring(env, RSTRING_CACHE_SAFE); - - return rstring->ptr; + return MemoryHandle::from(self)->get_rstring(env->state())->ptr; } char* rb_str_copied_ptr(VALUE self) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - String* str = c_as(env->get_object(self)); + String* str = MemoryHandle::object(self); char* data = (char*)malloc(sizeof(char) * str->byte_size() + 1); if(!data) { @@ -480,50 +383,45 @@ extern "C" { char* rb_str_ptr_readonly(VALUE self) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - RString* rstr = Handle::from(self)->as_rstring(env, RSTRING_CACHE_SAFE); - - return rstr->ptr; + return MemoryHandle::from(self)->get_rstring(env->state())->ptr; } char* rb_str_ptr_readonly_end(VALUE self) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - RString* rstr = Handle::from(self)->as_rstring(env, RSTRING_CACHE_SAFE); + RString* rstr = MemoryHandle::from(self)->get_rstring(env->state()); return rstr->ptr + rstr->len; } long rb_str_len(VALUE self) { - NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - - String* string = capi_get_string(env, self); + String* string = MemoryHandle::object(self); return string->byte_size(); } VALUE rb_str_length(VALUE self) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - String* string = capi_get_string(env, self); + String* string = MemoryHandle::object(self); return LONG2FIX(string->char_size(env->state())); } void rb_str_set_len(VALUE self, size_t len) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - String* string = capi_get_string(env, self); + String* string = MemoryHandle::object(self); size_t capacity = c_as(string->data())->size(); if(len > capacity) len = capacity - 1; string->byte_address()[len] = 0; string->num_bytes(env->state(), Fixnum::from(len)); - capi_update_string(env, self); } long rb_str_hash(VALUE self) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - String* string = capi_get_string(env, self); + String* string = MemoryHandle::object(self); return string->hash_string(env->state()); } @@ -531,10 +429,10 @@ extern "C" { void rb_str_update(VALUE self, long beg, long end, VALUE replacement) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - String* string = capi_get_string(env, self); + String* string = MemoryHandle::object(self); Class* klass = Module::mirror(env->state(), string); - VALUE mirror = capi_fast_call(env->get_handle(klass), rb_intern("new"), 1, self); + VALUE mirror = capi_fast_call(MemoryHandle::value(klass), rb_intern("new"), 1, self); capi_fast_call(mirror, rb_intern("splice"), 3, LONG2FIX(beg), LONG2FIX(end), replacement); } @@ -543,10 +441,10 @@ extern "C" { return Qtrue; } NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - String* string = capi_get_string(env, self); - String* other_str = capi_get_string(env, other); + String* string = MemoryHandle::object(self); + String* other_str = MemoryHandle::object(other); - return env->get_handle(string->equal(env->state(), other_str)); + return MemoryHandle::value(string->equal(env->state(), other_str)); } void rb_str_free(VALUE str) {} @@ -580,7 +478,7 @@ extern "C" { str->encoding(env->state(), enc); } - return rb_str_conv_enc(env->get_handle(str), enc->encoding(), + return rb_str_conv_enc(MemoryHandle::value(str), enc->encoding(), rb_default_internal_encoding()); } @@ -600,7 +498,7 @@ extern "C" { int rb_enc_str_coderange(VALUE string) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - String *str = c_as(env->get_object(string)); + String *str = MemoryHandle::object(string); bool valid = CBOOL(str->valid_encoding_p(env->state())); bool ascii = CBOOL(str->ascii_only_p(env->state())); @@ -682,7 +580,7 @@ extern "C" { PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); if(buffer == MAP_FAILED) { - return env->get_handle(String::create(env->state(), + return MemoryHandle::value(String::create(env->state(), "rb_vsprintf failed to allocate space for result")); } @@ -691,6 +589,6 @@ extern "C" { munmap(buffer, RBX_RB_VSPRINTF_LEN); - return env->get_handle(str); + return MemoryHandle::value(str); } } diff --git a/machine/capi/struct.cpp b/machine/capi/struct.cpp index 49c271b60a..6383ae54dd 100644 --- a/machine/capi/struct.cpp +++ b/machine/capi/struct.cpp @@ -25,12 +25,12 @@ extern "C" { char *sym; Array* array = Array::create(env->state(), 0); while((sym = va_arg(args, char*)) != 0) { - array->append(env->state(), env->get_object(rb_intern(sym))); + array->append(env->state(), MemoryHandle::object(rb_intern(sym))); } va_end(args); - return rb_funcall(rb_cStruct, rb_intern("make_struct"), 2, nm, env->get_handle(array)); + return rb_funcall(rb_cStruct, rb_intern("make_struct"), 2, nm, MemoryHandle::value(array)); } VALUE rb_struct_new(VALUE klass, ...) { diff --git a/machine/capi/symbol.cpp b/machine/capi/symbol.cpp index a25ea78e18..c6556d2857 100644 --- a/machine/capi/symbol.cpp +++ b/machine/capi/symbol.cpp @@ -17,7 +17,7 @@ extern "C" { VALUE rb_id2str(ID sym) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); String* str = reinterpret_cast(sym)->to_str(env->state()); - return env->get_handle(str); + return MemoryHandle::value(str); } int rb_is_const_id(ID sym) { diff --git a/machine/capi/thread.cpp b/machine/capi/thread.cpp index bbd91381ed..7dd511e001 100644 --- a/machine/capi/thread.cpp +++ b/machine/capi/thread.cpp @@ -100,7 +100,7 @@ extern "C" { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Thread* thread = env->state()->vm()->thread(); - return env->get_handle(thread); + return MemoryHandle::value(thread); } @@ -113,17 +113,17 @@ extern "C" { VALUE rb_thread_local_aref(VALUE thread, ID id) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Thread* thr = capi::c_as(env->get_object(thread)); - return env->get_handle( + Thread* thr = MemoryHandle::object(thread); + return MemoryHandle::value( thr->fiber_variable_get(env->state(), reinterpret_cast(id))); } VALUE rb_thread_local_aset(VALUE thread, ID id, VALUE value) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - Thread* thr = capi::c_as(env->get_object(thread)); - return env->get_handle( + Thread* thr = MemoryHandle::object(thread); + return MemoryHandle::value( thr->fiber_variable_set( - env->state(), reinterpret_cast(id), env->get_object(value))); + env->state(), reinterpret_cast(id), MemoryHandle::object(value))); } VALUE rb_thread_wakeup(VALUE thread) { @@ -266,10 +266,10 @@ extern "C" { state->vm()->set_call_frame(&call_frame); nmf.setup( - env->get_handle(thread), - env->get_handle(cNil), - env->get_handle(nm), - env->get_handle(nm->module())); + MemoryHandle::value(thread), + MemoryHandle::value(cNil), + MemoryHandle::value(nm), + MemoryHandle::value(nm->module())); ENTER_CAPI(state); @@ -286,7 +286,7 @@ extern "C" { state->vm()->thread()->exception(state, capi::c_as(state->vm()->thread_state()->current_exception())); } else { - value = env->get_object(nm->func()(ptr->pointer)); + value = MemoryHandle::object(nm->func()(ptr->pointer)); } LEAVE_CAPI(state); @@ -316,7 +316,7 @@ extern "C" { thr->group(state, state->vm()->thread()->group()); - VALUE thr_handle = env->get_handle(thr); + VALUE thr_handle = MemoryHandle::value(thr); thr->fork(state); return thr_handle; diff --git a/machine/capi/time.cpp b/machine/capi/time.cpp index 1552e16265..23b4633eec 100644 --- a/machine/capi/time.cpp +++ b/machine/capi/time.cpp @@ -18,7 +18,8 @@ extern "C" { ts.tv_sec = NUM2TIMET(num); ts.tv_nsec = 0; } else { - num = rb_funcall(env->get_handle(env->state()->globals().type.get()), rb_intern("coerce_to_exact_num"), 1, num); + num = rb_funcall(MemoryHandle::value( + env->state()->globals().type.get()), rb_intern("coerce_to_exact_num"), 1, num); VALUE parts = rb_funcall(num, rb_intern("divmod"), 1, INT2FIX(1)); ts.tv_sec = NUM2TIMET(rb_ary_entry(parts, 0)); @@ -41,7 +42,7 @@ extern "C" { Integer::from(env->state(), sec), Integer::from(env->state(), usec * 1000), cFalse, cNil); - return env->get_handle(obj); + return MemoryHandle::value(obj); } VALUE rb_time_nano_new(time_t sec, long nsec) { @@ -58,7 +59,7 @@ extern "C" { Integer::from(env->state(), sec), Integer::from(env->state(), nsec), cFalse, cNil); - return env->get_handle(obj); + return MemoryHandle::value(obj); } VALUE rb_time_num_new(VALUE num, VALUE offset) { @@ -68,8 +69,11 @@ extern "C" { struct timespec ts = capi_time_num_timespec(env, num); State* state = env->state(); - Time* obj = Time::specific(state, cls, Integer::from(state, ts.tv_sec), Integer::from(state, ts.tv_nsec), cFalse, env->get_object(offset)); - return env->get_handle(obj); + Time* obj = Time::specific(state, cls, + Integer::from(state, ts.tv_sec), + Integer::from(state, ts.tv_nsec), + cFalse, MemoryHandle::object(offset)); + return MemoryHandle::value(obj); } struct timeval rb_time_interval(VALUE time) { @@ -77,7 +81,7 @@ extern "C" { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); - if(kind_of