--- erts/emulator/beam/erl_trace.c@@/OTP_R12B-3 2008-04-07 15:58:12.000000000 +0200 +++ erts/emulator/beam/erl_trace.c@@/main/release/r12b_patch/r12b_otp_7399/1 2008-06-12 11:17:55.000000000 +0200 @@ -32,6 +32,8 @@ #include "dist.h" #include "beam_bp.h" #include "error.h" +#include "erl_binary.h" +#include "erl_bits.h" #if 0 #define DEBUG_PRINTOUTS @@ -1445,7 +1447,9 @@ #ifdef ERTS_SMP Eterm tracee; #endif - + Eterm transformed_args[MAX_ARG]; + ErlSubBin sub_bin_heap; + ASSERT(tracer_pid); if (*tracer_pid == am_true) { /* Breakpoint trace enabled without specifying tracer => @@ -1488,6 +1492,42 @@ #endif } + /* + * Because of the delayed sub-binary creation optimization introduced in + * R12B, (at most) one of arguments can be a match context instead of + * a binary. Since we don't want to handle match contexts in utility functions + * such as size_object() and copy_struct(), we must make sure that we + * temporarily convert any match contexts to sub binaries. + */ + arity = mfa[2]; +#ifdef DEBUG + sub_bin_heap.thing_word = 0; +#endif + for (i = 0; i < arity; i++) { + Eterm arg = args[i]; + if (is_boxed(arg) && header_is_bin_matchstate(*boxed_val(arg))) { + ErlBinMatchState* ms = (ErlBinMatchState *) boxed_val(arg); + ErlBinMatchBuffer* mb = &ms->mb; + ErlSubBin* sb = &sub_bin_heap; + Uint bit_size; + + ASSERT(sub_bin_heap.thing_word == 0); /* At most one of match context */ + + bit_size = mb->size - mb->offset; + sb->thing_word = HEADER_SUB_BIN; + sb->size = BYTE_OFFSET(bit_size); + sb->bitsize = BIT_OFFSET(bit_size); + sb->offs = BYTE_OFFSET(mb->offset); + sb->bitoffs = BIT_OFFSET(mb->offset); + sb->is_writable = 0; + sb->orig = mb->orig; + + arg = make_binary(sb); + } + transformed_args[i] = arg; + } + args = transformed_args; + if (is_internal_port(*tracer_pid)) { Eterm local_heap[64+MAX_ARG]; hp = local_heap; @@ -1525,7 +1565,6 @@ /* BEGIN this code should be the same for port and pid trace */ return_flags = 0; - arity = mfa[2]; if (match_spec) { pam_result = erts_match_set_run(p, match_spec, args, arity, &return_flags); @@ -1601,7 +1640,7 @@ Eterm tpid; #endif unsigned size; - unsigned sizes[256]; + unsigned sizes[MAX_ARG]; unsigned pam_result_size = 0; int invalid_tracer; #ifdef DEBUG @@ -1652,7 +1691,6 @@ /* BEGIN this code should be the same for port and pid trace */ return_flags = 0; - arity = mfa[2]; if (match_spec) { pam_result = erts_match_set_run(p, match_spec, args, arity, &return_flags);