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:
parent
23f1654ca0
commit
b2e3057c5c
11 changed files with 158 additions and 35 deletions
5
Rakefile
5
Rakefile
|
|
@ -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}"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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
37
ext/v8/ref.cc
Normal 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
17
ext/v8/rr.cc
Normal 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);
|
||||
}
|
||||
}
|
||||
51
ext/v8/rr.h
51
ext/v8/rr.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
require "v8/version"
|
||||
|
||||
require 'v8/vm'
|
||||
require 'v8/init'
|
||||
require 'v8/context'
|
||||
|
|
@ -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
29
spec/mem/blunt_spec.rb
Normal 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
|
||||
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue