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

« back to all changes in this revision

Viewing changes to vm_insnhelper.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_insnhelper.c - instruction helper functions.
4
4
 
5
 
  $Author: yugui $
 
5
  $Author: naruse $
6
6
 
7
7
  Copyright (C) 2007 Koichi Sasada
8
8
 
11
11
/* finish iseq array */
12
12
#include "insns.inc"
13
13
#include <math.h>
 
14
#include "constant.h"
 
15
#include "internal.h"
14
16
 
15
17
/* control stack frame */
16
18
 
131
133
}
132
134
 
133
135
#define VM_CALLEE_SETUP_ARG(ret, th, iseq, orig_argc, orig_argv, block) \
134
 
    if (LIKELY(iseq->arg_simple & 0x01)) { \
 
136
    if (LIKELY((iseq)->arg_simple & 0x01)) { \
135
137
        /* simple check */ \
136
 
        if (orig_argc != iseq->argc) { \
137
 
            argument_error(iseq, orig_argc, iseq->argc); \
 
138
        if ((orig_argc) != (iseq)->argc) { \
 
139
            argument_error((iseq), (orig_argc), (iseq)->argc); \
138
140
        } \
139
 
        ret = 0; \
 
141
        (ret) = 0; \
140
142
    } \
141
143
    else { \
142
 
        ret = vm_callee_setup_arg_complex(th, iseq, orig_argc, orig_argv, block); \
 
144
        (ret) = vm_callee_setup_arg_complex((th), (iseq), (orig_argc), (orig_argv), (block)); \
143
145
    }
144
146
 
145
147
static inline int
385
387
 
386
388
static inline VALUE
387
389
vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp,
388
 
              int num, VALUE recv, const rb_block_t *blockptr,
 
390
              int num, volatile VALUE recv, const rb_block_t *blockptr,
389
391
              const rb_method_entry_t *me)
390
392
{
391
 
    VALUE val = 0;
 
393
    volatile VALUE val = 0;
392
394
    const rb_method_definition_t *def = me->def;
393
395
    rb_control_frame_t *cfp;
394
396
 
404
406
    if (reg_cfp != th->cfp + 1) {
405
407
        rb_bug("cfp consistency error - send");
406
408
    }
 
409
#ifdef __llvm__
 
410
#define RB_LLVM_GUARD(v) RB_GC_GUARD(v)
 
411
    RB_LLVM_GUARD(reg_cfp);
 
412
#endif
407
413
 
408
414
    vm_pop_frame(th);
409
415
 
419
425
    rb_proc_t *proc;
420
426
    VALUE val;
421
427
 
 
428
    EXEC_EVENT_HOOK(th, RUBY_EVENT_CALL, recv, me->called_id, me->klass);
 
429
 
422
430
    /* control block frame */
423
431
    th->passed_me = me;
424
 
 
425
432
    GetProcPtr(me->def->body.proc, proc);
426
433
    val = rb_vm_invoke_proc(th, proc, recv, argc, argv, blockptr);
 
434
 
 
435
    EXEC_EVENT_HOOK(th, RUBY_EVENT_RETURN, recv, me->called_id, me->klass);
 
436
 
427
437
    return val;
428
438
}
429
439
 
628
638
            else if (!(flag & VM_CALL_OPT_SEND_BIT) && (me->flag & NOEX_MASK) & NOEX_PROTECTED) {
629
639
                VALUE defined_class = me->klass;
630
640
 
631
 
                if (TYPE(defined_class) == T_ICLASS) {
 
641
                if (RB_TYPE_P(defined_class, T_ICLASS)) {
632
642
                    defined_class = RBASIC(defined_class)->klass;
633
643
                }
634
644
 
718
728
        blockarg = Qnil;
719
729
    }
720
730
 
721
 
    vm_push_frame(th, 0, VM_FRAME_MAGIC_IFUNC,
 
731
    vm_push_frame(th, (rb_iseq_t *)ifunc, VM_FRAME_MAGIC_IFUNC,
722
732
                  self, (VALUE)block->dfp,
723
733
                  0, th->cfp->sp, block->lfp, 1);
724
734
 
1060
1070
{
1061
1071
    while (1) {
1062
1072
        if (lfp == dfp) {
 
1073
            if (!RUBY_VM_NORMAL_ISEQ_P(iseq)) return NULL;
1063
1074
            return iseq->cref_stack;
1064
1075
        }
1065
1076
        else if (dfp[-1] != Qnil) {
1085
1096
{
1086
1097
    rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
1087
1098
    NODE *cref = NEW_BLOCK(klass);
1088
 
    cref->nd_file = 0;
1089
1099
    cref->nd_visi = noex;
1090
1100
 
1091
1101
    if (blockptr) {
1154
1164
 
1155
1165
    if (orig_klass == Qnil) {
1156
1166
        /* in current lexical scope */
1157
 
        const NODE *cref = vm_get_cref(iseq, th->cfp->lfp, th->cfp->dfp);
1158
 
        const NODE *root_cref = NULL;
 
1167
        const NODE *root_cref = vm_get_cref(iseq, th->cfp->lfp, th->cfp->dfp);
 
1168
        const NODE *cref;
1159
1169
        VALUE klass = orig_klass;
1160
1170
 
 
1171
        while (root_cref && root_cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) {
 
1172
            root_cref = root_cref->nd_next;
 
1173
        }
 
1174
        cref = root_cref;
1161
1175
        while (cref && cref->nd_next) {
1162
 
            if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL)) {
 
1176
            if (cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) {
 
1177
                klass = Qnil;
 
1178
            }
 
1179
            else {
1163
1180
                klass = cref->nd_clss;
1164
 
                if (root_cref == NULL)
1165
 
                    root_cref = cref;
1166
1181
            }
1167
1182
            cref = cref->nd_next;
1168
1183
 
1169
1184
            if (!NIL_P(klass)) {
1170
1185
                VALUE am = 0;
 
1186
                st_data_t data;
1171
1187
              search_continue:
1172
 
                if (RCLASS_IV_TBL(klass) &&
1173
 
                    st_lookup(RCLASS_IV_TBL(klass), id, &val)) {
 
1188
                if (RCLASS_CONST_TBL(klass) &&
 
1189
                    st_lookup(RCLASS_CONST_TBL(klass), id, &data)) {
 
1190
                    val = ((rb_const_entry_t*)data)->value;
1174
1191
                    if (val == Qundef) {
1175
1192
                        if (am == klass) break;
1176
1193
                        am = klass;
 
1194
                        if (is_defined) return 1;
1177
1195
                        rb_autoload_load(klass, id);
1178
1196
                        goto search_continue;
1179
1197
                    }
1207
1225
    else {
1208
1226
        vm_check_if_namespace(orig_klass);
1209
1227
        if (is_defined) {
1210
 
            return rb_const_defined_from(orig_klass, id);
 
1228
            return rb_public_const_defined_from(orig_klass, id);
1211
1229
        }
1212
1230
        else {
1213
 
            return rb_const_get_from(orig_klass, id);
 
1231
            return rb_public_const_get_from(orig_klass, id);
1214
1232
        }
1215
1233
    }
1216
1234
}
1238
1256
    return klass;
1239
1257
}
1240
1258
 
 
1259
static VALUE
 
1260
vm_search_const_defined_class(const VALUE cbase, ID id)
 
1261
{
 
1262
    if (rb_const_defined_at(cbase, id)) return cbase;
 
1263
    if (cbase == rb_cObject) {
 
1264
        VALUE tmp = RCLASS_SUPER(cbase);
 
1265
        while (tmp) {
 
1266
            if (rb_const_defined_at(tmp, id)) return tmp;
 
1267
            tmp = RCLASS_SUPER(tmp);
 
1268
        }
 
1269
    }
 
1270
    return 0;
 
1271
}
1241
1272
 
1242
1273
#ifndef USE_IC_FOR_IVAR
1243
1274
#define USE_IC_FOR_IVAR 1
1251
1282
        VALUE val = Qundef;
1252
1283
        VALUE klass = RBASIC(obj)->klass;
1253
1284
 
1254
 
        if (ic->ic_class == klass) {
 
1285
        if (LIKELY(ic->ic_class == klass &&
 
1286
                   ic->ic_vmstat == GET_VM_STATE_VERSION())) {
1255
1287
            long index = ic->ic_value.index;
1256
1288
            long len = ROBJECT_NUMIV(obj);
1257
1289
            VALUE *ptr = ROBJECT_IVPTR(obj);
1273
1305
                    }
1274
1306
                    ic->ic_class = klass;
1275
1307
                    ic->ic_value.index = index;
 
1308
                    ic->ic_vmstat = GET_VM_STATE_VERSION();
1276
1309
                }
1277
1310
            }
1278
1311
        }
1297
1330
    if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4) {
1298
1331
        rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
1299
1332
    }
1300
 
    if (OBJ_FROZEN(obj)) {
1301
 
        rb_error_frozen("object");
1302
 
    }
 
1333
 
 
1334
    rb_check_frozen(obj);
1303
1335
 
1304
1336
    if (TYPE(obj) == T_OBJECT) {
1305
1337
        VALUE klass = RBASIC(obj)->klass;
1306
1338
        st_data_t index;
1307
1339
 
1308
 
        if (ic->ic_class == klass) {
 
1340
        if (LIKELY(ic->ic_class == klass &&
 
1341
                   ic->ic_vmstat == GET_VM_STATE_VERSION())) {
1309
1342
            long index = ic->ic_value.index;
1310
1343
            long len = ROBJECT_NUMIV(obj);
1311
1344
            VALUE *ptr = ROBJECT_IVPTR(obj);
1321
1354
            if (iv_index_tbl && st_lookup(iv_index_tbl, (st_data_t)id, &index)) {
1322
1355
                ic->ic_class = klass;
1323
1356
                ic->ic_value.index = index;
 
1357
                ic->ic_vmstat = GET_VM_STATE_VERSION();
1324
1358
            }
1325
1359
            /* fall through */
1326
1360
        }
1336
1370
{
1337
1371
    rb_method_entry_t *me;
1338
1372
#if OPT_INLINE_METHOD_CACHE
1339
 
    if (LIKELY(klass == ic->ic_class) &&
1340
 
        LIKELY(GET_VM_STATE_VERSION() == ic->ic_vmstat)) {
 
1373
    if (LIKELY(klass == ic->ic_class &&
 
1374
        GET_VM_STATE_VERSION() == ic->ic_vmstat)) {
1341
1375
        me = ic->ic_value.method;
1342
1376
    }
1343
1377
    else {
1374
1408
}
1375
1409
 
1376
1410
static void
1377
 
vm_search_superclass(rb_control_frame_t *reg_cfp, rb_iseq_t *ip,
 
1411
vm_search_superclass(rb_control_frame_t *reg_cfp, rb_iseq_t *iseq,
1378
1412
                     VALUE recv, VALUE sigval,
1379
1413
                     ID *idp, VALUE *klassp)
1380
1414
{
1381
1415
    ID id;
1382
1416
    VALUE klass;
1383
1417
 
1384
 
    while (ip && !ip->klass) {
1385
 
        ip = ip->parent_iseq;
 
1418
    while (iseq && !iseq->klass) {
 
1419
        iseq = iseq->parent_iseq;
1386
1420
    }
1387
1421
 
1388
 
    if (ip == 0) {
 
1422
    if (iseq == 0) {
1389
1423
        rb_raise(rb_eNoMethodError, "super called outside of method");
1390
1424
    }
1391
1425
 
1392
 
    id = ip->defined_method_id;
 
1426
    id = iseq->defined_method_id;
1393
1427
 
1394
 
    if (ip != ip->local_iseq) {
 
1428
    if (iseq != iseq->local_iseq) {
1395
1429
        /* defined by Module#define_method() */
1396
1430
        rb_control_frame_t *lcfp = GET_CFP();
1397
1431
 
1400
1434
            rb_raise(rb_eRuntimeError, "implicit argument passing of super from method defined by define_method() is not supported. Specify all arguments explicitly.");
1401
1435
        }
1402
1436
 
1403
 
        while (lcfp->iseq != ip) {
 
1437
        while (lcfp->iseq != iseq) {
 
1438
            rb_thread_t *th = GET_THREAD();
1404
1439
            VALUE *tdfp = GET_PREV_DFP(lcfp->dfp);
1405
1440
            while (1) {
1406
1441
                lcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(lcfp);
 
1442
                if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, lcfp)) {
 
1443
                    rb_raise(rb_eNoMethodError,
 
1444
                             "super called outside of method");
 
1445
                }
1407
1446
                if (lcfp->dfp == tdfp) {
1408
1447
                    break;
1409
1448
                }
1419
1458
        klass = vm_search_normal_superclass(lcfp->me->klass, recv);
1420
1459
    }
1421
1460
    else {
1422
 
        klass = vm_search_normal_superclass(ip->klass, recv);
 
1461
        klass = vm_search_normal_superclass(iseq->klass, recv);
1423
1462
    }
1424
1463
 
1425
1464
    *idp = id;
1519
1558
                rb_control_frame_t *cfp = GET_CFP();
1520
1559
                VALUE *dfp = GET_DFP();
1521
1560
                VALUE *lfp = GET_LFP();
 
1561
                int in_class_frame = 0;
1522
1562
 
1523
1563
                /* check orphan and get dfp */
1524
1564
                while ((VALUE *) cfp < th->stack + th->stack_size) {
1526
1566
                        lfp = cfp->lfp;
1527
1567
                    }
1528
1568
                    if (cfp->dfp == lfp && cfp->iseq->type == ISEQ_TYPE_CLASS) {
 
1569
                        in_class_frame = 1;
1529
1570
                        lfp = 0;
1530
1571
                    }
1531
1572
 
1533
1574
                        if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
1534
1575
                            VALUE *tdfp = dfp;
1535
1576
 
 
1577
                            if (in_class_frame) {
 
1578
                                /* lambda {class A; ... return ...; end} */
 
1579
                                dfp = cfp->dfp;
 
1580
                                goto valid_return;
 
1581
                            }
 
1582
 
1536
1583
                            while (lfp != tdfp) {
1537
1584
                                if (cfp->dfp == tdfp) {
1538
1585
                                    /* in lambda */
1690
1737
 
1691
1738
    {
1692
1739
        const rb_method_entry_t *me = vm_method_search(idEq, CLASS_OF(recv), ic);
1693
 
        extern VALUE rb_obj_equal(VALUE obj1, VALUE obj2);
1694
1740
 
1695
1741
        if (check_cfunc(me, rb_obj_equal)) {
1696
1742
            return recv == obj ? Qtrue : Qfalse;
1700
1746
    return Qundef;
1701
1747
}
1702
1748
 
1703
 
struct opt_case_dispatch_i_arg {
1704
 
    VALUE obj;
1705
 
    int label;
1706
 
};
1707
 
 
1708
 
static int
1709
 
opt_case_dispatch_i(st_data_t key, st_data_t data, st_data_t p)
1710
 
{
1711
 
    struct opt_case_dispatch_i_arg *arg = (void *)p;
1712
 
 
1713
 
    if (RTEST(rb_funcall((VALUE)key, idEqq, 1, arg->obj))) {
1714
 
        arg->label = FIX2INT((VALUE)data);
1715
 
        return ST_STOP;
1716
 
    }
1717
 
    else {
1718
 
        return ST_CONTINUE;
1719
 
    }
1720
 
}
1721