aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/beam/beam_debug.c26
-rw-r--r--erts/emulator/beam/copy.c12
-rw-r--r--erts/emulator/beam/global.h2
-rw-r--r--lib/kernel/src/erts_debug.erl8
4 files changed, 47 insertions, 1 deletions
diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c
index 40e3f4db4e..36f3cfabbc 100644
--- a/erts/emulator/beam/beam_debug.c
+++ b/erts/emulator/beam/beam_debug.c
@@ -89,6 +89,32 @@ erts_debug_size_shared_1(BIF_ALIST_1)
}
BIF_RETTYPE
+erts_debug_copy_shared_1(BIF_ALIST_1)
+{
+ Process* p = BIF_P;
+ Eterm term = BIF_ARG_1;
+ Uint size;
+ Eterm* hp;
+ Eterm copy;
+ shcopy_info info;
+#ifdef SHCOPY_DISABLE
+ extern int disable_copy_shared;
+#endif
+ INITIALIZE_INFO(info);
+
+ size = copy_shared_calculate(term, &info, 0);
+ if (size > 0) {
+ hp = HAlloc(p, size);
+ }
+ copy = copy_shared_perform(term, size, &info, &hp, &p->off_heap, 0);
+ DESTROY_INFO(info);
+#ifdef SHCOPY_DISABLE
+ disable_copy_shared = 0;
+#endif
+ BIF_RET(copy);
+}
+
+BIF_RETTYPE
erts_debug_breakpoint_2(BIF_ALIST_2)
{
Process* p = BIF_P;
diff --git a/erts/emulator/beam/copy.c b/erts/emulator/beam/copy.c
index b31e043f08..2566707717 100644
--- a/erts/emulator/beam/copy.c
+++ b/erts/emulator/beam/copy.c
@@ -901,6 +901,10 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
* Using an ESTACK but not very transparently; consider refactoring
*/
+#ifdef SHCOPY_DISABLE
+int disable_copy_shared = ERTS_SHCOPY_FLG_NONE;
+#endif
+
#define DECLARE_SHTABLE(s) \
DECLARE_ESTACK(s); \
Uint ESTK_CONCAT(s,_offset) = 0
@@ -1028,6 +1032,10 @@ Uint copy_shared_calculate(Eterm obj, shcopy_info *info, unsigned flags)
if (IS_CONST(obj))
return 0;
+#ifdef SHCOPY_DISABLE
+ flags |= disable_copy_shared;
+#endif
+
myself = erts_get_current_process();
if (myself == NULL || (flags & ERTS_SHCOPY_FLG_NONE))
return size_object(obj);
@@ -1276,6 +1284,10 @@ Uint copy_shared_perform(Eterm obj, Uint size, shcopy_info *info, Eterm** hpp, E
if (IS_CONST(obj))
return obj;
+#ifdef SHCOPY_DISABLE
+ flags |= disable_copy_shared;
+#endif
+
myself = erts_get_current_process();
if (myself == NULL || (flags & ERTS_SHCOPY_FLG_NONE))
return copy_struct(obj, size, hpp, off_heap);
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index a5e6ff6f1c..3e1f3664bc 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -1044,6 +1044,8 @@ void erl_error(char*, va_list);
#if defined(SHCOPY_SEND) \
|| defined(SHCOPY_SPAWN)
#define SHCOPY
+/* Use this if you want sharing-preserving copy to be initially disabled */
+#undef SHCOPY_DISABLE
/* Use this with care, it is *very* verbose! */
#undef SHCOPY_DEBUG
#endif
diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl
index 5e1cc09e7d..87f001fdf4 100644
--- a/lib/kernel/src/erts_debug.erl
+++ b/lib/kernel/src/erts_debug.erl
@@ -35,7 +35,7 @@
dump_monitors/1, dump_links/1, flat_size/1,
get_internal_state/1, instructions/0, lock_counters/1,
map_info/1, same/2, set_internal_state/2,
- size_shared/1]).
+ size_shared/1, copy_shared/1]).
-spec breakpoint(MFA, Flag) -> non_neg_integer() when
MFA :: {Module :: module(),
@@ -93,6 +93,12 @@ flat_size(_) ->
size_shared(_) ->
erlang:nif_error(undef).
+-spec copy_shared(Term) -> term() when
+ Term :: term().
+
+copy_shared(_) ->
+ erlang:nif_error(undef).
+
-spec get_internal_state(W) -> term() when
W :: reds_left | node_and_dist_references | monitoring_nodes
| next_pid | 'DbTable_words' | check_io_debug