llrb 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.gitmodules +4 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +56 -0
- data/README.md +311 -0
- data/Rakefile +30 -0
- data/bin/bm_app_fib +41 -0
- data/bin/bm_empty_method +33 -0
- data/bin/bm_loop_while +27 -0
- data/bin/bm_plus +33 -0
- data/bin/console +14 -0
- data/bin/loop_while.rb +5 -0
- data/bin/setup +8 -0
- data/ext/llrb/cfg.h +124 -0
- data/ext/llrb/compiler.c +987 -0
- data/ext/llrb/compiler/funcs.h +164 -0
- data/ext/llrb/compiler/stack.h +43 -0
- data/ext/llrb/cruby.h +42 -0
- data/ext/llrb/cruby/ccan/build_assert/build_assert.h +40 -0
- data/ext/llrb/cruby/ccan/check_type/check_type.h +63 -0
- data/ext/llrb/cruby/ccan/container_of/container_of.h +142 -0
- data/ext/llrb/cruby/ccan/list/list.h +773 -0
- data/ext/llrb/cruby/ccan/str/str.h +16 -0
- data/ext/llrb/cruby/internal.h +1774 -0
- data/ext/llrb/cruby/iseq.h +252 -0
- data/ext/llrb/cruby/method.h +213 -0
- data/ext/llrb/cruby/node.h +520 -0
- data/ext/llrb/cruby/probes_helper.h +43 -0
- data/ext/llrb/cruby/ruby_assert.h +54 -0
- data/ext/llrb/cruby/ruby_atomic.h +233 -0
- data/ext/llrb/cruby/thread_pthread.h +54 -0
- data/ext/llrb/cruby/vm_core.h +1646 -0
- data/ext/llrb/cruby/vm_debug.h +37 -0
- data/ext/llrb/cruby/vm_exec.h +182 -0
- data/ext/llrb/cruby/vm_opts.h +57 -0
- data/ext/llrb/cruby_extra/id.h +220 -0
- data/ext/llrb/cruby_extra/insns.inc +113 -0
- data/ext/llrb/cruby_extra/insns_info.inc +796 -0
- data/ext/llrb/cruby_extra/probes.h +80 -0
- data/ext/llrb/extconf.rb +102 -0
- data/ext/llrb/llrb.c +148 -0
- data/ext/llrb/optimizer.cc +118 -0
- data/ext/llrb/parser.c +191 -0
- data/ext/llrb/profiler.c +336 -0
- data/ext/llrb_insn_checkkeyword.c +20 -0
- data/ext/llrb_insn_checkmatch.c +28 -0
- data/ext/llrb_insn_concatarray.c +23 -0
- data/ext/llrb_insn_concatstrings.c +21 -0
- data/ext/llrb_insn_defined.c +9 -0
- data/ext/llrb_insn_getclassvariable.c +10 -0
- data/ext/llrb_insn_getinstancevariable.c +44 -0
- data/ext/llrb_insn_getlocal.c +14 -0
- data/ext/llrb_insn_getlocal_level0.c +8 -0
- data/ext/llrb_insn_getlocal_level1.c +8 -0
- data/ext/llrb_insn_getspecial.c +14 -0
- data/ext/llrb_insn_invokeblock.c +39 -0
- data/ext/llrb_insn_invokesuper.c +47 -0
- data/ext/llrb_insn_opt_aref.c +25 -0
- data/ext/llrb_insn_opt_aset.c +28 -0
- data/ext/llrb_insn_opt_div.c +32 -0
- data/ext/llrb_insn_opt_eq.c +57 -0
- data/ext/llrb_insn_opt_ge.c +28 -0
- data/ext/llrb_insn_opt_gt.c +38 -0
- data/ext/llrb_insn_opt_le.c +29 -0
- data/ext/llrb_insn_opt_lt.c +38 -0
- data/ext/llrb_insn_opt_ltlt.c +27 -0
- data/ext/llrb_insn_opt_minus.c +36 -0
- data/ext/llrb_insn_opt_mod.c +32 -0
- data/ext/llrb_insn_opt_mult.c +30 -0
- data/ext/llrb_insn_opt_neq.c +103 -0
- data/ext/llrb_insn_opt_plus.c +48 -0
- data/ext/llrb_insn_opt_send_without_block.c +45 -0
- data/ext/llrb_insn_opt_str_freeze.c +12 -0
- data/ext/llrb_insn_putspecialobject.c +23 -0
- data/ext/llrb_insn_send.c +49 -0
- data/ext/llrb_insn_setclassvariable.c +19 -0
- data/ext/llrb_insn_setconstant.c +23 -0
- data/ext/llrb_insn_setinstancevariable.c +48 -0
- data/ext/llrb_insn_setlocal.c +16 -0
- data/ext/llrb_insn_setlocal_level0.c +9 -0
- data/ext/llrb_insn_setlocal_level1.c +10 -0
- data/ext/llrb_insn_setspecial.c +15 -0
- data/ext/llrb_insn_splatarray.c +13 -0
- data/ext/llrb_insn_throw.c +11 -0
- data/ext/llrb_insn_trace.c +37 -0
- data/ext/llrb_push_result.c +14 -0
- data/ext/llrb_self_from_cfp.c +12 -0
- data/ext/llrb_set_pc.c +8 -0
- data/lib/llrb.rb +2 -0
- data/lib/llrb/jit.rb +76 -0
- data/lib/llrb/start.rb +2 -0
- data/lib/llrb/version.rb +3 -0
- data/llrb.gemspec +48 -0
- data/wercker.yml +31 -0
- metadata +227 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#include "cruby.h"
|
|
2
|
+
|
|
3
|
+
VALUE vm_get_cbase(const VALUE *ep);
|
|
4
|
+
VALUE vm_get_const_base(const VALUE *ep);
|
|
5
|
+
VALUE
|
|
6
|
+
llrb_insn_putspecialobject(rb_num_t value_type) {
|
|
7
|
+
enum vm_special_object_type type = (enum vm_special_object_type)value_type;
|
|
8
|
+
|
|
9
|
+
switch (type) {
|
|
10
|
+
case VM_SPECIAL_OBJECT_VMCORE:
|
|
11
|
+
return rb_mRubyVMFrozenCore;
|
|
12
|
+
case VM_SPECIAL_OBJECT_CBASE: {
|
|
13
|
+
rb_thread_t *th = GET_THREAD();
|
|
14
|
+
return vm_get_cbase(th->cfp->ep);
|
|
15
|
+
}
|
|
16
|
+
case VM_SPECIAL_OBJECT_CONST_BASE: {
|
|
17
|
+
rb_thread_t *th = GET_THREAD();
|
|
18
|
+
return vm_get_const_base(th->cfp->ep);
|
|
19
|
+
}
|
|
20
|
+
default:
|
|
21
|
+
rb_bug("putspecialobject insn: unknown value_type");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#include "cruby.h"
|
|
2
|
+
|
|
3
|
+
#define CALL_METHOD(calling, ci, cc) (*(cc)->call)(th, cfp, (calling), (ci), (cc))
|
|
4
|
+
void vm_search_method(const struct rb_call_info *ci, struct rb_call_cache *cc, VALUE recv);
|
|
5
|
+
VALUE vm_exec(rb_thread_t *th);
|
|
6
|
+
void vm_caller_setup_arg_block(const rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
|
7
|
+
struct rb_calling_info *calling, const struct rb_call_info *ci, rb_iseq_t *blockiseq, const int is_super);
|
|
8
|
+
|
|
9
|
+
static inline void
|
|
10
|
+
_llrb_push_result(rb_control_frame_t *cfp, VALUE result)
|
|
11
|
+
{
|
|
12
|
+
// PUSH(result)
|
|
13
|
+
*(cfp->sp) = result;
|
|
14
|
+
cfp->sp += 1;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
VALUE
|
|
18
|
+
llrb_insn_send(VALUE th_v, VALUE cfp_v, VALUE ci_v, VALUE cc_v, VALUE blockiseq_v, unsigned int stack_size, ...)
|
|
19
|
+
{
|
|
20
|
+
rb_thread_t *th = (rb_thread_t *)th_v;
|
|
21
|
+
rb_control_frame_t *cfp = (rb_control_frame_t *)cfp_v;
|
|
22
|
+
CALL_INFO ci = (CALL_INFO)ci_v;
|
|
23
|
+
CALL_CACHE cc = (CALL_CACHE)cc_v;
|
|
24
|
+
ISEQ blockiseq = (ISEQ)blockiseq_v;
|
|
25
|
+
|
|
26
|
+
VALUE recv = Qnil;
|
|
27
|
+
va_list ar;
|
|
28
|
+
va_start(ar, stack_size);
|
|
29
|
+
for (unsigned int i = 0; i < stack_size; i++) {
|
|
30
|
+
VALUE val = va_arg(ar, VALUE);
|
|
31
|
+
if (i == 0) recv = val;
|
|
32
|
+
_llrb_push_result(cfp, val);
|
|
33
|
+
}
|
|
34
|
+
va_end(ar);
|
|
35
|
+
|
|
36
|
+
struct rb_calling_info calling;
|
|
37
|
+
|
|
38
|
+
vm_caller_setup_arg_block(th, cfp, &calling, ci, blockiseq, 0);
|
|
39
|
+
calling.argc = ci->orig_argc;
|
|
40
|
+
calling.recv = recv;
|
|
41
|
+
vm_search_method(ci, cc, recv);
|
|
42
|
+
|
|
43
|
+
VALUE result = CALL_METHOD(&calling, ci, cc);
|
|
44
|
+
if (result == Qundef) {
|
|
45
|
+
VM_ENV_FLAGS_SET(th->cfp->ep, VM_FRAME_FLAG_FINISH);
|
|
46
|
+
return vm_exec(th);
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#include "cruby.h"
|
|
2
|
+
|
|
3
|
+
rb_cref_t * rb_vm_get_cref(const VALUE *ep);
|
|
4
|
+
static inline void
|
|
5
|
+
vm_ensure_not_refinement_module(VALUE self)
|
|
6
|
+
{
|
|
7
|
+
if (RB_TYPE_P(self, T_MODULE) && FL_TEST(self, RMODULE_IS_REFINEMENT)) {
|
|
8
|
+
rb_warn("not defined at the refinement, but at the outer class/module");
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
VALUE vm_get_cvar_base(const rb_cref_t *cref, rb_control_frame_t *cfp);
|
|
13
|
+
void
|
|
14
|
+
llrb_insn_setclassvariable(VALUE cfp_v, ID id, VALUE val)
|
|
15
|
+
{
|
|
16
|
+
rb_control_frame_t *cfp = (rb_control_frame_t *)cfp_v;
|
|
17
|
+
vm_ensure_not_refinement_module(cfp->self);
|
|
18
|
+
rb_cvar_set(vm_get_cvar_base(rb_vm_get_cref(cfp->ep), cfp), id, val);
|
|
19
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#include "cruby.h"
|
|
2
|
+
|
|
3
|
+
static inline void
|
|
4
|
+
vm_check_if_namespace(VALUE klass)
|
|
5
|
+
{
|
|
6
|
+
if (!RB_TYPE_P(klass, T_CLASS) && !RB_TYPE_P(klass, T_MODULE)) {
|
|
7
|
+
rb_raise(rb_eTypeError, "%+"PRIsVALUE" is not a class/module", klass);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
static inline void
|
|
11
|
+
vm_ensure_not_refinement_module(VALUE self)
|
|
12
|
+
{
|
|
13
|
+
if (RB_TYPE_P(self, T_MODULE) && FL_TEST(self, RMODULE_IS_REFINEMENT)) {
|
|
14
|
+
rb_warn("not defined at the refinement, but at the outer class/module");
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
// https://github.com/ruby/ruby/blob/v2_4_1/insns.def#L201-L223
|
|
18
|
+
void
|
|
19
|
+
llrb_insn_setconstant(VALUE self, VALUE cbase, ID id, VALUE val) {
|
|
20
|
+
vm_check_if_namespace(cbase);
|
|
21
|
+
vm_ensure_not_refinement_module(self);
|
|
22
|
+
rb_const_set(cbase, id, val);
|
|
23
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#include "cruby.h"
|
|
2
|
+
|
|
3
|
+
static inline VALUE
|
|
4
|
+
vm_setivar(VALUE obj, ID id, VALUE val, IC ic, struct rb_call_cache *cc, int is_attr)
|
|
5
|
+
{
|
|
6
|
+
rb_check_frozen(obj);
|
|
7
|
+
|
|
8
|
+
if (LIKELY(RB_TYPE_P(obj, T_OBJECT))) {
|
|
9
|
+
VALUE klass = RBASIC(obj)->klass;
|
|
10
|
+
st_data_t index;
|
|
11
|
+
|
|
12
|
+
if (LIKELY(
|
|
13
|
+
(!is_attr && ic->ic_serial == RCLASS_SERIAL(klass)) ||
|
|
14
|
+
(is_attr && cc->aux.index > 0))) {
|
|
15
|
+
VALUE *ptr = ROBJECT_IVPTR(obj);
|
|
16
|
+
index = !is_attr ? ic->ic_value.index : cc->aux.index-1;
|
|
17
|
+
|
|
18
|
+
if (index < ROBJECT_NUMIV(obj)) {
|
|
19
|
+
RB_OBJ_WRITE(obj, &ptr[index], val);
|
|
20
|
+
return val; /* inline cache hit */
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
|
|
25
|
+
|
|
26
|
+
if (iv_index_tbl && st_lookup(iv_index_tbl, (st_data_t)id, &index)) {
|
|
27
|
+
if (!is_attr) {
|
|
28
|
+
ic->ic_value.index = index;
|
|
29
|
+
ic->ic_serial = RCLASS_SERIAL(klass);
|
|
30
|
+
}
|
|
31
|
+
else if (index >= INT_MAX) {
|
|
32
|
+
rb_raise(rb_eArgError, "too many instance variables");
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
cc->aux.index = (int)(index + 1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/* fall through */
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return rb_ivar_set(obj, id, val);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
void
|
|
45
|
+
llrb_insn_setinstancevariable(VALUE obj, ID id, VALUE val, VALUE ic_v)
|
|
46
|
+
{
|
|
47
|
+
vm_setivar(obj, id, val, (IC)ic_v, 0, 0);
|
|
48
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#include "cruby.h"
|
|
2
|
+
|
|
3
|
+
void rb_vm_env_write(const VALUE *ep, int index, VALUE v);
|
|
4
|
+
|
|
5
|
+
void
|
|
6
|
+
llrb_insn_setlocal(VALUE cfp_v, lindex_t idx, rb_num_t level, VALUE val)
|
|
7
|
+
{
|
|
8
|
+
rb_control_frame_t *cfp = (rb_control_frame_t *)cfp_v;
|
|
9
|
+
int i, lev = (int)level;
|
|
10
|
+
const VALUE *ep = cfp->ep;
|
|
11
|
+
|
|
12
|
+
for (i = 0; i < lev; i++) {
|
|
13
|
+
ep = GET_PREV_EP(ep);
|
|
14
|
+
}
|
|
15
|
+
rb_vm_env_write(ep, -(int)idx, val);
|
|
16
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#include "cruby.h"
|
|
2
|
+
|
|
3
|
+
void rb_vm_env_write(const VALUE *ep, int index, VALUE v);
|
|
4
|
+
|
|
5
|
+
void
|
|
6
|
+
llrb_insn_setlocal_level1(VALUE cfp_v, lindex_t idx, VALUE val)
|
|
7
|
+
{
|
|
8
|
+
rb_control_frame_t *cfp = (rb_control_frame_t *)cfp_v;
|
|
9
|
+
rb_vm_env_write(GET_PREV_EP(cfp->ep), -(int)idx, val);
|
|
10
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#include "cruby.h"
|
|
2
|
+
|
|
3
|
+
void lep_svar_set(rb_thread_t *th, const VALUE *lep, rb_num_t key, VALUE val);
|
|
4
|
+
void
|
|
5
|
+
llrb_insn_setspecial(rb_num_t key, VALUE obj)
|
|
6
|
+
{
|
|
7
|
+
rb_thread_t *th = GET_THREAD();
|
|
8
|
+
|
|
9
|
+
const VALUE *ep = th->cfp->ep;
|
|
10
|
+
while (!VM_ENV_LOCAL_P(ep)) {
|
|
11
|
+
ep = VM_ENV_PREV_EP(ep);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
lep_svar_set(th, ep, key, obj);
|
|
15
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#include "cruby.h"
|
|
2
|
+
|
|
3
|
+
// https://github.com/ruby/ruby/blob/v2_4_1/insns.def#L515-L534
|
|
4
|
+
VALUE
|
|
5
|
+
llrb_insn_splatarray(VALUE ary, VALUE flag) {
|
|
6
|
+
VALUE tmp = rb_check_convert_type(ary, T_ARRAY, "Array", "to_a");
|
|
7
|
+
if (NIL_P(tmp)) {
|
|
8
|
+
tmp = rb_ary_new3(1, ary);
|
|
9
|
+
} else if (RTEST(flag)) {
|
|
10
|
+
tmp = rb_ary_dup(tmp);
|
|
11
|
+
}
|
|
12
|
+
return tmp;
|
|
13
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#include "cruby.h"
|
|
2
|
+
|
|
3
|
+
VALUE vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t throw_state, VALUE throwobj);
|
|
4
|
+
void
|
|
5
|
+
llrb_insn_throw(VALUE th_value, VALUE cfp_value, rb_num_t throw_state, VALUE throwobj)
|
|
6
|
+
{
|
|
7
|
+
rb_thread_t *th = (rb_thread_t *)th_value;
|
|
8
|
+
rb_control_frame_t *cfp = (rb_control_frame_t *)cfp_value;
|
|
9
|
+
RUBY_VM_CHECK_INTS(th);
|
|
10
|
+
th->errinfo = vm_throw(th, cfp, throw_state, throwobj);
|
|
11
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#include "cruby.h"
|
|
2
|
+
#include "cruby/probes_helper.h"
|
|
3
|
+
|
|
4
|
+
// TODO: Use vm_dtrace after Ruby 2.5
|
|
5
|
+
static inline void
|
|
6
|
+
_llrb_insn_trace(rb_thread_t *th, rb_control_frame_t *cfp, rb_event_flag_t flag, VALUE val)
|
|
7
|
+
{
|
|
8
|
+
if (RUBY_DTRACE_METHOD_ENTRY_ENABLED() ||
|
|
9
|
+
RUBY_DTRACE_METHOD_RETURN_ENABLED() ||
|
|
10
|
+
RUBY_DTRACE_CMETHOD_ENTRY_ENABLED() ||
|
|
11
|
+
RUBY_DTRACE_CMETHOD_RETURN_ENABLED()) {
|
|
12
|
+
|
|
13
|
+
switch (flag) {
|
|
14
|
+
case RUBY_EVENT_CALL:
|
|
15
|
+
RUBY_DTRACE_METHOD_ENTRY_HOOK(th, 0, 0);
|
|
16
|
+
break;
|
|
17
|
+
case RUBY_EVENT_C_CALL:
|
|
18
|
+
RUBY_DTRACE_CMETHOD_ENTRY_HOOK(th, 0, 0);
|
|
19
|
+
break;
|
|
20
|
+
case RUBY_EVENT_RETURN:
|
|
21
|
+
RUBY_DTRACE_METHOD_RETURN_HOOK(th, 0, 0);
|
|
22
|
+
break;
|
|
23
|
+
case RUBY_EVENT_C_RETURN:
|
|
24
|
+
RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, 0, 0);
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// TODO: Confirm it works!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
30
|
+
// Especially for :line event. We may need to update program counter.
|
|
31
|
+
EXEC_EVENT_HOOK(th, flag, cfp->self, 0, 0, 0 /* id and klass are resolved at callee */, val);
|
|
32
|
+
}
|
|
33
|
+
void
|
|
34
|
+
llrb_insn_trace(VALUE th, VALUE cfp, rb_event_flag_t flag, VALUE val)
|
|
35
|
+
{
|
|
36
|
+
_llrb_insn_trace((rb_thread_t *)th, (rb_control_frame_t *)cfp, flag, val);
|
|
37
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#include "cruby.h"
|
|
2
|
+
|
|
3
|
+
static inline void
|
|
4
|
+
_llrb_push_result(rb_control_frame_t *cfp, VALUE result)
|
|
5
|
+
{
|
|
6
|
+
// PUSH(result)
|
|
7
|
+
*(cfp->sp) = result;
|
|
8
|
+
cfp->sp += 1;
|
|
9
|
+
}
|
|
10
|
+
void
|
|
11
|
+
llrb_push_result(VALUE cfp, VALUE result)
|
|
12
|
+
{
|
|
13
|
+
_llrb_push_result((rb_control_frame_t *)cfp, result);
|
|
14
|
+
}
|
data/ext/llrb_set_pc.c
ADDED
data/lib/llrb.rb
ADDED
data/lib/llrb/jit.rb
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
require 'llrb/llrb'
|
|
2
|
+
|
|
3
|
+
module LLRB
|
|
4
|
+
module JIT
|
|
5
|
+
# Compile method to native code
|
|
6
|
+
#
|
|
7
|
+
# @param [Object] recv - receiver of method to be compiled
|
|
8
|
+
# @param [String,Symbol] method - precompiled method name
|
|
9
|
+
# @return [Boolean] - return true if precompiled
|
|
10
|
+
def self.compile(recv, name)
|
|
11
|
+
compile_proc(recv.method(name))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.compile_proc(func)
|
|
15
|
+
iseqw = RubyVM::InstructionSequence.of(func)
|
|
16
|
+
return false if iseqw.nil? # method defined with C function can't be compiled
|
|
17
|
+
|
|
18
|
+
#puts "#{iseqw.disasm}\n"
|
|
19
|
+
compile_iseq(iseqw)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Preview compiled method in LLVM IR
|
|
23
|
+
#
|
|
24
|
+
# @param [Object] recv - receiver of method to be compiled
|
|
25
|
+
# @param [String,Symbol] method_name - precompiled method name
|
|
26
|
+
def self.preview(recv, name)
|
|
27
|
+
method = recv.method(name)
|
|
28
|
+
iseqw = RubyVM::InstructionSequence.of(method)
|
|
29
|
+
return false if iseqw.nil?
|
|
30
|
+
|
|
31
|
+
puts "#{iseqw.disasm}\n"
|
|
32
|
+
preview_iseq(iseqw)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.compiled?(recv, name)
|
|
36
|
+
method = recv.method(name)
|
|
37
|
+
iseqw = RubyVM::InstructionSequence.of(method)
|
|
38
|
+
return false if iseqw.nil?
|
|
39
|
+
|
|
40
|
+
is_compiled(iseqw)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.start
|
|
44
|
+
hook_stop
|
|
45
|
+
start_internal
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Hook JIT stop at exit to safely shutdown Ruby VM. JIT touches Ruby VM and
|
|
49
|
+
# it should not run after Ruby VM destruction. Otherwise it will cause SEGV.
|
|
50
|
+
def self.hook_stop
|
|
51
|
+
return if defined?(@hook_stop)
|
|
52
|
+
@hook_stop = true
|
|
53
|
+
at_exit { LLRB::JIT.stop }
|
|
54
|
+
end
|
|
55
|
+
private_class_method :hook_stop
|
|
56
|
+
|
|
57
|
+
# Followings are defined in ext/llrb/llrb.cc
|
|
58
|
+
|
|
59
|
+
# @param [RubyVM::InstructionSequence] iseqw - RubyVM::InstructionSequence instance
|
|
60
|
+
# @return [Boolean] return true if compiled
|
|
61
|
+
private_class_method :compile_iseq
|
|
62
|
+
|
|
63
|
+
# @param [RubyVM::InstructionSequence] iseqw - RubyVM::InstructionSequence instance
|
|
64
|
+
# @return [Boolean] return true if compiled
|
|
65
|
+
private_class_method :preview_iseq
|
|
66
|
+
|
|
67
|
+
# @param [RubyVM::InstructionSequence] iseqw - RubyVM::InstructionSequence instance
|
|
68
|
+
# @return [Boolean] return true if compiled
|
|
69
|
+
private_class_method :is_compiled
|
|
70
|
+
|
|
71
|
+
# This does not hook stop, but it may cause SEGV if JIT runs after Ruby VM is shut down.
|
|
72
|
+
# To ensure JIT will be stopped on exit, you should use .start instead.
|
|
73
|
+
# @return [Boolean] return true if started JIT
|
|
74
|
+
private_class_method :start_internal
|
|
75
|
+
end
|
|
76
|
+
end
|
data/lib/llrb/start.rb
ADDED
data/lib/llrb/version.rb
ADDED
data/llrb.gemspec
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'llrb/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = 'llrb'
|
|
8
|
+
spec.version = LLRB::VERSION
|
|
9
|
+
spec.authors = ['Takashi Kokubun']
|
|
10
|
+
spec.email = ['takashikkbn@gmail.com']
|
|
11
|
+
|
|
12
|
+
spec.summary = 'LLRB is LLVM-based JIT compiler for Ruby. Note that this gem can be only installed to fork of CRuby.'
|
|
13
|
+
spec.description = 'LLRB is LLVM-based JIT compiler for Ruby. Note that this gem can be only installed to fork of CRuby.'
|
|
14
|
+
spec.homepage = 'https://github.com/k0kubun/llrb'
|
|
15
|
+
spec.license = 'MIT'
|
|
16
|
+
|
|
17
|
+
ccans = Dir.chdir("#{__dir__}/ext/llrb/cruby") { Dir.glob("ccan/**/*.h") }
|
|
18
|
+
cruby = (ccans + %w[
|
|
19
|
+
internal.h
|
|
20
|
+
iseq.h
|
|
21
|
+
method.h
|
|
22
|
+
node.h
|
|
23
|
+
probes_helper.h
|
|
24
|
+
ruby_assert.h
|
|
25
|
+
ruby_atomic.h
|
|
26
|
+
thread_pthread.h
|
|
27
|
+
vm_core.h
|
|
28
|
+
vm_debug.h
|
|
29
|
+
vm_exec.h
|
|
30
|
+
vm_opts.h
|
|
31
|
+
]).map { |f| "ext/llrb/cruby/#{f}" }
|
|
32
|
+
|
|
33
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
34
|
+
f.match(%r{^(test|spec|features)/})
|
|
35
|
+
end + cruby
|
|
36
|
+
|
|
37
|
+
spec.bindir = 'exe'
|
|
38
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
39
|
+
spec.require_paths = ['lib']
|
|
40
|
+
spec.extensions = ['ext/llrb/extconf.rb']
|
|
41
|
+
|
|
42
|
+
spec.add_development_dependency 'benchmark-ips'
|
|
43
|
+
spec.add_development_dependency 'bundler'
|
|
44
|
+
spec.add_development_dependency 'pry'
|
|
45
|
+
spec.add_development_dependency 'rake'
|
|
46
|
+
spec.add_development_dependency 'rake-compiler'
|
|
47
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
48
|
+
end
|