aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/Makefile12
-rw-r--r--erts/configure.in4
-rw-r--r--erts/doc/src/erl.xml7
-rw-r--r--erts/doc/src/erlang.xml28
-rw-r--r--erts/doc/src/notes.xml590
-rw-r--r--erts/emulator/beam/beam_bp.c21
-rw-r--r--erts/emulator/beam/beam_emu.c76
-rw-r--r--erts/emulator/beam/beam_load.c21
-rw-r--r--erts/emulator/beam/beam_load.h1
-rw-r--r--erts/emulator/beam/big.c25
-rw-r--r--erts/emulator/beam/big.h2
-rw-r--r--erts/emulator/beam/erl_alloc.c22
-rw-r--r--erts/emulator/beam/erl_alloc.h7
-rw-r--r--erts/emulator/beam/erl_cpu_topology.c11
-rw-r--r--erts/emulator/beam/erl_cpu_topology.h8
-rw-r--r--erts/emulator/beam/erl_db_util.c52
-rw-r--r--erts/emulator/beam/erl_gc.c2
-rw-r--r--erts/emulator/beam/erl_init.c24
-rw-r--r--erts/emulator/beam/erl_lock_count.c29
-rw-r--r--erts/emulator/beam/erl_lock_count.h3
-rw-r--r--erts/emulator/beam/erl_nif_api_funcs.h4
-rw-r--r--erts/emulator/beam/erl_port.h10
-rw-r--r--erts/emulator/beam/erl_port_task.c7
-rw-r--r--erts/emulator/beam/erl_port_task.h9
-rw-r--r--erts/emulator/beam/erl_process.c39
-rw-r--r--erts/emulator/beam/erl_process.h7
-rw-r--r--erts/emulator/beam/erl_smp.h2
-rw-r--r--erts/emulator/beam/erl_threads.h6
-rw-r--r--erts/emulator/beam/global.h2
-rw-r--r--erts/emulator/beam/io.c10
-rw-r--r--erts/emulator/beam/ops.tab128
-rw-r--r--erts/emulator/test/call_trace_SUITE.erl2
-rw-r--r--erts/emulator/test/code_SUITE.erl21
-rw-r--r--erts/emulator/test/driver_SUITE.erl2
-rw-r--r--erts/emulator/test/hipe_SUITE.erl68
-rw-r--r--erts/emulator/test/hipe_SUITE_data/trycatch_1.erl14
-rw-r--r--erts/emulator/test/hipe_SUITE_data/trycatch_2.erl10
-rw-r--r--erts/emulator/test/hipe_SUITE_data/trycatch_3.erl9
-rw-r--r--erts/emulator/test/mtx_SUITE.erl2
-rw-r--r--erts/emulator/test/signal_SUITE.erl2
-rw-r--r--erts/emulator/test/statistics_SUITE.erl4
-rw-r--r--erts/emulator/test/trace_SUITE.erl4
-rw-r--r--erts/emulator/test/trace_local_SUITE.erl1
-rw-r--r--erts/emulator/test/trace_meta_SUITE.erl2
-rwxr-xr-xerts/emulator/utils/beam_makeops151
-rw-r--r--erts/etc/common/erlexec.c105
-rw-r--r--erts/etc/unix/Makefile4
-rw-r--r--erts/start_scripts/Makefile2
-rw-r--r--erts/test/upgrade_SUITE.erl2
49 files changed, 556 insertions, 1018 deletions
diff --git a/erts/Makefile b/erts/Makefile
index e9928b6b47..12d2ec57a8 100644
--- a/erts/Makefile
+++ b/erts/Makefile
@@ -40,8 +40,8 @@ all: $(FLAVORS)
docs:
$(V_at)( cd doc/src && $(MAKE) $@ )
-.PHONY: debug opt clean
-debug opt clean:
+.PHONY: debug opt lcnt clean
+debug opt lcnt clean:
$(V_at)for d in emulator $(ERTSDIRS); do \
if test -d $$d; then \
( cd $$d && $(MAKE) $@ FLAVOR=$(FLAVOR) ) || exit $$? ; \
@@ -56,7 +56,9 @@ debug opt clean:
.PHONY: $(FLAVORS)
$(FLAVORS):
- $(V_at)( $(MAKE) opt FLAVOR=$@ )
+ $(V_at)for type in $(TYPES); do \
+ ( $(MAKE) $$type FLAVOR=$@ ); \
+ done
# Make erl script and erlc in $(ERL_TOP)/bin which runs the compiled version
# Note that erlc is not a script and requires extra handling on cygwin.
@@ -128,7 +130,9 @@ makefiles:
.PHONY: release
release:
$(V_at)for f in $(FLAVORS); do \
- ( cd emulator && $(MAKE) release FLAVOR=$$f ) \
+ for t in $(TYPES); do \
+ ( cd emulator && $(MAKE) release FLAVOR=$$f TYPE=$$t ) \
+ done \
done
$(V_at)for d in $(ERTSDIRS) $(XINSTDIRS); do \
if test -d $$d; then \
diff --git a/erts/configure.in b/erts/configure.in
index c82ebaa74c..830e3d7776 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -1002,6 +1002,7 @@ else
fi
FLAVORS=
+TYPES=opt
ERTS_BUILD_SMP_EMU=$enable_smp_support
AC_MSG_CHECKING(whether an emulator with smp support should be built)
case $ERTS_BUILD_SMP_EMU in
@@ -1210,6 +1211,7 @@ esac
AC_SUBST(ERTS_BUILD_PLAIN_EMU)
AC_SUBST(FLAVORS)
+AC_SUBST(TYPES)
case "$ERTS_BUILD_PLAIN_EMU-$ERTS_BUILD_SMP_EMU" in
no-no)
@@ -1365,7 +1367,7 @@ else
AC_MSG_CHECKING(whether lock counters should be enabled)
AC_MSG_RESULT($enable_lock_count)
if test "x$enable_lock_count" != "xno"; then
- EMU_THR_DEFS="$EMU_THR_DEFS -DERTS_ENABLE_LOCK_COUNT"
+ TYPES="$TYPES lcnt"
fi
case $host_os in
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml
index 6046e94599..e1aa5ce76e 100644
--- a/erts/doc/src/erl.xml
+++ b/erts/doc/src/erl.xml
@@ -239,6 +239,13 @@
<item>
<p>Useful for debugging. Prints the arguments sent to the emulator.</p>
</item>
+ <tag><c><![CDATA[-emu_type Type]]></c></tag>
+ <item>
+ <p>Start an emulator of a different type. For example, to start
+ the lock-counter emualator, use <c>-emu_type lcnt</c>. (The emulator
+ must already be built. Use the <c>configure</c> option
+ <c>--enable-lock-counter</c> to build the lock-counter emulator.)</p>
+ </item>
<tag><c><![CDATA[-env Variable Value]]></c></tag>
<item>
<p>Sets the host OS environment variable <c><![CDATA[Variable]]></c> to
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 6f70ae4a52..6d165e9eff 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -1813,8 +1813,9 @@ true</pre>
<fsummary>Get the call stack back-trace of the last exception.</fsummary>
<type name="stack_item"/>
<desc>
- <p>Gets the call stack back-trace (<em>stacktrace</em>) of the
- last exception in the calling process as a list of
+ <p>Gets the call stack back-trace (<em>stacktrace</em>) for an
+ exception that has just been caught
+ in the calling process as a list of
<c>{<anno>Module</anno>,<anno>Function</anno>,<anno>Arity</anno>,<anno>Location</anno>}</c>
tuples. Field <c><anno>Arity</anno></c> in the first tuple can be the
argument list of that function call instead of an arity integer,
@@ -1822,6 +1823,29 @@ true</pre>
<p>If there has not been any exceptions in a process, the
stacktrace is <c>[]</c>. After a code change for the process,
the stacktrace can also be reset to <c>[]</c>.</p>
+ <p><c>erlang:get_stacktrace/0</c> is only guaranteed to return
+ a stacktrace if called (directly or indirectly) from within the
+ scope of a <c>try</c> expression. That is, the following call works:</p>
+<pre>
+try Expr
+catch
+ C:R ->
+ {C,R,erlang:get_stacktrace()}
+end</pre>
+ <p>As does this call:</p>
+<pre>
+try Expr
+catch
+ C:R ->
+ {C,R,helper()}
+end
+
+helper() ->
+ erlang:get_stacktrace().</pre>
+
+ <warning><p>In a future release,
+ <c>erlang:get_stacktrace/0</c> will return <c>[]</c> if called
+ from outside a <c>try</c> expression.</p></warning>
<p>The stacktrace is the same data as operator <c>catch</c>
returns, for example:</p>
<pre>
diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml
index 628df1b9bd..08f6732036 100644
--- a/erts/doc/src/notes.xml
+++ b/erts/doc/src/notes.xml
@@ -32,481 +32,6 @@
<p>This document describes the changes made to the ERTS application.</p>
-<section><title>Erts 9.0</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>Fix various bugs regarding loading, upgrade and purge
- of HiPE compiled code:</p> <list> <item>The native code
- memory for a purged module was never deallocated.</item>
- <item>Wrong functions could in some cases be called after
- a module upgrade.</item>
- <item><c>erlang:check_process_code</c> did not check for
- recursive calls made from native code.</item> </list>
- <p>
- Own Id: OTP-13968</p>
- </item>
- <item>
- <p>
- Hipe optional LLVM backend does require LLVM version 3.9
- or later as older versions forced strong dependencies on
- erts internals structures.</p>
- <p>
- Own Id: OTP-14238</p>
- </item>
- <item>
- <p>
- Slogans in crash dumps have been extended to print more
- complex terms.</p>
- <p>
- Own Id: OTP-14303</p>
- </item>
- <item>
- <p>
- Fixed bug when using <c>enif_inspect_binary</c> in
- combination with <c>enif_copy</c>. In some circumstances
- the inspected binary could be realloced by the
- <c>enif_copy</c> call when it shouldn't have been.</p>
- <p>
- Own Id: OTP-14304</p>
- </item>
- <item>
- <p>
- Use <c>-fno-PIE</c> for Gentoo Hardened and others that
- don't accept linker flag <c>-no-pie</c>.</p>
- <p>
- Own Id: OTP-14307 Aux Id: PR-1379 </p>
- </item>
- <item>
- <p>
- Disable hipe for <c>ppc64le</c> architecture (little
- endian) as it is not, and has never been, supported. It
- was earlier equated with <c>ppc64</c> (big endian) which
- lead to broken build without <c>--disable-hipe</c>.</p>
- <p>
- Own Id: OTP-14314 Aux Id: ERL-369, PR-1394 </p>
- </item>
- <item>
- <p>
- Fix 'epmd -kill' to return a failure exit status code if
- epmd was not killed because of some error.</p>
- <p>
- Own Id: OTP-14324</p>
- </item>
- <item>
- <p>Fixed the following dirty scheduler related bugs:</p>
- <list> <item><p>the <c>+SDPcpu</c> command line argument
- could cause the amount of dirty CPU schedulers to be set
- to zero</p></item>
- <item><p><c>erlang:system_flag(multi_scheduling, _)</c>
- failed when only one normal scheduler was used together
- with dirty scheduler support</p></item> </list>
- <p>
- Own Id: OTP-14335</p>
- </item>
- <item>
- <p>
- Fix erlexec to handle mismatch in sysconf and proc fs
- when figuring out the cpu topology. This behaviour has
- been seen when using docker together with
- <c>--cpuset-cpus</c>.</p>
- <p>
- Own Id: OTP-14352</p>
- </item>
- <item>
- <p>
- Fixed memory segment cache used for multiblock carriers.
- Huge (> 2GB) memory segments could cause a VM crash.
- Creation of such huge memory segments used for multiblock
- carriers is however very uncommon.</p>
- <p>
- Own Id: OTP-14360 Aux Id: ERL-401, PR-1417 </p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Added <c>erlang:garbage_collect/2</c> that takes an
- option list as the last argument that can be used to
- control whether a minor or a major garbage collection is
- to be done. Doing a minor collection only collects terms
- that have recently died, but is cheaper than a mjor
- collection.</p>
- <p>
- Own Id: OTP-11695</p>
- </item>
- <item>
- <p>
- Optimized test for tuples with an atom as first element.</p>
- <p>
- Own Id: OTP-12148</p>
- </item>
- <item>
- <p>
- Erlang literals are no longer copied during process to
- process messaging.</p>
- <p>
- Own Id: OTP-13529</p>
- </item>
- <item>
- <p>Add support in the <c>erl_nif</c> API for asynchronous
- message notifications when sockets or other file
- descriptors are ready to accept read or write operations.
- The following functions have been added:</p> <list>
- <item><p>enif_select</p></item>
- <item><p>enif_monitor_process</p></item>
- <item><p>enif_demonitor_process</p></item>
- <item><p>enif_compare_monitors</p></item>
- <item><p>enif_open_resource_type_x</p></item> </list>
- <p>
- Own Id: OTP-13684</p>
- </item>
- <item>
- <p>There are two new guard BIFs '<c>floor/1</c>' and
- '<c>ceil/1</c>'. They both return integers. In the
- '<c>math</c>' module, there are two new BIFs with the
- same names that return floating point values.</p>
- <p>
- Own Id: OTP-13692</p>
- </item>
- <item>
- <p>
- Remove deprecated <c>erlang:hash/2</c>.</p>
- <p>
- *** POTENTIAL INCOMPATIBILITY ***</p>
- <p>
- Own Id: OTP-13827</p>
- </item>
- <item>
- <p>Replaced usage of deprecated symbolic <seealso
- marker="erts:erlang#type-time_unit"><c>time
- unit</c></seealso> representations.</p>
- <p>
- Own Id: OTP-13831 Aux Id: OTP-13735 </p>
- </item>
- <item>
- <p>
- Added support in zlib for extraction of the inflation
- dictionary.</p>
- <p>
- Own Id: OTP-13842</p>
- </item>
- <item>
- <p>
- The previously used purge strategy has been removed. The
- optional purge strategy introduced in ERTS version 8.1 is
- now the only strategy available.</p>
- <p>
- The new purge strategy is slightly incompatible with the
- old strategy. Previously processes holding <c>fun</c>s
- that referred to the module being purged either failed a
- soft purge, or was killed during a hard purge. The new
- strategy completely ignores <c>fun</c>s. If <c>fun</c>s
- referring to the code being purged exist, and are used
- after a purge, an exception will be raised upon usage.
- That is, the behavior will be exactly the same as the
- case when a <c>fun</c> is received by a process after the
- purge.</p>
- <p>
- For more information see the documentation of <seealso
- marker="erts:erlang#check_process_code/3"><c>erlang:check_process_code/3</c></seealso>.</p>
- <p>
- *** POTENTIAL INCOMPATIBILITY ***</p>
- <p>
- Own Id: OTP-13844 Aux Id: OTP-13833 </p>
- </item>
- <item>
- <p>
- Dirty schedulers are now enabled by default when the
- runtime system is built with SMP support.</p>
- <p>
- Own Id: OTP-13860</p>
- </item>
- <item>
- <p>
- Improved ETS lookup/insert/delete speed for large
- <c>set</c>, <c>bag</c> and <c>duplicate_bag</c> by a
- significant reduction of the hash load factor. This speed
- improvement comes at the expense of less than one word
- per table entry. Tables with less than 256 entries are
- not affected at all.</p>
- <p>
- Own Id: OTP-13903</p>
- </item>
- <item>
- <p>
- The NIF library <c>reload</c> feature is not supported
- anymore. It has been marked as deprecated since OTP R15B.
- This means that you are only allowed to do one successful
- call to <c>erlang:load_nif/2</c> for each module
- instance. A second call to <c>erlang:load_nif/2</c> will
- return <c>{error, {reload, _}}</c> even if the NIF
- library imlements the <c>reload</c> callback.</p>
- <p>
- Runtime upgrade of a NIF library is still supported by
- using the Erlang module upgrade mechanics with a current
- and an old module instance existing at the same time with
- their corresponding NIF libraries.</p>
- <p>
- *** POTENTIAL INCOMPATIBILITY ***</p>
- <p>
- Own Id: OTP-13908</p>
- </item>
- <item>
- <p>
- Add <c>erlang:system_info(atom_count)</c> and
- <c>erlang:system_info(atom_limit)</c> to provide a way to
- retrieve the current and maximum number of atoms.</p>
- <p>
- Own Id: OTP-13976</p>
- </item>
- <item>
- <p>The function <c>fmod/2</c> has been added to the
- <c>math</c> module.</p>
- <p>
- Own Id: OTP-14000</p>
- </item>
- <item>
- <p>
- <c>erlang:load_nif/2</c> returns new error type
- <c>notsup</c> when called for a HiPE compiled module,
- which is not supported.</p>
- <p>
- Own Id: OTP-14002</p>
- </item>
- <item>
- <p>
- Add driver and nif lock instrumentation to lcnt</p>
- <p>
- Own Id: OTP-14069</p>
- </item>
- <item>
- <p>
- Reduce memory pressure by converting sub-binaries to
- heap-binaries when possible. This is done during garbage
- collection.</p>
- <p>
- Own Id: OTP-14149</p>
- </item>
- <item>
- <p>
- Dirty schedulers are now enabled and supported on Erlang
- runtime systems with SMP support.</p>
- <p>
- Besides support for dirty NIFs also support for dirty
- BIFs and dirty garbage collection have been introduced.
- All garbage collections that potentially will take a long
- time to complete are now performed on dirty schedulers if
- enabled.</p>
- <p>
- <seealso
- marker="erts:erlang#statistics_scheduler_wall_time"><c>erlang:statistics(scheduler_wall_time)</c></seealso>
- now also includes information about dirty CPU schedulers.
- Code using <c>erlang:statistics(scheduler_wall_time)</c>
- may have to be rewritten to take this incompatibility
- into consideration.</p>
- <p>
- *** POTENTIAL INCOMPATIBILITY ***</p>
- <p>
- Own Id: OTP-14152</p>
- </item>
- <item>
- <p>Atoms may now contain arbitrary Unicode
- characters.</p>
- <p>
- Own Id: OTP-14178</p>
- </item>
- <item>
- <p>
- Introduce an event manager in Erlang to handle OS
- signals. A subset of OS signals may be subscribed to and
- those are described in the Kernel application.</p>
- <p>
- Own Id: OTP-14186</p>
- </item>
- <item>
- <p>
- The <c>escript</c> program now handles symbolic links to
- escripts.</p>
- <p>
- This is useful for standalone systems with
- <c>escript</c>s residing on a bin directory not included
- in the execution path (as it may cause their <c>erl</c>
- program(s) to override the desired one). Instead the
- <c>escript</c>s can be referred to via symbolic links
- from a bin directory in the path.</p>
- <p>
- Own Id: OTP-14201 Aux Id: PR-1293 </p>
- </item>
- <item>
- <p>
- All uses of the magic binary kludge has been replaced by
- uses of erlang references.</p>
- <p>
- A magic binary was presented as an empty binary, but
- actually referred other data internally in the Erlang VM.
- Since they were presented as empty binaries, different
- magic binaries compared as equal, and also lost their
- internal data when passed out of an erlang node.</p>
- <p>
- The new usage of references has not got any of these
- strange semantic issues, and the usage of these
- references has been optimized to give the same
- performance benefits as well as memory usage benefits as
- magic binaries had.</p>
- <p>
- A couple of examples of previous uses of magic binaries
- are match specifications and NIF resources.</p>
- <p>
- Own Id: OTP-14205</p>
- </item>
- <item>
- <p>
- The non-smp emulators have been deprecated and are
- scheduled for removal in OTP-21.</p>
- <p>
- In preperations for this, the threaded non-smp emulator
- is no longer built by default and has to be enabled using
- the --enable-plain-emulator to configure.</p>
- <p>
- *** POTENTIAL INCOMPATIBILITY ***</p>
- <p>
- Own Id: OTP-14272</p>
- </item>
- <item>
- <p>
- Allow HiPE to run on VM built with
- <c>--enable-m32-build</c>.</p>
- <p>
- Own Id: OTP-14330 Aux Id: PR-1397 </p>
- </item>
- <item>
- <p>
- Upgraded the OTP internal PCRE library from version 8.33
- to version 8.40. This library is used for implementation
- of the <seealso marker="stdlib:re"><c>re</c></seealso>
- regular expressions module.</p>
- <p>
- Besides various bug fixes, the new version allows for
- better stack protection. In order to utilize this
- feature, the stack size of normal scheduler threads is
- now by default set to 128 kilo words on all platforms.
- The stack size of normal scheduler threads can be set
- upon system start by passing the <seealso
- marker="erts:erl#sched_thread_stack_size"><c>+sss</c></seealso>
- command line argument to the <seealso
- marker="erts:erl"><c>erl</c></seealso> command.</p>
- <p>
- See <url
- href="http://pcre.org/original/changelog.txt"><c>http://pcre.org/original/changelog.txt</c></url>
- for information about changes made to PCRE between the
- versions 8.33 and 8.40.</p>
- <p>
- *** POTENTIAL INCOMPATIBILITY ***</p>
- <p>
- Own Id: OTP-14331 Aux Id: ERL-208 </p>
- </item>
- <item>
- <p>
- Remove generation of atoms in old latin1 external format.
- The old latin1 format can still be decoded but is never
- generated by <c>term_to_binary</c> or sent on a
- distribution channel. The new utf8 format for atoms was
- introduced in OTP R16. An OTP 20 node can therefore not
- connect to nodes older than R16.</p>
- <p>
- Own Id: OTP-14337</p>
- </item>
- <item>
- <p>
- Added function <c>re:version/0</c> which returns
- information about the OTP internal PCRE version used for
- implementation of the <c>re</c> module.</p>
- <p>
- Own Id: OTP-14347 Aux Id: PR-1412 </p>
- </item>
- <item>
- <p>
- Added new debug bif <c>erlang:list_to_port/1</c>.</p>
- <p>
- Own Id: OTP-14348</p>
- </item>
- <item>
- <p>
- Various improvements of timer management internally in
- the VM. These improvements both reduced memory
- consumption of timer wheels as well as reduce the amount
- of work that has to be performed in order to handle
- timers.</p>
- <p>
- Own Id: OTP-14356</p>
- </item>
- <item>
- <p> Sockets can now be bound to device (SO_BINDTODEVICE)
- on platforms where it is supported. </p> <p> This has
- been implemented e.g to support VRF-Lite under Linux; see
- <url
- href="https://www.kernel.org/doc/Documentation/networking/vrf.txt">
- VRF </url>, and GitHub pull request <url
- href="https://github.com/erlang/otp/pull/1326">#1326</url>.
- </p>
- <p>
- Own Id: OTP-14357 Aux Id: PR-1326 </p>
- </item>
- <item>
- <p>Added the following <seealso
- marker="erl"><c>erl</c></seealso> command line arguments
- with which you can set suggested stack for dirty
- schedulers:</p> <taglist> <tag><seealso
- marker="erl#dcpu_sched_thread_stack_size"><c>+sssdcpu</c></seealso></tag>
- <item><p>for dirty CPU schedulers</p></item>
- <tag><seealso
- marker="erl#dio_sched_thread_stack_size"><c>+sssdio</c></seealso></tag>
- <item><p>for dirty IO schedulers</p></item> </taglist>
- <p>The default suggested stack size for dirty schedulers
- is 40 kilo words.</p>
- <p>
- Own Id: OTP-14380</p>
- </item>
- <item>
- <p>
- Changed erts startup program name, argv 0, to use the
- environment variable <c>ESCRIPT_NAME</c> so that
- <c>erlc</c>, <c>dialyzer</c>, <c>typer</c>,
- <c>ct_run</c>, or the escript name can be seen with
- external programs, such as ps and htop (depending on
- options), on unix.</p>
- <p>
- If environment variable <c>ESCRIPT_NAME</c> is not set,
- argv 0 of the invoking program will be used, e.g. the
- name will be <c>erl</c>, <c>cerl</c>, or the soft link
- name.</p>
- <p>
- Own Id: OTP-14381</p>
- </item>
- <item>
- <p>
- Improvements of <c>escript</c> documentation.</p>
- <p>
- Own Id: OTP-14384 Aux Id: OTP-14201 </p>
- </item>
- <item>
- <p>
- Add function <c>enif_hash</c> for NIFs to calculate hash
- values of arbitrary terms.</p>
- <p>
- Own Id: OTP-14385 Aux Id: PR-1413 </p>
- </item>
- </list>
- </section>
-
-</section>
-
<section><title>Erts 8.3.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -2148,6 +1673,96 @@
</section>
+<section><title>Erts 7.3.1.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A bug has been fixed where if erlang was started +B on a
+ unix platform it would be killed by a SIGUSR2 signal when
+ creating a crash dump.</p>
+ <p>
+ Own Id: OTP-13425 Aux Id: ERL-94 </p>
+ </item>
+ <item>
+ <p>
+ Calls to <c>erl_drv_send_term()</c> or
+ <c>erl_drv_output_term()</c> from a non-scheduler thread
+ while the corresponding port was invalid caused the
+ emulator to enter an inconsistent state which eventually
+ caused an emulator crash.</p>
+ <p>
+ Own Id: OTP-13866</p>
+ </item>
+ <item>
+ <p>Driver and NIF operations accessing processes or ports
+ could cause an emulator crash when used from
+ non-scheduler threads. Those operations are:</p> <list>
+ <item><c>erl_drv_send_term()</c></item>
+ <item><c>driver_send_term()</c></item>
+ <item><c>erl_drv_output_term()</c></item>
+ <item><c>driver_output_term()</c></item>
+ <item><c>enif_send()</c></item>
+ <item><c>enif_port_command()</c></item> </list>
+ <p>
+ Own Id: OTP-13869</p>
+ </item>
+ <item>
+ <p>
+ Fix bug in <c>binary_to_term</c> for binaries created by
+ <c>term_to_binary </c> with option <c>compressed</c>. The
+ bug can cause <c>badarg</c> exception for a valid binary
+ when Erlang VM is linked against a <c>zlib</c> library of
+ version 1.2.9 or newer. Bug exists since OTP 17.0.</p>
+ <p>
+ Own Id: OTP-14159 Aux Id: ERL-340 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 7.3.1.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed a race that could cause a lost wakeup of a process
+ that timed out in a <c>receive ... after</c>. This bug
+ was introduced in ERTS version 7.0.</p>
+ <p>
+ Own Id: OTP-13798 Aux Id: OTP-11997 </p>
+ </item>
+ <item>
+ <p>
+ Fixed segfault after writing an erl crash dump.</p>
+ <p>
+ Own Id: OTP-13799</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 7.3.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix scheduler deadlock bug in <c>ets:update_counter/4</c>
+ when key is not found and inserting the default object
+ causes the table to grow.</p>
+ <p>
+ Own Id: OTP-13731 Aux Id: ERL-188 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 7.3.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -2399,6 +2014,31 @@
</section>
+<section><title>Erts 7.2.1.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Introduced new statistics functionality in order to
+ more efficiently retrieve information about run able and
+ active processes and ports. For more information see:</p>
+ <list> <item><seealso
+ marker="erlang#statistics_total_run_queue_lengths"><c>statistics(total_run_queue_lengths)</c></seealso></item>
+ <item><seealso
+ marker="erlang#statistics_run_queue_lengths"><c>statistics(run_queue_lengths)</c></seealso></item>
+ <item><seealso
+ marker="erlang#statistics_total_active_tasks"><c>statistics(total_active_tasks)</c></seealso></item>
+ <item><seealso
+ marker="erlang#statistics_active_tasks"><c>statistics(active_tasks)</c></seealso></item>
+ </list>
+ <p>
+ Own Id: OTP-13201</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 7.2.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c
index 92ede09102..b9453c1d9a 100644
--- a/erts/emulator/beam/beam_bp.c
+++ b/erts/emulator/beam/beam_bp.c
@@ -211,7 +211,7 @@ erts_bp_match_functions(BpFunctions* f, ErtsCodeMFA *mfa, int specified)
ci = code_hdr->functions[fi];
ASSERT(ci->op == (BeamInstr) BeamOp(op_i_func_info_IaaI));
- if (erts_is_native_break(ci)) {
+ if (erts_is_function_native(ci)) {
continue;
}
if (is_nil(ci->mfa.module)) { /* Ignore BIF stub */
@@ -277,7 +277,7 @@ erts_bp_match_export(BpFunctions* f, ErtsCodeMFA *mfa, int specified)
continue;
}
ASSERT(*pc == (BeamInstr) BeamOp(op_i_generic_breakpoint));
- } else if (erts_is_native_break(erts_code_to_codeinfo(ep->addressv[code_ix]))) {
+ } else if (erts_is_function_native(erts_code_to_codeinfo(ep->addressv[code_ix]))) {
continue;
}
@@ -611,7 +611,7 @@ erts_clear_module_break(Module *modp) {
n = (Uint)(UWord) code_hdr->num_functions;
for (i = 0; i < n; ++i) {
ErtsCodeInfo *ci = code_hdr->functions[i];
- if (erts_is_native_break(ci))
+ if (erts_is_function_native(ci))
continue;
clear_function_break(ci, ERTS_BPF_ALL);
}
@@ -620,7 +620,7 @@ erts_clear_module_break(Module *modp) {
for (i = 0; i < n; ++i) {
ErtsCodeInfo *ci = code_hdr->functions[i];
- if (erts_is_native_break(ci))
+ if (erts_is_function_native(ci))
continue;
uninstall_breakpoint(ci);
consolidate_bp_data(modp, ci, 1);
@@ -1212,17 +1212,6 @@ erts_is_mtrace_break(ErtsCodeInfo *ci, Binary **match_spec_ret,
return 0;
}
-int
-erts_is_native_break(ErtsCodeInfo *ci) {
-#ifdef HIPE
- ASSERT(ci->op == (BeamInstr) BeamOp(op_i_func_info_IaaI));
- return erts_codeinfo_to_code(ci)[0] == (BeamInstr) BeamOp(op_hipe_trap_call)
- || erts_codeinfo_to_code(ci)[0] == (BeamInstr) BeamOp(op_hipe_trap_call_closure);
-#else
- return 0;
-#endif
-}
-
int
erts_is_count_break(ErtsCodeInfo *ci, Uint *count_ret)
{
@@ -1731,7 +1720,7 @@ check_break(ErtsCodeInfo *ci, Uint break_flags)
GenericBp* g = ci->u.gen_bp;
ASSERT(ci->op == (BeamInstr) BeamOp(op_i_func_info_IaaI));
- if (erts_is_native_break(ci)) {
+ if (erts_is_function_native(ci)) {
return 0;
}
if (g) {
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 311bb94242..79d751d13e 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -158,7 +158,9 @@ do { \
/*
* Register target (X or Y register).
*/
-#define REG_TARGET(Target) (*(((Target) & 1) ? &yb(Target-1) : &xb(Target)))
+
+#define REG_TARGET_PTR(Target) (((Target) & 1) ? &yb(Target-1) : &xb(Target))
+#define REG_TARGET(Target) (*REG_TARGET_PTR(Target))
/*
* Store a result into a register given a destination descriptor.
@@ -172,8 +174,6 @@ do { \
REG_TARGET(stb_reg) = (Result); \
} while (0)
-#define StoreSimpleDest(Src, Dest) Dest = (Src)
-
/*
* Store a result into a register and execute the next instruction.
* Dst points to the word with a destination descriptor, which MUST
@@ -420,7 +420,7 @@ void** beam_ops;
#define TestHeapPutList(Need, Reg) \
do { \
TestHeap((Need), 1); \
- PutList(Reg, r(0), r(0), StoreSimpleDest); \
+ PutList(Reg, r(0), r(0)); \
CHECK_TERM(r(0)); \
} while (0)
@@ -547,11 +547,11 @@ void** beam_ops;
GetR((N)+1, Dst2); \
} while (0)
-#define PutList(H, T, Dst, Store) \
- do { \
- HTOP[0] = (H); HTOP[1] = (T); \
- Store(make_list(HTOP), Dst); \
- HTOP += 2; \
+#define PutList(H, T, Dst) \
+ do { \
+ HTOP[0] = (H); HTOP[1] = (T); \
+ Dst = make_list(HTOP); \
+ HTOP += 2; \
} while (0)
#define Swap(R1, R2) \
@@ -568,11 +568,7 @@ void** beam_ops;
R2 = Tmp = V; \
} while (0)
-#define Move(Src, Dst, Store) \
- do { \
- Eterm term = (Src); \
- Store(term, Dst); \
- } while (0)
+#define Move(Src, Dst) Dst = (Src)
#define Move2Par(S1, D1, S2, D2) \
do { \
@@ -911,7 +907,7 @@ do { \
Target = _uint_size * Unit; \
} while (0)
-#define BsGetFloat2(Ms, Live, Sz, Flags, Dst, Store, Fail) \
+#define BsGetFloat2(Ms, Live, Sz, Flags, Dst, Fail) \
do { \
ErlBinMatchBuffer *_mb; \
Eterm _result; Sint _size; \
@@ -922,12 +918,12 @@ do { \
LIGHT_SWAPOUT; \
_result = erts_bs_get_float_2(c_p, _size, (Flags), _mb); \
LIGHT_SWAPIN; \
- HEAP_SPACE_VERIFIED(0); \
+ HEAP_SPACE_VERIFIED(0); \
if (is_non_value(_result)) { Fail; } \
- else { Store(_result, Dst); } \
+ else { Dst = _result; } \
} while (0)
-#define BsGetBinaryImm_2(Ms, Live, Sz, Flags, Dst, Store, Fail) \
+#define BsGetBinaryImm_2(Ms, Live, Sz, Flags, Dst, Fail) \
do { \
ErlBinMatchBuffer *_mb; \
Eterm _result; \
@@ -936,12 +932,12 @@ do { \
LIGHT_SWAPOUT; \
_result = erts_bs_get_binary_2(c_p, (Sz), (Flags), _mb); \
LIGHT_SWAPIN; \
- HEAP_SPACE_VERIFIED(0); \
+ HEAP_SPACE_VERIFIED(0); \
if (is_non_value(_result)) { Fail; } \
- else { Store(_result, Dst); } \
+ else { Dst = _result; } \
} while (0)
-#define BsGetBinary_2(Ms, Live, Sz, Flags, Dst, Store, Fail) \
+#define BsGetBinary_2(Ms, Live, Sz, Flags, Dst, Fail) \
do { \
ErlBinMatchBuffer *_mb; \
Eterm _result; Uint _size; \
@@ -951,27 +947,27 @@ do { \
LIGHT_SWAPOUT; \
_result = erts_bs_get_binary_2(c_p, _size, (Flags), _mb); \
LIGHT_SWAPIN; \
- HEAP_SPACE_VERIFIED(0); \
+ HEAP_SPACE_VERIFIED(0); \
if (is_non_value(_result)) { Fail; } \
- else { Store(_result, Dst); } \
+ else { Dst = _result; } \
} while (0)
-#define BsGetBinaryAll_2(Ms, Live, Unit, Dst, Store, Fail) \
- do { \
- ErlBinMatchBuffer *_mb; \
- Eterm _result; \
- TestHeap(ERL_SUB_BIN_SIZE, Live); \
- _mb = ms_matchbuffer(Ms); \
- if (((_mb->size - _mb->offset) % Unit) == 0) { \
- LIGHT_SWAPOUT; \
- _result = erts_bs_get_binary_all_2(c_p, _mb); \
- LIGHT_SWAPIN; \
- HEAP_SPACE_VERIFIED(0); \
- ASSERT(is_value(_result)); \
- Store(_result, Dst); \
- } else { \
- HEAP_SPACE_VERIFIED(0); \
- Fail; } \
+#define BsGetBinaryAll_2(Ms, Live, Unit, Dst, Fail) \
+ do { \
+ ErlBinMatchBuffer *_mb; \
+ Eterm _result; \
+ TestHeap(ERL_SUB_BIN_SIZE, Live); \
+ _mb = ms_matchbuffer(Ms); \
+ if (((_mb->size - _mb->offset) % Unit) == 0) { \
+ LIGHT_SWAPOUT; \
+ _result = erts_bs_get_binary_all_2(c_p, _mb); \
+ LIGHT_SWAPIN; \
+ HEAP_SPACE_VERIFIED(0); \
+ ASSERT(is_value(_result)); \
+ Dst = _result; \
+ } else { \
+ HEAP_SPACE_VERIFIED(0); \
+ Fail; } \
} while (0)
#define BsSkipBits2(Ms, Bits, Unit, Fail) \
@@ -1814,6 +1810,7 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array)
c_p->catches--;
make_blank(yb(Arg(0)));
if (is_non_value(r(0))) {
+ c_p->fvalue = NIL;
if (x(1) == am_throw) {
r(0) = x(2);
} else {
@@ -1843,6 +1840,7 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array)
c_p->catches--;
make_blank(yb(Arg(0)));
if (is_non_value(r(0))) {
+ c_p->fvalue = NIL;
r(0) = x(1);
x(1) = x(2);
x(2) = x(3);
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index a0351746b9..23258dbe9c 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -5685,17 +5685,28 @@ erts_is_module_native(BeamCodeHeader* code_hdr)
if (code_hdr != NULL) {
num_functions = code_hdr->num_functions;
for (i=0; i<num_functions; i++) {
- BeamInstr* func_info = (BeamInstr *) code_hdr->functions[i];
- Eterm name = (Eterm) func_info[3];
- if (is_atom(name)) {
- return func_info[1] != 0;
+ ErtsCodeInfo* ci = code_hdr->functions[i];
+ if (is_atom(ci->mfa.function)) {
+ return erts_is_function_native(ci);
}
- else ASSERT(is_nil(name)); /* ignore BIF stubs */
+ else ASSERT(is_nil(ci->mfa.function)); /* ignore BIF stubs */
}
}
return 0;
}
+int
+erts_is_function_native(ErtsCodeInfo *ci)
+{
+#ifdef HIPE
+ ASSERT(ci->op == (BeamInstr) BeamOp(op_i_func_info_IaaI));
+ return erts_codeinfo_to_code(ci)[0] == (BeamInstr) BeamOp(op_hipe_trap_call)
+ || erts_codeinfo_to_code(ci)[0] == (BeamInstr) BeamOp(op_hipe_trap_call_closure);
+#else
+ return 0;
+#endif
+}
+
/*
* Builds a list of all functions including native addresses.
* [{Name,Arity,NativeAddress},...]
diff --git a/erts/emulator/beam/beam_load.h b/erts/emulator/beam/beam_load.h
index 659b9c303f..b8d8634e28 100644
--- a/erts/emulator/beam/beam_load.h
+++ b/erts/emulator/beam/beam_load.h
@@ -119,6 +119,7 @@ typedef struct beam_code_header {
void erts_release_literal_area(struct ErtsLiteralArea_* literal_area);
int erts_is_module_native(BeamCodeHeader* code);
+int erts_is_function_native(ErtsCodeInfo*);
void erts_beam_bif_load_init(void);
struct erl_fun_entry;
void erts_purge_state_add_fun(struct erl_fun_entry *fe);
diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c
index 4baee7900b..1f6feade1c 100644
--- a/erts/emulator/beam/big.c
+++ b/erts/emulator/beam/big.c
@@ -2266,21 +2266,6 @@ Eterm big_minus(Eterm x, Eterm y, Eterm *r)
}
/*
-** Subtract a digit from big number
-*/
-Eterm big_minus_small(Eterm x, Eterm y, Eterm *r)
-{
- Eterm* xp = big_val(x);
-
- if (BIG_SIGN(xp))
- return big_norm(r, D_add(BIG_V(xp),BIG_SIZE(xp), (ErtsDigit) y, BIG_V(r)),
- (short) BIG_SIGN(xp));
- else
- return big_norm(r, D_sub(BIG_V(xp),BIG_SIZE(xp), (ErtsDigit) y, BIG_V(r)),
- (short) BIG_SIGN(xp));
-}
-
-/*
** Multiply smallnums
*/
@@ -2412,16 +2397,6 @@ Eterm big_rem(Eterm x, Eterm y, Eterm *r)
}
}
-Eterm big_neg(Eterm x, Eterm *r)
-{
- Eterm* xp = big_val(x);
- dsize_t xsz = BIG_SIZE(xp);
- short xsgn = BIG_SIGN(xp);
-
- MOVE_DIGITS(BIG_V(r), BIG_V(xp), xsz);
- return big_norm(r, xsz, (short) !xsgn);
-}
-
Eterm big_band(Eterm x, Eterm y, Eterm *r)
{
Eterm* xp = big_val(x);
diff --git a/erts/emulator/beam/big.h b/erts/emulator/beam/big.h
index 4a96d971c3..258038a157 100644
--- a/erts/emulator/beam/big.h
+++ b/erts/emulator/beam/big.h
@@ -118,9 +118,7 @@ Eterm big_minus(Eterm, Eterm, Eterm*);
Eterm big_times(Eterm, Eterm, Eterm*);
Eterm big_div(Eterm, Eterm, Eterm*);
Eterm big_rem(Eterm, Eterm, Eterm*);
-Eterm big_neg(Eterm, Eterm*);
-Eterm big_minus_small(Eterm, Uint, Eterm*);
Eterm big_plus_small(Eterm, Uint, Eterm*);
Eterm big_times_small(Eterm, Uint, Eterm*);
diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c
index b2c1133ded..169e1e423d 100644
--- a/erts/emulator/beam/erl_alloc.c
+++ b/erts/emulator/beam/erl_alloc.c
@@ -3512,28 +3512,6 @@ void erts_allctr_wrapper_pre_unlock(void)
}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
- * Deprecated functions *
- * *
- * These functions are still defined since "non-OTP linked in drivers" may *
- * contain (illegal) calls to them. *
-\* */
-
-/* --- DO *NOT* USE THESE FUNCTIONS --- */
-
-void *sys_alloc(Uint sz)
-{ return erts_alloc_fnf(ERTS_ALC_T_UNDEF, sz); }
-void *sys_realloc(void *ptr, Uint sz)
-{ return erts_realloc_fnf(ERTS_ALC_T_UNDEF, ptr, sz); }
-void sys_free(void *ptr)
-{ erts_free(ERTS_ALC_T_UNDEF, ptr); }
-void *safe_alloc(Uint sz)
-{ return erts_alloc(ERTS_ALC_T_UNDEF, sz); }
-void *safe_realloc(void *ptr, Uint sz)
-{ return erts_realloc(ERTS_ALC_T_UNDEF, ptr, sz); }
-
-
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* NOTE: erts_alc_test() is only supposed to be used for testing. *
* *
diff --git a/erts/emulator/beam/erl_alloc.h b/erts/emulator/beam/erl_alloc.h
index 56a3b73bf9..758d529f87 100644
--- a/erts/emulator/beam/erl_alloc.h
+++ b/erts/emulator/beam/erl_alloc.h
@@ -173,13 +173,6 @@ __decl_noreturn void erts_realloc_n_enomem(ErtsAlcType_t,void*,Uint)
__decl_noreturn void erts_alc_fatal_error(int,int,ErtsAlcType_t,...)
__noreturn;
-/* --- DO *NOT* USE THESE DEPRECATED FUNCTIONS --- Instead use: */
-void *safe_alloc(Uint) __deprecated; /* erts_alloc() */
-void *safe_realloc(void *, Uint) __deprecated; /* erts_realloc() */
-void sys_free(void *) __deprecated; /* erts_free() */
-void *sys_alloc(Uint ) __deprecated; /* erts_alloc_fnf() */
-void *sys_realloc(void *, Uint) __deprecated; /* erts_realloc_fnf() */
-
#undef ERTS_HAVE_IS_IN_LITERAL_RANGE
#if defined(ARCH_32) || defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
# define ERTS_HAVE_IS_IN_LITERAL_RANGE
diff --git a/erts/emulator/beam/erl_cpu_topology.c b/erts/emulator/beam/erl_cpu_topology.c
index 28aaeeb479..4347f9f2b7 100644
--- a/erts/emulator/beam/erl_cpu_topology.c
+++ b/erts/emulator/beam/erl_cpu_topology.c
@@ -827,17 +827,6 @@ erts_sched_bind_atfork_child(int unbind)
return 0;
}
-char *
-erts_sched_bind_atvfork_child(int unbind)
-{
- if (unbind) {
- ERTS_SMP_LC_ASSERT(erts_lc_rwmtx_is_rlocked(&cpuinfo_rwmtx)
- || erts_lc_rwmtx_is_rwlocked(&cpuinfo_rwmtx));
- return erts_get_unbind_from_cpu_str(cpuinfo);
- }
- return "false";
-}
-
void
erts_sched_bind_atfork_parent(int unbind)
{
diff --git a/erts/emulator/beam/erl_cpu_topology.h b/erts/emulator/beam/erl_cpu_topology.h
index 45324ac4a0..cf139d95a9 100644
--- a/erts/emulator/beam/erl_cpu_topology.h
+++ b/erts/emulator/beam/erl_cpu_topology.h
@@ -85,22 +85,14 @@ void erts_sched_bind_atthrcreate_parent(int unbind);
int erts_sched_bind_atfork_prepare(void);
int erts_sched_bind_atfork_child(int unbind);
-char *erts_sched_bind_atvfork_child(int unbind);
void erts_sched_bind_atfork_parent(int unbind);
Eterm erts_fake_scheduler_bindings(Process *p, Eterm how);
Eterm erts_debug_cpu_groups_map(Process *c_p, int groups);
-
typedef void (*erts_cpu_groups_callback_t)(int,
ErtsSchedulerData *,
int,
void *);
-void erts_add_cpu_groups(int groups,
- erts_cpu_groups_callback_t callback,
- void *arg);
-void erts_remove_cpu_groups(erts_cpu_groups_callback_t callback,
- void *arg);
-
#endif
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index 91ac53ad0b..13eacaa8a9 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -1125,12 +1125,11 @@ error:
* Returns true if 'b' is guaranteed to always construct
* the same term as 'a' has matched.
*/
-static int db_match_eq_body(Eterm a, Eterm b)
+static int db_match_eq_body(Eterm a, Eterm b, int const_mode)
{
DECLARE_ESTACK(s);
Uint arity;
Eterm *ap, *bp;
- int const_mode = 0;
const Eterm CONST_MODE_OFF = THE_NON_VALUE;
while (1) {
@@ -1224,6 +1223,7 @@ int db_match_keeps_key(int keypos, Eterm match, Eterm guard, Eterm body)
Eterm single_body_subterm;
Eterm single_body_subterm_key;
Eterm* single_body_subterm_key_tpl;
+ int const_mode;
if (!is_list(body)) {
return 0;
@@ -1244,42 +1244,53 @@ int db_match_keeps_key(int keypos, Eterm match, Eterm guard, Eterm body)
return 0;
}
- single_body_term_tpl = tuple_val(single_body_term);
- if (arityval(*single_body_term_tpl) != 1) {
- // not the 1-element tuple we're expecting
- return 0;
- }
-
match_key = db_getkey(keypos, match);
if (!is_value(match_key)) {
// can't get key out of match
return 0;
}
- single_body_subterm = single_body_term_tpl[1];
+ single_body_term_tpl = tuple_val(single_body_term);
+ if (single_body_term_tpl[0] == make_arityval(2) &&
+ single_body_term_tpl[1] == am_const) {
+ /* {const, {"ets-tuple constant"}} */
+ single_body_subterm = single_body_term_tpl[2];
+ const_mode = 1;
+ }
+ else if (*single_body_term_tpl == make_arityval(1)) {
+ /* {{"ets-tuple construction"}} */
+ single_body_subterm = single_body_term_tpl[1];
+ const_mode = 0;
+ }
+ else {
+ /* not a tuple construction */
+ return 0;
+ }
+
single_body_subterm_key = db_getkey(keypos, single_body_subterm);
if (!is_value(single_body_subterm_key)) {
// can't get key out of single body subterm
return 0;
}
- if (db_match_eq_body(match_key, single_body_subterm_key)) {
+ if (db_match_eq_body(match_key, single_body_subterm_key, const_mode)) {
/* tuple with same key is returned */
return 1;
}
- if (!is_tuple(single_body_subterm_key)) {
- /* can't possibly be an element instruction */
+ if (const_mode) {
+ /* constant key did not match */
return 0;
}
- single_body_subterm_key_tpl = tuple_val(single_body_subterm_key);
- if (arityval(*single_body_subterm_key_tpl) != 3) {
+ if (!is_tuple(single_body_subterm_key)) {
/* can't possibly be an element instruction */
return 0;
}
- if (single_body_subterm_key_tpl[1] == am_element &&
+ single_body_subterm_key_tpl = tuple_val(single_body_subterm_key);
+ if (single_body_subterm_key_tpl[0] == make_arityval(3) &&
+ single_body_subterm_key_tpl[1] == am_element &&
single_body_subterm_key_tpl[3] == am_DollarUnderscore &&
single_body_subterm_key_tpl[2] == make_small(keypos))
{
@@ -1290,11 +1301,6 @@ int db_match_keeps_key(int keypos, Eterm match, Eterm guard, Eterm body)
return 0;
}
-/* This is used when tracing */
-Eterm erts_match_set_lint(Process *p, Eterm matchexpr) {
- return db_match_set_lint(p, matchexpr, DCOMP_TRACE);
-}
-
Eterm db_match_set_lint(Process *p, Eterm matchexpr, Uint flags)
{
Eterm l;
@@ -2006,7 +2012,8 @@ restart:
do_catch = 0;
fail_label = -1;
build_proc = psp;
- esdp->current_process = psp;
+ if (esdp)
+ esdp->current_process = psp;
#ifdef DEBUG
ASSERT(variables == mpsp->u.variables);
@@ -2675,7 +2682,8 @@ restart:
do_catch = 1;
if (in_flags & ERTS_PAM_COPY_RESULT) {
build_proc = c_p;
- esdp->current_process = c_p;
+ if (esdp)
+ esdp->current_process = c_p;
}
break;
case matchHalt:
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c
index a7a8da4ed8..2ff49c97b3 100644
--- a/erts/emulator/beam/erl_gc.c
+++ b/erts/emulator/beam/erl_gc.c
@@ -439,7 +439,7 @@ Eterm
erts_gc_after_bif_call(Process* p, Eterm result, Eterm* regs, Uint arity)
{
return erts_gc_after_bif_call_lhf(p, ERTS_INVALID_HFRAG_PTR,
- result, regs, arity);
+ result, regs, arity);
}
static ERTS_INLINE void reset_active_writer(Process *p)
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index fb38327d02..ac99f043e6 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -309,30 +309,6 @@ void erl_error(char *fmt, va_list args)
static int early_init(int *argc, char **argv);
-void
-erts_short_init(void)
-{
-
- int ncpu;
- int time_correction;
- ErtsTimeWarpMode time_warp_mode;
-
- set_default_time_adj(&time_correction,
- &time_warp_mode);
- ncpu = early_init(NULL, NULL);
- erl_init(ncpu,
- ERTS_DEFAULT_MAX_PROCESSES,
- 0,
- ERTS_DEFAULT_MAX_PORTS,
- 0,
- 0,
- time_correction,
- time_warp_mode,
- ERTS_NODE_TAB_DELAY_GC_DEFAULT,
- ERTS_DB_SPNCNT_NORMAL);
- erts_initialized = 1;
-}
-
static void
erl_init(int ncpu,
int proc_tab_sz,
diff --git a/erts/emulator/beam/erl_lock_count.c b/erts/emulator/beam/erl_lock_count.c
index 6354fc8663..aee9796171 100644
--- a/erts/emulator/beam/erl_lock_count.c
+++ b/erts/emulator/beam/erl_lock_count.c
@@ -299,22 +299,16 @@ erts_lcnt_lock_list_t *erts_lcnt_list_init(void) {
return list;
}
-/* only do this on the list with the deleted locks! */
-void erts_lcnt_list_clear(erts_lcnt_lock_list_t *list) {
- erts_lcnt_lock_t *lock = NULL,
- *next = NULL;
+static void lcnt_list_free(erts_lcnt_lock_t *head) {
+ erts_lcnt_lock_t *lock, *next;
- lock = list->head;
+ lock = head;
while(lock != NULL) {
next = lock->next;
free(lock);
lock = next;
}
-
- list->head = NULL;
- list->tail = NULL;
- list->n = 0;
}
void erts_lcnt_list_insert(erts_lcnt_lock_list_t *list, erts_lcnt_lock_t *lock) {
@@ -358,8 +352,11 @@ void erts_lcnt_init_lock(erts_lcnt_lock_t *lock, char *name, Uint16 flag ) {
void erts_lcnt_init_lock_x(erts_lcnt_lock_t *lock, char *name, Uint16 flag, Eterm id) {
int i;
- if (name == NULL) { ERTS_LCNT_CLEAR_FLAG(lock); return; }
- lcnt_lock();
+
+ if (flag & ERTS_LCNT_LT_DISABLE) {
+ ERTS_LCNT_CLEAR_FLAG(lock);
+ return;
+ }
lock->next = NULL;
lock->prev = NULL;
@@ -379,6 +376,7 @@ void erts_lcnt_init_lock_x(erts_lcnt_lock_t *lock, char *name, Uint16 flag, Eter
lcnt_clear_stats(&lock->stats[i]);
}
+ lcnt_lock();
erts_lcnt_list_insert(erts_lcnt_data->current_locks, lock);
lcnt_unlock();
}
@@ -675,12 +673,17 @@ void erts_lcnt_clear_counters(void) {
lock->n_stats = 1;
}
- /* empty deleted locks in lock list */
- erts_lcnt_list_clear(erts_lcnt_data->deleted_locks);
+ lock = erts_lcnt_data->deleted_locks->head;
+ erts_lcnt_data->deleted_locks->head = NULL;
+ erts_lcnt_data->deleted_locks->tail = NULL;
+ erts_lcnt_data->deleted_locks->n = 0;
lcnt_time(&timer_start);
lcnt_unlock();
+
+ /* free deleted locks */
+ lcnt_list_free(lock);
}
erts_lcnt_data_t *erts_lcnt_get_data(void) {
diff --git a/erts/emulator/beam/erl_lock_count.h b/erts/emulator/beam/erl_lock_count.h
index 3041474382..6caffbfe86 100644
--- a/erts/emulator/beam/erl_lock_count.h
+++ b/erts/emulator/beam/erl_lock_count.h
@@ -95,6 +95,8 @@
#define ERTS_LCNT_LO_READ (((Uint16) 1) << 6)
#define ERTS_LCNT_LO_WRITE (((Uint16) 1) << 7)
+#define ERTS_LCNT_LT_DISABLE (((Uint16) 1) << 8)
+
#define ERTS_LCNT_LO_READ_WRITE ( ERTS_LCNT_LO_READ \
| ERTS_LCNT_LO_WRITE )
@@ -204,7 +206,6 @@ void erts_lcnt_thread_exit_handler(void);
/* list operations (local) */
erts_lcnt_lock_list_t *erts_lcnt_list_init(void);
-void erts_lcnt_list_clear( erts_lcnt_lock_list_t *list);
void erts_lcnt_list_insert(erts_lcnt_lock_list_t *list, erts_lcnt_lock_t *lock);
void erts_lcnt_list_delete(erts_lcnt_lock_list_t *list, erts_lcnt_lock_t *lock);
diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h
index bbdadafade..c305732d63 100644
--- a/erts/emulator/beam/erl_nif_api_funcs.h
+++ b/erts/emulator/beam/erl_nif_api_funcs.h
@@ -177,8 +177,8 @@ ERL_NIF_API_FUNC_DECL(int,enif_thread_type,(void));
ERL_NIF_API_FUNC_DECL(int,enif_snprintf,(char * buffer, size_t size, const char *format, ...));
ERL_NIF_API_FUNC_DECL(int,enif_select,(ErlNifEnv* env, ErlNifEvent e, enum ErlNifSelectFlags flags, void* obj, const ErlNifPid* pid, ERL_NIF_TERM ref));
ERL_NIF_API_FUNC_DECL(ErlNifResourceType*,enif_open_resource_type_x,(ErlNifEnv*, const char* name_str, const ErlNifResourceTypeInit*, ErlNifResourceFlags flags, ErlNifResourceFlags* tried));
-ERL_NIF_API_FUNC_DECL(int, enif_monitor_process,(ErlNifEnv*,void* obj,const ErlNifPid*,ErlDrvMonitor *monitor));
-ERL_NIF_API_FUNC_DECL(int, enif_demonitor_process,(ErlNifEnv*,void* obj,const ErlDrvMonitor *monitor));
+ERL_NIF_API_FUNC_DECL(int, enif_monitor_process,(ErlNifEnv*,void* obj,const ErlNifPid*,ErlNifMonitor *monitor));
+ERL_NIF_API_FUNC_DECL(int, enif_demonitor_process,(ErlNifEnv*,void* obj,const ErlNifMonitor *monitor));
ERL_NIF_API_FUNC_DECL(int, enif_compare_monitors,(const ErlNifMonitor*,const ErlNifMonitor*));
ERL_NIF_API_FUNC_DECL(ErlNifUInt64,enif_hash,(ErlNifHash type, ERL_NIF_TERM term, ErlNifUInt64 salt));
diff --git a/erts/emulator/beam/erl_port.h b/erts/emulator/beam/erl_port.h
index 206078903d..5c947ad1c0 100644
--- a/erts/emulator/beam/erl_port.h
+++ b/erts/emulator/beam/erl_port.h
@@ -988,16 +988,6 @@ typedef enum {
ERTS_PORT_OP_DONE
} ErtsPortOpResult;
-ErtsPortOpResult
-erts_schedule_proc2port_signal(Process *,
- Port *,
- Eterm,
- Eterm *,
- ErtsProc2PortSigData *,
- int,
- ErtsPortTaskHandle *,
- ErtsProc2PortSigCallback);
-
int erts_deliver_port_exit(Port *, Eterm, Eterm, int, int);
/*
diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c
index 4836b9e2d3..55526e1d5e 100644
--- a/erts/emulator/beam/erl_port_task.c
+++ b/erts/emulator/beam/erl_port_task.c
@@ -2161,13 +2161,6 @@ begin_port_cleanup(Port *pp, ErtsPortTask **execqp, int *processing_busy_q_p)
#endif
}
-int
-erts_port_is_scheduled(Port *pp)
-{
- erts_aint32_t flags = erts_smp_atomic32_read_acqb(&pp->sched.flags);
- return (flags & (ERTS_PTS_FLG_IN_RUNQ|ERTS_PTS_FLG_EXEC)) != 0;
-}
-
#ifdef ERTS_SMP
void
diff --git a/erts/emulator/beam/erl_port_task.h b/erts/emulator/beam/erl_port_task.h
index e3550e878e..ab536c6f27 100644
--- a/erts/emulator/beam/erl_port_task.h
+++ b/erts/emulator/beam/erl_port_task.h
@@ -189,11 +189,13 @@ erts_port_task_init_sched(ErtsPortTaskSched *ptsp, Eterm instr_id)
erts_smp_atomic32_init_nob(&ptsp->flags, 0);
#ifdef ERTS_SMP
#ifdef ERTS_ENABLE_LOCK_COUNT
- if (!(erts_lcnt_rt_options & ERTS_LCNT_OPT_PORTLOCK))
- lock_str = NULL;
-#endif
+ erts_mtx_init_x_opt(&ptsp->mtx, lock_str, instr_id,
+ ((erts_lcnt_rt_options & ERTS_LCNT_OPT_PORTLOCK)
+ ? 0 : ERTS_LCNT_LT_DISABLE));
+#else
erts_mtx_init_x(&ptsp->mtx, lock_str, instr_id);
#endif
+#endif
}
ERTS_GLB_INLINE void
@@ -265,7 +267,6 @@ int erts_port_task_schedule(Eterm,
ErtsPortTaskType,
...);
void erts_port_task_free_port(Port *);
-int erts_port_is_scheduled(Port *);
ErtsProc2PortSigData *erts_port_task_alloc_p2p_sig_data(void);
ErtsProc2PortSigData *erts_port_task_alloc_p2p_sig_data_extra(size_t extra, void **extra_ptr);
void erts_port_task_free_p2p_sig_data(ErtsProc2PortSigData *sigdp);
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index a56ef4aedb..da27c7e7c6 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -1538,12 +1538,6 @@ proclist_destroy(ErtsProcList *plp)
}
ErtsProcList *
-erts_proclist_copy(ErtsProcList *plp)
-{
- return proclist_copy(plp);
-}
-
-ErtsProcList *
erts_proclist_create(Process *p)
{
return proclist_create(p);
@@ -3275,13 +3269,6 @@ thr_prgr_fin_wait(void *vssi)
static void init_aux_work_data(ErtsAuxWorkData *awdp, ErtsSchedulerData *esdp, char *dawwp);
-void
-erts_interupt_aux_thread_timed(ErtsMonotonicTime timeout_time)
-{
- /* TODO only poke when needed (based on timeout_time) */
- erts_sched_poke(ERTS_SCHED_SLEEP_INFO_IX(-1));
-}
-
static void *
aux_thread(void *unused)
{
@@ -9316,17 +9303,6 @@ erts_pid2proc_not_running(Process *c_p, ErtsProcLocks c_p_locks,
}
/*
- * Like erts_pid2proc_not_running(), but hands over the process
- * in a suspended state unless (c_p is looked up).
- */
-Process *
-erts_pid2proc_suspend(Process *c_p, ErtsProcLocks c_p_locks,
- Eterm pid, ErtsProcLocks pid_locks)
-{
- return pid2proc_not_running(c_p, c_p_locks, pid, pid_locks, 1);
-}
-
-/*
* erts_pid2proc_nropt() is normally the same as
* erts_pid2proc_not_running(). However it is only
* to be used when 'not running' is a pure optimization,
@@ -9444,21 +9420,6 @@ handle_pend_bif_async_suspend(Process *suspendee,
}
}
-#else
-
-/*
- * Non-smp version of erts_pid2proc_suspend().
- */
-Process *
-erts_pid2proc_suspend(Process *c_p, ErtsProcLocks c_p_locks,
- Eterm pid, ErtsProcLocks pid_locks)
-{
- Process *rp = erts_pid2proc(c_p, c_p_locks, pid, pid_locks);
- if (rp)
- erts_suspend(rp, pid_locks, NULL);
- return rp;
-}
-
#endif /* ERTS_SMP */
/*
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index 6113c8aa05..2b169bb9ce 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -1606,7 +1606,6 @@ Uint64 erts_ensure_later_proc_interval(Uint64);
Uint64 erts_step_proc_interval(void);
ErtsProcList *erts_proclist_create(Process *);
-ErtsProcList *erts_proclist_copy(ErtsProcList *);
void erts_proclist_destroy(ErtsProcList *);
ERTS_GLB_INLINE int erts_proclist_same(ErtsProcList *, Process *);
@@ -2556,10 +2555,6 @@ ERTS_TIME2REDS_IMPL__(ErtsMonotonicTime start, ErtsMonotonicTime end)
}
#endif
-Process *erts_pid2proc_suspend(Process *,
- ErtsProcLocks,
- Eterm,
- ErtsProcLocks);
#ifdef ERTS_SMP
Process *erts_pid2proc_not_running(Process *,
@@ -2601,8 +2596,6 @@ extern int erts_disable_proc_not_running_opt;
void erts_smp_notify_inc_runq(ErtsRunQueue *runq);
-void erts_interupt_aux_thread_timed(ErtsMonotonicTime timeout_time);
-
#ifdef ERTS_SMP
void erts_sched_finish_poke(ErtsSchedulerSleepInfo *, erts_aint32_t);
ERTS_GLB_INLINE void erts_sched_poke(ErtsSchedulerSleepInfo *ssi);
diff --git a/erts/emulator/beam/erl_smp.h b/erts/emulator/beam/erl_smp.h
index 14be511f86..55ba943bdd 100644
--- a/erts/emulator/beam/erl_smp.h
+++ b/erts/emulator/beam/erl_smp.h
@@ -1073,7 +1073,7 @@ ERTS_GLB_INLINE void
erts_smp_mtx_init_locked_x(erts_smp_mtx_t *mtx, char *name, Eterm extra)
{
#ifdef ERTS_SMP
- erts_mtx_init_locked_x(mtx, name, extra);
+ erts_mtx_init_locked_x_opt(mtx, name, extra, 0);
#endif
}
diff --git a/erts/emulator/beam/erl_threads.h b/erts/emulator/beam/erl_threads.h
index 9e75f6fee5..28ff5d3a42 100644
--- a/erts/emulator/beam/erl_threads.h
+++ b/erts/emulator/beam/erl_threads.h
@@ -481,7 +481,7 @@ ERTS_GLB_INLINE int erts_thr_getname(erts_tid_t tid, char *buf, size_t len);
ERTS_GLB_INLINE int erts_equal_tids(erts_tid_t x, erts_tid_t y);
ERTS_GLB_INLINE void erts_mtx_init_x(erts_mtx_t *mtx, char *name, Eterm extra);
ERTS_GLB_INLINE void erts_mtx_init_x_opt(erts_mtx_t *mtx, char *name, Eterm extra, Uint16 opt);
-ERTS_GLB_INLINE void erts_mtx_init_locked_x(erts_mtx_t *mtx, char *name, Eterm extra);
+ERTS_GLB_INLINE void erts_mtx_init_locked_x_opt(erts_mtx_t *mtx, char *name, Eterm extra, Uint16 opt);
ERTS_GLB_INLINE void erts_mtx_init(erts_mtx_t *mtx, char *name);
ERTS_GLB_INLINE void erts_mtx_init_locked(erts_mtx_t *mtx, char *name);
ERTS_GLB_INLINE void erts_mtx_destroy(erts_mtx_t *mtx);
@@ -2192,7 +2192,7 @@ erts_mtx_init_x_opt(erts_mtx_t *mtx, char *name, Eterm extra, Uint16 opt)
ERTS_GLB_INLINE void
-erts_mtx_init_locked_x(erts_mtx_t *mtx, char *name, Eterm extra)
+erts_mtx_init_locked_x_opt(erts_mtx_t *mtx, char *name, Eterm extra, Uint16 opt)
{
#ifdef USE_THREADS
int res = ethr_mutex_init(&mtx->mtx);
@@ -2202,7 +2202,7 @@ erts_mtx_init_locked_x(erts_mtx_t *mtx, char *name, Eterm extra)
erts_lc_init_lock_x(&mtx->lc, name, ERTS_LC_FLG_LT_MUTEX, extra);
#endif
#ifdef ERTS_ENABLE_LOCK_COUNT
- erts_lcnt_init_lock_x(&mtx->lcnt, name, ERTS_LCNT_LT_MUTEX, extra);
+ erts_lcnt_init_lock_x(&mtx->lcnt, name, ERTS_LCNT_LT_MUTEX | opt, extra);
#endif
ethr_mutex_lock(&mtx->mtx);
#ifdef ERTS_ENABLE_LOCK_CHECK
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index e3be6a5a22..fc95535ec3 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -1132,7 +1132,6 @@ extern erts_tid_t erts_main_thread;
#endif
extern int erts_compat_rel;
extern int erts_use_sender_punish;
-void erts_short_init(void);
void erl_start(int, char**);
void erts_usage(void);
Eterm erts_preloaded(Process* p);
@@ -1439,7 +1438,6 @@ do { \
#define MatchSetGetSource(MPSP) erts_match_set_get_source(MPSP)
extern Binary *erts_match_set_compile(Process *p, Eterm matchexpr, Eterm MFA);
-Eterm erts_match_set_lint(Process *p, Eterm matchexpr);
extern void erts_match_set_release_result(Process* p);
ERTS_GLB_INLINE void erts_match_set_release_result_trace(Process* p, Eterm);
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index bf89740fda..d25e53ada0 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -260,10 +260,12 @@ static ERTS_INLINE void port_init_instr(Port *prt
if (!prt->drv_ptr->lock) {
char *lock_str = "port_lock";
#ifdef ERTS_ENABLE_LOCK_COUNT
- if (!(erts_lcnt_rt_options & ERTS_LCNT_OPT_PORTLOCK))
- lock_str = NULL;
+ Uint16 opt = ((erts_lcnt_rt_options & ERTS_LCNT_OPT_PORTLOCK)
+ ? 0 : ERTS_LCNT_LT_DISABLE);
+#else
+ Uint16 opt = 0;
#endif
- erts_mtx_init_locked_x(prt->lock, lock_str, id);
+ erts_mtx_init_locked_x_opt(prt->lock, lock_str, id, opt);
}
#endif
erts_port_task_init_sched(&prt->sched, id);
@@ -1509,7 +1511,7 @@ port_sched_op_reply(Eterm to, Uint32 *ref_num, Eterm msg, Port* prt)
}
-ErtsPortOpResult
+static ErtsPortOpResult
erts_schedule_proc2port_signal(Process *c_p,
Port *prt,
Eterm caller,
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index 9b5bd7a749..8abe871c14 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -182,15 +182,7 @@ i_jump_on_val x f I I
i_jump_on_val y f I I
%macro: get_list GetList -pack
-get_list x x x
-get_list x x y
-get_list x y x
-get_list x y y
-
-get_list y x x
-get_list y x y
-get_list y y x
-get_list y y y
+get_list xy xy xy
# The following get_list instructions using x(0) are frequently used.
get_list r x x
@@ -218,12 +210,10 @@ set_tuple_element s d P
# Get tuple element
%macro: i_get_tuple_element GetTupleElement -pack
-i_get_tuple_element x P x
-i_get_tuple_element y P x
+i_get_tuple_element xy P x
%cold
-i_get_tuple_element x P y
-i_get_tuple_element y P y
+i_get_tuple_element xy P y
%hot
%macro: i_get_tuple_element2 GetTupleElement2 -pack
@@ -270,11 +260,7 @@ system_limit j
move C=cxy x==0 | jump Lbl => move_jump Lbl C
%macro: move_jump MoveJump -nonext
-move_jump f n
-move_jump f c
-move_jump f x
-move_jump f y
-
+move_jump f ncxy
# Movement to and from the stack is common
# Try to pack as much as we can into one instruction
@@ -326,12 +312,10 @@ swap_temp R1 R2 Tmp | line Loc | call_ext_last Live Addr D | \
is_killed(Tmp, Live) => swap R1 R2 | line Loc | call_ext_last Live Addr D
%macro: swap_temp SwapTemp -pack
-swap_temp x x x
-swap_temp x y x
+swap_temp x xy x
%macro: swap Swap -pack
-swap x x
-swap x y
+swap x xy
move Src=x D1=x | move Src=x D2=x => move_dup Src D1 D2
move Src=x SD=x | move SD=x D=x => move_dup Src SD D
@@ -381,10 +365,7 @@ move_shift x y x
move_shift x x y
%macro: move_dup MoveDup -pack
-move_dup x x x
-move_dup x x y
-move_dup y x x
-move_dup y x y
+move_dup xy x xy
%macro: move2_par Move2Par -pack
@@ -409,7 +390,7 @@ move3 x x x x x x
move S=n D=y => init D
move S=c D=y => move S x | move x D
-%macro:move Move -pack -gen_dest
+%macro:move Move -pack
move x x
move x y
move y x
@@ -483,8 +464,7 @@ i_is_ne_exact_literal f y c
is_eq_exact Lbl Y=y X=x => is_eq_exact Lbl X Y
%macro: is_eq_exact EqualExact -fail_action -pack
-is_eq_exact f x x
-is_eq_exact f x y
+is_eq_exact f x xy
is_eq_exact f s s
%macro: is_lt IsLessThan -fail_action
@@ -538,7 +518,7 @@ i_put_tuple y I
#
put_list Const=c n Dst => move Const x | put_list x n Dst
-%macro:put_list PutList -pack -gen_dest
+%macro:put_list PutList -pack
put_list x n x
put_list y n x
@@ -630,9 +610,7 @@ is_tagged_tuple Fail=f c Arity Atom => jump Fail
%macro:is_tagged_tuple IsTaggedTuple -fail_action
-is_tagged_tuple f r A a
-is_tagged_tuple f x A a
-is_tagged_tuple f y A a
+is_tagged_tuple f rxy A a
# Test tuple & arity (head)
@@ -642,21 +620,16 @@ is_tuple Fail=f S=xy | test_arity Fail=f S=xy Arity => is_tuple_of_arity Fail S
%macro:is_tuple_of_arity IsTupleOfArity -fail_action
-is_tuple_of_arity f r A
-is_tuple_of_arity f x A
-is_tuple_of_arity f y A
+is_tuple_of_arity f rxy A
%macro: is_tuple IsTuple -fail_action
-is_tuple f r
-is_tuple f x
-is_tuple f y
+is_tuple f rxy
test_arity Fail Literal=q Arity => move Literal x | test_arity Fail x Arity
test_arity Fail=f c Arity => jump Fail
%macro: test_arity IsArity -fail_action
-test_arity f x A
-test_arity f y A
+test_arity f xy A
get_tuple_element Reg=x P1 D1=x | get_tuple_element Reg=x P2 D2=x | \
get_tuple_element Reg=x P3 D3=x | \
@@ -681,8 +654,7 @@ is_integer Fail=f S=x | allocate Need Regs => is_integer_allocate Fail S Need Re
is_integer_allocate f x I I
%macro: is_integer IsInteger -fail_action
-is_integer f x
-is_integer f y
+is_integer f xy
is_list Fail=f n =>
is_list Fail Literal=q => move Literal x | is_list Fail x
@@ -696,8 +668,7 @@ is_list f y
is_nonempty_list Fail=f S=x | allocate Need Rs => is_nonempty_list_allocate Fail S Need Rs
%macro:is_nonempty_list_allocate IsNonemptyListAllocate -fail_action -pack
-is_nonempty_list_allocate f r I t
-is_nonempty_list_allocate f x I t
+is_nonempty_list_allocate f rx I t
is_nonempty_list F=f x==0 | test_heap I1 I2 => is_non_empty_list_test_heap F I1 I2
@@ -708,12 +679,10 @@ is_nonempty_list Fail=f S=x | get_list S D1=x D2=x => \
is_nonempty_list_get_list Fail S D1 D2
%macro: is_nonempty_list_get_list IsNonemptyListGetList -fail_action -pack
-is_nonempty_list_get_list f r x x
-is_nonempty_list_get_list f x x x
+is_nonempty_list_get_list f rx x x
%macro: is_nonempty_list IsNonemptyList -fail_action
-is_nonempty_list f x
-is_nonempty_list f y
+is_nonempty_list f xy
%macro: is_atom IsAtom -fail_action
is_atom f x
@@ -735,8 +704,7 @@ is_nil Fail=f n =>
is_nil Fail=f qia => jump Fail
%macro: is_nil IsNil -fail_action
-is_nil f x
-is_nil f y
+is_nil f xy
is_binary Fail Literal=q => move Literal x | is_binary Fail x
is_binary Fail=f c => jump Fail
@@ -784,8 +752,7 @@ is_boolean Fail=f ac => jump Fail
%cold
%macro: is_boolean IsBoolean -fail_action
-is_boolean f x
-is_boolean f y
+is_boolean f xy
%hot
is_function2 Fail=f acq Arity => jump Fail
@@ -1079,8 +1046,7 @@ i_get_hash c I d
i_get s d
%macro: self Self
-self x
-self y
+self xy
%macro: node Node
node x
@@ -1091,8 +1057,7 @@ node y
i_fast_element j x I d
i_fast_element j y I d
-i_element j x s d
-i_element j y s d
+i_element j xy s d
bif1 f b s d
bif1_body b s d
@@ -1111,8 +1076,7 @@ i_move_call c f
%macro:move_call MoveCall -arg_f -size -nonext
move_call/2
-move_call x f
-move_call y f
+move_call xy f
move S=c x==0 | call_last Ar P=f D => i_move_call_last P D S
move S x==0 | call_last Ar P=f D => move_call_last S P D
@@ -1122,8 +1086,7 @@ i_move_call_last f P c
%macro:move_call_last MoveCallLast -arg_f -nonext -pack
move_call_last/3
-move_call_last x f Q
-move_call_last y f Q
+move_call_last xy f Q
move S=c x==0 | call_only Ar P=f => i_move_call_only P S
move S=x x==0 | call_only Ar P=f => move_call_only S P
@@ -1167,8 +1130,7 @@ i_make_fun I t
%hot
%macro: is_function IsFunction -fail_action
-is_function f x
-is_function f y
+is_function f xy
is_function Fail=f c => jump Fail
func_info M F A => i_func_info u M F A
@@ -1180,8 +1142,7 @@ func_info M F A => i_func_info u M F A
%cold
bs_start_match2 Fail=f ica X Y D => jump Fail
bs_start_match2 Fail Bin X Y D => i_bs_start_match2 Bin Fail X Y D
-i_bs_start_match2 x f I I d
-i_bs_start_match2 y f I I d
+i_bs_start_match2 xy f I I d
bs_save2 Reg Index => gen_bs_save(Reg, Index)
i_bs_save2 x I
@@ -1209,9 +1170,9 @@ i_bs_get_integer_32 x f I d
bs_get_binary2 Fail=f Ms=x Live=u Sz=sq Unit=u Flags=u Dst=d => \
gen_get_binary2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
-%macro: i_bs_get_binary_imm2 BsGetBinaryImm_2 -fail_action -gen_dest
-%macro: i_bs_get_binary2 BsGetBinary_2 -fail_action -gen_dest
-%macro: i_bs_get_binary_all2 BsGetBinaryAll_2 -fail_action -gen_dest
+%macro: i_bs_get_binary_imm2 BsGetBinaryImm_2 -fail_action
+%macro: i_bs_get_binary2 BsGetBinary_2 -fail_action
+%macro: i_bs_get_binary_all2 BsGetBinaryAll_2 -fail_action
i_bs_get_binary_imm2 f x I I I d
i_bs_get_binary2 f x I s I d
@@ -1224,7 +1185,7 @@ bs_get_float2 Fail=f Ms=x Live=u Sz=s Unit=u Flags=u Dst=d => \
bs_get_float2 Fail=f Ms=x Live=u Sz=q Unit=u Flags=u Dst=d => jump Fail
-%macro: i_bs_get_float2 BsGetFloat2 -fail_action -gen_dest
+%macro: i_bs_get_float2 BsGetFloat2 -fail_action
i_bs_get_float2 f x I s I d
# Miscellanous
@@ -1236,8 +1197,7 @@ bs_skip_bits2 Fail=f Ms=x Sz=sq Unit=u Flags=u => \
i_bs_skip_bits_imm2 f x I
%macro: i_bs_skip_bits2 BsSkipBits2 -fail_action
-i_bs_skip_bits2 f x x I
-i_bs_skip_bits2 f x y I
+i_bs_skip_bits2 f x xy I
%macro: i_bs_skip_bits_all2 BsSkipBitsAll2 -fail_action
i_bs_skip_bits_all2 f x I
@@ -1302,8 +1262,7 @@ bs_init2 Fail Sz Words=u==0 Regs Flags Dst => \
bs_init2 Fail Sz Words Regs Flags Dst => \
i_bs_init_fail_heap Sz Words Fail Regs Dst
-i_bs_init_fail x j I d
-i_bs_init_fail y j I d
+i_bs_init_fail xy j I d
i_bs_init_fail_heap s I j I d
@@ -1324,8 +1283,7 @@ bs_init_bits Fail Sz Words=u==0 Regs Flags Dst => \
bs_init_bits Fail Sz Words Regs Flags Dst => \
i_bs_init_bits_fail_heap Sz Words Fail Regs Dst
-i_bs_init_bits_fail x j I d
-i_bs_init_bits_fail y j I d
+i_bs_init_bits_fail xy j I d
i_bs_init_bits_fail_heap s I j I d
@@ -1493,8 +1451,7 @@ is_map Fail Lit=q | literal_is_map(Lit) =>
is_map Fail cq => jump Fail
%macro: is_map IsMap -fail_action
-is_map f x
-is_map f y
+is_map f xy
## Transform has_map_fields #{ K1 := _, K2 := _ } to has_map_elements
@@ -1514,16 +1471,10 @@ i_get_map_element Fail Src=xy Key=y Dst => \
move Key x | i_get_map_element Fail Src x Dst
%macro: i_get_map_element_hash GetMapElementHash -fail_action
-i_get_map_element_hash f x c I x
-i_get_map_element_hash f y c I x
-i_get_map_element_hash f x c I y
-i_get_map_element_hash f y c I y
+i_get_map_element_hash f xy c I xy
%macro: i_get_map_element GetMapElement -fail_action
-i_get_map_element f x x x
-i_get_map_element f y x x
-i_get_map_element f x x y
-i_get_map_element f y x y
+i_get_map_element f xy x xy
#
# Convert the plus operations to a generic plus instruction.
@@ -1589,12 +1540,9 @@ gc_bif2 Fail Live u$bif:erlang:bxor/2 S1 S2 Dst => \
gc_bif1 Fail I u$bif:erlang:bnot/1 Src Dst=d => i_int_bnot Fail Src I Dst
-i_increment r I I d
-i_increment x I I d
-i_increment y I I d
+i_increment rxy I I d
-i_plus j I x x d
-i_plus j I x y d
+i_plus j I x xy d
i_plus j I s s d
i_minus j I x x d
diff --git a/erts/emulator/test/call_trace_SUITE.erl b/erts/emulator/test/call_trace_SUITE.erl
index 1216863c51..95171d04ce 100644
--- a/erts/emulator/test/call_trace_SUITE.erl
+++ b/erts/emulator/test/call_trace_SUITE.erl
@@ -60,7 +60,7 @@ all() ->
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
Config.
-end_per_testcase(_Func, Config) ->
+end_per_testcase(_Func, _Config) ->
%% Reloading the module will clear all trace patterns, and
%% in a debug-compiled emulator run assertions of the counters
%% for the number of traced exported functions in this module.
diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl
index d07166ed98..35f7baf2cf 100644
--- a/erts/emulator/test/code_SUITE.erl
+++ b/erts/emulator/test/code_SUITE.erl
@@ -229,27 +229,6 @@ multi_proc_purge(Config) when is_list(Config) ->
Pid9, Pid10, Pid11, Pid12, Pid13, Pid14, Pid15, Pid16]),
ok.
-body(F, Fakes) ->
- receive
- jog ->
- 40 = F(3),
- erlang:garbage_collect(),
- body(F, Fakes);
- drop_funs ->
- dropped_body()
- end.
-
-dropped_body() ->
- receive
- X -> exit(X)
- end.
-
-gc() ->
- erlang:garbage_collect(),
- gc1().
-gc1() -> ok.
-
-
%% Test the erlang:check_old_code/1 BIF.
t_check_old_code(Config) when is_list(Config) ->
Data = proplists:get_value(data_dir, Config),
diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl
index 2fbf6eae61..e854a5f945 100644
--- a/erts/emulator/test/driver_SUITE.erl
+++ b/erts/emulator/test/driver_SUITE.erl
@@ -127,7 +127,7 @@ init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
0 = element(1, erts_debug:get_internal_state(check_io_debug)),
[{testcase, Case}|Config].
-end_per_testcase(Case, Config) ->
+end_per_testcase(Case, _Config) ->
erlang:display({end_per_testcase, Case}),
0 = element(1, erts_debug:get_internal_state(check_io_debug)),
ok.
diff --git a/erts/emulator/test/hipe_SUITE.erl b/erts/emulator/test/hipe_SUITE.erl
index 0b44dd7fb7..5083f01f34 100644
--- a/erts/emulator/test/hipe_SUITE.erl
+++ b/erts/emulator/test/hipe_SUITE.erl
@@ -22,6 +22,7 @@
-export([all/0
,t_copy_literals/1
,t_purge/1
+ ,t_trycatch/1
]).
all() ->
@@ -29,6 +30,7 @@ all() ->
undefined -> {skip, "HiPE is disabled"};
_ -> [t_copy_literals
,t_purge
+ ,t_trycatch
]
end.
@@ -118,3 +120,69 @@ t_purge(Config) when is_list(Config) ->
call(Pid, Call) ->
Pid ! {Call, self()},
receive {Pid, Res} -> Res end.
+
+t_trycatch(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ Files = ["trycatch_1.erl","trycatch_2.erl","trycatch_3.erl"],
+ Sources0 = [filename:join(DataDir, Src) || Src <- Files],
+ Sources = trycatch_combine(Sources0),
+ t_trycatch_1(Sources).
+
+t_trycatch_1([S|Ss]) ->
+ io:format("~p", [S]),
+ compile_and_load(S),
+ call_trycatch(try_catch),
+ call_trycatch(plain_catch),
+ io:nl(),
+ t_trycatch_1(Ss);
+t_trycatch_1([]) ->
+ ok.
+
+trycatch_combine([N|Ns]) ->
+ Combined = trycatch_combine(Ns),
+ lists:append([[[{N,[]}|C],[{N,[native]},C]] || C <- Combined]);
+trycatch_combine([]) ->
+ [[]].
+
+call_trycatch(Func) ->
+ case do_call_trycatch(error, Func, {error,whatever}) of
+ {error,whatever,[{trycatch_3,three,1,_}|_]} ->
+ ok
+ end,
+ case do_call_trycatch(error, Func, fc) of
+ {error,function_clause,[{trycatch_3,three,[fc],_}|_]} ->
+ ok;
+ {error,function_clause,[{trycatch_3,three,1,_}|_]} ->
+ ok
+ end,
+ case do_call_trycatch(throw, Func, {throw,{a,b}}) of
+ {throw,{a,b},[{trycatch_3,three,1,_}|_]} ->
+ ok
+ end,
+ case do_call_trycatch(exit, Func, {exit,{a,b,c}}) of
+ {exit,{a,b,c},[{trycatch_3,three,1,_}|_]} ->
+ ok
+ end,
+ ok.
+
+do_call_trycatch(_Class, try_catch, Argument) ->
+ trycatch_1:one_try_catch(Argument);
+do_call_trycatch(error, plain_catch, Argument) ->
+ {{'EXIT',{Reason,Stk}},Stk} = trycatch_1:one_plain_catch(Argument),
+ {error,Reason,Stk};
+do_call_trycatch(throw, plain_catch, Argument) ->
+ {Reason,Stk} = trycatch_1:one_plain_catch(Argument),
+ {throw,Reason,Stk};
+do_call_trycatch(exit, plain_catch, Argument) ->
+ {{'EXIT',Reason},Stk} = trycatch_1:one_plain_catch(Argument),
+ {exit,Reason,Stk}.
+
+compile_and_load(Sources) ->
+ _ = [begin
+ {ok,Mod,Bin} = compile:file(Src, [binary,report|Opts]),
+ code:purge(Mod),
+ code:delete(Mod),
+ code:purge(Mod),
+ {module,Mod} = code:load_binary(Mod, atom_to_list(Mod), Bin)
+ end || {Src,Opts} <- Sources],
+ ok.
diff --git a/erts/emulator/test/hipe_SUITE_data/trycatch_1.erl b/erts/emulator/test/hipe_SUITE_data/trycatch_1.erl
new file mode 100644
index 0000000000..702b14b5b9
--- /dev/null
+++ b/erts/emulator/test/hipe_SUITE_data/trycatch_1.erl
@@ -0,0 +1,14 @@
+-module(trycatch_1).
+-export([one_try_catch/1,one_plain_catch/1]).
+
+one_try_catch(Term) ->
+ try
+ trycatch_2:two(Term)
+ catch
+ C:R ->
+ Stk = erlang:get_stacktrace(),
+ {C,R,Stk}
+ end.
+
+one_plain_catch(Term) ->
+ {catch trycatch_2:two(Term),erlang:get_stacktrace()}.
diff --git a/erts/emulator/test/hipe_SUITE_data/trycatch_2.erl b/erts/emulator/test/hipe_SUITE_data/trycatch_2.erl
new file mode 100644
index 0000000000..ffac420197
--- /dev/null
+++ b/erts/emulator/test/hipe_SUITE_data/trycatch_2.erl
@@ -0,0 +1,10 @@
+-module(trycatch_2).
+-export([two/1]).
+
+two(Term) ->
+ Res = trycatch_3:three(Term),
+ foo(),
+ Res.
+
+foo() ->
+ ok.
diff --git a/erts/emulator/test/hipe_SUITE_data/trycatch_3.erl b/erts/emulator/test/hipe_SUITE_data/trycatch_3.erl
new file mode 100644
index 0000000000..578fa0e87e
--- /dev/null
+++ b/erts/emulator/test/hipe_SUITE_data/trycatch_3.erl
@@ -0,0 +1,9 @@
+-module(trycatch_3).
+-export([three/1]).
+
+three({error,Term}) ->
+ error(Term);
+three({throw,Term}) ->
+ throw(Term);
+three({exit,Term}) ->
+ exit(Term).
diff --git a/erts/emulator/test/mtx_SUITE.erl b/erts/emulator/test/mtx_SUITE.erl
index 12928ed6d8..0d6ab5cdb2 100644
--- a/erts/emulator/test/mtx_SUITE.erl
+++ b/erts/emulator/test/mtx_SUITE.erl
@@ -97,7 +97,7 @@ init_per_testcase(_Case, Config) ->
wait_deallocations(),
Config.
-end_per_testcase(_Func, Config) ->
+end_per_testcase(_Func, _Config) ->
ok.
wait_deallocations() ->
diff --git a/erts/emulator/test/signal_SUITE.erl b/erts/emulator/test/signal_SUITE.erl
index 7e516176f7..d788360812 100644
--- a/erts/emulator/test/signal_SUITE.erl
+++ b/erts/emulator/test/signal_SUITE.erl
@@ -53,7 +53,7 @@ init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
available_internal_state(true),
[{testcase, Func}|Config].
-end_per_testcase(_Func, Config) ->
+end_per_testcase(_Func, _Config) ->
ok.
init_per_suite(Config) ->
diff --git a/erts/emulator/test/statistics_SUITE.erl b/erts/emulator/test/statistics_SUITE.erl
index 3057905f4c..0cea941687 100644
--- a/erts/emulator/test/statistics_SUITE.erl
+++ b/erts/emulator/test/statistics_SUITE.erl
@@ -396,7 +396,7 @@ msb_swt_hog(false) ->
count(1000000),
msb_swt_hog(false).
-msb_scheduler_wall_time(Config) ->
+msb_scheduler_wall_time(_Config) ->
erlang:system_flag(scheduler_wall_time, true),
Dirty = erlang:system_info(dirty_cpu_schedulers) /= 0,
Hogs = lists:map(fun (_) ->
@@ -493,7 +493,7 @@ badarg(Config) when is_list(Config) ->
tok_loop() ->
tok_loop().
-run_queues_lengths_active_tasks(Config) ->
+run_queues_lengths_active_tasks(_Config) ->
TokLoops = lists:map(fun (_) ->
spawn_opt(fun () ->
tok_loop()
diff --git a/erts/emulator/test/trace_SUITE.erl b/erts/emulator/test/trace_SUITE.erl
index f846b0f4b9..643c2e0472 100644
--- a/erts/emulator/test/trace_SUITE.erl
+++ b/erts/emulator/test/trace_SUITE.erl
@@ -733,7 +733,7 @@ set_on_first_spawn(Config) when is_list(Config) ->
%% Tests trace(Pid, How, [set_on_link]).
-set_on_link(Config) ->
+set_on_link(_Config) ->
Listener = fun_spawn(fun process/0),
%% Create and trace a process with the set_on_link flag.
@@ -756,7 +756,7 @@ set_on_link(Config) ->
%% Tests trace(Pid, How, [set_on_first_spawn]).
-set_on_first_link(Config) ->
+set_on_first_link(_Config) ->
ct:timetrap({seconds, 10}),
Listener = fun_spawn(fun process/0),
diff --git a/erts/emulator/test/trace_local_SUITE.erl b/erts/emulator/test/trace_local_SUITE.erl
index 5b65889f4a..1cbe6201c3 100644
--- a/erts/emulator/test/trace_local_SUITE.erl
+++ b/erts/emulator/test/trace_local_SUITE.erl
@@ -298,6 +298,7 @@ basic_test() ->
setup([call]),
NumMatches = erlang:trace_pattern({?MODULE,'_','_'},[],[local]),
NumMatches = erlang:trace_pattern({?MODULE,'_','_'},[],[local]),
+ false = code:is_module_native(?MODULE), % got fooled by local trace
erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
[1,1,1,997] = apply_slave(?MODULE,exported_wrap,[1]),
?CT(?MODULE,exported_wrap,[1]),
diff --git a/erts/emulator/test/trace_meta_SUITE.erl b/erts/emulator/test/trace_meta_SUITE.erl
index b6a6fd5404..ef58978749 100644
--- a/erts/emulator/test/trace_meta_SUITE.erl
+++ b/erts/emulator/test/trace_meta_SUITE.erl
@@ -74,7 +74,7 @@ config(priv_dir,_) ->
init_per_testcase(_Case, Config) ->
Config.
-end_per_testcase(_Case, Config) ->
+end_per_testcase(_Case, _Config) ->
shutdown(),
ok.
diff --git a/erts/emulator/utils/beam_makeops b/erts/emulator/utils/beam_makeops
index 9813142585..05cd48d434 100755
--- a/erts/emulator/utils/beam_makeops
+++ b/erts/emulator/utils/beam_makeops
@@ -332,9 +332,9 @@ while (<>) {
if (/^\%macro:(.*)/) {
my($op, $macro, @flags) = split(' ', $1);
defined($macro) and $macro =~ /^-/ and
- &error("A macro must not start with a hyphen");
+ error("A macro must not start with a hyphen");
foreach (@flags) {
- /^-/ or &error("Flags for macros should start with a hyphen");
+ /^-/ or error("Flags for macros should start with a hyphen");
}
error("Macro for '$op' is already defined")
if defined $macro{$op};
@@ -347,7 +347,7 @@ while (<>) {
# Handle transformations.
#
if (/=>/) {
- &parse_transformation($_);
+ parse_transformation($_);
next;
}
@@ -357,8 +357,8 @@ while (<>) {
$op_num = undef;
if (s/^(\d+):\s*//) {
$op_num = $1;
- $op_num != 0 or &error("Opcode 0 invalid");
- &error("Opcode $op_num already defined")
+ $op_num != 0 or error("Opcode 0 invalid");
+ error("Opcode $op_num already defined")
if defined $gen_opname[$op_num];
}
@@ -369,11 +369,11 @@ while (<>) {
my($obsolete) = $1;
my($name) = $2;
my($arity) = $3;
- $name =~ /^[a-z]/ or &error("Opname must start with a lowercase letter");
+ $name =~ /^[a-z]/ or error("Opname must start with a lowercase letter");
defined $gen_arity{$name} and $gen_arity{$name} != $arity and
- &error("Opname $name already defined with arity $gen_arity{$name}");
+ error("Opname $name already defined with arity $gen_arity{$name}");
defined $unnumbered{$name,$arity} and
- &error("Opname $name already defined with arity $gen_arity{$name}");
+ error("Opname $name already defined with arity $gen_arity{$name}");
if (defined $op_num) { # Numbered generic operation
$gen_opname[$op_num] = $name;
@@ -395,16 +395,16 @@ while (<>) {
# Name Arg1 Arg2...
#
my($name, @args) = split;
- &error("too many operands")
+ error("too many operands")
if @args > $max_spec_operands;
- &syntax_check($name, @args);
+ syntax_check($name, @args);
my $arity = @args;
if (defined $gen_opnum{$name,$arity} and $obsolete[$gen_opnum{$name,$arity}]) {
error("specific instructions may not be specified for obsolete instructions");
}
- push(@{$specific_op{"$name/$arity"}}, [$name, $hot, @args]);
+ save_specific_ops($name, $arity, $hot, @args);
if (defined $op_num) {
- &error("specific instructions must not be numbered");
+ error("specific instructions must not be numbered");
} elsif (!defined($gen_arity{$name}) && !defined($unnumbered{$name,$arity})) {
#
# Create an unumbered generic instruction too.
@@ -446,7 +446,7 @@ $num_file_opcodes = @gen_opname;
# Produce output for the chosen target.
#
-&$target;
+&$target();
#
# Produce output needed by the emulator/loader.
@@ -462,7 +462,7 @@ sub emulator_output {
#
$name = "$outdir/beam_opcodes.c";
open(STDOUT, ">$name") || die "Failed to open $name for writing: $!\n";
- &comment('C');
+ comment('C');
print "#ifdef HAVE_CONFIG_H\n";
print "# include \"config.h\"\n";
print "#endif\n\n";
@@ -525,7 +525,7 @@ sub emulator_output {
# Call a generator to calculate size and generate macros
# for the emulator.
#
- my($size, $code, $pack) = &basic_generator($name, $hot, @args);
+ my($size, $code, $pack) = basic_generator($name, $hot, @args);
#
# Save the generated $code for later.
@@ -587,7 +587,7 @@ sub emulator_output {
# Generate transformations.
#
- &tr_gen(@transformations);
+ tr_gen(@transformations);
#
# Print the generic instruction table.
@@ -602,7 +602,7 @@ sub emulator_output {
my($arity) = $gen_arity[$i];
printf "/* %3d */ ", $i;
if (!defined $name) {
- &init_item("", 0, 0, 0, -1);
+ init_item("", 0, 0, 0, -1);
} else {
my($key) = "$name/$arity";
my($tr) = defined $gen_transform_offset{$key} ?
@@ -614,7 +614,7 @@ sub emulator_output {
$is_transformed{$name,$arity} or
error("instruction $key has no specific instruction");
$spec_op = -1 unless defined $spec_op;
- &init_item($name, $arity, $spec_op, $num_specific, $tr);
+ init_item($name, $arity, $spec_op, $num_specific, $tr);
}
}
print "};\n";
@@ -624,7 +624,7 @@ sub emulator_output {
#
$name = "$outdir/beam_opcodes.h";
open(STDOUT, ">$name") || die "Failed to open $name for writing: $!\n";
- &comment('C');
+ comment('C');
print "#ifndef __OPCODES_H__\n";
print "#define __OPCODES_H__\n\n";
@@ -662,14 +662,14 @@ sub emulator_output {
my $letter;
my $tag_num = 0;
- &comment('C', "The following operand types for generic instructions",
+ comment('C', "The following operand types for generic instructions",
"occur in beam files.");
foreach $letter (split('', $compiler_types)) {
print "#define TAG_$letter $tag_num\n";
$tag_num++;
}
print "\n";
- &comment('C', "The following operand types are only used in the loader.");
+ comment('C', "The following operand types are only used in the loader.");
foreach $letter (split('', $loader_types)) {
print "#define TAG_$letter $tag_num\n";
$tag_num++;
@@ -736,26 +736,26 @@ sub emulator_output {
$name = "$outdir/beam_tr_funcs.h";
open(STDOUT, ">$name") || die "Failed to open $name for writing: $!\n";
- &comment('C');
- &tr_gen_call(@call_table);
+ comment('C');
+ tr_gen_call(@call_table);
$name = "$outdir/beam_pred_funcs.h";
open(STDOUT, ">$name") || die "Failed to open $name for writing: $!\n";
- &comment('C');
- &tr_gen_call(@pred_table);
+ comment('C');
+ tr_gen_call(@pred_table);
#
# Implementation of operations for emulator.
#
$name = "$outdir/beam_hot.h";
open(STDOUT, ">$name") || die "Failed to open $name for writing: $!\n";
- &comment('C');
- &print_code(\%hot_code);
+ comment('C');
+ print_code(\%hot_code);
$name = "$outdir/beam_cold.h";
open(STDOUT, ">$name") || die "Failed to open $name for writing: $!\n";
- &comment('C');
- &print_code(\%cold_code);
+ comment('C');
+ print_code(\%cold_code);
}
@@ -818,7 +818,7 @@ sub compiler_output {
open(STDOUT, ">$outdir/$name") || die "Failed to open $name for writing: $!\n";
print "-module($module).\n";
- &comment('erlang');
+ comment('erlang');
print "-export([format_number/0]).\n";
print "-export([opcode/2,opname/1]).\n";
@@ -830,7 +830,7 @@ sub compiler_output {
for ($i = 0; $i < @gen_opname; $i++) {
next unless defined $gen_opname[$i];
print "%%" if $obsolete[$i];
- print "opcode(", &quote($gen_opname[$i]), ", $gen_arity[$i]) -> $i;\n";
+ print "opcode(", quote($gen_opname[$i]), ", $gen_arity[$i]) -> $i;\n";
}
print "opcode(Name, Arity) -> erlang:error(badarg, [Name,Arity]).\n\n";
@@ -838,7 +838,7 @@ sub compiler_output {
for ($i = 0; $i < @gen_opname; $i++) {
next unless defined $gen_opname[$i];
print "opname($i) -> {",
- &quote($gen_opname[$i]), ",$gen_arity[$i]};\n";
+ quote($gen_opname[$i]), ",$gen_arity[$i]};\n";
}
print "opname(Number) -> erlang:error(badarg, [Number]).\n";
@@ -847,7 +847,7 @@ sub compiler_output {
#
my($hrl_name) = "$outdir/${module}.hrl";
open(STDOUT, ">$hrl_name") || die "Failed to open $hrl_name for writing: $!\n";
- &comment('erlang');
+ comment('erlang');
for ($i = 0; $i < @tag_type && $i < 8; $i++) {
print "-define(tag_$tag_type[$i], $i).\n";
@@ -863,11 +863,33 @@ sub syntax_check {
my($name, @args) = @_;
my($i);
- &error("Bad opcode name '$name'")
+ error("Bad opcode name '$name'")
unless $name =~ /^[a-z][\w\d_]*$/;
for ($i = 0; $i < @args; $i++) {
- &error("Argument " . ($i+1) . ": invalid type '$args[$i]'")
- unless defined $arg_size{$args[$i]};
+ foreach my $type (split(//, $args[$i])) {
+ error("Argument " . ($i+1) . ": invalid type '$type'")
+ unless defined $arg_size{$type};
+ }
+ }
+}
+
+sub save_specific_ops {
+ my($name,$arity,$hot,@args) = @_;
+ my(@res) = ("");
+
+ foreach my $arg (@args) {
+ my @new_res = ();
+ foreach my $type (split(//, $arg)) {
+ foreach my $args (@res) {
+ push @new_res, "$args$type";
+ }
+ }
+ @res = @new_res;
+ }
+ my $key = "$name/$arity";
+ foreach my $args (@res) {
+ @args = split //, $args;
+ push @{$specific_op{$key}}, [$name,$hot,@args];
}
}
@@ -928,7 +950,6 @@ sub basic_generator {
my($tmp_arg_num) = 1;
my($pack_spec) = '';
my($var_decls) = '';
- my($gen_dest_arg) = 'StoreSimpleDest';
my($i);
my($no_prefetch) = 0;
@@ -964,7 +985,7 @@ sub basic_generator {
#
if ($flags =~ /-pack/ && $hot) {
- ($prefix, $pack_spec, @args) = &do_pack(@args);
+ ($prefix, $pack_spec, @args) = do_pack(@args);
}
#
@@ -994,11 +1015,11 @@ sub basic_generator {
push(@f_types, $_);
$prefix .= "GetR($size, $tmp);\n";
last SWITCH; };
- /d/ and do { $var_decls .= "Eterm dst; ";
- push(@f, "dst");
+ /d/ and do { $var_decls .= "Eterm dst; Eterm* dst_ptr; ";
+ push(@f, "*dst_ptr");
push(@f_types, $_);
$prefix .= "dst = Arg($size);\n";
- $gen_dest_arg = 'StoreResult';
+ $prefix .= "dst_ptr = REG_TARGET_PTR(dst);\n";
last SWITCH;
};
defined($incl_arg{$_})
@@ -1017,14 +1038,6 @@ sub basic_generator {
}
#
- # If requested, pass a pointer to the destination register.
- # The destination must be the last operand.
- #
- if ($flags =~ /-gen_dest/) {
- push(@f, $gen_dest_arg);
- }
-
- #
# Add a fail action macro if requested.
#
@@ -1195,7 +1208,7 @@ sub do_pack {
}
$down = "$instr[$ap]$down";
- my($unpack) = &make_unpack($tmpnum, $shift[$ap], $mask[$ap]);
+ my($unpack) = make_unpack($tmpnum, $shift[$ap], $mask[$ap]);
$args[$i] = "pack:$this_size:$reg" . "b($unpack)";
if (++$ap == $args_per_word) {
@@ -1259,7 +1272,7 @@ sub parse_transformation {
foreach (@from) {
if (/^(\w+)\((.*?)\)/) {
my($name, $arglist) = ($1, $2);
- $_ = (&compile_transform_function($name, split(/\s*,\s*/, $arglist)));
+ $_ = (compile_transform_function($name, split(/\s*,\s*/, $arglist)));
} else {
(@op) = split;
($rest_var,$_) = compile_transform(1, $rest_var, @op);
@@ -1275,7 +1288,7 @@ sub parse_transformation {
my @to;
if ($to =~ /^(\w+)\((.*?)\)/) {
my($name, $arglist) = ($1, $2);
- @to = (&compile_transform_function($name, split(/\s*,\s*/, $arglist)));
+ @to = (compile_transform_function($name, split(/\s*,\s*/, $arglist)));
} else {
@to = split(/\s*\|\s*/, $to);
foreach (@to) {
@@ -1297,7 +1310,7 @@ sub compile_transform {
my $arity = 0;
foreach (@ops) {
- my(@list) = &tr_parse_op($src, $_);
+ my(@list) = tr_parse_op($src, $_);
if ($list[1] eq '*') {
$rest_var = $list[0];
} elsif (defined $rest_var and $list[0] eq $rest_var) {
@@ -1334,7 +1347,7 @@ sub tr_parse_op {
if (/^([A-Z]\w*)(.*)/) {
$var = $1;
$_ = $2;
- &error("garbage after variable")
+ error("garbage after variable")
unless /^=(.*)/ or /^(\s*)$/;
$_ = $1;
}
@@ -1345,7 +1358,7 @@ sub tr_parse_op {
$type = $1;
$_ = $2;
foreach (split('', $type)) {
- &error("bad type in $op")
+ error("bad type in $op")
unless defined $type_bit{$_} or $type eq '*';
$_ eq 'r' and
error("$op: 'r' is not allowed in transformations")
@@ -1392,7 +1405,7 @@ sub tr_parse_op {
# Nothing more is allowed after the command.
- &error("garbage '$_' after operand: $op")
+ error("garbage '$_' after operand: $op")
unless /^\s*$/;
# Test that destination has no conditions.
@@ -1519,7 +1532,7 @@ sub tr_gen_from {
# Check that $name/$arity refers to a valid generic instruction.
#
- &error($where, "invalid generic op $name/$arity")
+ error($where, "invalid generic op $name/$arity")
unless defined $gen_opnum{$name,$arity};
$opnum = $gen_opnum{$name,$arity};
@@ -1547,11 +1560,11 @@ sub tr_gen_from {
$type_mask |= $type_bit{$_};
}
if ($cond ne 'is_eq') {
- push(@code, &make_op($types, 'is_type', $type_mask));
+ push(@code, make_op($types, 'is_type', $type_mask));
} else {
$cond = '';
- push(@code, &make_op("$types== $val", 'is_type_eq',
- $type_mask, $val));
+ push(@code, make_op("$types== $val", 'is_type_eq',
+ $type_mask, $val));
}
}
}
@@ -1560,12 +1573,12 @@ sub tr_gen_from {
my($m, $f, $a) = split(/:/, $val);
$ignored_var = '';
$may_fail = 1;
- push(@code, &make_op('', "$cond", "am_$m",
+ push(@code, make_op('', "$cond", "am_$m",
"am_$f", $a));
} elsif ($cond ne '') {
$ignored_var = '';
$may_fail = 1;
- push(@code, &make_op('', "$cond", $val));
+ push(@code, make_op('', "$cond", $val));
}
if ($var ne '') {
@@ -1591,7 +1604,7 @@ sub tr_gen_from {
$var_type{$var} = 'scalar';
$var{$var} = $var_num;
$var_num++;
- push(@code, &make_op($var, 'set_var', $var{$var}));
+ push(@code, make_op($var, 'set_var', $var{$var}));
}
}
if (is_instr($code[$#code], 'set_var')) {
@@ -1600,7 +1613,7 @@ sub tr_gen_from {
my $var = $ref->[1][1];
push(@code, make_op($comment, 'set_var_next_arg', $var));
} else {
- push(@code, &make_op($ignored_var, 'next_arg'));
+ push(@code, make_op($ignored_var, 'next_arg'));
}
}
@@ -1645,7 +1658,7 @@ sub tr_gen_to {
my(@args);
foreach $var (@ops) {
- &error($where, "variable '$var' unbound")
+ error($where, "variable '$var' unbound")
unless defined $var{$var};
if ($var_type{$var} eq 'scalar') {
push(@args, "var[$var{$var}]");
@@ -1668,7 +1681,7 @@ sub tr_gen_to {
#
my($key) = "$name/$arity";
- &error($where, "invalid generic op $name/$arity")
+ error($where, "invalid generic op $name/$arity")
unless defined $gen_opnum{$name,$arity};
my $opnum = $gen_opnum{$name,$arity};
@@ -1683,15 +1696,15 @@ sub tr_gen_to {
if ($type eq '*') {
push(@code, make_op($var, 'store_rest_args'));
} elsif ($var ne '') {
- &error($where, "variable '$var' unbound")
+ error($where, "variable '$var' unbound")
unless defined $var{$var};
my $op = make_op($var, 'store_var_next_arg', $var{$var});
op_slot_usage($op, $var{$var});
push(@code, $op);
} elsif ($type ne '') {
- push(@code, &make_op('', 'store_type', "TAG_$type"));
+ push(@code, make_op('', 'store_type', "TAG_$type"));
if ($type_val) {
- push(@code, &make_op('', 'store_val', $type_val));
+ push(@code, make_op('', 'store_val', $type_val));
}
push(@code, make_op('', 'next_arg'));
}
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index f73c4ef1ca..70520eea15 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -184,17 +184,6 @@ static char *plusz_val_switches[] = {
#endif
#define SMP_SUFFIX ".smp"
-#define DEBUG_SUFFIX ".debug"
-#define EMU_TYPE_SUFFIX_LENGTH strlen(DEBUG_SUFFIX)
-
-/*
- * Define flags for different memory architectures.
- */
-#define EMU_TYPE_SMP 0x0001
-
-#ifdef __WIN32__
-#define EMU_TYPE_DEBUG 0x0004
-#endif
void usage(const char *switchname);
static void usage_format(char *format, ...);
@@ -221,7 +210,7 @@ static void *erealloc(void *p, size_t size);
static void efree(void *p);
static char* strsave(char* string);
static int is_one_of_strings(char *str, char *strs[]);
-static char *write_str(char *to, char *from);
+static char *write_str(char *to, const char *from);
static void get_home(void);
static void add_epmd_port(void);
#ifdef __WIN32__
@@ -255,9 +244,8 @@ static int verbose = 0; /* If non-zero, print some extra information. */
static int start_detached = 0; /* If non-zero, the emulator should be
* started detached (in the background).
*/
-static int emu_type = 0; /* If non-zero, start beam.ARCH or beam.ARCH.exe
- * instead of beam or beam.exe, where ARCH is defined by flags. */
-static int emu_type_passed = 0; /* Types explicitly set */
+static int start_smp_emu = 0; /* Start the smp emulator. */
+static const char* emu_type = 0; /* Type of emulator (lcnt, valgrind, etc) */
#ifdef __WIN32__
static char *start_emulator_program = NULL; /* For detachec mode -
@@ -352,11 +340,11 @@ free_env_val(char *value)
}
/*
- * Add the architecture suffix to the program name if needed,
- * except on Windows, where we insert it just before ".DLL".
+ * Add the type and architecture suffix to the program name if needed.
+ * On Windows, we insert it just before ".DLL".
*/
static char*
-add_extra_suffixes(char *prog, int type)
+add_extra_suffixes(char *prog)
{
char *res;
char *p;
@@ -366,16 +354,10 @@ add_extra_suffixes(char *prog, int type)
int dll = 0;
#endif
- if (!type) {
- return prog;
- }
-
len = strlen(prog);
- /* Worst-case allocation */
- p = emalloc(len +
- EMU_TYPE_SUFFIX_LENGTH +
- + 1);
+ /* Allocate enough extra space for suffixes */
+ p = emalloc(len + 100);
res = p;
p = write_str(p, prog);
@@ -392,13 +374,11 @@ add_extra_suffixes(char *prog, int type)
}
#endif
-#ifdef __WIN32__
- if (type & EMU_TYPE_DEBUG) {
- p = write_str(p, DEBUG_SUFFIX);
- type &= ~(EMU_TYPE_DEBUG);
+ if (emu_type) {
+ p = write_str(p, ".");
+ p = write_str(p, emu_type);
}
-#endif
- if (type == EMU_TYPE_SMP) {
+ if (start_smp_emu) {
p = write_str(p, SMP_SUFFIX);
}
#ifdef __WIN32__
@@ -489,12 +469,11 @@ int main(int argc, char **argv)
cpuinfo = erts_cpu_info_create();
/* '-smp auto' is default */
#ifdef ERTS_HAVE_SMP_EMU
- emu_type |= EMU_TYPE_SMP;
+ start_smp_emu = 1;
#endif
#if defined(__WIN32__) && defined(WIN32_ALWAYS_DEBUG)
- emu_type_passed |= EMU_TYPE_DEBUG;
- emu_type |= EMU_TYPE_DEBUG;
+ emu_type = "debug";
#endif
/* We need to do this before the ordinary processing. */
@@ -519,57 +498,42 @@ int main(int argc, char **argv)
if (strcmp(argv[i+1], "auto") == 0) {
i++;
- smp_auto:
- emu_type_passed |= EMU_TYPE_SMP;
-#if defined(ERTS_HAVE_PLAIN_EMU) && !defined(ERTS_HAVE_SMP_EMU)
- emu_type &= ~EMU_TYPE_SMP;
-#else
- emu_type |= EMU_TYPE_SMP;
-#endif
- }
- else if (strcmp(argv[i+1], "enable") == 0) {
+ } else if (strcmp(argv[i+1], "enable") == 0) {
i++;
smp_enable:
- emu_type_passed |= EMU_TYPE_SMP;
-#ifdef ERTS_HAVE_SMP_EMU
- emu_type |= EMU_TYPE_SMP;
-#else
+ ;
+#if !defined(ERTS_HAVE_SMP_EMU)
usage_notsup("-smp enable", "");
#endif
- }
- else if (strcmp(argv[i+1], "disable") == 0) {
+ } else if (strcmp(argv[i+1], "disable") == 0) {
i++;
smp_disable:
- emu_type_passed &= ~EMU_TYPE_SMP;
#ifdef ERTS_HAVE_PLAIN_EMU
- emu_type &= ~EMU_TYPE_SMP;
+ start_smp_emu = 0;
#else
usage_notsup("-smp disable", " Use \"+S 1\" instead.");
#endif
- }
- else {
+ } else {
smp:
-
- emu_type_passed |= EMU_TYPE_SMP;
-#ifdef ERTS_HAVE_SMP_EMU
- emu_type |= EMU_TYPE_SMP;
-#else
+ ;
+#if !defined(ERTS_HAVE_SMP_EMU)
usage_notsup("-smp", "");
#endif
}
} else if (strcmp(argv[i], "-smpenable") == 0) {
goto smp_enable;
} else if (strcmp(argv[i], "-smpauto") == 0) {
- goto smp_auto;
+ ;
} else if (strcmp(argv[i], "-smpdisable") == 0) {
goto smp_disable;
-#ifdef __WIN32__
- } else if (strcmp(argv[i], "-debug") == 0) {
- emu_type_passed |= EMU_TYPE_DEBUG;
- emu_type |= EMU_TYPE_DEBUG;
-#endif
} else if (strcmp(argv[i], "-extra") == 0) {
break;
+ } else if (strcmp(argv[i], "-emu_type") == 0) {
+ if (i + 1 >= argc) {
+ usage(argv[i]);
+ }
+ emu_type = argv[i+1];
+ i++;
}
}
i++;
@@ -582,7 +546,7 @@ int main(int argc, char **argv)
if (strcmp(malloc_lib, "libc") != 0)
usage("+MYm");
}
- emu = add_extra_suffixes(emu, emu_type);
+ emu = add_extra_suffixes(emu);
emu_name = strsave(emu);
erts_snprintf(tmpStr, sizeof(tmpStr), "%s" DIRSEP "%s" BINARY_EXT, bindir, emu);
emu = strsave(tmpStr);
@@ -1176,7 +1140,11 @@ int main(int argc, char **argv)
{
execv(emu, Eargsp);
}
- error("Error %d executing \'%s\'.", errno, emu);
+ if (errno == ENOENT) {
+ error("The emulator \'%s\' does not exist.", emu);
+ } else {
+ error("Error %d executing \'%s\'.", errno, emu);
+ }
return 1;
#endif
}
@@ -1376,7 +1344,7 @@ is_one_of_strings(char *str, char *strs[])
return 0;
}
-static char *write_str(char *to, char *from)
+static char *write_str(char *to, const char *from)
{
while (*from)
*(to++) = *(from++);
@@ -1903,6 +1871,7 @@ read_args_file(char *filename)
#undef SAVE_CHAR
}
+
typedef struct {
char **argv;
int argc;
diff --git a/erts/etc/unix/Makefile b/erts/etc/unix/Makefile
index 2fa9cd047b..17de4d8878 100644
--- a/erts/etc/unix/Makefile
+++ b/erts/etc/unix/Makefile
@@ -24,7 +24,7 @@ include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
include ../../vsn.mk
-opt debug: etc
+opt debug lcnt: etc
.PHONY: etc
etc: etp-commands
@@ -44,4 +44,4 @@ clean:
include $(ERL_TOP)/make/otp_release_targets.mk
.PHONY: release_spec
-release_spec: etc \ No newline at end of file
+release_spec: etc
diff --git a/erts/start_scripts/Makefile b/erts/start_scripts/Makefile
index ae2521474e..047e42170a 100644
--- a/erts/start_scripts/Makefile
+++ b/erts/start_scripts/Makefile
@@ -68,7 +68,7 @@ include $(LIBPATH)/stdlib/vsn.mk
##############################################################################
-debug opt script: rel $(INSTALL_SCRIPTS) $(RELEASES_SRC)
+debug opt lcnt script: rel $(INSTALL_SCRIPTS) $(RELEASES_SRC)
rel: $(REL_SCRIPTS)
diff --git a/erts/test/upgrade_SUITE.erl b/erts/test/upgrade_SUITE.erl
index 4185aa6a9e..a5639d927d 100644
--- a/erts/test/upgrade_SUITE.erl
+++ b/erts/test/upgrade_SUITE.erl
@@ -39,7 +39,7 @@
%% - dialyzer requires hipe (in the .app file)
%% - erl_interface, jinterface support no upgrade
-define(appup_exclude,
- [dialyzer,hipe,erl_interface,jinterface,ose]).
+ [dialyzer,hipe,typer,erl_interface,jinterface,ose]).
init_per_suite(Config) ->
%% Check that a real release is running, not e.g. cerl