aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/hipe
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/hipe')
-rw-r--r--erts/emulator/hipe/TODO2
-rw-r--r--erts/emulator/hipe/elf64ppc.x2
-rw-r--r--erts/emulator/hipe/hipe_amd64.c118
-rw-r--r--erts/emulator/hipe/hipe_amd64.h2
-rw-r--r--erts/emulator/hipe/hipe_amd64.tab2
-rw-r--r--erts/emulator/hipe/hipe_amd64_asm.m424
-rw-r--r--erts/emulator/hipe/hipe_amd64_bifs.m45
-rw-r--r--erts/emulator/hipe/hipe_amd64_gc.h2
-rw-r--r--erts/emulator/hipe/hipe_amd64_glue.S4
-rw-r--r--erts/emulator/hipe/hipe_amd64_glue.h2
-rw-r--r--erts/emulator/hipe/hipe_amd64_primops.h2
-rw-r--r--erts/emulator/hipe/hipe_arch.h2
-rw-r--r--erts/emulator/hipe/hipe_arm.c2
-rw-r--r--erts/emulator/hipe/hipe_arm.h2
-rw-r--r--erts/emulator/hipe/hipe_arm.tab2
-rw-r--r--erts/emulator/hipe/hipe_arm_asm.m434
-rw-r--r--erts/emulator/hipe/hipe_arm_bifs.m435
-rw-r--r--erts/emulator/hipe/hipe_arm_gc.h2
-rw-r--r--erts/emulator/hipe/hipe_arm_glue.S6
-rw-r--r--erts/emulator/hipe/hipe_arm_glue.h2
-rw-r--r--erts/emulator/hipe/hipe_arm_primops.h2
-rw-r--r--erts/emulator/hipe/hipe_bif0.c92
-rw-r--r--erts/emulator/hipe/hipe_bif0.h2
-rw-r--r--erts/emulator/hipe/hipe_bif0.tab2
-rw-r--r--erts/emulator/hipe/hipe_bif1.c756
-rw-r--r--erts/emulator/hipe/hipe_bif1.h2
-rw-r--r--erts/emulator/hipe/hipe_bif1.tab23
-rw-r--r--erts/emulator/hipe/hipe_bif2.c2
-rw-r--r--erts/emulator/hipe/hipe_bif2.tab2
-rw-r--r--erts/emulator/hipe/hipe_bif64.c2
-rw-r--r--erts/emulator/hipe/hipe_bif64.h2
-rw-r--r--erts/emulator/hipe/hipe_bif64.tab2
-rw-r--r--erts/emulator/hipe/hipe_bif_list.m449
-rw-r--r--erts/emulator/hipe/hipe_debug.c4
-rw-r--r--erts/emulator/hipe/hipe_debug.h2
-rw-r--r--erts/emulator/hipe/hipe_gbif_list.h2
-rw-r--r--erts/emulator/hipe/hipe_gc.c159
-rw-r--r--erts/emulator/hipe/hipe_gc.h2
-rw-r--r--erts/emulator/hipe/hipe_mkliterals.c8
-rw-r--r--erts/emulator/hipe/hipe_mode_switch.c140
-rw-r--r--erts/emulator/hipe/hipe_mode_switch.h10
-rw-r--r--erts/emulator/hipe/hipe_native_bif.c52
-rw-r--r--erts/emulator/hipe/hipe_native_bif.h2
-rw-r--r--erts/emulator/hipe/hipe_ops.tab2
-rw-r--r--erts/emulator/hipe/hipe_ppc.c2
-rw-r--r--erts/emulator/hipe/hipe_ppc.h2
-rw-r--r--erts/emulator/hipe/hipe_ppc.tab2
-rw-r--r--erts/emulator/hipe/hipe_ppc64.tab2
-rw-r--r--erts/emulator/hipe/hipe_ppc_asm.m42
-rw-r--r--erts/emulator/hipe/hipe_ppc_bifs.m438
-rw-r--r--erts/emulator/hipe/hipe_ppc_gc.h2
-rw-r--r--erts/emulator/hipe/hipe_ppc_glue.S2
-rw-r--r--erts/emulator/hipe/hipe_ppc_glue.h2
-rw-r--r--erts/emulator/hipe/hipe_ppc_primops.h2
-rw-r--r--erts/emulator/hipe/hipe_primops.h2
-rw-r--r--erts/emulator/hipe/hipe_process.h8
-rw-r--r--erts/emulator/hipe/hipe_risc_gc.h15
-rw-r--r--erts/emulator/hipe/hipe_risc_glue.h2
-rw-r--r--erts/emulator/hipe/hipe_risc_stack.c2
-rw-r--r--erts/emulator/hipe/hipe_signal.h2
-rw-r--r--erts/emulator/hipe/hipe_sparc.c2
-rw-r--r--erts/emulator/hipe/hipe_sparc.h2
-rw-r--r--erts/emulator/hipe/hipe_sparc.tab2
-rw-r--r--erts/emulator/hipe/hipe_sparc_asm.m42
-rw-r--r--erts/emulator/hipe/hipe_sparc_bifs.m436
-rw-r--r--erts/emulator/hipe/hipe_sparc_gc.h2
-rw-r--r--erts/emulator/hipe/hipe_sparc_glue.S2
-rw-r--r--erts/emulator/hipe/hipe_sparc_glue.h2
-rw-r--r--erts/emulator/hipe/hipe_sparc_primops.h2
-rw-r--r--erts/emulator/hipe/hipe_stack.c2
-rw-r--r--erts/emulator/hipe/hipe_stack.h5
-rw-r--r--erts/emulator/hipe/hipe_x86.c6
-rw-r--r--erts/emulator/hipe/hipe_x86.h2
-rw-r--r--erts/emulator/hipe/hipe_x86.tab2
-rw-r--r--erts/emulator/hipe/hipe_x86_abi.txt2
-rw-r--r--erts/emulator/hipe/hipe_x86_asm.m42
-rw-r--r--erts/emulator/hipe/hipe_x86_bifs.m45
-rw-r--r--erts/emulator/hipe/hipe_x86_gc.h19
-rw-r--r--erts/emulator/hipe/hipe_x86_glue.S2
-rw-r--r--erts/emulator/hipe/hipe_x86_glue.h2
-rw-r--r--erts/emulator/hipe/hipe_x86_primops.h2
-rw-r--r--erts/emulator/hipe/hipe_x86_signal.c203
-rw-r--r--erts/emulator/hipe/hipe_x86_stack.c2
83 files changed, 717 insertions, 1251 deletions
diff --git a/erts/emulator/hipe/TODO b/erts/emulator/hipe/TODO
index dd9760ea1c..0c28616a30 100644
--- a/erts/emulator/hipe/TODO
+++ b/erts/emulator/hipe/TODO
@@ -1,7 +1,7 @@
%CopyrightBegin%
- Copyright Ericsson AB 2004-2009. All Rights Reserved.
+ Copyright Ericsson AB 2004-2016. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/elf64ppc.x b/erts/emulator/hipe/elf64ppc.x
index 3cd4010cb3..46d2632970 100644
--- a/erts/emulator/hipe/elf64ppc.x
+++ b/erts/emulator/hipe/elf64ppc.x
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_amd64.c b/erts/emulator/hipe/hipe_amd64.c
index 1bb336637d..62739d2a78 100644
--- a/erts/emulator/hipe/hipe_amd64.c
+++ b/erts/emulator/hipe/hipe_amd64.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -83,21 +83,6 @@ int hipe_patch_call(void *callAddress, void *destAddress, void *trampoline)
return 0;
}
-/*
- * Memory allocator for executable code.
- *
- * This is required on AMD64 because some Linux kernels
- * (including 2.6.10-rc1 and newer www.kernel.org ones)
- * default to non-executable memory mappings, causing
- * ordinary malloc() memory to be non-executable.
- *
- * Implementing this properly also allows us to ensure that
- * executable code ends up in the low 2GB of the address space,
- * as required by HiPE/AMD64's small code model.
- */
-static unsigned int code_bytes;
-static char *code_next;
-
#if 0 /* change to non-zero to get allocation statistics at exit() */
static unsigned int total_mapped, nr_joins, nr_splits, total_alloc, nr_allocs, nr_large, total_lost;
static unsigned int atexit_done;
@@ -121,101 +106,20 @@ static void atexit_alloc_code_stats(void)
#define ALLOC_CODE_STATS(X) do{}while(0)
#endif
-/* FreeBSD 6.1 breakage */
-#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-
-static int morecore(unsigned int alloc_bytes)
-{
- unsigned int map_bytes;
- char *map_hint, *map_start;
-
- /* Page-align the amount to allocate. */
- map_bytes = (alloc_bytes + 4095) & ~4095;
-
- /* Round up small allocations. */
- if (map_bytes < 1024*1024)
- map_bytes = 1024*1024;
- else
- ALLOC_CODE_STATS(++nr_large);
-
- /* Create a new memory mapping, ensuring it is executable
- and in the low 2GB of the address space. Also attempt
- to make it adjacent to the previous mapping. */
- map_hint = code_next + code_bytes;
-#if !defined(MAP_32BIT)
- /* FreeBSD doesn't have MAP_32BIT, and it doesn't respect
- a plain map_hint (returns high mappings even though the
- hint refers to a free area), so we have to use both map_hint
- and MAP_FIXED to get addresses below the 2GB boundary.
- This is even worse than the Linux/ppc64 case.
- Similarly, Solaris 10 doesn't have MAP_32BIT,
- and it doesn't respect a plain map_hint. */
- if (!map_hint) /* first call */
- map_hint = (char*)(512*1024*1024); /* 0.5GB */
-#endif
- if ((unsigned long)map_hint & 4095)
- abort();
- map_start = mmap(map_hint, map_bytes,
- PROT_EXEC|PROT_READ|PROT_WRITE,
- MAP_PRIVATE|MAP_ANONYMOUS
-#if defined(MAP_32BIT)
- |MAP_32BIT
-#elif defined(__FreeBSD__) || defined(__sun__)
- |MAP_FIXED
-#endif
- ,
- -1, 0);
- ALLOC_CODE_STATS(fprintf(stderr, "%s: mmap(%p,%u,...) == %p\r\n", __FUNCTION__, map_hint, map_bytes, map_start));
-#if !defined(MAP_32BIT)
- if (map_start != MAP_FAILED &&
- (((unsigned long)map_start + (map_bytes-1)) & ~0x7FFFFFFFUL)) {
- fprintf(stderr, "mmap with hint %p returned code memory %p\r\n", map_hint, map_start);
- abort();
- }
-#endif
- if (map_start == MAP_FAILED)
- return -1;
-
- ALLOC_CODE_STATS(total_mapped += map_bytes);
-
- /* Merge adjacent mappings, so the trailing portion of the previous
- mapping isn't lost. In practice this is quite successful. */
- if (map_start == map_hint) {
- ALLOC_CODE_STATS(++nr_joins);
- code_bytes += map_bytes;
-#if !defined(MAP_32BIT)
- if (!code_next) /* first call */
- code_next = map_start;
-#endif
- } else {
- ALLOC_CODE_STATS(++nr_splits);
- ALLOC_CODE_STATS(total_lost += code_bytes);
- code_next = map_start;
- code_bytes = map_bytes;
- }
-
- ALLOC_CODE_STATS(atexit_alloc_code_stats());
-
- return 0;
-}
-
+/*
+ * Memory allocator for executable code.
+ *
+ * We use a dedicated allocator for executable code (from OTP 19.0)
+ * to make sure the memory we get is executable (PROT_EXEC)
+ * and to ensure that executable code ends up in the low 2GB
+ * of the address space, as required by HiPE/AMD64's small code model.
+ */
static void *alloc_code(unsigned int alloc_bytes)
{
- void *res;
-
- /* Align function entries. */
- alloc_bytes = (alloc_bytes + 3) & ~3;
-
- if (code_bytes < alloc_bytes && morecore(alloc_bytes) != 0)
- return NULL;
ALLOC_CODE_STATS(++nr_allocs);
ALLOC_CODE_STATS(total_alloc += alloc_bytes);
- res = code_next;
- code_next += alloc_bytes;
- code_bytes -= alloc_bytes;
- return res;
+
+ return erts_alloc(ERTS_ALC_T_HIPE_EXEC, alloc_bytes);
}
void *hipe_alloc_code(Uint nrbytes, Eterm callees, Eterm *trampolines, Process *p)
diff --git a/erts/emulator/hipe/hipe_amd64.h b/erts/emulator/hipe/hipe_amd64.h
index 09b55a1243..750a26fcb9 100644
--- a/erts/emulator/hipe/hipe_amd64.h
+++ b/erts/emulator/hipe/hipe_amd64.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_amd64.tab b/erts/emulator/hipe/hipe_amd64.tab
index 70287034a0..e5ff31b985 100644
--- a/erts/emulator/hipe/hipe_amd64.tab
+++ b/erts/emulator/hipe/hipe_amd64.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2011. All Rights Reserved.
+# Copyright Ericsson AB 2004-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_amd64_asm.m4 b/erts/emulator/hipe/hipe_amd64_asm.m4
index ecb25ec5c8..409fd0ef89 100644
--- a/erts/emulator/hipe/hipe_amd64_asm.m4
+++ b/erts/emulator/hipe/hipe_amd64_asm.m4
@@ -2,7 +2,7 @@ changecom(`/*', `*/')dnl
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -121,6 +121,22 @@ define(NSP,%rsp)dnl
/*
+ * Debugging macros
+ *
+ * Keeps track of whether context has been saved in the debug build, allowing us
+ * to detect when the garbage collector is called when it shouldn't.
+ */
+`#ifdef DEBUG
+# define SET_GC_UNSAFE \
+ movq $1, P_GCUNSAFE(P)
+# define SET_GC_SAFE \
+ movq $0, P_GCUNSAFE(P)
+#else
+# define SET_GC_UNSAFE
+# define SET_GC_SAFE
+#endif'
+
+/*
* Context switching macros.
*/
`#define SWITCH_C_TO_ERLANG_QUICK \
@@ -133,12 +149,14 @@ define(NSP,%rsp)dnl
`#define SAVE_CACHED_STATE \
SAVE_HP; \
- SAVE_FCALLS'
+ SAVE_FCALLS; \
+ SET_GC_SAFE'
`#define RESTORE_CACHED_STATE \
RESTORE_HP; \
RESTORE_HEAP_LIMIT; \
- RESTORE_FCALLS'
+ RESTORE_FCALLS; \
+ SET_GC_UNSAFE'
`#define SWITCH_C_TO_ERLANG \
RESTORE_CACHED_STATE; \
diff --git a/erts/emulator/hipe/hipe_amd64_bifs.m4 b/erts/emulator/hipe/hipe_amd64_bifs.m4
index 602e71c195..21739726bb 100644
--- a/erts/emulator/hipe/hipe_amd64_bifs.m4
+++ b/erts/emulator/hipe/hipe_amd64_bifs.m4
@@ -2,7 +2,7 @@ changecom(`/*', `*/')dnl
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2012. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -600,10 +600,11 @@ noproc_primop_interface_0(nbif_handle_fp_exception, erts_restore_fpu)
define(gc_bif_interface_0,`nofail_primop_interface_0($1, $2)')
/*
- * Implement gc_bif_interface_N as standard_bif_interface_N (N=1,2).
+ * Implement gc_bif_interface_N as standard_bif_interface_N (N=1,2,3).
*/
define(gc_bif_interface_1,`standard_bif_interface_1($1, $2)')
define(gc_bif_interface_2,`standard_bif_interface_2($1, $2)')
+define(gc_bif_interface_3,`standard_bif_interface_3($1, $2)')
/*
* Implement gc_nofail_primop_interface_1 as nofail_primop_interface_1.
diff --git a/erts/emulator/hipe/hipe_amd64_gc.h b/erts/emulator/hipe/hipe_amd64_gc.h
index e7a156c910..6b95d54904 100644
--- a/erts/emulator/hipe/hipe_amd64_gc.h
+++ b/erts/emulator/hipe/hipe_amd64_gc.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_amd64_glue.S b/erts/emulator/hipe/hipe_amd64_glue.S
index 6fb93bce53..f3404888d5 100644
--- a/erts/emulator/hipe/hipe_amd64_glue.S
+++ b/erts/emulator/hipe/hipe_amd64_glue.S
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -94,6 +94,7 @@ ASYM(nbif_return):
.nosave_exit:
/* switch to C stack */
SWITCH_ERLANG_TO_C_QUICK
+ SET_GC_SAFE
/* restore C callee-save registers, drop frame, return */
movq (%rsp), %rbp # kills P
movq 8(%rsp), %rbx
@@ -398,6 +399,7 @@ nbif_4_simple_exception:
movl %eax, P_NARITY(P) # Note: narity is a 32-bit field
/* find and prepare to invoke the handler */
SWITCH_ERLANG_TO_C_QUICK # The cached state is clean and need not be saved.
+ SET_GC_SAFE
movq P, %rdi
call CSYM(hipe_handle_exception) # Note: hipe_handle_exception() conses
SWITCH_C_TO_ERLANG # %rsp updated by hipe_find_handler()
diff --git a/erts/emulator/hipe/hipe_amd64_glue.h b/erts/emulator/hipe/hipe_amd64_glue.h
index e54b8b3a3f..089658f4b5 100644
--- a/erts/emulator/hipe/hipe_amd64_glue.h
+++ b/erts/emulator/hipe/hipe_amd64_glue.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_amd64_primops.h b/erts/emulator/hipe/hipe_amd64_primops.h
index 23d8202e46..94c39a9433 100644
--- a/erts/emulator/hipe/hipe_amd64_primops.h
+++ b/erts/emulator/hipe/hipe_amd64_primops.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_arch.h b/erts/emulator/hipe/hipe_arch.h
index 21dabc7cb6..6f959815bb 100644
--- a/erts/emulator/hipe/hipe_arch.h
+++ b/erts/emulator/hipe/hipe_arch.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2003-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2003-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_arm.c b/erts/emulator/hipe/hipe_arm.c
index 01512e9aa1..f8ef468341 100644
--- a/erts/emulator/hipe/hipe_arm.c
+++ b/erts/emulator/hipe/hipe_arm.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2012. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_arm.h b/erts/emulator/hipe/hipe_arm.h
index a0e07cd6ce..b5fe6317c9 100644
--- a/erts/emulator/hipe/hipe_arm.h
+++ b/erts/emulator/hipe/hipe_arm.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_arm.tab b/erts/emulator/hipe/hipe_arm.tab
index bcac2cd79d..152319edbd 100644
--- a/erts/emulator/hipe/hipe_arm.tab
+++ b/erts/emulator/hipe/hipe_arm.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2011. All Rights Reserved.
+# Copyright Ericsson AB 2005-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_arm_asm.m4 b/erts/emulator/hipe/hipe_arm_asm.m4
index 8ce8600f97..68a6faa70b 100644
--- a/erts/emulator/hipe/hipe_arm_asm.m4
+++ b/erts/emulator/hipe/hipe_arm_asm.m4
@@ -2,7 +2,7 @@ changecom(`/*', `*/')dnl
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,6 +48,24 @@ define(NR_ARG_REGS,3)dnl admissible values are 0 to 6, inclusive
`#define TEMP_LR r8'
/*
+ * Debugging macros
+ *
+ * Keeps track of whether context has been saved in the debug build, allowing us
+ * to detect when the garbage collector is called when it shouldn't.
+ */
+`#ifdef DEBUG
+# define SET_GC_UNSAFE(SCRATCH) \
+ mov SCRATCH, #1; \
+ str SCRATCH, [P, #P_GCUNSAFE]
+# define SET_GC_SAFE(SCRATCH) \
+ mov SCRATCH, #0; \
+ str SCRATCH, [P, #P_GCUNSAFE]
+#else
+# define SET_GC_UNSAFE(SCRATCH)
+# define SET_GC_SAFE(SCRATCH)
+#endif'
+
+/*
* Context switching macros.
*
* RESTORE_CONTEXT and RESTORE_CONTEXT_QUICK do not affect
@@ -59,12 +77,14 @@ define(NR_ARG_REGS,3)dnl admissible values are 0 to 6, inclusive
`#define RESTORE_CONTEXT_QUICK \
mov lr, TEMP_LR'
-`#define SAVE_CACHED_STATE \
- str HP, [P, #P_HP]; \
- str NSP, [P, #P_NSP]'
+`#define SAVE_CACHED_STATE \
+ str HP, [P, #P_HP]; \
+ str NSP, [P, #P_NSP]; \
+ SET_GC_SAFE(HP)'
-`#define RESTORE_CACHED_STATE \
- ldr HP, [P, #P_HP]; \
+`#define RESTORE_CACHED_STATE \
+ SET_GC_UNSAFE(HP); \
+ ldr HP, [P, #P_HP]; \
ldr NSP, [P, #P_NSP]'
`#define SAVE_CONTEXT_BIF \
@@ -75,12 +95,14 @@ define(NR_ARG_REGS,3)dnl admissible values are 0 to 6, inclusive
ldr HP, [P, #P_HP]'
`#define SAVE_CONTEXT_GC \
+ SET_GC_SAFE(TEMP_LR); \
mov TEMP_LR, lr; \
str lr, [P, #P_NRA]; \
str NSP, [P, #P_NSP]; \
str HP, [P, #P_HP]'
`#define RESTORE_CONTEXT_GC \
+ SET_GC_UNSAFE(HP); \
ldr HP, [P, #P_HP]'
/*
diff --git a/erts/emulator/hipe/hipe_arm_bifs.m4 b/erts/emulator/hipe/hipe_arm_bifs.m4
index 3efe961964..d7a2fec04a 100644
--- a/erts/emulator/hipe/hipe_arm_bifs.m4
+++ b/erts/emulator/hipe/hipe_arm_bifs.m4
@@ -2,7 +2,7 @@ changecom(`/*', `*/')dnl
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2012. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -198,8 +198,9 @@ $1:
* gc_bif_interface_0(nbif_name, cbif_name)
* gc_bif_interface_1(nbif_name, cbif_name)
* gc_bif_interface_2(nbif_name, cbif_name)
+ * gc_bif_interface_3(nbif_name, cbif_name)
*
- * Generate native interface for a BIF with 0-2 parameters and
+ * Generate native interface for a BIF with 0-3 parameters and
* standard failure mode.
* The BIF may do a GC.
*/
@@ -279,6 +280,36 @@ $1:
.type $1, %function
#endif')
+define(gc_bif_interface_3,
+`
+#ifndef HAVE_$1
+#`define' HAVE_$1
+ .global $1
+$1:
+ /* Set up C argument registers. */
+ mov r0, P
+ NBIF_ARG(r1,3,0)
+ NBIF_ARG(r2,3,1)
+ NBIF_ARG(r3,3,2)
+
+ /* Save caller-save registers and call the C function. */
+ SAVE_CONTEXT_GC
+ str r1, [r0, #P_ARG0] /* Store BIF__ARGS in def_arg_reg[] */
+ str r2, [r0, #P_ARG1]
+ str r3, [r0, #P_ARG2]
+ add r1, r0, #P_ARG0
+ CALL_BIF($2)
+ TEST_GOT_MBUF(3)
+
+ /* Restore registers. Check for exception. */
+ cmp r0, #THE_NON_VALUE
+ RESTORE_CONTEXT_GC
+ beq nbif_3_simple_exception
+ NBIF_RET(3)
+ .size $1, .-$1
+ .type $1, %function
+#endif')
+
/*
* gc_nofail_primop_interface_1(nbif_name, cbif_name)
*
diff --git a/erts/emulator/hipe/hipe_arm_gc.h b/erts/emulator/hipe/hipe_arm_gc.h
index dfffd6c630..e8eb900978 100644
--- a/erts/emulator/hipe/hipe_arm_gc.h
+++ b/erts/emulator/hipe/hipe_arm_gc.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_arm_glue.S b/erts/emulator/hipe/hipe_arm_glue.S
index e4ce9b75ef..5b7f8ad52d 100644
--- a/erts/emulator/hipe/hipe_arm_glue.S
+++ b/erts/emulator/hipe/hipe_arm_glue.S
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -342,6 +342,7 @@ nbif_4_gc_after_bif:
str r1, [P, #P_NARITY]
str TEMP_LR, [P, #P_NRA]
str NSP, [P, #P_NSP]
+ SET_GC_SAFE(TEMP_LR)
mov TEMP_LR, lr
mov r3, #0 /* Pass 0 in arity */
mov r2, #0 /* Pass NULL in regs */
@@ -349,6 +350,7 @@ nbif_4_gc_after_bif:
mov r0, P
bl erts_gc_after_bif_call
mov lr, TEMP_LR
+ SET_GC_UNSAFE(TEMP_LR)
ldr TEMP_LR, [P, #P_NRA]
mov r1, #0
str r1, [P, #P_NARITY]
@@ -404,6 +406,7 @@ nbif_4_simple_exception:
str NSP, [P, #P_NSP]
str TEMP_LR, [P, #P_NRA]
str r1, [P, #P_NARITY]
+ SET_GC_SAFE(r0)
/* find and prepare to invoke the handler */
mov r0, P
bl hipe_handle_exception /* Note: hipe_handle_exception() conses */
@@ -423,6 +426,7 @@ nbif_4_simple_exception:
str NSP, [P, #P_NSP]
str r1, [P, #P_NARITY]
str TEMP_LR, [P, #P_NRA]
+ SET_GC_SAFE(NSP)
b .nosave_exit
/*
diff --git a/erts/emulator/hipe/hipe_arm_glue.h b/erts/emulator/hipe/hipe_arm_glue.h
index 39bc27ec5f..dffc5aef03 100644
--- a/erts/emulator/hipe/hipe_arm_glue.h
+++ b/erts/emulator/hipe/hipe_arm_glue.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_arm_primops.h b/erts/emulator/hipe/hipe_arm_primops.h
index 0e8f84dfb9..c080b67699 100644
--- a/erts/emulator/hipe/hipe_arm_primops.h
+++ b/erts/emulator/hipe/hipe_arm_primops.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_bif0.c b/erts/emulator/hipe/hipe_bif0.c
index c838150db8..c0ebc34771 100644
--- a/erts/emulator/hipe/hipe_bif0.c
+++ b/erts/emulator/hipe/hipe_bif0.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2013. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2017. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -418,6 +418,8 @@ BIF_RETTYPE hipe_bifs_enter_code_2(BIF_ALIST_2)
BIF_RET(make_tuple(hp));
}
+#define IS_POWER_OF_TWO(Val) (((Val) > 0) && (((Val) & ((Val)-1)) == 0))
+
/*
* Allocate memory for arbitrary non-Erlang data.
*/
@@ -427,16 +429,18 @@ BIF_RETTYPE hipe_bifs_alloc_data_2(BIF_ALIST_2)
void *block;
if (is_not_small(BIF_ARG_1) || is_not_small(BIF_ARG_2) ||
- (align = unsigned_val(BIF_ARG_1),
- align != sizeof(long) && align != sizeof(double)))
+ (align = unsigned_val(BIF_ARG_1), !IS_POWER_OF_TWO(align)))
BIF_ERROR(BIF_P, BADARG);
nrbytes = unsigned_val(BIF_ARG_2);
if (nrbytes == 0)
BIF_RET(make_small(0));
block = erts_alloc(ERTS_ALC_T_HIPE, nrbytes);
- if ((unsigned long)block & (align-1))
+ if ((unsigned long)block & (align-1)) {
fprintf(stderr, "%s: erts_alloc(%lu) returned %p which is not %lu-byte aligned\r\n",
__FUNCTION__, (unsigned long)nrbytes, block, (unsigned long)align);
+ erts_free(ERTS_ALC_T_HIPE, block);
+ BIF_ERROR(BIF_P, EXC_NOTSUP);
+ }
BIF_RET(address_to_term(block, BIF_P));
}
@@ -488,7 +492,7 @@ static void *const_term_alloc(void *tmpl)
alloc_size = size + (offsetof(struct const_term, mem)/sizeof(Eterm));
hipe_constants_size += alloc_size;
- p = (struct const_term*)erts_alloc(ERTS_ALC_T_HIPE, alloc_size * sizeof(Eterm));
+ p = (struct const_term*)erts_alloc(ERTS_ALC_T_LITERAL, alloc_size * sizeof(Eterm));
/* I have absolutely no idea if having a private 'off_heap'
works or not. _Some_ off_heap object is required for
@@ -497,6 +501,8 @@ static void *const_term_alloc(void *tmpl)
hp = &p->mem[0];
p->val = copy_struct(obj, size, &hp, &const_term_table_off_heap);
+ erts_set_literal_tag(&p->val, &p->mem[0], size);
+
return &p->bucket;
}
@@ -507,6 +513,9 @@ static void init_const_term_table(void)
f.cmp = (HCMP_FUN) const_term_cmp;
f.alloc = (HALLOC_FUN) const_term_alloc;
f.free = (HFREE_FUN) NULL;
+ f.meta_alloc = (HMALLOC_FUN) erts_alloc;
+ f.meta_free = (HMFREE_FUN) erts_free;
+ f.meta_print = (HMPRINT_FUN) erts_print;
hash_init(ERTS_ALC_T_HIPE, &const_term_table, "const_term_table", 97, f);
}
@@ -528,13 +537,13 @@ BIF_RETTYPE hipe_bifs_merge_term_1(BIF_ALIST_1)
BIF_RET(val);
}
-struct mfa {
+struct mfa_t {
Eterm mod;
Eterm fun;
Uint ari;
};
-static int term_to_mfa(Eterm term, struct mfa *mfa)
+static int term_to_mfa(Eterm term, struct mfa_t *mfa)
{
Eterm mod, fun, a;
Uint ari;
@@ -574,15 +583,15 @@ static void print_mfa(Eterm mod, Eterm fun, unsigned int ari)
static Uint *hipe_find_emu_address(Eterm mod, Eterm name, unsigned int arity)
{
Module *modp;
- Uint *code_base;
+ BeamCodeHeader* code_hdr;
int i, n;
modp = erts_get_module(mod, erts_active_code_ix());
- if (modp == NULL || (code_base = modp->curr.code) == NULL)
+ if (modp == NULL || (code_hdr = modp->curr.code_hdr) == NULL)
return NULL;
- n = code_base[MI_NUM_FUNCTIONS];
+ n = code_hdr->num_functions;
for (i = 0; i < n; ++i) {
- Uint *code_ptr = (Uint*)code_base[MI_FUNCTIONS+i];
+ Uint *code_ptr = (Uint*)code_hdr->functions[i];
ASSERT(code_ptr[0] == BeamOpCode(op_i_func_info_IaaI));
if (code_ptr[3] == name && code_ptr[4] == arity)
return code_ptr+5;
@@ -592,7 +601,7 @@ static Uint *hipe_find_emu_address(Eterm mod, Eterm name, unsigned int arity)
Uint *hipe_bifs_find_pc_from_mfa(Eterm term)
{
- struct mfa mfa;
+ struct mfa_t mfa;
if (!term_to_mfa(term, &mfa))
return NULL;
@@ -612,7 +621,7 @@ BIF_RETTYPE hipe_bifs_set_native_address_3(BIF_ALIST_3)
Eterm *pc;
void *address;
int is_closure;
- struct mfa mfa;
+ struct mfa_t mfa;
switch (BIF_ARG_3) {
case am_false:
@@ -688,7 +697,7 @@ static struct nbif nbifs[BIF_SIZE] = {
#undef BIF_LIST
};
-#define NBIF_HASH(m,f,a) ((m)*(f)+(a))
+#define NBIF_HASH(m,f,a) (atom_val(m) ^ atom_val(f) ^ (a))
static Hash nbif_table;
static HashValue nbif_hash(struct nbif *x)
@@ -715,6 +724,9 @@ static void init_nbif_table(void)
f.cmp = (HCMP_FUN) nbif_cmp;
f.alloc = (HALLOC_FUN) nbif_alloc;
f.free = NULL;
+ f.meta_alloc = (HMALLOC_FUN) erts_alloc;
+ f.meta_free = (HMFREE_FUN) erts_free;
+ f.meta_print = (HMPRINT_FUN) erts_print;
hash_init(ERTS_ALC_T_NBIF_TABLE, &nbif_table, "nbif_table", 500, f);
@@ -808,6 +820,9 @@ static void init_primop_table(void)
f.cmp = (HCMP_FUN) primop_cmp;
f.alloc = (HALLOC_FUN) primop_alloc;
f.free = NULL;
+ f.meta_alloc = (HMALLOC_FUN) erts_alloc;
+ f.meta_free = (HMFREE_FUN) erts_free;
+ f.meta_print = (HMPRINT_FUN) erts_print;
hash_init(ERTS_ALC_T_HIPE, &primop_table, "primop_table", 50, f);
@@ -977,7 +992,7 @@ BIF_RETTYPE hipe_bifs_set_native_address_in_fe_2(BIF_ALIST_2)
BIF_ERROR(BIF_P, BADARG);
fe->native_address = native_address;
- if (erts_refc_dectest(&fe->refc, 0) == 0)
+ if (erts_smp_refc_dectest(&fe->refc, 0) == 0)
erts_erase_fun_entry(fe);
BIF_RET(am_true);
}
@@ -1048,7 +1063,7 @@ static inline void hipe_mfa_info_table_rwunlock(void)
erts_smp_rwmtx_rwunlock(&hipe_mfa_info_table.lock);
}
-#define HIPE_MFA_HASH(M,F,A) ((M) * (F) + (A))
+#define HIPE_MFA_HASH(M,F,A) (atom_val(M) ^ atom_val(F) ^ (A))
static struct hipe_mfa_info **hipe_mfa_info_table_alloc_bucket(unsigned int size)
{
@@ -1129,10 +1144,13 @@ static inline struct hipe_mfa_info *hipe_mfa_info_table_get_locked(Eterm m, Eter
h = HIPE_MFA_HASH(m, f, arity);
i = h & hipe_mfa_info_table.mask;
p = hipe_mfa_info_table.bucket[i];
- for (; p; p = p->bucket.next)
- /* XXX: do we want to compare p->bucket.hvalue as well? */
- if (p->m == m && p->f == f && p->a == arity)
- return p;
+ for (; p; p = p->bucket.next) {
+ if (p->bucket.hvalue == h) {
+ if (p->m == m && p->f == f && p->a == arity)
+ return p;
+ }
+ else ASSERT(!(p->m == m && p->f == f && p->a == arity));
+ }
return NULL;
}
@@ -1156,10 +1174,13 @@ static struct hipe_mfa_info *hipe_mfa_info_table_put_rwlocked(Eterm m, Eterm f,
h = HIPE_MFA_HASH(m, f, arity);
i = h & hipe_mfa_info_table.mask;
p = hipe_mfa_info_table.bucket[i];
- for (; p; p = p->bucket.next)
- /* XXX: do we want to compare p->bucket.hvalue as well? */
- if (p->m == m && p->f == f && p->a == arity)
- return p;
+ for (; p; p = p->bucket.next) {
+ if (p->bucket.hvalue == h) {
+ if (p->m == m && p->f == f && p->a == arity)
+ return p;
+ }
+ else ASSERT(!(p->m == m && p->f == f && p->a == arity));
+ }
p = hipe_mfa_info_table_alloc(m, f, arity);
p->bucket.hvalue = h;
p->bucket.next = hipe_mfa_info_table.bucket[i];
@@ -1214,7 +1235,7 @@ void hipe_mfa_set_trampoline(Eterm m, Eterm f, unsigned int arity, void *trampol
BIF_RETTYPE hipe_bifs_set_funinfo_native_address_3(BIF_ALIST_3)
{
- struct mfa mfa;
+ struct mfa_t mfa;
void *address;
int is_exported;
@@ -1236,7 +1257,7 @@ BIF_RETTYPE hipe_bifs_set_funinfo_native_address_3(BIF_ALIST_3)
BIF_RETTYPE hipe_bifs_invalidate_funinfo_native_addresses_1(BIF_ALIST_1)
{
Eterm lst;
- struct mfa mfa;
+ struct mfa_t mfa;
struct hipe_mfa_info *p;
hipe_mfa_info_table_rwlock();
@@ -1405,7 +1426,7 @@ BIF_RETTYPE hipe_find_na_or_make_stub(BIF_ALIST_3)
BIF_RETTYPE hipe_bifs_find_na_or_make_stub_2(BIF_ALIST_2)
{
- struct mfa mfa;
+ struct mfa_t mfa;
void *address;
int is_remote;
@@ -1455,6 +1476,10 @@ int hipe_find_mfa_from_ra(const void *ra, Eterm *m, Eterm *f, unsigned int *a)
struct hipe_mfa_info **bucket;
unsigned int i, nrbuckets;
+ if (hipe_is_ra_mode_switch(ra)) {
+ return 0;
+ }
+
/* Note about locking: the table is only updated from the
loader, which runs with the rest of the system suspended. */
/* XXX: alas not true; see comment at hipe_mfa_info_table.lock */
@@ -1507,9 +1532,9 @@ struct ref {
*/
BIF_RETTYPE hipe_bifs_add_ref_2(BIF_ALIST_2)
{
- struct mfa callee;
+ struct mfa_t callee;
Eterm *tuple;
- struct mfa caller;
+ struct mfa_t caller;
void *address;
void *trampoline;
unsigned int flags;
@@ -1586,7 +1611,7 @@ BIF_RETTYPE hipe_bifs_add_ref_2(BIF_ALIST_2)
*/
BIF_RETTYPE hipe_bifs_mark_referred_from_1(BIF_ALIST_1) /* get_refs_from */
{
- struct mfa mfa;
+ struct mfa_t mfa;
const struct hipe_mfa_info *p;
struct ref *ref;
@@ -1638,7 +1663,7 @@ static void hipe_purge_all_refs(void)
BIF_RETTYPE hipe_bifs_remove_refs_from_1(BIF_ALIST_1)
{
- struct mfa mfa;
+ struct mfa_t mfa;
struct hipe_mfa_info *caller_mfa, *callee_mfa;
struct hipe_mfa_info_list *refers_to, *tmp_refers_to;
struct ref **prev, *ref;
@@ -1692,7 +1717,7 @@ BIF_RETTYPE hipe_bifs_remove_refs_from_1(BIF_ALIST_1)
*/
BIF_RETTYPE hipe_bifs_redirect_referred_from_1(BIF_ALIST_1)
{
- struct mfa mfa;
+ struct mfa_t mfa;
struct hipe_mfa_info *p;
struct ref **prev, *ref;
int is_remote, res;
@@ -1826,6 +1851,9 @@ static void init_modinfo_table(void)
f.cmp = (HCMP_FUN) modinfo_cmp;
f.alloc = (HALLOC_FUN) modinfo_alloc;
f.free = (HFREE_FUN) NULL;
+ f.meta_alloc = (HMALLOC_FUN) erts_alloc;
+ f.meta_free = (HMFREE_FUN) erts_free;
+ f.meta_print = (HMPRINT_FUN) erts_print;
hash_init(ERTS_ALC_T_HIPE, &modinfo_table, "modinfo_table", 11, f);
}
diff --git a/erts/emulator/hipe/hipe_bif0.h b/erts/emulator/hipe/hipe_bif0.h
index 5527c6c3ed..c9a8216368 100644
--- a/erts/emulator/hipe/hipe_bif0.h
+++ b/erts/emulator/hipe/hipe_bif0.h
@@ -2,7 +2,7 @@
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_bif0.tab b/erts/emulator/hipe/hipe_bif0.tab
index 5ce254314a..99237aae05 100644
--- a/erts/emulator/hipe/hipe_bif0.tab
+++ b/erts/emulator/hipe/hipe_bif0.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2011. All Rights Reserved.
+# Copyright Ericsson AB 2001-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_bif1.c b/erts/emulator/hipe/hipe_bif1.c
index a2682992a4..5e127755c6 100644
--- a/erts/emulator/hipe/hipe_bif1.c
+++ b/erts/emulator/hipe/hipe_bif1.c
@@ -2,7 +2,7 @@
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2012. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -124,757 +124,3 @@ BIF_RETTYPE hipe_bifs_trap_count_clear_0(BIF_ALIST_0)
hipe_trap_count = 0;
BIF_RET(make_small(count));
}
-
-/*****************************************************************************
- * BIFs for benchmarking. These only do useful things if
- * __BENCHMARK__ is defined in beam/benchmark.h. For documentation
- * about how to add new counters or maintain the existing counters,
- * see benchmark.h.
- *
- * If benchmarking is not enabled all BIFs will return false. If the
- * required benchmark feature is not enabled, the counter will remain
- * zero.
- *
- * process_info/0 -> { Number of live processes,
- * Processes spawned in total }
- *
- * Live processes are increased when a new process is created, and
- * decreased when a process dies. Processes spawned is increased
- * when a process is created.
- *
- *
- * process_info_clear/0 -> true
- *
- * Will reset the processes spawned-counters to zero. If this is
- * done at some improper time, live processes may become a negative
- * value. This is not a problem in itself, just as long as you know
- * about it.
- *
- *
- * message_info/0 -> { Messages sent,
- * Messages copied,
- * Ego messages (sender = receiver),
- * Words sent,
- * Words copied,
- * Words preallocated }
- *
- * Counting the words sent in a shared heap system will affect
- * runtime performance since it means that we have to calculate the
- * size of the mesage. With private heaps, this is done anyway and
- * will not affect performance.
- *
- *
- * message_info_clear/0 -> true
- *
- * Reset the message counters to zero.
- *
- *
- * message_sizes/0 -> true
- *
- * Displays a text-mode bar diagram with message sizes. There are no
- * guaranties that this is printed in a way the Erlang system is
- * supposed to print things.
- *
- *
- * gc_info/0 -> { Minor collections,
- * Major collections,
- * Used heap,
- * Allocated heap,
- * Max used heap,
- * Max allocated heap }
- *
- * Information about private heap garbage collections. Number of
- * minor and major collections, how much heap is used and allocated
- * and how much heap has been in use and allocated at most since the
- * counters were reset.
- *
- *
- * shared_gc_info/0 -> { Minor collections of the shared heap,
- * Major collections of the shared heap,
- * Used shared heap,
- * Allocated shared heap,
- * Max used shared heap,
- * Max allocated shared heap }
- *
- * The same as above, but for the shared heap / message area. Note,
- * that in a shared heap system the max used heap and max allocated
- * heap are mostly the same, since the heap allways is filled before
- * a garbage collection, and most garbage collections do not enlarge
- * the heap. The private heap numbers are much more interesting.
- *
- *
- * incremental_gc_info/0 -> { Complete minor GC cycles,
- * Complete major GC cycles,
- * Minor GC stages,
- * Major GC stages }
- *
- *
- * gc_info_clear/0 -> true
- *
- * Reset counters for both private and shared garbage collection.
- *
- *
- * BM Timers
- * ---------
- *
- * All timers returns tuples of the kind: { Minutes, Seconds, Milliseconds }
- * except for the max times in garbage collection where times are normally
- * small. The tuple is therefor: { Seconds, Milliseconds, Microseconds }
- *
- * system_timer/0 -> Mutator time
- *
- * This timer is not a real-time clock, it only runs when a process
- * is scheduled to run. You can not find out the accual time a
- * program has taken to run using this timer.
- *
- *
- * system_timer_clear/0 -> true
- *
- * Reset system timer to zero.
- *
- *
- * send_timer/0 -> { Send time,
- * Copy time,
- * Size time }
- *
- * Time spent in sending messages. The copy time and size time are
- * only active if the copying is needed in send. Copying of data
- * into ETS-tables etc is not timed with this timer.
- *
- *
- * send_timer_clear/0 -> true
- *
- * Reset send timers to zero.
- *
- *
- * gc_timer/0 -> { Time in minor collection,
- * Time in major collection,
- * Max time in minor collection (�s),
- * Max time in major collection (�s) }
- *
- * Total time spent in garbage collection of the private heaps. The
- * max times are for one separate collection.
- *
- *
- * shared_gc_timer/0 -> { Time in minor collection,
- * Time in major collection,
- * Max time in minor collection (�s),
- * Max time in major collection (�s) }
- *
- * Total time spent in garbage collection of the shared heap /
- * message area. The max times are for one separate collection.
- *
- *
- * gc_timer_clear/0 -> true
- *
- * Reset private and shared garbage collection timers to zero. Note,
- * that the max-times are also reset.
- *
- *
- * misc_timer/0 -> { Misc 0, Misc 1, Misc 2 }
- *
- * Timers for debug purposes. In a normal system, these timers are
- * never used. Add these timers at places where you want to time
- * something not covered here. Use BM_SWAP_TIMER(from,to) to start
- * one of the misc timers.
- *
- * ... code timed by the system timer ...
- * BM_SWAP_TIMER(system,misc1);
- * ... code we want to time ...
- * BM_SWAP_TIMER(misc1,system);
- * ... back on system time ...
- *
- *
- * misc_timer_clear/0 -> true
- *
- * Reset misc timers to zero.
- */
-
-BIF_RETTYPE hipe_bifs_process_info_0(BIF_ALIST_0)
-{
-#ifdef __BENCHMARK__
-#ifndef BM_COUNTERS
- Uint processes_busy = 0;
- Uint processes_spawned = 0;
-#endif
- Eterm *hp;
-
- hp = HAlloc(BIF_P, 3);
- BIF_RET(TUPLE2(hp,
- make_small(processes_busy),
- make_small(processes_spawned)));
-#else
- BIF_RET(am_false);
-#endif
-}
-
-BIF_RETTYPE hipe_bifs_process_info_clear_0(BIF_ALIST_0)
-{
-#ifdef __BENCHMARK__
-#ifdef BM_COUNTERS
- processes_spawned = 0;
-#endif
- BIF_RET(am_true);
-#else
- BIF_RET(am_false);
-#endif
-}
-
-BIF_RETTYPE hipe_bifs_message_info_0(BIF_ALIST_0)
-{
-#ifdef __BENCHMARK__
- Eterm *hp;
-#ifndef BM_COUNTERS
- unsigned long messages_sent = 0;
- unsigned long messages_copied = 0;
- unsigned long messages_ego = 0;
-#endif
-#ifndef BM_MESSAGE_SIZES
- unsigned long words_sent = 0;
- unsigned long words_copied = 0;
- unsigned long words_prealloc = 0;
-#endif
-
- hp = HAlloc(BIF_P, 7);
- BIF_RET(TUPLE6(hp,
- make_small(messages_sent),
- make_small(messages_copied),
- make_small(messages_ego),
- make_small(words_sent),
- make_small(words_copied),
- make_small(words_prealloc)));
-#else
- BIF_RET(am_false);
-#endif
-}
-
-BIF_RETTYPE hipe_bifs_message_info_clear_0(BIF_ALIST_0)
-{
-#ifdef __BENCHMARK__
-#ifdef BM_COUNTERS
- messages_sent = 0;
- messages_copied = 0;
- messages_ego = 0;
-#endif
-#ifdef BM_MESSAGE_SIZES
- words_sent = 0;
- words_copied = 0;
- words_prealloc = 0;
- {
- int i;
- for (i = 0; i < 1000; i++)
- message_sizes[i] = 0;
- }
-#endif
- BIF_RET(am_true);
-#else
- BIF_RET(am_false);
-#endif
-}
-
-BIF_RETTYPE hipe_bifs_message_sizes_0(BIF_ALIST_0)
-{
-#ifdef BM_MESSAGE_SIZES
- int i, j, max = 0;
- int tmp[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
-
- for (i = 0; i < 65; i++) {
- tmp[0] += message_sizes[i];
- if (tmp[0] > max)
- max = tmp[0];
- }
- for (i = 65; i < 999; i++) {
- tmp[i / 100 + 1] += message_sizes[i];
- if (tmp[i / 100 + 1] > max)
- max = tmp[i / 100 + 1];
- }
- tmp[11] = message_sizes[999];
- if (tmp[11] > max)
- max = tmp[11];
- for (i = -1; i < 11; i++) {
- int num = (tmp[i + 1] * 50) / max;
- if (i == -1)
- printf("\n\r 0 - 64: (%6d) |", tmp[0]);
- else if (i == 0)
- printf("\n\r 65 - 99: (%6d) |", tmp[1]);
- else if (i == 10)
- printf("\n\r >= 1000: (%6d) |", tmp[11]);
- else
- printf("\n\r%3d - %3d: (%6d) |", i * 100, i * 100 + 99,
- tmp[i + 1]);
-
- for (j = 0; j < num; j++)
- printf(".");
- }
- printf("\n\r");
-
- BIF_RET(am_true);
-#else
- BIF_RET(am_false);
-#endif
-}
-
-BIF_RETTYPE hipe_bifs_gc_info_0(BIF_ALIST_0)
-{
-#ifdef __BENCHMARK__
-#ifndef BM_COUNTERS
- Uint minor_gc = 0;
- Uint major_gc = 0;
-#endif
-#ifndef BM_HEAP_SIZES
- Uint max_used_heap = 0;
- Uint max_allocated_heap = 0;
-#endif
- Eterm *hp;
- Uint used_heap = (BIF_P->htop - BIF_P->heap) +
- (OLD_HTOP(BIF_P) - OLD_HEAP(BIF_P)) +
- MBUF_SIZE(BIF_P);
-
- Uint alloc_heap = (BIF_P->hend - BIF_P->heap) +
- (OLD_HEND(BIF_P) - OLD_HEAP(BIF_P)) +
- MBUF_SIZE(BIF_P);
-
- hp = HAlloc(BIF_P, 7);
- BIF_RET(TUPLE6(hp,
- make_small((Uint)minor_gc),
- make_small((Uint)major_gc),
- make_small((Uint)used_heap),
- make_small((Uint)alloc_heap),
- make_small(max_used_heap),
- make_small(max_allocated_heap)));
-#else
- BIF_RET(am_false);
-#endif
-}
-
-BIF_RETTYPE hipe_bifs_shared_gc_info_0(BIF_ALIST_0)
-{
-#ifdef __BENCHMARK__
-#if !(defined(BM_COUNTERS))
- Uint minor_global_gc = 0;
- Uint major_global_gc = 0;
-#endif
-#ifndef BM_HEAP_SIZES
- Uint max_used_global_heap = 0;
- Uint max_allocated_global_heap = 0;
-#endif
- Eterm *hp;
-
- Uint tmp_used_heap = 0;
- Uint tmp_allocated_heap = 0;
-
- hp = HAlloc(BIF_P, 7);
- BIF_RET(TUPLE6(hp,
- make_small((uint)minor_global_gc),
- make_small((uint)major_global_gc),
- make_small(tmp_used_heap),
- make_small(tmp_allocated_heap),
- make_small(max_used_global_heap),
- make_small(max_allocated_global_heap)));
-#else
- BIF_RET(am_false);
-#endif
-}
-
-BIF_RETTYPE hipe_bifs_incremental_gc_info_0(BIF_ALIST_0)
-{
-#ifdef __BENCHMARK__
-#if !defined(BM_COUNTERS)
- Uint minor_gc_cycles = 0;
- Uint major_gc_cycles = 0;
- Uint minor_gc_stages = 0;
- Uint major_gc_stages = 0;
-#endif
- Eterm *hp;
-
- hp = HAlloc(BIF_P, 5);
- BIF_RET(TUPLE4(hp,
- make_small(minor_gc_cycles),
- make_small(major_gc_cycles),
- make_small(minor_gc_stages),
- make_small(major_gc_stages)));
-#else
- BIF_RET(am_false);
-#endif
-}
-
-BIF_RETTYPE hipe_bifs_gc_info_clear_0(BIF_ALIST_0)
-{
-#ifdef __BENCHMARK__
-
-#ifdef BM_COUNTERS
- minor_gc = 0;
- major_gc = 0;
-#endif
-
-#ifdef BM_HEAP_SIZES
- max_used_heap = 0;
- max_allocated_heap = 0;
- max_used_global_heap = 0;
- max_allocated_global_heap = 0;
-#endif
-
- BIF_RET(am_true);
-#else
- BIF_RET(am_false);
-#endif
-}
-
-BIF_RETTYPE hipe_bifs_pause_times_0(BIF_ALIST_0)
-{
-#ifdef BM_TIMERS
- int i;
- int total_time = 0, n = 0;
- int left = 0, right = 0, mid = 0;
-
- printf("Pause times in minor collection:\r\n");
- for (i = 0; i < MAX_PAUSE_TIME; i++) {
- if (pause_times[i] > 0) {
- printf("%d: %ld\r\n", i, pause_times[i]);
- total_time += pause_times[i] * i;
- n += pause_times[i];
-
- if (i > mid)
- right += pause_times[i];
-
- while (right > left) {
- left += pause_times[mid++];
- right -= pause_times[mid];
- }
- }
- }
-
- printf("Number of collections: %d\r\n", n);
- printf("Total collection time: %d\r\n", total_time);
- if (n > 0)
- printf("Mean pause time: %d\r\n", total_time / n);
-
- printf("Geometrical mean: %d\r\n", mid);
-
- total_time = 0; n = 0;
- left = 0; right = 0; mid = 0;
- printf("Pause times in major collection:\r\n");
- for (i = 0; i < MAX_PAUSE_TIME; i++) {
- if (pause_times_old[i] > 0) {
- printf("%d: %ld\r\n", i, pause_times_old[i]);
- total_time += pause_times_old[i] * i;
- n += pause_times_old[i];
- }
- }
-
- printf("Number of collections: %d\r\n", n);
- printf("Total collection time: %d\r\n", total_time);
- if (n > 0)
- printf("Mean pause time: %d\r\n", total_time / n);
-
- BIF_RET(am_true);
-#else
- BIF_RET(am_false);
-#endif
-}
-
-/* XXX: these macros have free variables */
-#ifdef BM_TIMERS
-#define MAKE_TIME(_timer_) { \
- BM_TIMER_T tmp = _timer_##_time / 1000000; \
- milli = tmp % 1000; \
- tmp /= 1000; \
- sec = tmp % 60; \
- min = tmp / 60; }
-
-#define MAKE_MICRO_TIME(_timer_) { \
- BM_TIMER_T tmp = _timer_##_time / 1000; \
- micro = tmp % 1000; \
- tmp /= 1000; \
- milli = tmp % 1000; \
- sec = tmp / 1000; }
-
-#else
-#define MAKE_TIME(_timer_)
-#define MAKE_MICRO_TIME(_timer_)
-#endif
-
-BIF_RETTYPE hipe_bifs_system_timer_0(BIF_ALIST_0)
-{
-#ifdef __BENCHMARK__
- uint min = 0;
- uint sec = 0;
- uint milli = 0;
- Eterm *hp;
-
- hp = HAlloc(BIF_P, 4);
- MAKE_TIME(system);
- BIF_RET(TUPLE3(hp,
- make_small(min),
- make_small(sec),
- make_small(milli)));
-#else
- BIF_RET(am_false);
-#endif
-}
-
-BIF_RETTYPE hipe_bifs_system_timer_clear_0(BIF_ALIST_0)
-{
-#ifdef BM_TIMERS
- system_time = 0;
- BIF_RET(am_true);
-#else
- BIF_RET(am_false);
-#endif
-}
-
-BIF_RETTYPE hipe_bifs_send_timer_0(BIF_ALIST_0)
-{
-#ifdef __BENCHMARK__
- uint min = 0;
- uint sec = 0;
- uint milli = 0;
- Eterm *hp;
- Eterm sendtime, copytime, sizetime;
-
- hp = HAlloc(BIF_P, 4 * 4);
-
- MAKE_TIME(send);
- sendtime = TUPLE3(hp,
- make_small(min),
- make_small(sec),
- make_small(milli));
- hp += 4;
-
- MAKE_TIME(copy);
- copytime = TUPLE3(hp,
- make_small(min),
- make_small(sec),
- make_small(milli));
- hp += 4;
-
- MAKE_TIME(size);
- sizetime = TUPLE3(hp,
- make_small(min),
- make_small(sec),
- make_small(milli));
- hp += 4;
- BIF_RET(TUPLE3(hp, sendtime, copytime, sizetime));
-#else
- BIF_RET(am_false);
-#endif
-}
-
-BIF_RETTYPE hipe_bifs_send_timer_clear_0(BIF_ALIST_0)
-{
-#ifdef BM_TIMERS
- send_time = 0;
- copy_time = 0;
- size_time = 0;
- BIF_RET(am_true);
-#else
- BIF_RET(am_false);
-#endif
-}
-
-BIF_RETTYPE hipe_bifs_gc_timer_0(BIF_ALIST_0)
-{
-#ifdef __BENCHMARK__
- Eterm *hp;
- uint min = 0;
- uint sec = 0;
- uint milli = 0;
- uint micro = 0;
- Eterm minor, major, max_min, max_maj;
-
- hp = HAlloc(BIF_P, 4 * 4 + 5);
-
- MAKE_TIME(minor_gc);
- minor = TUPLE3(hp,
- make_small(min),
- make_small(sec),
- make_small(milli));
- hp += 4;
-
- MAKE_TIME(major_gc);
- major = TUPLE3(hp,
- make_small(min),
- make_small(sec),
- make_small(milli));
- hp += 4;
-
- MAKE_MICRO_TIME(max_minor);
- max_min = TUPLE3(hp,
- make_small(sec),
- make_small(milli),
- make_small(micro));
- hp += 4;
-
- MAKE_MICRO_TIME(max_major);
- max_maj = TUPLE3(hp,
- make_small(sec),
- make_small(milli),
- make_small(micro));
- hp += 4;
-
- BIF_RET(TUPLE4(hp, minor, major, max_min, max_maj));
-#else
- BIF_RET(am_false);
-#endif
-}
-
-BIF_RETTYPE hipe_bifs_shared_gc_timer_0(BIF_ALIST_0)
-{
-#ifdef __BENCHMARK__
- Eterm *hp;
- uint min = 0;
- uint sec = 0;
- uint milli = 0;
- uint micro = 0;
- Eterm minor, major, max_min, max_maj;
-
- hp = HAlloc(BIF_P, 4 * 4 + 5);
-
- MAKE_TIME(minor_global_gc);
- minor = TUPLE3(hp,
- make_small(min),
- make_small(sec),
- make_small(milli));
- hp += 4;
-
- MAKE_TIME(major_global_gc);
- major = TUPLE3(hp,
- make_small(min),
- make_small(sec),
- make_small(milli));
- hp += 4;
-
- MAKE_MICRO_TIME(max_global_minor);
- max_min = TUPLE3(hp,
- make_small(sec),
- make_small(milli),
- make_small(micro));
- hp += 4;
-
- MAKE_MICRO_TIME(max_global_major);
- max_maj = TUPLE3(hp,
- make_small(sec),
- make_small(milli),
- make_small(micro));
- hp += 4;
-
- BIF_RET(TUPLE4(hp, minor, major, max_min, max_maj));
-#else
- BIF_RET(am_false);
-#endif
-}
-
-BIF_RETTYPE hipe_bifs_gc_timer_clear_0(BIF_ALIST_0)
-{
-#ifdef BM_TIMERS
- minor_gc_time = 0;
- major_gc_time = 0;
- max_minor_time = 0;
- max_major_time = 0;
- minor_global_gc_time = 0;
- major_global_gc_time = 0;
- max_global_minor_time = 0;
- max_global_major_time = 0;
- BIF_RET(am_true);
-#else
- BIF_RET(am_false);
-#endif
-}
-
-BIF_RETTYPE hipe_bifs_misc_timer_0(BIF_ALIST_0)
-{
-#ifdef __BENCHMARK__
- uint min = 0;
- uint sec = 0;
- uint milli = 0;
- Eterm *hp;
- Eterm misctime1, misctime2, misctime3;
-
- hp = HAlloc(BIF_P, 4 * 4);
-
- MAKE_TIME(misc0);
- misctime1 = TUPLE3(hp,
- make_small(min),
- make_small(sec),
- make_small(milli));
- hp += 4;
-
- MAKE_TIME(misc1);
- misctime2 = TUPLE3(hp,
- make_small(min),
- make_small(sec),
- make_small(milli));
- hp += 4;
-
- MAKE_TIME(misc2);
- misctime3 = TUPLE3(hp,
- make_small(min),
- make_small(sec),
- make_small(milli));
- hp += 4;
- BIF_RET(TUPLE3(hp, misctime1, misctime2, misctime3));
-#else
- BIF_RET(am_false);
-#endif
-}
-
-BIF_RETTYPE hipe_bifs_misc_timer_clear_0(BIF_ALIST_0)
-{
-#ifdef BM_TIMERS
- misc0_time = 0;
- misc1_time = 0;
- misc2_time = 0;
- BIF_RET(am_true);
-#else
- BIF_RET(am_false);
-#endif
-}
-
-#undef MAKE_TIME
-#undef MAKE_MICRO_TIME
-
-/*
- * HiPE hrvtime().
- * These implementations are currently available:
- * + The fallback, which is the same as {X,_} = runtime(statistics).
- */
-
-static double fallback_get_hrvtime(void)
-{
- unsigned long ms_user;
-
- elapsed_time_both(&ms_user, NULL, NULL, NULL);
- return (double)ms_user;
-}
-
-/*
- * Fallback, if nothing better exists.
- * This is the same as {X,_} = statistics(runtime), which uses
- * times(2) on Unix systems.
- */
-
-#define hrvtime_is_started() 1
-#define start_hrvtime() do{}while(0)
-#define stop_hrvtime() do{}while(0)
-#define get_hrvtime() fallback_get_hrvtime()
-
-BIF_RETTYPE hipe_bifs_get_hrvtime_0(BIF_ALIST_0)
-{
- Eterm *hp;
- Eterm res;
- FloatDef f;
-
- if (!hrvtime_is_started())
- start_hrvtime();
- f.fd = get_hrvtime();
- hp = HAlloc(BIF_P, FLOAT_SIZE_OBJECT);
- res = make_float(hp);
- PUT_DOUBLE(f, hp);
- BIF_RET(res);
-}
-
-BIF_RETTYPE hipe_bifs_stop_hrvtime_0(BIF_ALIST_0)
-{
- stop_hrvtime();
- BIF_RET(am_true);
-}
diff --git a/erts/emulator/hipe/hipe_bif1.h b/erts/emulator/hipe/hipe_bif1.h
index 80cdeb4a82..e12bb1a1f3 100644
--- a/erts/emulator/hipe/hipe_bif1.h
+++ b/erts/emulator/hipe/hipe_bif1.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_bif1.tab b/erts/emulator/hipe/hipe_bif1.tab
index 6c4e05afdb..4be0ad0e9c 100644
--- a/erts/emulator/hipe/hipe_bif1.tab
+++ b/erts/emulator/hipe/hipe_bif1.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2009. All Rights Reserved.
+# Copyright Ericsson AB 2001-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -27,24 +27,3 @@ bif hipe_bifs:call_count_get/1
bif hipe_bifs:call_count_clear/1
bif hipe_bifs:trap_count_get/0
bif hipe_bifs:trap_count_clear/0
-bif hipe_bifs:process_info/0
-bif hipe_bifs:process_info_clear/0
-bif hipe_bifs:message_info/0
-bif hipe_bifs:message_info_clear/0
-bif hipe_bifs:message_sizes/0
-bif hipe_bifs:gc_info/0
-bif hipe_bifs:shared_gc_info/0
-bif hipe_bifs:incremental_gc_info/0
-bif hipe_bifs:gc_info_clear/0
-bif hipe_bifs:pause_times/0
-bif hipe_bifs:system_timer/0
-bif hipe_bifs:system_timer_clear/0
-bif hipe_bifs:send_timer/0
-bif hipe_bifs:send_timer_clear/0
-bif hipe_bifs:gc_timer/0
-bif hipe_bifs:shared_gc_timer/0
-bif hipe_bifs:gc_timer_clear/0
-bif hipe_bifs:misc_timer/0
-bif hipe_bifs:misc_timer_clear/0
-bif hipe_bifs:get_hrvtime/0
-bif hipe_bifs:stop_hrvtime/0
diff --git a/erts/emulator/hipe/hipe_bif2.c b/erts/emulator/hipe/hipe_bif2.c
index 2328e69886..dfd34e31d4 100644
--- a/erts/emulator/hipe/hipe_bif2.c
+++ b/erts/emulator/hipe/hipe_bif2.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2012. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_bif2.tab b/erts/emulator/hipe/hipe_bif2.tab
index a29e1fbdbb..bbcb577be0 100644
--- a/erts/emulator/hipe/hipe_bif2.tab
+++ b/erts/emulator/hipe/hipe_bif2.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2012. All Rights Reserved.
+# Copyright Ericsson AB 2001-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_bif64.c b/erts/emulator/hipe/hipe_bif64.c
index b97cf2b7ee..a1a3c81bfe 100644
--- a/erts/emulator/hipe/hipe_bif64.c
+++ b/erts/emulator/hipe/hipe_bif64.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_bif64.h b/erts/emulator/hipe/hipe_bif64.h
index 856b4003dc..a97ce311d3 100644
--- a/erts/emulator/hipe/hipe_bif64.h
+++ b/erts/emulator/hipe/hipe_bif64.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_bif64.tab b/erts/emulator/hipe/hipe_bif64.tab
index 3062ab5848..eefca379a0 100644
--- a/erts/emulator/hipe/hipe_bif64.tab
+++ b/erts/emulator/hipe/hipe_bif64.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2011. All Rights Reserved.
+# Copyright Ericsson AB 2004-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_bif_list.m4 b/erts/emulator/hipe/hipe_bif_list.m4
index 7240280345..dcf3447af9 100644
--- a/erts/emulator/hipe/hipe_bif_list.m4
+++ b/erts/emulator/hipe/hipe_bif_list.m4
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2014. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -96,6 +96,7 @@
* gc_bif_interface_0(nbif_name, cbif_name)
* gc_bif_interface_1(nbif_name, cbif_name)
* gc_bif_interface_2(nbif_name, cbif_name)
+ * gc_bif_interface_3(nbif_name, cbif_name)
*
* A BIF which may do a GC or walk the native stack.
* May read NSP, NSP_LIMIT, NRA, HP, HP_LIMIT, and FCALLS.
@@ -263,32 +264,34 @@ noproc_primop_interface_1(nbif_atomic_inc, hipe_atomic_inc)
',)dnl
/*
- * Standard BIFs.
- * BIF_LIST(ModuleAtom,FunctionAtom,Arity,CFun,Index)
+ * BIFs that disable GC while trapping are called via a wrapper
+ * to reserve stack space for the "trap frame".
+ * They occasionally need to call the garbage collector in order to make room
+ * for the trap frame on the BEAM stack.
*/
+gc_bif_interface_1(nbif_term_to_binary_1, hipe_wrapper_term_to_binary_1)
+gc_bif_interface_2(nbif_term_to_binary_2, hipe_wrapper_term_to_binary_2)
+gc_bif_interface_1(nbif_binary_to_term_1, hipe_wrapper_binary_to_term_1)
+gc_bif_interface_2(nbif_binary_to_term_2, hipe_wrapper_binary_to_term_2)
+gc_bif_interface_1(nbif_binary_to_list_1, hipe_wrapper_binary_to_list_1)
+gc_bif_interface_3(nbif_binary_to_list_3, hipe_wrapper_binary_to_list_3)
+gc_bif_interface_1(nbif_bitstring_to_list_1, hipe_wrapper_bitstring_to_list_1)
+gc_bif_interface_1(nbif_list_to_binary_1, hipe_wrapper_list_to_binary_1)
+gc_bif_interface_1(nbif_iolist_to_binary_1, hipe_wrapper_iolist_to_binary_1)
+gc_bif_interface_1(nbif_binary_list_to_bin_1, hipe_wrapper_binary_list_to_bin_1)
+gc_bif_interface_1(nbif_list_to_bitstring_1, hipe_wrapper_list_to_bitstring_1)
+gc_bif_interface_2(nbif_send_2, hipe_wrapper_send_2)
+gc_bif_interface_3(nbif_send_3, hipe_wrapper_send_3)
+gc_bif_interface_2(nbif_ebif_bang_2, hipe_wrapper_ebif_bang_2)
+gc_bif_interface_2(nbif_maps_merge_2, hipe_wrapper_maps_merge_2)
-/* BIFs that disable GC while trapping are called via a wrapper
- * to reserve stack space for the "trap frame".
+
+/*
+ * Standard BIFs.
+ * BIF_LIST(ModuleAtom,FunctionAtom,Arity,CFun,Index)
*/
-define(CFUN,`ifelse(
-$1, term_to_binary_1, hipe_wrapper_$1,
-$1, term_to_binary_2, hipe_wrapper_$1,
-$1, binary_to_term_1, hipe_wrapper_$1,
-$1, binary_to_term_2, hipe_wrapper_$1,
-$1, binary_to_list_1, hipe_wrapper_$1,
-$1, binary_to_list_3, hipe_wrapper_$1,
-$1, bitstring_to_list_1, hipe_wrapper_$1,
-$1, list_to_binary_1, hipe_wrapper_$1,
-$1, iolist_to_binary_1, hipe_wrapper_$1,
-$1, binary_list_to_bin_1, hipe_wrapper_$1,
-$1, list_to_bitstring_1, hipe_wrapper_$1,
-$1, send_2, hipe_wrapper_$1,
-$1, send_3, hipe_wrapper_$1,
-$1, ebif_bang_2, hipe_wrapper_$1,
-$1, maps_merge_2, hipe_wrapper_$1,
-$1)')
-define(BIF_LIST,`standard_bif_interface_$3(nbif_$4, CFUN($4))')
+define(BIF_LIST,`standard_bif_interface_$3(nbif_$4, $4)')
include(TARGET/`erl_bif_list.h')
/*
diff --git a/erts/emulator/hipe/hipe_debug.c b/erts/emulator/hipe/hipe_debug.c
index a48578c468..ace489452f 100644
--- a/erts/emulator/hipe/hipe_debug.c
+++ b/erts/emulator/hipe/hipe_debug.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2013. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -195,7 +195,7 @@ void hipe_print_pcb(Process *p)
U("rcount ", rcount);
U("id ", common.id);
U("reds ", reds);
- U("tracer_pr..", common.tracer_proc);
+ U("tracer ", common.tracer);
U("trace_fla..", common.trace_flags);
U("group_lea..", group_leader);
U("flags ", flags);
diff --git a/erts/emulator/hipe/hipe_debug.h b/erts/emulator/hipe/hipe_debug.h
index bf10d5a2a8..c510eac949 100644
--- a/erts/emulator/hipe/hipe_debug.h
+++ b/erts/emulator/hipe/hipe_debug.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_gbif_list.h b/erts/emulator/hipe/hipe_gbif_list.h
index dc93741a1d..424b001298 100644
--- a/erts/emulator/hipe/hipe_gbif_list.h
+++ b/erts/emulator/hipe/hipe_gbif_list.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_gc.c b/erts/emulator/hipe/hipe_gc.c
index 2c747771ac..68c65dea27 100644
--- a/erts/emulator/hipe/hipe_gc.c
+++ b/erts/emulator/hipe/hipe_gc.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2012. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,9 +46,7 @@ Eterm *fullsweep_nstack(Process *p, Eterm *n_htop)
/* arch-specific nstack walk state */
struct nstack_walk_state walk_state;
- /* fullsweep-specific state */
- char *src, *oh;
- Uint src_size, oh_size;
+ ASSERT(!p->hipe.gc_is_unsafe);
if (!p->hipe.nstack) {
ASSERT(!p->hipe.nsp && !p->hipe.nstend);
@@ -66,11 +64,6 @@ Eterm *fullsweep_nstack(Process *p, Eterm *n_htop)
sdesc = nstack_walk_init_sdesc(p, &walk_state);
- src = (char*)HEAP_START(p);
- src_size = (char*)HEAP_TOP(p) - src;
- oh = (char*)OLD_HEAP(p);
- oh_size = (char*)OLD_HTOP(p) - oh;
-
for (;;) {
if (nstack_walk_nsp_reached_end(nsp, nsp_end)) {
if (nsp == nsp_end) {
@@ -97,8 +90,7 @@ Eterm *fullsweep_nstack(Process *p, Eterm *n_htop)
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*nsp_i = val;
- } else if (in_area(ptr, src, src_size) ||
- in_area(ptr, oh, oh_size)) {
+ } else if (!erts_is_literal(gval, ptr)) {
MOVE_BOXED(ptr, val, n_htop, nsp_i);
}
} else if (is_list(gval)) {
@@ -106,8 +98,7 @@ Eterm *fullsweep_nstack(Process *p, Eterm *n_htop)
Eterm val = *ptr;
if (IS_MOVED_CONS(val)) {
*nsp_i = ptr[1];
- } else if (in_area(ptr, src, src_size) ||
- in_area(ptr, oh, oh_size)) {
+ } else if (!erts_is_literal(gval, ptr)) {
ASSERT(within(ptr, p));
MOVE_CONS(ptr, val, n_htop, nsp_i);
}
@@ -139,11 +130,15 @@ void gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop)
unsigned int mask;
/* arch-specific nstack walk state */
struct nstack_walk_state walk_state;
+ char *oh;
+ Uint oh_size;
/* gensweep-specific state */
Eterm *old_htop, *n_htop;
- char *heap;
- Uint heap_size, mature_size;
+ char *mature;
+ Uint mature_size;
+
+ ASSERT(!p->hipe.gc_is_unsafe);
if (!p->hipe.nstack) {
ASSERT(!p->hipe.nsp && !p->hipe.nstend);
@@ -168,9 +163,10 @@ void gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop)
old_htop = *ptr_old_htop;
n_htop = *ptr_n_htop;
- heap = (char*)HEAP_START(p);
- heap_size = (char*)HEAP_TOP(p) - heap;
- mature_size = (char*)HIGH_WATER(p) - heap;
+ mature = (char *) (p->abandoned_heap ? p->abandoned_heap : p->heap);
+ mature_size = (char*)HIGH_WATER(p) - mature;
+ oh = (char*)OLD_HEAP(p);
+ oh_size = (char*)OLD_HTOP(p) - oh;
for (;;) {
if (nstack_walk_nsp_reached_end(nsp, nsp_end)) {
@@ -209,9 +205,9 @@ void gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop)
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*nsp_i = val;
- } else if (in_area(ptr, heap, mature_size)) {
+ } else if (ErtsInArea(ptr, mature, mature_size)) {
MOVE_BOXED(ptr, val, old_htop, nsp_i);
- } else if (in_area(ptr, heap, heap_size)) {
+ } else if (ErtsInYoungGen(gval, ptr, oh, oh_size)) {
ASSERT(within(ptr, p));
MOVE_BOXED(ptr, val, n_htop, nsp_i);
}
@@ -220,9 +216,9 @@ void gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop)
Eterm val = *ptr;
if (IS_MOVED_CONS(val)) {
*nsp_i = ptr[1];
- } else if (in_area(ptr, heap, mature_size)) {
+ } else if (ErtsInArea(ptr, mature, mature_size)) {
MOVE_CONS(ptr, val, old_htop, nsp_i);
- } else if (in_area(ptr, heap, heap_size)) {
+ } else if (ErtsInYoungGen(gval, ptr, oh, oh_size)) {
ASSERT(within(ptr, p));
MOVE_CONS(ptr, val, n_htop, nsp_i);
}
@@ -241,3 +237,122 @@ void gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop)
}
abort();
}
+
+Eterm *sweep_literals_nstack(Process *p, Eterm *old_htop, char *area,
+ Uint area_size)
+{
+ /* known nstack walk state */
+ Eterm *nsp;
+ Eterm *nsp_end;
+ const struct sdesc *sdesc;
+ /* arch-specific nstack walk state */
+ struct nstack_walk_state walk_state;
+
+ ASSERT(!p->hipe.gc_is_unsafe);
+
+ if (!p->hipe.nstack) {
+ ASSERT(!p->hipe.nsp && !p->hipe.nstend);
+ return old_htop;
+ }
+ if (!nstack_walk_init_check(p))
+ return old_htop;
+
+ ASSERT(p->hipe.nsp && p->hipe.nstend);
+ nsp = nstack_walk_nsp_begin(p);
+ nsp_end = nstack_walk_nsp_end(p);
+ sdesc = nstack_walk_init_sdesc_ignore_trap(p, &walk_state);
+
+ while (!nstack_walk_nsp_reached_end(nsp, nsp_end)) {
+ unsigned long ra;
+ unsigned sdesc_size = nstack_walk_frame_size(sdesc);
+ unsigned i = 0;
+ unsigned mask = sdesc->livebits[0];
+ for (;;) {
+ if (mask & 1) {
+ Eterm *nsp_i = nstack_walk_frame_index(nsp, i);
+ Eterm gval = *nsp_i;
+ if (is_boxed(gval)) {
+ Eterm *ptr = boxed_val(gval);
+ Eterm val = *ptr;
+ if (IS_MOVED_BOXED(val)) {
+ ASSERT(is_boxed(val));
+ *nsp_i = val;
+ } else if (ErtsInArea(ptr, area, area_size)) {
+ MOVE_BOXED(ptr, val, old_htop, nsp_i);
+ }
+ } else if (is_list(gval)) {
+ Eterm *ptr = list_val(gval);
+ Eterm val = *ptr;
+ if (IS_MOVED_CONS(val)) {
+ *nsp_i = ptr[1];
+ } else if (ErtsInArea(ptr, area, area_size)) {
+ MOVE_CONS(ptr, val, old_htop, nsp_i);
+ }
+ }
+ }
+ if (++i >= sdesc_size)
+ break;
+ if (i & 31)
+ mask >>= 1;
+ else
+ mask = sdesc->livebits[i >> 5];
+ }
+ ra = nstack_walk_frame_ra(nsp, sdesc);
+ if (ra == (unsigned long)nbif_stack_trap_ra)
+ ra = (unsigned long)p->hipe.ngra;
+ sdesc = hipe_find_sdesc(ra);
+ nsp = nstack_walk_next_frame(nsp, sdesc_size);
+ }
+ return old_htop;
+}
+
+int
+nstack_any_heap_ref_ptrs(Process *rp, char* mod_start, Uint mod_size)
+{
+ Eterm *nsp;
+ Eterm *nsp_end;
+ const struct sdesc *sdesc;
+ /* arch-specific nstack walk state */
+ struct nstack_walk_state walk_state;
+
+ ASSERT(!rp->hipe.gc_is_unsafe);
+
+ if (!rp->hipe.nstack || !nstack_walk_init_check(rp)) return 0;
+ ASSERT(rp->hipe.nsp && rp->hipe.nstend);
+ nsp = nstack_walk_nsp_begin(rp);
+ nsp_end = nstack_walk_nsp_end(rp);
+ sdesc = nstack_walk_init_sdesc_ignore_trap(rp, &walk_state);
+
+ while (!nstack_walk_nsp_reached_end(nsp, nsp_end)) {
+ unsigned long ra;
+ unsigned sdesc_size = nstack_walk_frame_size(sdesc);
+ unsigned i = 0;
+ unsigned mask = sdesc->livebits[0];
+ for (;;) {
+ if (mask & 1) {
+ Eterm *nsp_i = nstack_walk_frame_index(nsp, i);
+ Eterm val = *nsp_i;
+ switch (primary_tag(val)) {
+ case TAG_PRIMARY_BOXED:
+ case TAG_PRIMARY_LIST:
+ if (ErtsInArea(val, mod_start, mod_size)) {
+ return 1;
+ }
+ break;
+ }
+ }
+ if (++i >= sdesc_size)
+ break;
+ if (i & 31)
+ mask >>= 1;
+ else
+ mask = sdesc->livebits[i >> 5];
+ }
+ ra = nstack_walk_frame_ra(nsp, sdesc);
+ if (ra == (unsigned long)nbif_stack_trap_ra)
+ ra = (unsigned long)rp->hipe.ngra;
+ sdesc = hipe_find_sdesc(ra);
+ nsp = nstack_walk_next_frame(nsp, sdesc_size);
+ }
+ return 0;
+}
diff --git a/erts/emulator/hipe/hipe_gc.h b/erts/emulator/hipe/hipe_gc.h
index e373324cdd..5b5eb29175 100644
--- a/erts/emulator/hipe/hipe_gc.h
+++ b/erts/emulator/hipe/hipe_gc.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_mkliterals.c b/erts/emulator/hipe/hipe_mkliterals.c
index dfa5313739..b9d4226705 100644
--- a/erts/emulator/hipe/hipe_mkliterals.c
+++ b/erts/emulator/hipe/hipe_mkliterals.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2012. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -525,6 +525,12 @@ static const struct rts_param rts_params[] = {
{ 51, "P_CALLEE_EXP", 1, offsetof(struct process, hipe.u.callee_exp) },
{ 52, "THE_NON_VALUE", 1, (int)THE_NON_VALUE },
+
+ { 53, "P_GCUNSAFE",
+#ifdef DEBUG
+ 1, offsetof(struct process, hipe.gc_is_unsafe)
+#endif
+ },
};
#define NR_PARAMS ARRAY_SIZE(rts_params)
diff --git a/erts/emulator/hipe/hipe_mode_switch.c b/erts/emulator/hipe/hipe_mode_switch.c
index 9243e029f6..ed95045292 100644
--- a/erts/emulator/hipe/hipe_mode_switch.c
+++ b/erts/emulator/hipe/hipe_mode_switch.c
@@ -2,7 +2,7 @@
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2014. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -59,6 +59,7 @@
* TODO: check PCB consistency at native BIF calls
*/
int hipe_modeswitch_debug = 0;
+extern BeamInstr beam_exit[];
#define HIPE_DEBUG 0
@@ -173,6 +174,33 @@ void hipe_mode_switch_init(void)
make_catch(beam_catches_cons(hipe_beam_pc_throw, BEAM_CATCHES_NIL));
hipe_mfa_info_table_init();
+
+#if (defined(__i386__) || defined(__x86_64__)) && defined(__linux__)
+ /* Verify that the offset of c-p->hipe does not change.
+ The ErLLVM hipe backend depends on it being in a specific
+ position. Kostis et al has promised to fix this in upstream
+ llvm by OTP 20, so it should be possible to remove these asserts
+ after that. */
+ ERTS_CT_ASSERT(sizeof(ErtsPTabElementCommon) ==
+ (sizeof(Eterm) + /* id */
+ sizeof(((ErtsPTabElementCommon*)0)->refc) +
+ sizeof(ErtsTracer) + /* tracer */
+ sizeof(Uint) + /* trace_flags */
+ sizeof(erts_smp_atomic_t) + /* timer */
+ sizeof(((ErtsPTabElementCommon*)0)->u)));
+
+ ERTS_CT_ASSERT(offsetof(Process, hipe) ==
+ (sizeof(ErtsPTabElementCommon) + /* common */
+ sizeof(Eterm*) + /* htop */
+ sizeof(Eterm*) + /* stop */
+ sizeof(Eterm*) + /* heap */
+ sizeof(Eterm*) + /* hend */
+ sizeof(Uint) + /* heap_sz */
+ sizeof(Uint) + /* min_heap_size */
+ sizeof(Uint) + /* min_vheap_size */
+ sizeof(volatile unsigned long))); /* fp_exception */
+#endif
+
}
void hipe_set_call_trap(Uint *bfun, void *nfun, int is_closure)
@@ -196,7 +224,7 @@ hipe_push_beam_trap_frame(Process *p, Eterm reg[], unsigned arity)
ASSERT(!(p->flags & F_DISABLE_GC));
if ((p->stop - 2) < p->htop) {
DPRINTF("calling gc to increase BEAM stack size");
- p->fcalls -= erts_garbage_collect(p, 2, reg, arity);
+ erts_garbage_collect(p, 2, reg, arity);
ASSERT(!((p->stop - 2) < p->htop));
}
p->stop -= 2;
@@ -218,15 +246,37 @@ static __inline__ void hipe_pop_beam_trap_frame(Process *p)
Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[])
{
unsigned result;
-#if NR_ARG_REGS > 5
- /* When NR_ARG_REGS > 5, we need to protect the process' input
- reduction count (which BEAM stores in def_arg_reg[5]) from
- being clobbered by the arch glue code. */
Eterm reds_in = p->def_arg_reg[5];
-#endif
-#if NR_ARG_REGS > 4
- Eterm o_reds = p->def_arg_reg[4];
-#endif
+ /*
+ * Process is in the normal case scheduled out when reduction
+ * count reach zero. When "save calls" is enabled reduction
+ * count is subtracted with CONTEXT_REDS, i.e. initial reduction
+ * count will be zero or less and process is scheduled out
+ * when -CONTEXT_REDS is reached.
+ *
+ * HiPE does not support the "save calls" feature, so we switch
+ * to using a positive reduction counter when executing in
+ * hipe mode, but need to restore the "save calls" when
+ * returning to beam. We also need to hide the save calls buffer
+ * from BIFs. We do that by moving the saved calls buf to
+ * suspended saved calls buf.
+ *
+ * Beam has initial reduction count in stored in p->def_arg_reg[5].
+ *
+ * Beam expects -neg_o_reds to be found in p->def_arg_reg[4]
+ * on return to beam.
+ */
+
+ {
+ struct saved_calls *scb = ERTS_PROC_SET_SAVED_CALLS_BUF(p, NULL);
+ if (scb) {
+ reds_in += CONTEXT_REDS;
+ p->fcalls += CONTEXT_REDS;
+ ERTS_PROC_SET_SUSPENDED_SAVED_CALLS_BUF(p, scb);
+ }
+ }
+
+ p->flags |= F_HIPE_MODE; /* inform bifs where we are comming from... */
p->i = NULL;
/* Set current_function to undefined. stdlib hibernate tests rely on it. */
@@ -481,12 +531,25 @@ Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[])
erts_smp_proc_unlock(p, ERTS_PROC_LOCKS_MSG_RECEIVE);
do_schedule:
{
-#if !(NR_ARG_REGS > 5)
- int reds_in = p->def_arg_reg[5];
+ struct saved_calls *scb;
+
+ scb = ERTS_PROC_SET_SUSPENDED_SAVED_CALLS_BUF(p, NULL);
+ if (scb)
+ ERTS_PROC_SET_SAVED_CALLS_BUF(p, scb);
+
+ /* The process may have died while it was executing,
+ if so we return out from native code to the interpreter */
+ if (erts_smp_atomic32_read_nob(&p->state) & ERTS_PSFLG_EXITING)
+ p->i = beam_exit;
+#ifdef DEBUG
+ ASSERT(p->debug_reds_in == reds_in);
#endif
+ p->flags &= ~F_HIPE_MODE;
+
ERTS_SMP_UNREQ_PROC_MAIN_LOCK(p);
- p = schedule(p, reds_in - p->fcalls);
+ p = erts_schedule(NULL, p, reds_in - p->fcalls);
ERTS_SMP_REQ_PROC_MAIN_LOCK(p);
+ ASSERT(!(p->flags & F_HIPE_MODE));
#ifdef ERTS_SMP
p->hipe_smp.have_receive_locks = 0;
reg = p->scheduler_data->x_reg_array;
@@ -501,28 +564,32 @@ Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[])
reg[i] = argp[i];
}
{
-#if !(NR_ARG_REGS > 5)
- Eterm reds_in;
-#endif
-#if !(NR_ARG_REGS > 4)
- Eterm o_reds;
-#endif
+ struct saved_calls *scb;
reds_in = p->fcalls;
- o_reds = 0;
- if (ERTS_PROC_GET_SAVED_CALLS_BUF(p)) {
- o_reds = reds_in;
- reds_in = 0;
- p->fcalls = 0;
- }
- p->def_arg_reg[4] = o_reds;
p->def_arg_reg[5] = reds_in;
+#ifdef DEBUG
+ p->debug_reds_in = reds_in;
+#endif
if (p->i == hipe_beam_pc_resume) {
+ p->flags |= F_HIPE_MODE; /* inform bifs where we are comming from... */
+ scb = ERTS_PROC_SET_SAVED_CALLS_BUF(p, NULL);
+ if (scb)
+ ERTS_PROC_SET_SUSPENDED_SAVED_CALLS_BUF(p, scb);
p->i = NULL;
p->arity = 0;
goto do_resume;
}
+
+ scb = ERTS_PROC_GET_SAVED_CALLS_BUF(p);
+ if (!scb)
+ p->def_arg_reg[4] = 0;
+ else {
+ p->def_arg_reg[4] = CONTEXT_REDS;
+ p->fcalls = -CONTEXT_REDS + reds_in;
+ }
}
+
HIPE_CHECK_PCB(p);
result = HIPE_MODE_SWITCH_RES_CALL_BEAM;
p->def_arg_reg[3] = result;
@@ -562,14 +629,29 @@ Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[])
default:
erts_exit(ERTS_ERROR_EXIT, "hipe_mode_switch: result %#x\r\n", result);
}
+
+ {
+ struct saved_calls *scb = ERTS_PROC_SET_SUSPENDED_SAVED_CALLS_BUF(p, NULL);
+ if (!scb)
+ p->def_arg_reg[4] = 0;
+ else {
+ p->def_arg_reg[4] = CONTEXT_REDS;
+ p->fcalls -= CONTEXT_REDS;
+ ERTS_PROC_SET_SAVED_CALLS_BUF(p, scb);
+ }
+ }
+
HIPE_CHECK_PCB(p);
p->def_arg_reg[3] = result;
-#if NR_ARG_REGS > 4
- p->def_arg_reg[4] = o_reds;
-#endif
#if NR_ARG_REGS > 5
+ /*
+ * When NR_ARG_REGS > 5, we need to protect the process' input
+ * reduction count (which BEAM stores in def_arg_reg[5]) from
+ * being clobbered by the arch glue code.
+ */
p->def_arg_reg[5] = reds_in;
#endif
+ p->flags &= ~F_HIPE_MODE;
return p;
}
diff --git a/erts/emulator/hipe/hipe_mode_switch.h b/erts/emulator/hipe/hipe_mode_switch.h
index bc863a4f36..e54b81cf78 100644
--- a/erts/emulator/hipe/hipe_mode_switch.h
+++ b/erts/emulator/hipe/hipe_mode_switch.h
@@ -2,7 +2,7 @@
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -64,6 +64,7 @@ Eterm hipe_build_stacktrace(Process *p, struct StackTrace *s);
ERTS_GLB_INLINE void hipe_reserve_beam_trap_frame(Process*, Eterm reg[], unsigned arity);
ERTS_GLB_INLINE void hipe_unreserve_beam_trap_frame(Process*);
+ERTS_GLB_INLINE int hipe_is_ra_mode_switch(const void* ra);
extern Uint hipe_beam_pc_return[];
extern Uint hipe_beam_pc_throw[];
@@ -95,7 +96,7 @@ ERTS_GLB_INLINE void hipe_reserve_beam_trap_frame(Process *p, Eterm reg[], unsig
/* ensure that at least 2 words are available on the BEAM stack */
if ((p->stop - 2) < p->htop) {
- p->fcalls -= erts_garbage_collect(p, 2, reg, arity);
+ erts_garbage_collect(p, 2, reg, arity);
ASSERT(!((p->stop - 2) < p->htop));
}
p->stop -= 2;
@@ -112,6 +113,11 @@ ERTS_GLB_INLINE void hipe_unreserve_beam_trap_frame(Process *p)
p->stop += 2;
}
+ERTS_GLB_INLINE int hipe_is_ra_mode_switch(const void* ra)
+{
+ return ra == nbif_return;
+}
+
#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
#endif /* ASM */
diff --git a/erts/emulator/hipe/hipe_native_bif.c b/erts/emulator/hipe/hipe_native_bif.c
index 994f963ece..860791074d 100644
--- a/erts/emulator/hipe/hipe_native_bif.c
+++ b/erts/emulator/hipe/hipe_native_bif.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2013. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2017. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -80,7 +80,7 @@ Eterm hipe_show_nstack_1(BIF_ALIST_1)
void hipe_gc(Process *p, Eterm need)
{
hipe_set_narity(p, 1);
- p->fcalls -= erts_garbage_collect(p, unsigned_val(need), NULL, 0);
+ erts_garbage_collect(p, unsigned_val(need), NULL, 0);
hipe_set_narity(p, 0);
}
@@ -157,13 +157,22 @@ BIF_RETTYPE hipe_set_timeout(BIF_ALIST_1)
*/
void hipe_select_msg(Process *p)
{
- ErlMessage *msgp;
+ ErtsMessage *msgp;
msgp = PEEK_MESSAGE(p);
UNLINK_MESSAGE(p, msgp); /* decrements global 'erts_proc_tot_mem' variable */
JOIN_MESSAGE(p);
CANCEL_TIMER(p); /* calls erts_cancel_proc_timer() */
- free_message(msgp);
+ erts_save_message_in_proc(p, msgp);
+ p->flags &= ~F_DELAY_GC;
+ if (ERTS_IS_GC_DESIRED(p)) {
+ /*
+ * We want to GC soon but we leave a few
+ * reductions giving the message some time
+ * to turn into garbage.
+ */
+ ERTS_VBUMP_LEAVE_REDS(p, 5);
+ }
}
void hipe_fclearerror_error(Process *p)
@@ -217,11 +226,6 @@ void hipe_handle_exception(Process *c_p)
ASSERT(c_p->freason != TRAP); /* Should have been handled earlier. */
- if (c_p->mbuf) {
- erts_printf("%s line %u: p==%p, p->mbuf==%p\n", __FUNCTION__, __LINE__, c_p, c_p->mbuf);
- /* erts_garbage_collect(c_p, 0, NULL, 0); */
- }
-
/*
* Check if we have an arglist for the top level call. If so, this
* is encoded in Value, so we have to dig out the real Value as well
@@ -250,11 +254,6 @@ void hipe_handle_exception(Process *c_p)
/* Synthesized to avoid having to generate code for it. */
c_p->def_arg_reg[0] = exception_tag[GET_EXC_CLASS(c_p->freason)];
- if (c_p->mbuf) {
- /* erts_printf("%s line %u: p==%p, p->mbuf==%p, p->lastbif==%p\n", __FUNCTION__, __LINE__, c_p, c_p->mbuf, c_p->hipe.lastbif); */
- erts_garbage_collect(c_p, 0, NULL, 0);
- }
-
hipe_find_handler(c_p);
}
@@ -322,7 +321,7 @@ char *hipe_bs_allocate(int len)
Binary *bptr;
bptr = erts_bin_nrml_alloc(len);
- erts_smp_atomic_init_nob(&bptr->refc, 1);
+ erts_refc_init(&bptr->refc, 1);
return bptr->orig_bytes;
}
@@ -520,8 +519,9 @@ BIF_RETTYPE hipe_is_divisible(BIF_ALIST_2)
*/
Eterm hipe_check_get_msg(Process *c_p)
{
- Eterm ret;
- ErlMessage *msgp;
+ ErtsMessage *msgp;
+
+ c_p->flags |= F_DELAY_GC;
next_message:
@@ -543,25 +543,29 @@ Eterm hipe_check_get_msg(Process *c_p)
/* XXX: BEAM doesn't need this */
c_p->hipe_smp.have_receive_locks = 1;
#endif
+ c_p->flags &= ~F_DELAY_GC;
return THE_NON_VALUE;
#ifdef ERTS_SMP
}
#endif
}
- ErtsMoveMsgAttachmentIntoProc(msgp, c_p, c_p->stop, HEAP_TOP(c_p),
- c_p->fcalls, (void) 0, (void) 0);
- ret = ERL_MESSAGE_TERM(msgp);
- if (is_non_value(ret)) {
+
+ if (is_non_value(ERL_MESSAGE_TERM(msgp))
+ && !erts_decode_dist_message(c_p, ERTS_PROC_LOCK_MAIN, msgp, 0)) {
/*
* A corrupt distribution message that we weren't able to decode;
* remove it...
*/
ASSERT(!msgp->data.attached);
UNLINK_MESSAGE(c_p, msgp);
- free_message(msgp);
+ msgp->next = NULL;
+ erts_cleanup_messages(msgp);
goto next_message;
}
- return ret;
+
+ ASSERT(is_value(ERL_MESSAGE_TERM(msgp)));
+
+ return ERL_MESSAGE_TERM(msgp);
}
/*
@@ -587,7 +591,7 @@ void hipe_clear_timeout(Process *c_p)
}
#endif
if (IS_TRACED_FL(c_p, F_TRACE_RECEIVE)) {
- trace_receive(c_p, am_timeout);
+ trace_receive(c_p, am_clock_service, am_timeout, NULL);
}
c_p->flags &= ~F_TIMO;
JOIN_MESSAGE(c_p);
diff --git a/erts/emulator/hipe/hipe_native_bif.h b/erts/emulator/hipe/hipe_native_bif.h
index 55a0d3bb1b..a02d26087b 100644
--- a/erts/emulator/hipe/hipe_native_bif.h
+++ b/erts/emulator/hipe/hipe_native_bif.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_ops.tab b/erts/emulator/hipe/hipe_ops.tab
index d021c72ac9..96e4c0da91 100644
--- a/erts/emulator/hipe/hipe_ops.tab
+++ b/erts/emulator/hipe/hipe_ops.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2011. All Rights Reserved.
+# Copyright Ericsson AB 2001-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_ppc.c b/erts/emulator/hipe/hipe_ppc.c
index 3f86de626d..9b2048c457 100644
--- a/erts/emulator/hipe/hipe_ppc.c
+++ b/erts/emulator/hipe/hipe_ppc.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_ppc.h b/erts/emulator/hipe/hipe_ppc.h
index 777c9384d5..e86c122fb1 100644
--- a/erts/emulator/hipe/hipe_ppc.h
+++ b/erts/emulator/hipe/hipe_ppc.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_ppc.tab b/erts/emulator/hipe/hipe_ppc.tab
index 5bf2320cbe..274612d9ce 100644
--- a/erts/emulator/hipe/hipe_ppc.tab
+++ b/erts/emulator/hipe/hipe_ppc.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2011. All Rights Reserved.
+# Copyright Ericsson AB 2004-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_ppc64.tab b/erts/emulator/hipe/hipe_ppc64.tab
index 301a9752f7..a291185b57 100644
--- a/erts/emulator/hipe/hipe_ppc64.tab
+++ b/erts/emulator/hipe/hipe_ppc64.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2011. All Rights Reserved.
+# Copyright Ericsson AB 2005-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_ppc_asm.m4 b/erts/emulator/hipe/hipe_ppc_asm.m4
index ea74923d1f..be25d65725 100644
--- a/erts/emulator/hipe/hipe_ppc_asm.m4
+++ b/erts/emulator/hipe/hipe_ppc_asm.m4
@@ -2,7 +2,7 @@ changecom(`/*', `*/')dnl
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_ppc_bifs.m4 b/erts/emulator/hipe/hipe_ppc_bifs.m4
index 28518827ec..b540562185 100644
--- a/erts/emulator/hipe/hipe_ppc_bifs.m4
+++ b/erts/emulator/hipe/hipe_ppc_bifs.m4
@@ -2,7 +2,7 @@ changecom(`/*', `*/')dnl
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2012. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -212,8 +212,9 @@ ASYM($1):
* gc_bif_interface_0(nbif_name, cbif_name)
* gc_bif_interface_1(nbif_name, cbif_name)
* gc_bif_interface_2(nbif_name, cbif_name)
+ * gc_bif_interface_3(nbif_name, cbif_name)
*
- * Generate native interface for a BIF with 0-2 parameters and
+ * Generate native interface for a BIF with 0-3 parameters and
* standard failure mode.
* The BIF may do a GC.
*/
@@ -300,6 +301,39 @@ ASYM($1):
TYPE_FUNCTION(ASYM($1))
#endif')
+define(gc_bif_interface_3,
+`
+#ifndef HAVE_$1
+#`define' HAVE_$1
+ GLOBAL(ASYM($1))
+ASYM($1):
+ /* Set up C argument registers. */
+ mr r3, P
+ NBIF_ARG(r4,3,0)
+ NBIF_ARG(r5,3,1)
+ NBIF_ARG(r6,3,2)
+
+ /* Save caller-save registers and call the C function. */
+ SAVE_CONTEXT_GC
+ STORE r4, P_ARG0(r3) /* Store BIF__ARGS in def_arg_reg[] */
+ STORE r5, P_ARG1(r3)
+ STORE r6, P_ARG2(r3)
+ addi r4, r3, P_ARG0
+ CALL_BIF($2)
+ TEST_GOT_MBUF
+
+ /* Restore registers. Check for exception. */
+ CMPI r3, THE_NON_VALUE
+ RESTORE_CONTEXT_GC
+ beq- 1f
+ NBIF_RET(3)
+1: /* workaround for bc:s small offset operand */
+ b CSYM(nbif_3_simple_exception)
+ HANDLE_GOT_MBUF(3)
+ SET_SIZE(ASYM($1))
+ TYPE_FUNCTION(ASYM($1))
+#endif')
+
/*
* gc_nofail_primop_interface_1(nbif_name, cbif_name)
*
diff --git a/erts/emulator/hipe/hipe_ppc_gc.h b/erts/emulator/hipe/hipe_ppc_gc.h
index 0854d9e950..a6ec1338ff 100644
--- a/erts/emulator/hipe/hipe_ppc_gc.h
+++ b/erts/emulator/hipe/hipe_ppc_gc.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_ppc_glue.S b/erts/emulator/hipe/hipe_ppc_glue.S
index 6e2022603c..44351dc06c 100644
--- a/erts/emulator/hipe/hipe_ppc_glue.S
+++ b/erts/emulator/hipe/hipe_ppc_glue.S
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_ppc_glue.h b/erts/emulator/hipe/hipe_ppc_glue.h
index 93ca39fcb3..2bfa10298c 100644
--- a/erts/emulator/hipe/hipe_ppc_glue.h
+++ b/erts/emulator/hipe/hipe_ppc_glue.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_ppc_primops.h b/erts/emulator/hipe/hipe_ppc_primops.h
index ce3dda9eb3..540605de9f 100644
--- a/erts/emulator/hipe/hipe_ppc_primops.h
+++ b/erts/emulator/hipe/hipe_ppc_primops.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_primops.h b/erts/emulator/hipe/hipe_primops.h
index 0bec677574..4fcbc9df38 100644
--- a/erts/emulator/hipe/hipe_primops.h
+++ b/erts/emulator/hipe/hipe_primops.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_process.h b/erts/emulator/hipe/hipe_process.h
index 60d09ea1c9..a8d5972280 100644
--- a/erts/emulator/hipe/hipe_process.h
+++ b/erts/emulator/hipe/hipe_process.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,6 +52,9 @@ struct hipe_process_state {
#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
void (*bif_callee)(void); /* When calling BIF's via debug wrapper */
#endif
+#ifdef DEBUG
+ UWord gc_is_unsafe; /* Nonzero when GC-required state is on stack */
+#endif
};
extern void hipe_arch_print_pcb(struct hipe_process_state *p);
@@ -68,6 +71,9 @@ static __inline__ void hipe_init_process(struct hipe_process_state *p)
p->nra = NULL;
#endif
p->narity = 0;
+#ifdef DEBUG
+ p->gc_is_unsafe = 0;
+#endif
}
static __inline__ void hipe_delete_process(struct hipe_process_state *p)
diff --git a/erts/emulator/hipe/hipe_risc_gc.h b/erts/emulator/hipe/hipe_risc_gc.h
index 770ec93459..09568c140e 100644
--- a/erts/emulator/hipe/hipe_risc_gc.h
+++ b/erts/emulator/hipe/hipe_risc_gc.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,6 +51,19 @@ nstack_walk_init_sdesc(const Process *p, struct nstack_walk_state *state)
return sdesc;
}
+static inline const struct sdesc*
+nstack_walk_init_sdesc_ignore_trap(const Process *p,
+ struct nstack_walk_state *state)
+{
+ unsigned long ra = (unsigned long)p->hipe.nra;
+ const struct sdesc *sdesc;
+ if (ra == (unsigned long)&nbif_stack_trap_ra)
+ ra = (unsigned long)p->hipe.ngra;
+ sdesc = hipe_find_sdesc(ra);
+ state->sdesc0 = sdesc;
+ return sdesc;
+}
+
static inline void nstack_walk_update_trap(Process *p, const struct sdesc *sdesc0)
{
Eterm *nsp = p->hipe.nsp;
diff --git a/erts/emulator/hipe/hipe_risc_glue.h b/erts/emulator/hipe/hipe_risc_glue.h
index 51db7eac01..0284265307 100644
--- a/erts/emulator/hipe/hipe_risc_glue.h
+++ b/erts/emulator/hipe/hipe_risc_glue.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_risc_stack.c b/erts/emulator/hipe/hipe_risc_stack.c
index fd04421381..dc98c96b8f 100644
--- a/erts/emulator/hipe/hipe_risc_stack.c
+++ b/erts/emulator/hipe/hipe_risc_stack.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_signal.h b/erts/emulator/hipe/hipe_signal.h
index b2f461797d..5d8621135b 100644
--- a/erts/emulator/hipe/hipe_signal.h
+++ b/erts/emulator/hipe/hipe_signal.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_sparc.c b/erts/emulator/hipe/hipe_sparc.c
index bd95bc5d98..23020f34ee 100644
--- a/erts/emulator/hipe/hipe_sparc.c
+++ b/erts/emulator/hipe/hipe_sparc.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2003-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2003-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_sparc.h b/erts/emulator/hipe/hipe_sparc.h
index 0b74b2db26..25d513e988 100644
--- a/erts/emulator/hipe/hipe_sparc.h
+++ b/erts/emulator/hipe/hipe_sparc.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2003-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2003-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_sparc.tab b/erts/emulator/hipe/hipe_sparc.tab
index 2f528c0607..bc90d38168 100644
--- a/erts/emulator/hipe/hipe_sparc.tab
+++ b/erts/emulator/hipe/hipe_sparc.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2011. All Rights Reserved.
+# Copyright Ericsson AB 2004-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_sparc_asm.m4 b/erts/emulator/hipe/hipe_sparc_asm.m4
index 227a1658b4..8a9a516eab 100644
--- a/erts/emulator/hipe/hipe_sparc_asm.m4
+++ b/erts/emulator/hipe/hipe_sparc_asm.m4
@@ -2,7 +2,7 @@ changecom(`/*', `*/')dnl
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2007-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2007-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_sparc_bifs.m4 b/erts/emulator/hipe/hipe_sparc_bifs.m4
index a7bbe5b2cc..1389beaa61 100644
--- a/erts/emulator/hipe/hipe_sparc_bifs.m4
+++ b/erts/emulator/hipe/hipe_sparc_bifs.m4
@@ -2,7 +2,7 @@ changecom(`/*', `*/')dnl
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -210,8 +210,9 @@ $1:
* gc_bif_interface_0(nbif_name, cbif_name)
* gc_bif_interface_1(nbif_name, cbif_name)
* gc_bif_interface_2(nbif_name, cbif_name)
+ * gc_bif_interface_3(nbif_name, cbif_name)
*
- * Generate native interface for a BIF with 0-2 parameters and
+ * Generate native interface for a BIF with 0-3 parameters and
* standard failure mode.
* The BIF may do a GC.
*/
@@ -295,6 +296,37 @@ $1:
.type $1, #function
#endif')
+define(gc_bif_interface_3,
+`
+#ifndef HAVE_$1
+#`define' HAVE_$1
+ .global $1
+$1:
+ /* Set up C argument registers. */
+ mov P, %o0
+ NBIF_ARG(%o1,3,0)
+ NBIF_ARG(%o2,3,1)
+ NBIF_ARG(%o3,3,2)
+
+ /* Save caller-save registers and call the C function. */
+ SAVE_CONTEXT_GC
+ st %o1, [%o0+P_ARG0] ! Store BIF__ARGS in def_arg_reg
+ st %o2, [%o0+P_ARG1]
+ st %o3, [%o0+P_ARG2]
+ add %o0, P_ARG0, %o1
+ CALL_BIF($2)
+ nop
+ TEST_GOT_MBUF
+
+ /* Restore registers. Check for exception. */
+ TEST_GOT_EXN(3)
+ RESTORE_CONTEXT_GC
+ NBIF_RET(3)
+ HANDLE_GOT_MBUF(3)
+ .size $1, .-$1
+ .type $1, #function
+#endif')
+
/*
* gc_nofail_primop_interface_1(nbif_name, cbif_name)
*
diff --git a/erts/emulator/hipe/hipe_sparc_gc.h b/erts/emulator/hipe/hipe_sparc_gc.h
index 99e55df1ce..eea0268ed5 100644
--- a/erts/emulator/hipe/hipe_sparc_gc.h
+++ b/erts/emulator/hipe/hipe_sparc_gc.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_sparc_glue.S b/erts/emulator/hipe/hipe_sparc_glue.S
index 7e47ffb52f..077db9b8ad 100644
--- a/erts/emulator/hipe/hipe_sparc_glue.S
+++ b/erts/emulator/hipe/hipe_sparc_glue.S
@@ -2,7 +2,7 @@
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_sparc_glue.h b/erts/emulator/hipe/hipe_sparc_glue.h
index 95ce1e5b4a..3a1795f408 100644
--- a/erts/emulator/hipe/hipe_sparc_glue.h
+++ b/erts/emulator/hipe/hipe_sparc_glue.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_sparc_primops.h b/erts/emulator/hipe/hipe_sparc_primops.h
index e42bcbad62..2ecfa1293e 100644
--- a/erts/emulator/hipe/hipe_sparc_primops.h
+++ b/erts/emulator/hipe/hipe_sparc_primops.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_stack.c b/erts/emulator/hipe/hipe_stack.c
index e088b45c57..e2e6eb74b1 100644
--- a/erts/emulator/hipe/hipe_stack.c
+++ b/erts/emulator/hipe/hipe_stack.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2003-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2003-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_stack.h b/erts/emulator/hipe/hipe_stack.h
index f575b97ce3..afa0ed4256 100644
--- a/erts/emulator/hipe/hipe_stack.h
+++ b/erts/emulator/hipe/hipe_stack.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2012. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -131,5 +131,8 @@ static __inline__ void hipe_check_nstack(Process *p, unsigned nwords)
*/
extern Eterm *fullsweep_nstack(Process *p, Eterm *n_htop);
extern void gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop);
+extern Eterm *sweep_literals_nstack(Process *p, Eterm *n_htop, char *area,
+ Uint area_size);
+extern int nstack_any_heap_ref_ptrs(Process *, char* mod_start, Uint mod_size);
#endif /* HIPE_STACK_H */
diff --git a/erts/emulator/hipe/hipe_x86.c b/erts/emulator/hipe/hipe_x86.c
index 19b70afced..5f6c8c200e 100644
--- a/erts/emulator/hipe/hipe_x86.c
+++ b/erts/emulator/hipe/hipe_x86.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2003-2013. All Rights Reserved.
+ * Copyright Ericsson AB 2003-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@
void hipe_patch_load_fe(Uint32 *address, Uint32 value)
{
/* address points to a disp32 or imm32 operand */
- *address = value;
+ *address += value;
}
int hipe_patch_insn(void *address, Uint32 value, Eterm type)
@@ -54,7 +54,7 @@ int hipe_patch_insn(void *address, Uint32 value, Eterm type)
default:
return -1;
}
- *(Uint32*)address = value;
+ *(Uint32*)address += value;
return 0;
}
diff --git a/erts/emulator/hipe/hipe_x86.h b/erts/emulator/hipe/hipe_x86.h
index 30dc5666ae..8967793171 100644
--- a/erts/emulator/hipe/hipe_x86.h
+++ b/erts/emulator/hipe/hipe_x86.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2003-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2003-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_x86.tab b/erts/emulator/hipe/hipe_x86.tab
index 55fb03cde8..b922f05165 100644
--- a/erts/emulator/hipe/hipe_x86.tab
+++ b/erts/emulator/hipe/hipe_x86.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2011. All Rights Reserved.
+# Copyright Ericsson AB 2004-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_x86_abi.txt b/erts/emulator/hipe/hipe_x86_abi.txt
index b74fcef127..31a4a0e121 100644
--- a/erts/emulator/hipe/hipe_x86_abi.txt
+++ b/erts/emulator/hipe/hipe_x86_abi.txt
@@ -1,7 +1,7 @@
%CopyrightBegin%
- Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ Copyright Ericsson AB 2001-2016. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_x86_asm.m4 b/erts/emulator/hipe/hipe_x86_asm.m4
index 3457574622..91c60382eb 100644
--- a/erts/emulator/hipe/hipe_x86_asm.m4
+++ b/erts/emulator/hipe/hipe_x86_asm.m4
@@ -2,7 +2,7 @@ changecom(`/*', `*/')dnl
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_x86_bifs.m4 b/erts/emulator/hipe/hipe_x86_bifs.m4
index 0c0a8da6eb..c0c149733c 100644
--- a/erts/emulator/hipe/hipe_x86_bifs.m4
+++ b/erts/emulator/hipe/hipe_x86_bifs.m4
@@ -2,7 +2,7 @@ changecom(`/*', `*/')dnl
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2012. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -671,10 +671,11 @@ noproc_primop_interface_0(nbif_handle_fp_exception, erts_restore_fpu)
define(gc_bif_interface_0,`nofail_primop_interface_0($1, $2)')
/*
- * Implement gc_bif_interface_N as standard_bif_interface_N (N=1,2).
+ * Implement gc_bif_interface_N as standard_bif_interface_N (N=1,2,3).
*/
define(gc_bif_interface_1,`standard_bif_interface_1($1, $2)')
define(gc_bif_interface_2,`standard_bif_interface_2($1, $2)')
+define(gc_bif_interface_3,`standard_bif_interface_3($1, $2)')
/*
* Implement gc_nofail_primop_interface_1 as nofail_primop_interface_1.
diff --git a/erts/emulator/hipe/hipe_x86_gc.h b/erts/emulator/hipe/hipe_x86_gc.h
index a8770ef4f9..00fe03d8f9 100644
--- a/erts/emulator/hipe/hipe_x86_gc.h
+++ b/erts/emulator/hipe/hipe_x86_gc.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2013. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -81,6 +81,23 @@ nstack_walk_init_sdesc(const Process *p, struct nstack_walk_state *state)
#endif
}
+static inline const struct sdesc*
+nstack_walk_init_sdesc_ignore_trap(const Process *p,
+ struct nstack_walk_state *state)
+{
+#ifdef SKIP_YOUNGEST_FRAME
+ unsigned long ra = p->hipe.nsp[0];
+ const struct sdesc *sdesc;
+ if (ra == (unsigned long)nbif_stack_trap_ra)
+ ra = (unsigned long)p->hipe.ngra;
+ sdesc = hipe_find_sdesc(ra);
+ state->sdesc0 = sdesc;
+ return sdesc;
+#else
+ return nstack_walk_init_sdesc(p, state);
+#endif
+}
+
static inline void nstack_walk_update_trap(Process *p, const struct sdesc *sdesc0)
{
#ifdef SKIP_YOUNGEST_FRAME
diff --git a/erts/emulator/hipe/hipe_x86_glue.S b/erts/emulator/hipe/hipe_x86_glue.S
index cf382c480d..8d6e377730 100644
--- a/erts/emulator/hipe/hipe_x86_glue.S
+++ b/erts/emulator/hipe/hipe_x86_glue.S
@@ -2,7 +2,7 @@
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_x86_glue.h b/erts/emulator/hipe/hipe_x86_glue.h
index 6c123e8938..818d7444e2 100644
--- a/erts/emulator/hipe/hipe_x86_glue.h
+++ b/erts/emulator/hipe/hipe_x86_glue.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_x86_primops.h b/erts/emulator/hipe/hipe_x86_primops.h
index 3e057059bc..68a284203e 100644
--- a/erts/emulator/hipe/hipe_x86_primops.h
+++ b/erts/emulator/hipe/hipe_x86_primops.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/hipe/hipe_x86_signal.c b/erts/emulator/hipe/hipe_x86_signal.c
index b7dae88417..50d08b96d3 100644
--- a/erts/emulator/hipe/hipe_x86_signal.c
+++ b/erts/emulator/hipe/hipe_x86_signal.c
@@ -2,7 +2,7 @@
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2014. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,9 +38,6 @@
*
* Our solution is to override the C library's signal handler setup
* procedure with our own which enforces the SA_ONSTACK flag.
- *
- * XXX: This code only supports Linux with glibc-2.1 or above,
- * and Solaris 8.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -55,27 +52,6 @@
#include "hipe_signal.h"
#if __GLIBC__ == 2 && (__GLIBC_MINOR__ >= 3)
-/* See comment below for glibc 2.2. */
-#ifndef __USE_GNU
-#define __USE_GNU /* to un-hide RTLD_NEXT */
-#endif
-#include <dlfcn.h>
-static int (*__next_sigaction)(int, const struct sigaction*, struct sigaction*);
-#define init_done() (__next_sigaction != 0)
-extern int __sigaction(int, const struct sigaction*, struct sigaction*);
-#define __SIGACTION __sigaction
-static void do_init(void)
-{
- __next_sigaction = dlsym(RTLD_NEXT, "__sigaction");
- if (__next_sigaction != 0)
- return;
- perror("dlsym");
- abort();
-}
-#define INIT() do { if (!init_done()) do_init(); } while (0)
-#endif /* glibc 2.3 */
-
-#if __GLIBC__ == 2 && (__GLIBC_MINOR__ == 2 /*|| __GLIBC_MINOR__ == 3*/)
/*
* __libc_sigaction() is the core routine.
* Without libpthread, sigaction() and __sigaction() are both aliases
@@ -100,65 +76,14 @@ static void do_init(void)
* old BSD or SysV interfaces.
* glibc's internal calls to __sigaction() appear to be mostly safe.
* hipe_signal_init() fixes some unsafe ones, e.g. the SIGPROF handler.
- *
- * Tested with glibc-2.1.92 on RedHat 7.0, glibc-2.2.2 on RedHat 7.1,
- * glibc-2.2.4 on RedHat 7.2, and glibc-2.2.5 on RedHat 7.3.
*/
-#if 0
-/* works with 2.2.5 and 2.2.4, but not 2.2.2 or 2.1.92 */
+#ifndef __USE_GNU
#define __USE_GNU /* to un-hide RTLD_NEXT */
-#include <dlfcn.h>
-static int (*__next_sigaction)(int, const struct sigaction*, struct sigaction*);
-#define init_done() (__next_sigaction != 0)
-#define __SIGACTION __sigaction
-static void do_init(void)
-{
- __next_sigaction = dlsym(RTLD_NEXT, "__sigaction");
- if (__next_sigaction != 0)
- return;
- perror("dlsym");
- abort();
-}
-#define INIT() do { if (!init_done()) do_init(); } while (0)
-#else
-/* semi-works with all 2.2 versions so far */
-extern int __sigaction(int, const struct sigaction*, struct sigaction*);
-#define __next_sigaction __sigaction /* pthreads-aware version */
-#undef __SIGACTION /* we can't override __sigaction() */
-#define INIT() do{}while(0)
#endif
-#endif /* glibc 2.2 */
-
-#if __GLIBC__ == 2 && __GLIBC_MINOR__ == 1
-/*
- * __sigaction() is the core routine.
- * Without libpthread, sigaction() is an alias for __sigaction().
- * libpthread redefines sigaction() as a non-trivial wrapper around
- * __sigaction().
- * glibc has internal calls to both sigaction() and __sigaction().
- *
- * Overriding __sigaction() would be ideal, but doing so breaks
- * libpthread (threads hang). Instead we override sigaction() and
- * use dlsym RTLD_NEXT to find glibc's version of sigaction().
- * glibc's internal calls to __sigaction() appear to be mostly safe.
- * hipe_signal_init() fixes some unsafe ones, e.g. the SIGPROF handler.
- *
- * Tested with glibc-2.1.3 on RedHat 6.2.
- */
-#include <dlfcn.h>
-static int (*__next_sigaction)(int, const struct sigaction*, struct sigaction*);
-#define init_done() (__next_sigaction != 0)
-#undef __SIGACTION
-static void do_init(void)
-{
- __next_sigaction = dlsym(RTLD_NEXT, "sigaction");
- if (__next_sigaction != 0)
- return;
- perror("dlsym");
- abort();
-}
-#define INIT() do { if (!init_done()) do_init(); } while (0)
-#endif /* glibc 2.1 */
+#define NEXT_SIGACTION "__sigaction"
+#define LIBC_SIGACTION __sigaction
+#define OVERRIDE_SIGACTION
+#endif /* glibc >= 2.3 */
/* Is there no standard identifier for Darwin/MacOSX ? */
#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__)
@@ -181,21 +106,10 @@ static void do_init(void)
* The other _sigaction, _sigaction_no_bind I don't understand the purpose
* of and don't modify.
*/
-#include <dlfcn.h>
-static int (*__next_sigaction)(int, const struct sigaction*, struct sigaction*);
-#define init_done() (__next_sigaction != 0)
-extern int _sigaction(int, const struct sigaction*, struct sigaction*);
-#define __SIGACTION _sigaction
-static void do_init(void)
-{
- __next_sigaction = dlsym(RTLD_NEXT, "sigaction");
- if (__next_sigaction != 0)
- return;
- perror("dlsym_darwin");
- abort();
-}
+#define NEXT_SIGACTION "sigaction"
+#define LIBC_SIGACTION _sigaction
+#undef OVERRIDE_SIGACTION
#define _NSIG NSIG
-#define INIT() do { if (!init_done()) do_init(); } while (0)
#endif /* __DARWIN__ */
#if defined(__sun__)
@@ -218,20 +132,10 @@ static void do_init(void)
* our init routine has had a chance to find _sigaction()'s address.
* This forces us to initialise at the first call.
*/
-#include <dlfcn.h>
-static int (*__next_sigaction)(int, const struct sigaction*, struct sigaction*);
-#define init_done() (__next_sigaction != 0)
-#define __SIGACTION _sigaction
-static void do_init(void)
-{
- __next_sigaction = dlsym(RTLD_NEXT, "_sigaction");
- if (__next_sigaction != 0)
- return;
- perror("dlsym");
- abort();
-}
+#define NEXT_SIGACTION "_sigaction"
+#define LIBC_SIGACTION _sigaction
+#define OVERRIDE_SIGACTION
#define _NSIG NSIG
-#define INIT() do { if (!init_done()) do_init(); } while (0)
#endif /* __sun__ */
#if defined(__FreeBSD__)
@@ -239,23 +143,22 @@ static void do_init(void)
* This is a copy of Darwin code for FreeBSD.
* CAVEAT: detailed semantics are not verified yet.
*/
-#include <dlfcn.h>
-static int (*__next_sigaction)(int, const struct sigaction*, struct sigaction*);
-#define init_done() (__next_sigaction != 0)
-extern int _sigaction(int, const struct sigaction*, struct sigaction*);
-#define __SIGACTION _sigaction
-static void do_init(void)
-{
- __next_sigaction = dlsym(RTLD_NEXT, "sigaction");
- if (__next_sigaction != 0)
- return;
- perror("dlsym_freebsd");
- abort();
-}
+#define NEXT_SIGACTION "sigaction"
+#define LIBC_SIGACTION _sigaction
+#undef OVERRIDE_SIGACTION
#define _NSIG NSIG
-#define INIT() do { if (!init_done()) do_init(); } while (0)
#endif /* __FreeBSD__ */
+#if defined(__NetBSD__)
+/*
+ * Note: This is only stub code to allow the build to succeed.
+ * Whether this actually provides the needed overrides for safe
+ * signal delivery or not is unknown.
+ */
+#undef NEXT_SIGACTION
+#undef OVERRIDE_SIGACTION
+#endif /* __NetBSD__ */
+
#if !(defined(__GLIBC__) || defined(__DARWIN__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__sun__))
/*
* Unknown libc -- assume musl. Note: musl deliberately does not provide a musl-specific
@@ -265,30 +168,40 @@ static void do_init(void)
* There are libc-internal calls to __libc_sigaction which install handlers, so we must
* override __libc_sigaction rather than __sigaction.
*/
+#define NEXT_SIGACTION "__libc_sigaction"
+#define LIBC_SIGACTION __libc_sigaction
+#define OVERRIDE_SIGACTION
+#ifndef _NSIG
+#define _NSIG NSIG
+#endif
+#endif /* !(__GLIBC__ || __DARWIN__ || __NetBSD__ || __FreeBSD__ || __sun__) */
+
+#if defined(NEXT_SIGACTION)
+/*
+ * Initialize a function pointer to the libc core sigaction routine,
+ * to be used by our wrappers.
+ */
#include <dlfcn.h>
-static int (*__next_sigaction)(int, const struct sigaction*, struct sigaction*);
-#define init_done() (__next_sigaction != 0)
-#define __SIGACTION __libc_sigaction
+static int (*next_sigaction)(int, const struct sigaction*, struct sigaction*);
static void do_init(void)
{
- __next_sigaction = dlsym(RTLD_NEXT, "__libc_sigaction");
- if (__next_sigaction != 0)
+ next_sigaction = dlsym(RTLD_NEXT, NEXT_SIGACTION);
+ if (next_sigaction != 0)
return;
perror("dlsym");
abort();
}
-#ifndef _NSIG
-#define _NSIG NSIG
-#endif
-#define INIT() do { if (!init_done()) do_init(); } while (0)
-#endif /* !(__GLIBC__ || __DARWIN__ || __NetBSD__ || __FreeBSD__ || __sun__) */
+#define INIT() do { if (!next_sigaction) do_init(); } while (0)
+#else /* !defined(NEXT_SIGACTION) */
+#define INIT() do { } while (0)
+#endif /* !defined(NEXT_SIGACTION) */
-#if !defined(__NetBSD__)
+#if defined(NEXT_SIGACTION)
/*
* This is our wrapper for sigaction(). sigaction() can be called before
* hipe_signal_init() has been executed, especially when threads support
* has been linked with the executable. Therefore, we must initialise
- * __next_sigaction() dynamically, the first time it's needed.
+ * next_sigaction() dynamically, the first time it's needed.
*/
static int my_sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
{
@@ -304,24 +217,26 @@ static int my_sigaction(int signum, const struct sigaction *act, struct sigactio
newact.sa_flags |= SA_ONSTACK;
act = &newact;
}
- return __next_sigaction(signum, act, oldact);
+ return next_sigaction(signum, act, oldact);
}
#endif
+
+#if defined(LIBC_SIGACTION)
/*
* This overrides the C library's core sigaction() procedure, catching
* all its internal calls.
*/
-#ifdef __SIGACTION
-int __SIGACTION(int signum, const struct sigaction *act, struct sigaction *oldact)
+extern int LIBC_SIGACTION(int, const struct sigaction*, struct sigaction*);
+int LIBC_SIGACTION(int signum, const struct sigaction *act, struct sigaction *oldact)
{
return my_sigaction(signum, act, oldact);
}
#endif
+#if defined(OVERRIDE_SIGACTION)
/*
* This catches the application's own sigaction() calls.
*/
-#if !defined(__DARWIN__) && !defined(__NetBSD__) && !defined(__FreeBSD__)
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
{
return my_sigaction(signum, act, oldact);
@@ -336,15 +251,11 @@ static void hipe_sigaltstack(void *ss_sp)
stack_t ss;
ss.ss_sp = ss_sp;
- ss.ss_flags = SS_ONSTACK;
+ ss.ss_flags = 0;
ss.ss_size = SIGSTKSZ;
if (sigaltstack(&ss, NULL) < 0) {
- /* might be a broken pre-2.4 Linux kernel, try harder */
- ss.ss_flags = 0;
- if (sigaltstack(&ss, NULL) < 0) {
- perror("sigaltstack");
- abort();
- }
+ perror("sigaltstack");
+ abort();
}
}
@@ -381,9 +292,7 @@ void hipe_signal_init(void)
struct sigaction sa;
int i;
-#ifndef __NetBSD__
INIT();
-#endif
hipe_sigaltstack_init();
diff --git a/erts/emulator/hipe/hipe_x86_stack.c b/erts/emulator/hipe/hipe_x86_stack.c
index 6629713a05..f1559b1451 100644
--- a/erts/emulator/hipe/hipe_x86_stack.c
+++ b/erts/emulator/hipe/hipe_x86_stack.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.