~ubuntu-branches/ubuntu/trusty/erlang/trusty

« back to all changes in this revision

Viewing changes to erts/emulator/beam/erl_trace.c

  • Committer: Bazaar Package Importer
  • Author(s): Clint Byrum
  • Date: 2011-05-05 15:48:43 UTC
  • mfrom: (3.5.13 sid)
  • Revision ID: james.westby@ubuntu.com-20110505154843-0om6ekzg6m7ugj27
Tags: 1:14.b.2-dfsg-3ubuntu1
* Merge from debian unstable.  Remaining changes:
  - Drop libwxgtk2.8-dev build dependency. Wx isn't in main, and not
    supposed to.
  - Drop erlang-wx binary.
  - Drop erlang-wx dependency from -megaco, -common-test, and -reltool, they
    do not really need wx. Also drop it from -debugger; the GUI needs wx,
    but it apparently has CLI bits as well, and is also needed by -megaco,
    so let's keep the package for now.
  - debian/patches/series: Do what I meant, and enable build-options.patch
    instead.
* Additional changes:
  - Drop erlang-wx from -et
* Dropped Changes:
  - patches/pcre-crash.patch: CVE-2008-2371: outer level option with
    alternatives caused crash. (Applied Upstream)
  - fix for ssl certificate verification in newSSL: 
    ssl_cacertfile_fix.patch (Applied Upstream)
  - debian/patches/series: Enable native.patch again, to get stripped beam
    files and reduce the package size again. (build-options is what
    actually accomplished this)
  - Remove build-options.patch on advice from upstream and because it caused
    odd build failures.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * %CopyrightBegin%
3
 
 * 
4
 
 * Copyright Ericsson AB 1999-2009. All Rights Reserved.
5
 
 * 
 
3
 *
 
4
 * Copyright Ericsson AB 1999-2011. All Rights Reserved.
 
5
 *
6
6
 * The contents of this file are subject to the Erlang Public License,
7
7
 * Version 1.1, (the "License"); you may not use this file except in
8
8
 * compliance with the License. You should have received a copy of the
9
9
 * Erlang Public License along with this software. If not, it can be
10
10
 * retrieved online at http://www.erlang.org/.
11
 
 * 
 
11
 *
12
12
 * Software distributed under the License is distributed on an "AS IS"
13
13
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
14
14
 * the License for the specific language governing rights and limitations
15
15
 * under the License.
16
 
 * 
 
16
 *
17
17
 * %CopyrightEnd%
18
18
 */
19
19
 
43
43
#undef DEBUG_PRINTOUTS
44
44
#endif
45
45
 
46
 
extern Eterm beam_return_to_trace[1]; /* OpCode(i_return_to_trace) */
47
 
extern Eterm beam_return_trace[1];    /* OpCode(i_return_trace) */
 
46
extern Eterm beam_return_to_trace[1];   /* OpCode(i_return_to_trace) */
 
47
extern Eterm beam_return_trace[1];      /* OpCode(i_return_trace) */
 
48
extern Eterm beam_return_time_trace[1]; /* OpCode(i_return_time_trace) */
48
49
 
49
50
/* Pseudo export entries. Never filled in with data, only used to
50
51
   yield unique pointers of the correct type. */
397
398
 */
398
399
static void 
399
400
do_send_schedfix_to_port(Port *trace_port, Eterm pid, Eterm timestamp) {
400
 
    Eterm local_heap[4+5+5];
 
401
#define LOCAL_HEAP_SIZE (4+5+5)
 
402
    DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
401
403
    Eterm message;
402
404
    Eterm *hp;
403
405
    Eterm mfarity;
404
406
 
 
407
    UseTmpHeapNoproc(LOCAL_HEAP_SIZE);
405
408
    ASSERT(is_pid(pid));
406
409
    ASSERT(is_tuple(timestamp));
407
410
    ASSERT(*tuple_val(timestamp) == make_arityval(3));
426
429
                    pid,
427
430
                    SYS_MSG_TYPE_UNDEFINED,
428
431
                    message);
 
432
    UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
433
#undef LOCAL_HEAP_SIZE
429
434
}
430
435
#endif
431
436
 
442
447
             Eterm *tracer_pid, Uint *tracee_flags) {
443
448
    Port* trace_port;
444
449
#ifndef ERTS_SMP
445
 
    Eterm ts, local_heap[4], *hp;
 
450
#define LOCAL_HEAP_SIZE (4)
 
451
    Eterm ts, *hp;
 
452
    DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
446
453
#endif
447
454
 
448
455
    ASSERT(is_internal_port(*tracer_pid));
486
493
     * (e.g. getting_linked) need not be the current process. That other
487
494
     * process might not have timestamps enabled.
488
495
     */
 
496
    UseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
497
 
489
498
    if (*tracee_flags & F_TIMESTAMP) {
490
499
        ASSERT(is_tuple(message));
491
500
        hp = tuple_val(message);
522
531
         */
523
532
        do_send_schedfix_to_port(trace_port, c_p->id, ts);
524
533
    }
 
534
    UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
535
#undef LOCAL_HEAP_SIZE
525
536
#endif
526
537
}
527
538
 
589
600
{
590
601
    Port* trace_port;
591
602
#ifndef ERTS_SMP
592
 
    Eterm ts, local_heap[4], *hp;
 
603
    Eterm ts, *hp;
 
604
#define LOCAL_HEAP_SIZE (4)
 
605
    DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
 
606
    UseTmpHeapNoproc(LOCAL_HEAP_SIZE);
593
607
#endif
594
608
 
595
609
    ASSERT(is_internal_port(seq_tracer));
607
621
    if (INVALID_TRACER_PORT(trace_port, seq_tracer)) {
608
622
    invalid_tracer_port:
609
623
        system_seq_tracer = am_false;
 
624
#ifndef ERTS_SMP
 
625
        UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
626
#endif
610
627
        return;
611
628
    }
612
629
 
620
637
                        message);
621
638
 
622
639
#ifndef ERTS_SMP
 
640
        UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
623
641
        return;
624
642
    }
625
643
    /* Make a fake schedule only if the current process is traced
660
678
         */
661
679
        do_send_schedfix_to_port(trace_port, c_p->id, ts);
662
680
    }
 
681
    UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
682
#undef LOCAL_HEAP_SIZE
663
683
#endif
664
684
}
665
685
 
719
739
static void
720
740
trace_sched_aux(Process *p, Eterm what, int never_fake_sched)
721
741
{
722
 
    Eterm local_heap[5+4+1+TS_HEAP_WORDS];
 
742
#define LOCAL_HEAP_SIZE (5+4+1+TS_HEAP_WORDS)
 
743
    DeclareTmpHeap(local_heap,LOCAL_HEAP_SIZE,p);
723
744
    Eterm tmp, mess, *hp;
724
745
    ErlHeapFragment *bp = NULL;
725
746
    ErlOffHeap *off_heap;
768
789
        curr_func = p->current != NULL;
769
790
    }
770
791
 
 
792
    UseTmpHeap(LOCAL_HEAP_SIZE,p);
 
793
 
771
794
    if (to_port)
772
 
        hp = &local_heap[0];
 
795
        hp = local_heap;
773
796
    else {
774
797
        Uint size = 5;
775
798
        if (curr_func)
802
825
    }
803
826
 
804
827
    send_to_tracer(p, tracer_ref, mess, &hp, bp, no_fake_sched);
 
828
    UnUseTmpHeap(LOCAL_HEAP_SIZE,p);
 
829
#undef LOCAL_HEAP_SIZE
805
830
}
806
831
 
807
832
/* Send {trace_ts, Pid, What, {Mod, Func, Arity}, Timestamp}
848
873
    }
849
874
 
850
875
    if (is_internal_port(p->tracer_proc)) {
851
 
        Eterm local_heap[11];
 
876
#define LOCAL_HEAP_SIZE (11)
 
877
        DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
 
878
        UseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
879
 
852
880
        hp = local_heap;
853
881
        mess = TUPLE5(hp, am_trace, p->id, operation, msg, to);
854
882
        hp += 6;
857
885
            hp = patch_ts(mess, hp);
858
886
        }
859
887
        send_to_port(p, mess, &p->tracer_proc, &p->trace_flags);
 
888
        UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
889
#undef LOCAL_HEAP_SIZE
860
890
        erts_smp_mtx_unlock(&smq_mtx);
861
891
    } else {
862
892
        Uint need;
908
938
    Eterm* hp;
909
939
 
910
940
    if (is_internal_port(rp->tracer_proc)) {
911
 
        Eterm local_heap[10];
 
941
#define LOCAL_HEAP_SIZE (10)
 
942
        DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
 
943
        UseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
944
 
912
945
        hp = local_heap;
913
946
        mess = TUPLE4(hp, am_trace, rp->id, am_receive, msg);
914
947
        hp += 5;
917
950
            hp = patch_ts(mess, hp);
918
951
        }
919
952
        send_to_port(rp, mess, &rp->tracer_proc, &rp->trace_flags);
 
953
        UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
954
#undef LOCAL_HEAP_SIZE
920
955
        erts_smp_mtx_unlock(&smq_mtx);
921
956
    } else {
922
957
        Uint hsz;
1018
1053
    }
1019
1054
 
1020
1055
    if (is_internal_port(seq_tracer)) {
1021
 
        Eterm local_heap[64];
 
1056
#define LOCAL_HEAP_SIZE (64)
 
1057
        DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
 
1058
        UseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
1059
 
1022
1060
        hp = local_heap;
1023
1061
        label = SEQ_TRACE_T_LABEL(token);
1024
1062
        lastcnt_serial = TUPLE2(hp, SEQ_TRACE_T_LASTCNT(token),
1043
1081
            mess = TUPLE4(hp, am_seq_trace, label, mess, ts);
1044
1082
            seq_trace_send_to_port(process, seq_tracer, mess, ts);
1045
1083
        }
 
1084
        UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
1085
#undef LOCAL_HEAP_SIZE
1046
1086
        erts_smp_mtx_unlock(&smq_mtx);
1047
1087
    } else {
1048
1088
#ifndef ERTS_SMP
1143
1183
 * or   {trace, Pid, return_to, {Mod, Func, Arity}}
1144
1184
 */
1145
1185
void 
1146
 
erts_trace_return_to(Process *p, Uint *pc)
 
1186
erts_trace_return_to(Process *p, BeamInstr *pc)
1147
1187
{
 
1188
#define LOCAL_HEAP_SIZE (4+5+5)
1148
1189
    Eterm* hp;
1149
1190
    Eterm mfa;
1150
1191
    Eterm mess;
1151
 
    Eterm local_heap[4+5+5];
1152
 
 
1153
 
    Eterm *code_ptr = find_function_from_pc(pc);
 
1192
    DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
 
1193
 
 
1194
    BeamInstr *code_ptr = find_function_from_pc(pc);
 
1195
 
 
1196
 
 
1197
    UseTmpHeapNoproc(LOCAL_HEAP_SIZE);
1154
1198
 
1155
1199
    hp = local_heap;
1156
1200
 
1196
1240
        mess = copy_struct(mess, size, &hp, off_heap);
1197
1241
        ERTS_ENQ_TRACE_MSG(p->id, tracer_ref, mess, bp);
1198
1242
    }
 
1243
    UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
1244
#undef LOCAL_HEAP_SIZE
1199
1245
    erts_smp_mtx_unlock(&smq_mtx);
1200
1246
}
1201
1247
 
1204
1250
 * or   {trace, Pid, return_from, {Mod, Name, Arity}, Retval}
1205
1251
 */
1206
1252
void
1207
 
erts_trace_return(Process* p, Eterm* fi, Eterm retval, Eterm *tracer_pid)
 
1253
erts_trace_return(Process* p, BeamInstr* fi, Eterm retval, Eterm *tracer_pid)
1208
1254
{
1209
1255
    Eterm* hp;
1210
1256
    Eterm mfa;
1262
1308
    arity = fi[2];
1263
1309
    
1264
1310
    if (is_internal_port(*tracer_pid)) {
1265
 
        Eterm local_heap[4+6+5];
 
1311
#define LOCAL_HEAP_SIZE (4+6+5)
 
1312
        DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
 
1313
        UseTmpHeapNoproc(LOCAL_HEAP_SIZE);
1266
1314
        hp = local_heap;
1267
1315
        mfa = TUPLE3(hp, mod, name, make_small(arity));
1268
1316
        hp += 4;
1273
1321
            hp = patch_ts(mess, hp);
1274
1322
        }
1275
1323
        send_to_port(p, mess, tracer_pid, tracee_flags);
 
1324
        UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
1325
#undef LOCAL_HEAP_SIZE
1276
1326
        erts_smp_mtx_unlock(&smq_mtx);
1277
1327
    } else {
1278
1328
        ErlHeapFragment *bp;
1331
1381
 * Where Class is atomic but Value is any term.
1332
1382
 */
1333
1383
void
1334
 
erts_trace_exception(Process* p, Eterm mfa[3], Eterm class, Eterm value, 
 
1384
erts_trace_exception(Process* p, BeamInstr mfa[3], Eterm class, Eterm value,
1335
1385
                     Eterm *tracer_pid)
1336
1386
{
1337
1387
    Eterm* hp;
1385
1435
    }
1386
1436
    
1387
1437
    if (is_internal_port(*tracer_pid)) {
1388
 
        Eterm local_heap[4+3+6+5];
 
1438
#define LOCAL_HEAP_SIZE (4+3+6+5)
 
1439
        DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
 
1440
        UseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
1441
 
1389
1442
        hp = local_heap;
1390
 
        mfa_tuple = TUPLE3(hp, mfa[0], mfa[1], make_small(mfa[2]));
 
1443
        mfa_tuple = TUPLE3(hp, (Eterm) mfa[0], (Eterm) mfa[1], make_small((Eterm)mfa[2]));
1391
1444
        hp += 4;
1392
1445
        cv = TUPLE2(hp, class, value);
1393
1446
        hp += 3;
1394
1447
        mess = TUPLE5(hp, am_trace, p->id, am_exception_from, mfa_tuple, cv);
1395
1448
        hp += 6;
1396
 
        ASSERT((hp - local_heap)*sizeof(*hp) <= sizeof(local_heap));
 
1449
        ASSERT((hp - local_heap) <= LOCAL_HEAP_SIZE);
1397
1450
        erts_smp_mtx_lock(&smq_mtx);
1398
1451
        if (*tracee_flags & F_TIMESTAMP) {
1399
1452
            hp = patch_ts(mess, hp); /* hp += 5 */
1400
 
            ASSERT((hp - local_heap)*sizeof(*hp) == sizeof(local_heap));
 
1453
            ASSERT((hp - local_heap) == LOCAL_HEAP_SIZE);
1401
1454
        }
1402
1455
        send_to_port(p, mess, tracer_pid, tracee_flags);
 
1456
        UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
1457
#undef LOCAL_HEAP_SIZE
1403
1458
        erts_smp_mtx_unlock(&smq_mtx);
1404
1459
    } else {
1405
1460
        ErlHeapFragment *bp;
1431
1486
         * Build the trace tuple and put it into receive queue of the tracer process.
1432
1487
         */
1433
1488
        
1434
 
        mfa_tuple = TUPLE3(hp, mfa[0], mfa[1], make_small(mfa[2]));
 
1489
        mfa_tuple = TUPLE3(hp, (Eterm) mfa[0], (Eterm) mfa[1], make_small((Eterm) mfa[2]));
1435
1490
        hp += 4;
1436
1491
        value = copy_struct(value, value_size, &hp, off_heap);
1437
1492
        cv = TUPLE2(hp, class, value);
1468
1523
 * if it is a pid or port we do a meta trace.
1469
1524
 */
1470
1525
Uint32
1471
 
erts_call_trace(Process* p, Eterm mfa[3], Binary *match_spec, 
 
1526
erts_call_trace(Process* p, BeamInstr mfa[3], Binary *match_spec,
1472
1527
                Eterm* args, int local, Eterm *tracer_pid)
1473
1528
{
1474
1529
    Eterm* hp;
1483
1538
    Eterm tracee;
1484
1539
#endif
1485
1540
    Eterm transformed_args[MAX_ARG];
1486
 
    ErlSubBin sub_bin_heap;
 
1541
    DeclareTmpHeap(sub_bin_heap_et,ERL_SUB_BIN_SIZE,p);
 
1542
    ErlSubBin *sub_bin_heap = (ErlSubBin *) sub_bin_heap_et;
1487
1543
 
1488
1544
    ASSERT(tracer_pid);
1489
1545
    if (*tracer_pid == am_true) {
1534
1590
     * such as size_object() and copy_struct(), we must make sure that we
1535
1591
     * temporarily convert any match contexts to sub binaries.
1536
1592
     */
1537
 
    arity = mfa[2];
 
1593
    arity = (Eterm) mfa[2];
 
1594
    UseTmpHeap(ERL_SUB_BIN_SIZE,p);
1538
1595
#ifdef DEBUG
1539
 
    sub_bin_heap.thing_word = 0;
 
1596
    sub_bin_heap->thing_word = 0;
1540
1597
#endif
1541
1598
    for (i = 0; i < arity; i++) {
1542
1599
        Eterm arg = args[i];
1543
1600
        if (is_boxed(arg) && header_is_bin_matchstate(*boxed_val(arg))) {
1544
1601
            ErlBinMatchState* ms = (ErlBinMatchState *) boxed_val(arg);
1545
1602
            ErlBinMatchBuffer* mb = &ms->mb;
1546
 
            ErlSubBin* sb = &sub_bin_heap;
 
1603
            ErlSubBin* sb = sub_bin_heap;
1547
1604
            Uint bit_size;
1548
1605
 
1549
 
            ASSERT(sub_bin_heap.thing_word == 0); /* At most one of match context */
 
1606
            ASSERT(sub_bin_heap->thing_word == 0); /* At most one of match context */
1550
1607
 
1551
1608
            bit_size = mb->size - mb->offset;
1552
1609
            sb->thing_word = HEADER_SUB_BIN;
1564
1621
    args = transformed_args;
1565
1622
 
1566
1623
    if (is_internal_port(*tracer_pid)) {
 
1624
#if HEAP_ON_C_STACK
1567
1625
        Eterm local_heap[64+MAX_ARG];
 
1626
#else
 
1627
        Eterm *local_heap = erts_alloc(ERTS_ALC_T_TEMP_TERM,
 
1628
                                       sizeof(Eterm)*(64+MAX_ARG));
 
1629
#endif
1568
1630
        hp = local_heap;
1569
1631
 
1570
1632
        if (!erts_is_valid_tracer_port(*tracer_pid)) {
1579
1641
            if (is_not_nil(tracee))
1580
1642
                erts_smp_proc_unlock(p, ERTS_PROC_LOCKS_ALL_MINOR);
1581
1643
#endif
 
1644
#if !HEAP_ON_C_STACK
 
1645
            erts_free(ERTS_ALC_T_TEMP_TERM,local_heap);
 
1646
#endif
 
1647
            UnUseTmpHeap(ERL_SUB_BIN_SIZE,p);
1582
1648
            return 0;
1583
1649
        }
1584
1650
        
1602
1668
        return_flags = 0;
1603
1669
        if (match_spec) {
1604
1670
            pam_result = erts_match_set_run(p, match_spec, args, arity,
1605
 
                                            &return_flags);
 
1671
                                            ERTS_PAM_TMP_RESULT, &return_flags);
1606
1672
            if (is_non_value(pam_result)) {
1607
1673
                erts_match_set_release_result(p);
 
1674
#if !HEAP_ON_C_STACK
 
1675
                erts_free(ERTS_ALC_T_TEMP_TERM,local_heap);
 
1676
#endif
 
1677
                UnUseTmpHeap(ERL_SUB_BIN_SIZE,p);
1608
1678
                return 0;
1609
1679
            }
1610
1680
        }
1612
1682
            /* Meta trace */
1613
1683
            if (pam_result == am_false) {
1614
1684
                erts_match_set_release_result(p);
 
1685
#if !HEAP_ON_C_STACK
 
1686
                erts_free(ERTS_ALC_T_TEMP_TERM,local_heap);
 
1687
#endif
 
1688
                UnUseTmpHeap(ERL_SUB_BIN_SIZE,p);
1615
1689
                return return_flags;
1616
1690
            }
1617
1691
        } else {
1618
1692
            /* Non-meta trace */
1619
1693
            if (*tracee_flags & F_TRACE_SILENT) { 
1620
1694
                erts_match_set_release_result(p);
 
1695
#if !HEAP_ON_C_STACK
 
1696
                erts_free(ERTS_ALC_T_TEMP_TERM,local_heap);
 
1697
#endif
 
1698
                UnUseTmpHeap(ERL_SUB_BIN_SIZE,p);
1621
1699
                return 0;
1622
1700
            }
1623
1701
            if (pam_result == am_false) {
1624
1702
                erts_match_set_release_result(p);
 
1703
#if !HEAP_ON_C_STACK
 
1704
                erts_free(ERTS_ALC_T_TEMP_TERM,local_heap);
 
1705
#endif
 
1706
                UnUseTmpHeap(ERL_SUB_BIN_SIZE,p);
1625
1707
                return return_flags;
1626
1708
            }
1627
1709
            if (local && (*tracee_flags & F_TRACE_RETURN_TO)) {
1644
1726
                hp += 2;
1645
1727
            }
1646
1728
        }
1647
 
        mfa_tuple = TUPLE3(hp, mfa[0], mfa[1], mfa_tuple);
 
1729
        mfa_tuple = TUPLE3(hp, (Eterm) mfa[0], (Eterm) mfa[1], mfa_tuple);
1648
1730
        hp += 4;
1649
1731
        
1650
1732
        /*
1664
1746
        send_to_port(p, mess, tracer_pid, tracee_flags);
1665
1747
        erts_smp_mtx_unlock(&smq_mtx);
1666
1748
        erts_match_set_release_result(p);
 
1749
#if !HEAP_ON_C_STACK
 
1750
        erts_free(ERTS_ALC_T_TEMP_TERM,local_heap);
 
1751
#endif
 
1752
        UnUseTmpHeap(ERL_SUB_BIN_SIZE,p);
1667
1753
        return *tracer_pid == NIL ? 0 : return_flags;
1668
1754
 
1669
1755
    } else {
1706
1792
            if (is_not_nil(tracee))
1707
1793
                erts_smp_proc_unlock(p, ERTS_PROC_LOCKS_ALL_MINOR);
1708
1794
#endif
 
1795
            UnUseTmpHeap(ERL_SUB_BIN_SIZE,p);
1709
1796
            return 0;
1710
1797
        }
1711
1798
 
1728
1815
        return_flags = 0;
1729
1816
        if (match_spec) {
1730
1817
            pam_result = erts_match_set_run(p, match_spec, args, arity,
1731
 
                                            &return_flags);
 
1818
                                            ERTS_PAM_TMP_RESULT, &return_flags);
1732
1819
            if (is_non_value(pam_result)) {
1733
1820
                erts_match_set_release_result(p);
 
1821
                UnUseTmpHeap(ERL_SUB_BIN_SIZE,p);
1734
1822
                return 0;
1735
1823
            }
1736
1824
        }
1738
1826
            /* Meta trace */
1739
1827
            if (pam_result == am_false) {
1740
1828
                erts_match_set_release_result(p);
 
1829
                UnUseTmpHeap(ERL_SUB_BIN_SIZE,p);
1741
1830
                return return_flags;
1742
1831
            }
1743
1832
        } else {
1744
1833
            /* Non-meta trace */
1745
1834
            if (*tracee_flags & F_TRACE_SILENT) { 
1746
1835
                erts_match_set_release_result(p);
 
1836
                UnUseTmpHeap(ERL_SUB_BIN_SIZE,p);
1747
1837
                return 0;
1748
1838
            }
1749
1839
            if (pam_result == am_false) {
1750
1840
                erts_match_set_release_result(p);
 
1841
                UnUseTmpHeap(ERL_SUB_BIN_SIZE,p);
1751
1842
                return return_flags;
1752
1843
            }
1753
1844
            if (local && (*tracee_flags & F_TRACE_RETURN_TO)) {
1798
1889
                hp += 2;
1799
1890
            }
1800
1891
        }
1801
 
        mfa_tuple = TUPLE3(hp, mfa[0], mfa[1], mfa_tuple);
 
1892
        mfa_tuple = TUPLE3(hp, (Eterm) mfa[0], (Eterm) mfa[1], mfa_tuple);
1802
1893
        hp += 4;
1803
1894
        
1804
1895
        /*
1831
1922
        ASSERT(hp == limit);
1832
1923
        ERTS_ENQ_TRACE_MSG(tracee, tracer_ref, mess, bp);
1833
1924
        erts_smp_mtx_unlock(&smq_mtx);
 
1925
        UnUseTmpHeap(ERL_SUB_BIN_SIZE,p);
1834
1926
        return return_flags;
1835
1927
    }
1836
1928
}
1850
1942
    Eterm* hp;
1851
1943
    int need;
1852
1944
 
 
1945
    ERTS_SMP_LC_ASSERT((erts_proc_lc_my_proc_locks(t_p) != 0) || erts_is_system_blocked(0));
1853
1946
    if (is_internal_port(t_p->tracer_proc)) {
1854
 
        Eterm local_heap[5+5];
 
1947
#define LOCAL_HEAP_SIZE (5+5)
 
1948
        DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
 
1949
        UseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
1950
 
 
1951
 
1855
1952
        hp = local_heap;
1856
1953
        mess = TUPLE4(hp, am_trace, t_p->id, what, data);
1857
1954
        hp += 5;
1868
1965
            c_p,
1869
1966
#endif
1870
1967
            mess, &t_p->tracer_proc, &t_p->trace_flags);
 
1968
        UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
1969
#undef LOCAL_HEAP_SIZE
1871
1970
        erts_smp_mtx_unlock(&smq_mtx);
1872
1971
    } else {
1873
1972
        Eterm tmp;
1919
2018
    Eterm* hp;
1920
2019
 
1921
2020
    if (is_internal_port(p->tracer_proc)) {
1922
 
        Eterm local_heap[4+6+5];
 
2021
#define LOCAL_HEAP_SIZE (4+6+5)
 
2022
        DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
 
2023
        UseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
2024
 
1923
2025
        hp = local_heap;
1924
2026
        mfa = TUPLE3(hp, mod, func, args);
1925
2027
        hp += 4;
1930
2032
            hp = patch_ts(mess, hp);
1931
2033
        }
1932
2034
        send_to_port(p, mess, &p->tracer_proc, &p->trace_flags);
 
2035
        UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
2036
#undef LOCAL_HEAP_SIZE
1933
2037
        erts_smp_mtx_unlock(&smq_mtx);
1934
2038
    } else {
1935
2039
        Eterm tmp;
1991
2095
 */
1992
2096
Eterm
1993
2097
erts_bif_trace(int bif_index, Process* p, 
1994
 
               Eterm arg1, Eterm arg2, Eterm arg3, Uint *I)
 
2098
               Eterm arg1, Eterm arg2, Eterm arg3, BeamInstr *I)
1995
2099
{
1996
2100
    Eterm result;
1997
2101
    int meta = !!(erts_bif_trace_flags[bif_index] & BIF_TRACE_AS_META);
2005
2109
         * no tracing will occur. Doing the whole else branch will 
2006
2110
         * also do nothing, only slower.
2007
2111
         */
2008
 
        Eterm (*func)(Process*, Eterm, Eterm, Eterm, Uint*) = bif_table[bif_index].f;
 
2112
        Eterm (*func)(Process*, Eterm, Eterm, Eterm, BeamInstr*) = bif_table[bif_index].f;
2009
2113
        result = func(p, arg1, arg2, arg3, I);
2010
2114
    } else {
2011
 
        Eterm (*func)(Process*, Eterm, Eterm, Eterm, Uint*);
 
2115
        Eterm (*func)(Process*, Eterm, Eterm, Eterm, BeamInstr*);
2012
2116
        Export* ep = bif_export[bif_index];
2013
2117
        Uint32 flags = 0, flags_meta = 0;
2014
2118
        int global = !!(erts_bif_trace_flags[bif_index] & BIF_TRACE_AS_GLOBAL);
2015
2119
        int local  = !!(erts_bif_trace_flags[bif_index] & BIF_TRACE_AS_LOCAL);
 
2120
        int time   = !!(erts_bif_trace_flags[bif_index] & BIF_TRACE_AS_CALL_TIME);
2016
2121
        Eterm meta_tracer_pid = NIL;
2017
2122
        int applying = (I == &(ep->code[3])); /* Yup, the apply code for a bif
2018
2123
                                               * is actually in the 
2019
2124
                                               * export entry */
2020
 
        Eterm *cp = p->cp;
 
2125
        BeamInstr *cp = p->cp;
2021
2126
        
2022
 
#ifndef _OSE_
2023
2127
        Eterm args[3] = {arg1, arg2, arg3};
2024
 
#else
2025
 
        Eterm args[3];
2026
 
        args[0] = arg1;
2027
 
        args[1] = arg2;
2028
 
        args[2] = arg3;
2029
 
#endif
2030
2128
        
2031
2129
        /* 
2032
2130
         * Make continuation pointer OK, it is not during direct BIF calls,
2043
2141
            flags_meta = erts_bif_mtrace(p, ep->code+3, args, local, 
2044
2142
                                         &meta_tracer_pid);
2045
2143
        }
 
2144
        if (time) {
 
2145
            BpDataTime *bdt = NULL;
 
2146
            BeamInstr *pc = (BeamInstr *)ep->code+3;
 
2147
 
 
2148
            bdt = (BpDataTime *) erts_get_time_break(p, pc);
 
2149
            ASSERT(bdt);
 
2150
 
 
2151
            if (!bdt->pause) {
 
2152
                erts_trace_time_break(p, pc, bdt, ERTS_BP_CALL_TIME_CALL);
 
2153
            }
 
2154
        }
2046
2155
        /* Restore original continuation pointer (if changed). */
2047
2156
        p->cp = cp;
2048
2157
        
2051
2160
        result = func(p, arg1, arg2, arg3, I);
2052
2161
        
2053
2162
        if (applying && (flags & MATCH_SET_RETURN_TO_TRACE)) {
2054
 
            Uint i_return_trace = beam_return_trace[0];
2055
 
            Uint i_return_to_trace = beam_return_to_trace[0];
 
2163
            BeamInstr i_return_trace      = beam_return_trace[0];
 
2164
            BeamInstr i_return_to_trace   = beam_return_to_trace[0];
 
2165
            BeamInstr i_return_time_trace = beam_return_time_trace[0];
2056
2166
            Eterm *cpp;
2057
2167
            /* Maybe advance cp to skip trace stack frames */
2058
2168
            for (cpp = p->stop;  ;  cp = cp_val(*cpp++)) {
2059
 
                ASSERT(is_CP((Eterm) cp));
2060
 
                if (*cp_val((Eterm) cp) == i_return_trace) {
 
2169
                if (*cp == i_return_trace) {
2061
2170
                    /* Skip stack frame variables */
2062
2171
                    while (is_not_CP(*cpp)) cpp++;
2063
2172
                    cpp += 2; /* Skip return_trace parameters */
2064
 
                } else if (*cp_val((Eterm) cp) == i_return_to_trace) {
 
2173
                } else if (*cp == i_return_time_trace) {
 
2174
                    /* Skip stack frame variables */
 
2175
                    while (is_not_CP(*cpp)) cpp++;
 
2176
                    cpp += 1; /* Skip return_time_trace parameters */
 
2177
                } else if (*cp == i_return_to_trace) {
2065
2178
                    /* A return_to trace message is going to be generated
2066
2179
                     * by normal means, so we do not have to.
2067
2180
                     */
2078
2191
            if (reason != TRAP) {
2079
2192
                Eterm class;
2080
2193
                Eterm value = p->fvalue;
2081
 
                Eterm nocatch[3];
 
2194
                DeclareTmpHeapNoproc(nocatch,3);
 
2195
                UseTmpHeapNoproc(3);
2082
2196
                /* Expand error value like in handle_error() */
2083
2197
                if (reason & EXF_ARGLIST) {
2084
2198
                    Eterm *tp;
2126
2240
                        }
2127
2241
                    }
2128
2242
                }
 
2243
                UnUseTmpHeapNoproc(3);
2129
2244
                if ((flags_meta|flags) & MATCH_SET_EXCEPTION_TRACE) {
2130
2245
                    erts_smp_proc_lock(p, ERTS_PROC_LOCKS_ALL_MINOR);
2131
2246
                    p->trace_flags |= F_EXCEPTION_TRACE;
2171
2286
void
2172
2287
trace_gc(Process *p, Eterm what)
2173
2288
{
 
2289
    ERTS_DECL_AM(bin_vheap_size);
 
2290
    ERTS_DECL_AM(bin_vheap_block_size);
 
2291
    ERTS_DECL_AM(bin_old_vheap_size);
 
2292
    ERTS_DECL_AM(bin_old_vheap_block_size);
 
2293
 
2174
2294
    ErlHeapFragment *bp = NULL;
2175
2295
    ErlOffHeap *off_heap;
2176
2296
    ERTS_TRACER_REF_TYPE tracer_ref = ERTS_NULL_TRACER_REF;     /* Initialized
2180
2300
    Eterm* hp;
2181
2301
    Eterm msg = NIL;
2182
2302
    Uint size;
 
2303
 
2183
2304
    Eterm tags[] = {
2184
2305
        am_old_heap_block_size,
2185
2306
        am_heap_block_size,
2187
2308
        am_recent_size,
2188
2309
        am_stack_size,
2189
2310
        am_old_heap_size,
2190
 
        am_heap_size
 
2311
        am_heap_size,
 
2312
        AM_bin_vheap_size,
 
2313
        AM_bin_vheap_block_size,
 
2314
        AM_bin_old_vheap_size,
 
2315
        AM_bin_old_vheap_block_size
2191
2316
    };
 
2317
 
2192
2318
    Uint values[] = {
2193
2319
        OLD_HEAP(p) ? OLD_HEND(p) - OLD_HEAP(p) : 0,
2194
2320
        HEAP_SIZE(p),
2196
2322
        HIGH_WATER(p) - HEAP_START(p),
2197
2323
        STACK_START(p) - p->stop,
2198
2324
        OLD_HEAP(p) ? OLD_HTOP(p) - OLD_HEAP(p) : 0,
2199
 
        HEAP_TOP(p) - HEAP_START(p)
 
2325
        HEAP_TOP(p) - HEAP_START(p),
 
2326
        MSO(p).overhead,
 
2327
        BIN_VHEAP_SZ(p),
 
2328
        BIN_OLD_VHEAP(p),
 
2329
        BIN_OLD_VHEAP_SZ(p)
2200
2330
    };
2201
 
    Eterm local_heap[(sizeof(values)/sizeof(Uint))
2202
 
                     *(2/*cons*/ + 3/*2-tuple*/ + BIG_UINT_HEAP_SIZE)
2203
 
                     + 5/*4-tuple */ + TS_HEAP_WORDS];
 
2331
#define LOCAL_HEAP_SIZE                                         \
 
2332
    (sizeof(values)/sizeof(Eterm)) *                            \
 
2333
        (2/*cons*/ + 3/*2-tuple*/ + BIG_UINT_HEAP_SIZE) +       \
 
2334
        5/*4-tuple */ + TS_HEAP_WORDS
 
2335
    DeclareTmpHeap(local_heap,LOCAL_HEAP_SIZE,p);
2204
2336
#ifdef DEBUG
2205
2337
    Eterm* limit;
2206
2338
#endif
2207
2339
 
2208
2340
    ASSERT(sizeof(values)/sizeof(Uint) == sizeof(tags)/sizeof(Eterm));
2209
2341
 
 
2342
    UseTmpHeap(LOCAL_HEAP_SIZE,p);
 
2343
 
2210
2344
    if (is_internal_port(p->tracer_proc)) {
2211
2345
        hp = local_heap;
2212
2346
#ifdef DEBUG
2237
2371
 
2238
2372
#ifdef DEBUG
2239
2373
    limit = hp + size;
2240
 
    ASSERT(size <= sizeof(local_heap)/sizeof(Eterm));
 
2374
    ASSERT(size <= LOCAL_HEAP_SIZE);
2241
2375
#endif
2242
2376
 
2243
2377
    msg = erts_bld_atom_uint_2tup_list(&hp,
2260
2394
    else
2261
2395
        ERTS_ENQ_TRACE_MSG(p->id, tracer_ref, msg, bp);
2262
2396
    erts_smp_mtx_unlock(&smq_mtx);
 
2397
    UnUseTmpHeap(LOCAL_HEAP_SIZE,p);
 
2398
#undef LOCAL_HEAP_SIZE
2263
2399
}
2264
2400
 
2265
2401
 
2450
2586
    Uint Ms, s, us;
2451
2587
 
2452
2588
#ifndef ERTS_SMP
2453
 
    Eterm local_heap[4 + 7];
 
2589
#define LOCAL_HEAP_SIZE (4 + 7)
 
2590
    DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
 
2591
    UseTmpHeapNoproc(LOCAL_HEAP_SIZE);
2454
2592
    hp = local_heap;
2455
2593
#else
2456
2594
    ErlHeapFragment *bp;
2483
2621
 
2484
2622
#ifndef ERTS_SMP
2485
2623
    profile_send(msg);
 
2624
    UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
2625
#undef LOCAL_HEAP_SIZE
2486
2626
#else
2487
2627
    enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SYSPROF, NIL, NIL, msg, bp);
2488
2628
#endif
2495
2635
    Eterm *hp, msg, timestamp;
2496
2636
    
2497
2637
#ifndef ERTS_SMP        
2498
 
    Eterm local_heap[4 + 7];
 
2638
#define LOCAL_HEAP_SIZE (4 + 7)
 
2639
    DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
 
2640
    UseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
2641
 
2499
2642
    hp = local_heap;
2500
2643
#else    
2501
2644
    ErlHeapFragment *bp;
2513
2656
    msg = TUPLE6(hp, am_profile, am_scheduler, scheduler_id, state, no_schedulers, timestamp); hp += 7;
2514
2657
#ifndef ERTS_SMP
2515
2658
    profile_send(msg);
 
2659
    UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
2660
#undef LOCAL_HEAP_SIZE
2516
2661
#else
2517
2662
    enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SYSPROF, NIL, NIL, msg, bp);
2518
2663
#endif
2543
2688
    Eterm* hp;
2544
2689
 
2545
2690
    if (is_internal_port(p->tracer_proc)) {
2546
 
        Eterm local_heap[5+6];
 
2691
#define LOCAL_HEAP_SIZE (5+6)
 
2692
        DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
 
2693
        UseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
2694
 
2547
2695
        hp = local_heap;
2548
2696
 
2549
2697
        mess = TUPLE5(hp, am_trace, calling_pid, am_open, p->id, drv_name);
2554
2702
        }
2555
2703
        /* No fake schedule */
2556
2704
        send_to_port(NULL, mess, &p->tracer_proc, &p->trace_flags);
 
2705
        UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
2706
#undef LOCAL_HEAP_SIZE
2557
2707
        erts_smp_mtx_unlock(&smq_mtx);
2558
2708
    } else {
2559
2709
        ErlHeapFragment *bp;
2597
2747
    Eterm mess;
2598
2748
    Eterm* hp;
2599
2749
 
 
2750
    ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(t_p) || erts_is_system_blocked(0));
 
2751
 
2600
2752
    if (is_internal_port(t_p->tracer_proc)) {
2601
 
        Eterm local_heap[5+5];
 
2753
#define LOCAL_HEAP_SIZE (5+5)
 
2754
        DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
 
2755
        UseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
2756
 
2602
2757
        hp = local_heap;
2603
2758
        mess = TUPLE4(hp, am_trace, t_p->id, what, data);
2604
2759
        hp += 5;
2608
2763
        }
2609
2764
        /* No fake schedule */
2610
2765
        send_to_port(NULL, mess, &t_p->tracer_proc, &t_p->trace_flags);
 
2766
        UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
2767
#undef LOCAL_HEAP_SIZE
2611
2768
        erts_smp_mtx_unlock(&smq_mtx);
2612
2769
    } else {
2613
2770
        ErlHeapFragment *bp;
2659
2816
    Eterm sched_id = am_undefined;
2660
2817
    
2661
2818
    if (is_internal_port(p->tracer_proc)) {
2662
 
        Eterm local_heap[5+6];
 
2819
#define LOCAL_HEAP_SIZE (5+6)
 
2820
        DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
 
2821
        UseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
2822
 
2663
2823
        hp = local_heap;
2664
2824
        
2665
2825
        if (IS_TRACED_FL(p, F_TRACE_SCHED_NO)) {
2685
2845
        
2686
2846
        /* No fake scheduling */
2687
2847
        send_to_port(NULL, mess, &p->tracer_proc, &p->trace_flags);
 
2848
        UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
2849
#undef LOCAL_HEAP_SIZE
2688
2850
        erts_smp_mtx_unlock(&smq_mtx);
2689
2851
    } else  {
2690
2852
        ErlHeapFragment *bp;
2735
2897
    Eterm count = make_small(0);
2736
2898
 
2737
2899
#ifndef ERTS_SMP
2738
 
    Eterm local_heap[4 + 6];
 
2900
#define LOCAL_HEAP_SIZE (4 + 6)
 
2901
 
 
2902
    DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
 
2903
    UseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
2904
 
2739
2905
    hp = local_heap;
2740
2906
    
2741
2907
#else
2756
2922
 
2757
2923
#ifndef ERTS_SMP
2758
2924
    profile_send(msg);
 
2925
    UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
2926
#undef LOCAL_HEAP_SIZE
2759
2927
#else
2760
2928
    enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SYSPROF, NIL, NIL, msg, bp);
2761
2929
#endif
2770
2938
    Eterm where = am_undefined;
2771
2939
 
2772
2940
#ifndef ERTS_SMP
2773
 
    Eterm local_heap[4 + 6 + 4];
 
2941
#define LOCAL_HEAP_SIZE (4 + 6 + 4)
 
2942
 
 
2943
    DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
 
2944
    UseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
2945
 
2774
2946
    hp = local_heap;
2775
2947
#else
2776
2948
    ErlHeapFragment *bp;
2803
2975
    msg = TUPLE5(hp, am_profile, p->id, status, where, timestamp); hp += 6;
2804
2976
#ifndef ERTS_SMP
2805
2977
    profile_send(msg);
 
2978
    UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
 
2979
#undef LOCAL_HEAP_SIZE
2806
2980
#else
2807
2981
    enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SYSPROF, NIL, NIL, msg, bp);
2808
2982
#endif