~ubuntu-branches/ubuntu/quantal/ruby1.9.1/quantal

« back to all changes in this revision

Viewing changes to vm.c

  • Committer: Bazaar Package Importer
  • Author(s): Lucas Nussbaum
  • Date: 2011-09-24 19:16:17 UTC
  • mfrom: (1.1.8 upstream) (13.1.7 experimental)
  • Revision ID: james.westby@ubuntu.com-20110924191617-o1qz4rcmqjot8zuy
Tags: 1.9.3~rc1-1
* New upstream release: 1.9.3 RC1.
  + Includes load.c fixes. Closes: #639959.
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 
3
3
  vm.c -
4
4
 
5
 
  $Author: yugui $
 
5
  $Author: nobu $
6
6
 
7
7
  Copyright (C) 2004-2007 Koichi Sasada
8
8
 
9
9
**********************************************************************/
10
10
 
11
11
#include "ruby/ruby.h"
 
12
#include "ruby/vm.h"
12
13
#include "ruby/st.h"
13
14
#include "ruby/encoding.h"
 
15
#include "internal.h"
14
16
 
15
17
#include "gc.h"
16
18
#include "vm_core.h"
35
37
VALUE rb_cEnv;
36
38
VALUE rb_mRubyVMFrozenCore;
37
39
 
38
 
VALUE ruby_vm_global_state_version = 1;
39
40
VALUE ruby_vm_const_missing_count = 0;
40
41
 
41
42
char ruby_vm_redefined_flag[BOP_LAST_];
45
46
 
46
47
static void thread_free(void *ptr);
47
48
 
48
 
VALUE rb_insns_name_array(void);
49
 
 
50
49
void vm_analysis_operand(int insn, int n, VALUE op);
51
50
void vm_analysis_register(int reg, int isset);
52
51
void vm_analysis_insn(int insn);
53
52
 
 
53
/*
 
54
 * TODO: replace with better interface at the next release.
 
55
 *
 
56
 * these functions are exported just as a workaround for ruby-debug
 
57
 * for the time being.
 
58
 */
 
59
RUBY_FUNC_EXPORTED VALUE rb_vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp);
 
60
RUBY_FUNC_EXPORTED int rb_vm_get_sourceline(const rb_control_frame_t *cfp);
 
61
 
54
62
void
55
63
rb_vm_change_state(void)
56
64
{
57
65
    INC_VM_STATE_VERSION();
58
66
}
59
67
 
 
68
static void vm_clear_global_method_cache(void);
 
69
 
 
70
static void
 
71
vm_clear_all_inline_method_cache(void)
 
72
{
 
73
    /* TODO: Clear all inline cache entries in all iseqs.
 
74
             How to iterate all iseqs in sweep phase?
 
75
             rb_objspace_each_objects() doesn't work at sweep phase.
 
76
     */
 
77
}
 
78
 
 
79
static void
 
80
vm_clear_all_cache()
 
81
{
 
82
    vm_clear_global_method_cache();
 
83
    vm_clear_all_inline_method_cache();
 
84
    ruby_vm_global_state_version = 1;
 
85
}
 
86
 
60
87
void
61
88
rb_vm_inc_const_missing_count(void)
62
89
{
172
199
    return 0;
173
200
}
174
201
 
 
202
/* at exit */
 
203
 
 
204
void
 
205
ruby_vm_at_exit(void (*func)(rb_vm_t *))
 
206
{
 
207
    rb_ary_push((VALUE)&GET_VM()->at_exit, (VALUE)func);
 
208
}
 
209
 
 
210
static void
 
211
ruby_vm_run_at_exit_hooks(rb_vm_t *vm)
 
212
{
 
213
    VALUE hook = (VALUE)&vm->at_exit;
 
214
 
 
215
    while (RARRAY_LEN(hook) > 0) {
 
216
        typedef void rb_vm_at_exit_func(rb_vm_t*);
 
217
        rb_vm_at_exit_func *func = (rb_vm_at_exit_func*)rb_ary_pop(hook);
 
218
        (*func)(vm);
 
219
    }
 
220
    rb_ary_free(hook);
 
221
}
 
222
 
175
223
/* Env */
176
224
 
177
225
/*
244
292
 
245
293
static const rb_data_type_t env_data_type = {
246
294
    "VM/env",
247
 
    env_mark, env_free, env_memsize,
 
295
    {env_mark, env_free, env_memsize,},
248
296
};
249
297
 
250
298
static VALUE
376
424
    if (!RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
377
425
        /* TODO */
378
426
        env->block.iseq = 0;
 
427
    } else {
 
428
        rb_vm_rewrite_dfp_in_errinfo(th, cfp);
379
429
    }
380
430
    return envval;
381
431
}
439
489
}
440
490
 
441
491
void
442
 
rb_vm_stack_to_heap(rb_thread_t * const th)
 
492
rb_vm_rewrite_dfp_in_errinfo(rb_thread_t *th, rb_control_frame_t *cfp)
 
493
{
 
494
    /* rewrite dfp in errinfo to point to heap */
 
495
    if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq) &&
 
496
        (cfp->iseq->type == ISEQ_TYPE_RESCUE ||
 
497
         cfp->iseq->type == ISEQ_TYPE_ENSURE)) {
 
498
        VALUE errinfo = cfp->dfp[-2]; /* #$! */
 
499
        if (RB_TYPE_P(errinfo, T_NODE)) {
 
500
            VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(errinfo);
 
501
            if (! ENV_IN_HEAP_P(th, escape_dfp)) {
 
502
                VALUE dfpval = *escape_dfp;
 
503
                if (CLASS_OF(dfpval) == rb_cEnv) {
 
504
                    rb_env_t *dfpenv;
 
505
                    GetEnvPtr(dfpval, dfpenv);
 
506
                    SET_THROWOBJ_CATCH_POINT(errinfo, (VALUE)(dfpenv->env + dfpenv->local_size));
 
507
                }
 
508
            }
 
509
        }
 
510
    }
 
511
}
 
512
 
 
513
void
 
514
rb_vm_stack_to_heap(rb_thread_t *th)
443
515
{
444
516
    rb_control_frame_t *cfp = th->cfp;
445
517
    while ((cfp = rb_vm_get_ruby_level_next_cfp(th, cfp)) != 0) {
453
525
static VALUE
454
526
vm_make_proc_from_block(rb_thread_t *th, rb_block_t *block)
455
527
{
456
 
    VALUE proc = block->proc;
457
 
 
458
 
    if (block->proc) {
459
 
        return block->proc;
 
528
    if (!block->proc) {
 
529
        block->proc = rb_vm_make_proc(th, block, rb_cProc);
460
530
    }
461
 
 
462
 
    proc = rb_vm_make_proc(th, block, rb_cProc);
463
 
    block->proc = proc;
464
 
 
465
 
    return proc;
 
531
    return block->proc;
466
532
}
467
533
 
468
534
VALUE
477
543
    }
478
544
 
479
545
    if (GC_GUARDED_PTR_REF(cfp->lfp[0])) {
480
 
            rb_proc_t *p;
481
 
 
482
 
            blockprocval = vm_make_proc_from_block(
483
 
                th, (rb_block_t *)GC_GUARDED_PTR_REF(*cfp->lfp));
484
 
 
485
 
            GetProcPtr(blockprocval, p);
486
 
            *cfp->lfp = GC_GUARDED_PTR(&p->block);
487
 
        }
 
546
        rb_proc_t *p;
 
547
 
 
548
        blockprocval = vm_make_proc_from_block(
 
549
            th, (rb_block_t *)GC_GUARDED_PTR_REF(*cfp->lfp));
 
550
 
 
551
        GetProcPtr(blockprocval, p);
 
552
        *cfp->lfp = GC_GUARDED_PTR(&p->block);
 
553
    }
488
554
 
489
555
    envval = rb_vm_make_env_object(th, cfp);
490
556
 
821
887
{
822
888
    rb_thread_t *th = GET_THREAD();
823
889
    rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
 
890
 
 
891
    if (cfp == 0) {
 
892
        rb_raise(rb_eRuntimeError, "Can't call on top of Fiber or Thread");
 
893
    }
824
894
    return vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
825
895
}
826
896
 
842
912
    rb_thread_t *th = GET_THREAD();
843
913
    rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
844
914
 
 
915
    if (cfp == 0) {
 
916
        rb_raise(rb_eRuntimeError, "Can't call on top of Fiber or Thread");
 
917
    }
845
918
    return vm_get_cbase(cfp->iseq, cfp->lfp, cfp->dfp);
846
919
}
847
920
 
954
1027
static void
955
1028
rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me)
956
1029
{
957
 
    VALUE bop;
 
1030
    st_data_t bop;
958
1031
    if (!me->def || me->def->type == VM_METHOD_TYPE_CFUNC) {
959
1032
        if (st_lookup(vm_opt_method_table, (st_data_t)me, &bop)) {
960
1033
            ruby_vm_redefined_flag[bop] = 1;
1452
1525
 
1453
1526
VALUE
1454
1527
rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg,
1455
 
                 const rb_block_t *blockptr, VALUE filename, VALUE filepath)
 
1528
                 const rb_block_t *blockptr, VALUE filename)
1456
1529
{
1457
1530
    rb_thread_t *th = GET_THREAD();
1458
1531
    const rb_control_frame_t *reg_cfp = th->cfp;
1459
 
    volatile VALUE iseqval = rb_iseq_new(0, filename, filename, filepath, 0, ISEQ_TYPE_TOP);
 
1532
    volatile VALUE iseqval = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP);
1460
1533
    VALUE val;
1461
1534
 
1462
1535
    vm_push_frame(th, DATA_PTR(iseqval), VM_FRAME_MAGIC_TOP,
1525
1598
#define vm_free 0
1526
1599
 
1527
1600
int
1528
 
ruby_vm_destruct(void *ptr)
 
1601
ruby_vm_destruct(rb_vm_t *vm)
1529
1602
{
1530
1603
    RUBY_FREE_ENTER("vm");
1531
 
    if (ptr) {
1532
 
        rb_vm_t *vm = ptr;
 
1604
    if (vm) {
1533
1605
        rb_thread_t *th = vm->main_thread;
1534
1606
#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
1535
1607
        struct rb_objspace *objspace = vm->objspace;
1543
1615
            st_free_table(vm->living_threads);
1544
1616
            vm->living_threads = 0;
1545
1617
        }
1546
 
        rb_thread_lock_unlock(&vm->global_vm_lock);
1547
 
        rb_thread_lock_destroy(&vm->global_vm_lock);
 
1618
#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
 
1619
        if (objspace) {
 
1620
            rb_objspace_free(objspace);
 
1621
        }
 
1622
#endif
 
1623
        ruby_vm_run_at_exit_hooks(vm);
 
1624
        rb_vm_gvl_destroy(vm);
1548
1625
        ruby_xfree(vm);
1549
1626
        ruby_current_vm = 0;
1550
 
#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
1551
 
        if (objspace) {
1552
 
            rb_objspace_free(objspace);
1553
 
        }
1554
 
#endif
1555
1627
    }
1556
1628
    RUBY_FREE_LEAVE("vm");
1557
1629
    return 0;
1571
1643
 
1572
1644
static const rb_data_type_t vm_data_type = {
1573
1645
    "VM",
1574
 
    rb_vm_mark, vm_free, vm_memsize,
 
1646
    {rb_vm_mark, vm_free, vm_memsize,},
1575
1647
};
1576
1648
 
1577
1649
static void
1579
1651
{
1580
1652
    MEMZERO(vm, rb_vm_t, 1);
1581
1653
    vm->src_encoding_index = -1;
 
1654
    vm->at_exit.basic.flags = (T_ARRAY | RARRAY_EMBED_FLAG) & ~RARRAY_EMBED_LEN_MASK; /* len set 0 */
 
1655
    vm->at_exit.basic.klass = 0;
1582
1656
}
1583
1657
 
1584
1658
/* Thread */
1627
1701
}
1628
1702
#endif
1629
1703
 
1630
 
void rb_gc_mark_machine_stack(rb_thread_t *th);
1631
 
 
1632
1704
void
1633
1705
rb_thread_mark(void *ptr)
1634
1706
{
1706
1778
        }
1707
1779
 
1708
1780
        if (th->locking_mutex != Qfalse) {
1709
 
            rb_bug("thread_free: locking_mutex must be NULL (%p:%ld)", (void *)th, th->locking_mutex);
 
1781
            rb_bug("thread_free: locking_mutex must be NULL (%p:%p)", (void *)th, (void *)th->locking_mutex);
1710
1782
        }
1711
1783
        if (th->keeping_mutexes != NULL) {
1712
 
            rb_bug("thread_free: keeping_mutexes must be NULL (%p:%p)", (void *)th, th->keeping_mutexes);
 
1784
            rb_bug("thread_free: keeping_mutexes must be NULL (%p:%p)", (void *)th, (void *)th->keeping_mutexes);
1713
1785
        }
1714
1786
 
1715
1787
        if (th->local_storage) {
1716
1788
            st_free_table(th->local_storage);
1717
1789
        }
1718
1790
 
1719
 
#if USE_VALUE_CACHE
1720
 
        {
1721
 
            VALUE *ptr = th->value_cache_ptr;
1722
 
            while (*ptr) {
1723
 
                VALUE v = *ptr;
1724
 
                RBASIC(v)->flags = 0;
1725
 
                RBASIC(v)->klass = 0;
1726
 
                ptr++;
1727
 
            }
1728
 
        }
1729
 
#endif
1730
 
 
1731
1791
        if (th->vm && th->vm->main_thread == th) {
1732
1792
            RUBY_GC_INFO("main thread\n");
1733
1793
        }
1739
1799
#endif
1740
1800
            ruby_xfree(ptr);
1741
1801
        }
 
1802
        if (ruby_current_thread == th)
 
1803
            ruby_current_thread = NULL;
1742
1804
    }
1743
1805
    RUBY_FREE_LEAVE("thread");
1744
1806
}
1754
1816
            size += th->stack_size * sizeof(VALUE);
1755
1817
        }
1756
1818
        if (th->local_storage) {
1757
 
            st_memsize(th->local_storage);
 
1819
            size += st_memsize(th->local_storage);
1758
1820
        }
1759
1821
        return size;
1760
1822
    }
1763
1825
    }
1764
1826
}
1765
1827
 
1766
 
static const rb_data_type_t thread_data_type = {
 
1828
#define thread_data_type ruby_threadptr_data_type
 
1829
const rb_data_type_t ruby_threadptr_data_type = {
1767
1830
    "VM/thread",
1768
 
    rb_thread_mark,
1769
 
    thread_free,
1770
 
    thread_memsize,
 
1831
    {
 
1832
        rb_thread_mark,
 
1833
        thread_free,
 
1834
        thread_memsize,
 
1835
    },
1771
1836
};
1772
1837
 
 
1838
VALUE
 
1839
rb_obj_is_thread(VALUE obj)
 
1840
{
 
1841
    if (rb_typeddata_is_kind_of(obj, &thread_data_type)) {
 
1842
        return Qtrue;
 
1843
    }
 
1844
    else {
 
1845
        return Qfalse;
 
1846
    }
 
1847
}
 
1848
 
1773
1849
static VALUE
1774
1850
thread_alloc(VALUE klass)
1775
1851
{
1785
1861
}
1786
1862
 
1787
1863
static void
1788
 
th_init2(rb_thread_t *th, VALUE self)
 
1864
th_init(rb_thread_t *th, VALUE self)
1789
1865
{
1790
1866
    th->self = self;
1791
1867
 
1792
1868
    /* allocate thread stack */
 
1869
#ifdef USE_SIGALTSTACK
 
1870
    /* altstack of main thread is reallocated in another place */
 
1871
    th->altstack = malloc(ALT_STACK_SIZE);
 
1872
#endif
1793
1873
    th->stack_size = RUBY_VM_THREAD_STACK_SIZE;
1794
1874
    th->stack = thread_recycle_stack(th->stack_size);
1795
1875
 
1801
1881
    th->status = THREAD_RUNNABLE;
1802
1882
    th->errinfo = Qnil;
1803
1883
    th->last_status = Qnil;
1804
 
 
1805
 
#if USE_VALUE_CACHE
1806
 
    th->value_cache_ptr = &th->value_cache[0];
1807
 
#endif
1808
 
}
1809
 
 
1810
 
static void
1811
 
th_init(rb_thread_t *th, VALUE self)
1812
 
{
1813
 
    th_init2(th, self);
 
1884
    th->waiting_fd = -1;
1814
1885
}
1815
1886
 
1816
1887
static VALUE
1845
1916
    rb_iseq_t *miseq;
1846
1917
    GetISeqPtr(iseqval, miseq);
1847
1918
 
 
1919
    if (miseq->klass) {
 
1920
        iseqval = rb_iseq_clone(iseqval, 0);
 
1921
        RB_GC_GUARD(iseqval);
 
1922
        GetISeqPtr(iseqval, miseq);
 
1923
    }
 
1924
 
1848
1925
    if (NIL_P(klass)) {
1849
1926
        rb_raise(rb_eTypeError, "no class/module to add method");
1850
1927
    }
1856
1933
                     rb_id2name(id), rb_obj_classname(obj));
1857
1934
        }
1858
1935
 
1859
 
        if (OBJ_FROZEN(obj)) {
1860
 
            rb_error_frozen("object");
1861
 
        }
1862
 
 
 
1936
        rb_check_frozen(obj);
1863
1937
        klass = rb_singleton_class(obj);
1864
1938
        noex = NOEX_PUBLIC;
1865
1939
    }
1866
1940
 
1867
1941
    /* dup */
1868
1942
    COPY_CREF(miseq->cref_stack, cref);
 
1943
    miseq->cref_stack->nd_visi = NOEX_PUBLIC;
1869
1944
    miseq->klass = klass;
1870
1945
    miseq->defined_method_id = id;
1871
1946
    rb_add_method(klass, id, VM_METHOD_TYPE_ISEQ, miseq, noex);
1936
2011
        rb_thread_t *th = GET_THREAD();
1937
2012
        rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
1938
2013
        VALUE proc;
1939
 
        extern void rb_call_end_proc(VALUE data);
 
2014
 
 
2015
        if (cfp == 0) {
 
2016
            rb_bug("m_core_set_postexe: unreachable");
 
2017
        }
1940
2018
 
1941
2019
        GetISeqPtr(iseqval, blockiseq);
1942
2020
 
2040
2118
    rb_ary_push(opts, rb_str_new2("call threaded code"));
2041
2119
#endif
2042
2120
 
2043
 
#if OPT_BASIC_OPERATIONS
2044
 
    rb_ary_push(opts, rb_str_new2("optimize basic operation"));
2045
 
#endif
2046
 
 
2047
2121
#if OPT_STACK_CACHING
2048
2122
    rb_ary_push(opts, rb_str_new2("stack caching"));
2049
2123
#endif
2102
2176
        th->cfp->pc = iseq->iseq_encoded;
2103
2177
        th->cfp->self = th->top_self;
2104
2178
 
 
2179
        /*
 
2180
         * The Binding of the top level scope
 
2181
         */
2105
2182
        rb_define_global_const("TOPLEVEL_BINDING", rb_binding_new());
2106
2183
    }
2107
2184
    vm_init_redefined_flag();
2119
2196
#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
2120
2197
struct rb_objspace *rb_objspace_alloc(void);
2121
2198
#endif
2122
 
void ruby_thread_init_stack(rb_thread_t *th);
2123
 
 
2124
 
extern void Init_native_thread(void);
2125
2199
 
2126
2200
void
2127
2201
Init_BareVM(void)
2144
2218
    ruby_current_vm = vm;
2145
2219
 
2146
2220
    Init_native_thread();
2147
 
    th_init2(th, 0);
 
2221
    th_init(th, 0);
2148
2222
    th->vm = vm;
2149
2223
    ruby_thread_init_stack(th);
2150
2224
}