aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/ops.tab
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2018-12-06 13:07:42 +0100
committerBjörn Gustavsson <[email protected]>2018-12-18 11:40:07 +0100
commit1ea57e5498d92b730644cb37b659d16e51f56b4d (patch)
tree3464aa1912825e297d0609abe0af8b3eeb1af315 /erts/emulator/beam/ops.tab
parent472b0669788e155f28851999b4e60bf8302ca2d5 (diff)
downloadotp-1ea57e5498d92b730644cb37b659d16e51f56b4d.tar.gz
otp-1ea57e5498d92b730644cb37b659d16e51f56b4d.tar.bz2
otp-1ea57e5498d92b730644cb37b659d16e51f56b4d.zip
Make length/1 yielding
The guard BIF `length/1` would calculate the length of the list in one go without yielding, even if the list was were long. To make it even worse, the call to `length/1` would only cost a single reduction. This commit reimplements `length/1` so that it eats a number of reductions proportional to the length of the list, and yields if the available reductions run out.
Diffstat (limited to 'erts/emulator/beam/ops.tab')
-rw-r--r--erts/emulator/beam/ops.tab11
1 files changed, 11 insertions, 0 deletions
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index fbed2e56e1..cb414143fc 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -1588,6 +1588,17 @@ bif1 Fail u$bif:erlang:round/1 s d => too_old_compiler
bif1 Fail u$bif:erlang:trunc/1 s d => too_old_compiler
#
+# Handle the length/1 guard BIF specially to make it trappable.
+#
+
+gc_bif1 Fail=j Live u$bif:erlang:length/1 Src Dst => \
+ i_length_setup Live Src | i_length Fail Live Dst
+
+i_length_setup t xyc
+
+i_length j? t d
+
+#
# Guard BIFs.
#
gc_bif1 p Live Bif Src Dst => i_bif1_body Bif Src Dst