1
0
Fork 0
mirror of https://github.com/rubyjs/therubyracer synced 2023-03-27 23:21:42 -04:00

Outline reference data structures.

This commit is contained in:
Charles Lowell 2012-05-01 11:53:01 -07:00
parent 23f1654ca0
commit b2e3057c5c
11 changed files with 158 additions and 35 deletions

View file

@ -1,13 +1,14 @@
#!/usr/bin/env rake
require 'bundler/setup'
require "bundler/gem_tasks"
task :clean do
sh "rm -rf lib/v8/vm.bundle lib/v8/vm.so"
sh "rm -rf lib/v8/init.bundle lib/v8/init.so"
sh "rm -rf pkg"
end
require "rake/extensiontask"
Rake::ExtensionTask.new("vm", eval(File.read("therubyracer.gemspec"))) do |ext|
Rake::ExtensionTask.new("init", eval(File.read("therubyracer.gemspec"))) do |ext|
ext.ext_dir = "ext/v8"
ext.lib_dir = "lib/v8"
ext.source_pattern = "*.{cc,h}"

View file

@ -1,5 +1,29 @@
#include "rr.h"
namespace rr {
void Context::Initialize() {}
} //namespace rr
VALUE ContextClass;
VALUE New(VALUE ContextClass) {
v8::Persistent<v8::Context> context = v8::Context::New();
Ref<v8::Context> ref = Ref<v8::Context>::create(context, ContextClass);
context.Dispose();
return ref;
}
VALUE Enter(VALUE self) {
Context(self)->Enter();
return Qnil;
}
VALUE Exit(VALUE self) {
Context(self)->Exit();
return Qnil;
}
void Context::Init() {
ContextClass = defineClass("Context");
RR_DEFINE_SINGLETON_METHOD(ContextClass, "New", &New, 0);
RR_DEFINE_METHOD(ContextClass, "Enter", &Enter, 0);
RR_DEFINE_METHOD(ContextClass, "Exit", &Exit, 0);
}
}

View file

@ -5,22 +5,24 @@ rescue LoadError
require 'rubygems'
require 'libv8'
end
include Libv8
have_library('objc') if RUBY_PLATFORM =~ /darwin/
#we have to manually prepend the libv8 include path to INCFLAGS
#since find_header() does not actually work as advertized.
#see https://github.com/cowboyd/therubyracer/issues/91
$INCFLAGS.insert 0, "-I#{Libv8.include_path} "
$INCFLAGS.insert 0, "#{libv8_include_flags} "
$CPPFLAGS += " -Wall" unless $CPPFLAGS.split.include? "-Wall"
$CPPFLAGS += " -g" unless $CPPFLAGS.split.include? "-g"
$CPPFLAGS += " -rdynamic" unless $CPPFLAGS.split.include? "-rdynamic"
$CPPFLAGS += " -fPIC" unless $CPPFLAGS.split.include? "-rdynamic" or RUBY_PLATFORM =~ /darwin/
$DEFLIBPATH.unshift(Libv8.library_path)
$LIBS << ' -lv8 -lpthread'
$LDFLAGS.insert 0, libv8_objects.join(' ') + " "
$LIBS << ' -lpthread '
CONFIG['LDSHARED'] = '$(CXX) -shared' unless RUBY_PLATFORM =~ /darwin/
create_makefile('vm')
create_makefile('init')

View file

@ -1,13 +1,13 @@
#include "rr.h"
extern "C" {
void Init_vm();
void Init_init();
}
using namespace rr;
extern "C" {
void Init_vm() {
Context::Initialize();
void Init_init() {
Context::Init();
}
}

37
ext/v8/ref.cc Normal file
View file

@ -0,0 +1,37 @@
#include "rr.h"
namespace rr {
template<typename T>
Ref<T> Ref<T>::create(v8::Handle<T> handle, VALUE klass) {
return Ref<T>(new Holder(handle, klass));
}
template<typename T>
Ref<T>::Ref(Ref<T>::Holder* holder) {
this->holder = holder;
}
template<typename T>
Ref<T>::Ref(VALUE wrapper) {
Holder* holder = NULL;
Data_Get_Struct(wrapper, class Holder, holder) ;
this->holder = holder;
}
template<typename T>
Ref<T>::operator VALUE() {
return holder->value;
}
template<typename T>
Ref<T>::Holder::Holder(v8::Handle<T> handle, VALUE klass) {
this->handle = v8::Persistent<T>::New(handle);
this->value = Data_Wrap_Struct(klass, 0, &Holder::enqueue, this);
}
template<typename T>
Ref<T>::Holder::~Holder() {
this->handle.Dispose();
}
template<typename T>
void Ref<T>::Holder::enqueue(Holder* holder) {
holder->value = Qnil;
printf("enqueuing a reference for garbage collection (should actually do something)\n");
}
}

17
ext/v8/rr.cc Normal file
View file

@ -0,0 +1,17 @@
#include "rr.h"
namespace rr {
VALUE defineClass(const char *name, VALUE superclass) {
VALUE V8 = rb_define_module("V8");
VALUE V8_C = rb_define_module_under(V8, "C");
VALUE klass = rb_define_class_under(V8_C, name, superclass);
rb_funcall(klass, rb_intern("private_class_method"), 1, rb_str_new2("new"));
return klass;
}
VALUE defineModule(const char *name) {
VALUE V8 = rb_define_module("V8");
VALUE V8_C = rb_define_module_under(V8, "C");
return rb_define_module_under(V8_C, name);
}
}

View file

@ -1,34 +1,45 @@
#ifndef THE_RUBY_RACER
#define THE_RUBY_RACER
#include <stdio.h>
#include <v8.h>
#include <ruby.h>
#define RR_DEFINE_METHOD(klass, name, impl, argc) rb_define_method(klass, name, (VALUE(*)(...))impl, argc)
namespace rr {
/**
* A Reference to a V8 managed object
*/
template <class T> class Ref {
public:
Ref<T>(VALUE wrapper);
virtual operator VALUE();
static Ref<T> create(v8::Handle<T> handle, VALUE klass);
inline v8::Handle<T> operator->() const { return holder->handle; }
private:
class Holder {
Holder(v8::Handle<T> handle, VALUE klass);
virtual ~Holder();
class Object {
public:
Object(VALUE value);
inline operator VALUE() {return value;};
private:
VALUE value;
};
VALUE value;
v8::Persistent<T> handle;
friend class Ref<T>;
class Class {
public:
Class(const char* name);
Class defineSingletonMethod(const char* name, VALUE(*impl)(...), int argc);
Class defineMethod(const char* name, VALUE(*impl)(...), int argc);
};
static void enqueue(Holder* holder);
};
Ref(Holder* holder);
Holder* holder;
};
class Context {
public:
static void Initialize();
};
class Context : public Ref<v8::Context> {
public:
inline Context(VALUE value) : Ref<v8::Context>(value) {};
static void Init();
};
VALUE defineClass(const char *name, VALUE superclass = rb_cObject);
VALUE defineModule(const char *name);
}
#define RR_DEFINE_METHOD(klass, name, impl, argc) rb_define_method(klass, name, (VALUE(*)(...))impl, argc)
#define RR_DEFINE_SINGLETON_METHOD(object, name, impl, argc) rb_define_singleton_method(object, name, (VALUE(*)(...))impl, argc)
#endif

View file

@ -1,4 +1,4 @@
require "v8/version"
require 'v8/vm'
require 'v8/init'
require 'v8/context'

View file

@ -1,10 +1,12 @@
module V8
class Context
def initialize
@native = V8::C::Context::New()
end
def eval(*args)
def eval(source, filename = '<eval>', line = 1)
nil
end
end
end

29
spec/mem/blunt_spec.rb Normal file
View file

@ -0,0 +1,29 @@
require 'spec_helper'
describe "A Very blunt test to make sure that we aren't doing stupid leaks" do
before do
@start_memory = process_memory
GC.stress = true
end
after do
GC.stress = false
end
it "won't leak the context" do
500.times do
V8::Context.new
end
gc_completely
process_memory.should <= @start_memory * 1.05
end
def process_memory
/\w*[ ]*#{Process.pid}[ ]*([.,\d]*)[ ]*([.,\d]*)[ ]*([\d]*)[ ]*([\d]*)/.match(`ps aux`)[4].to_i
end
def gc_completely
end
end

View file

@ -16,7 +16,7 @@ Gem::Specification.new do |gem|
gem.require_paths = ["lib", "ext"]
gem.version = V8::VERSION
gem.add_dependency "libv8", "~> 3.8.9"
gem.add_dependency "libv8", "~> 3.9.24"
gem.add_development_dependency "rake"
gem.add_development_dependency "rake-compiler"