aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2015-10-08 13:04:40 +0200
committerBjörn Gustavsson <[email protected]>2015-10-09 10:31:19 +0200
commit93f5844185a459cbf9efc3843919c463a2eef0fe (patch)
tree4188b1ce168a8d4d432646d061f11c315c1cf9ba /erts/emulator
parent5472eb516e969f7f9ac50ab57b195e5b043e1d79 (diff)
downloadotp-93f5844185a459cbf9efc3843919c463a2eef0fe.tar.gz
otp-93f5844185a459cbf9efc3843919c463a2eef0fe.tar.bz2
otp-93f5844185a459cbf9efc3843919c463a2eef0fe.zip
Teach erlang:is_builtin/3 that erlang:apply/3 is built-in
erlang:is_builtin(erlang, apply, 3) returns 'false'. That seems to be an oversight in the implementation of erlang:is_builtin/3 rather than a conscious design decision. Part of apply/3 is implemented in C (as a special instruction), and part of it in Erlang (only used if apply/3 is used recursively). That makes apply/3 special compared to all other BIFs. From the viewpoint of the user, apply/3 is a built-in function, since it cannot possibly be implemented in pure Erlang. Noticed-by: Stavros Aronis
Diffstat (limited to 'erts/emulator')
-rw-r--r--erts/emulator/beam/beam_emu.c9
-rw-r--r--erts/emulator/test/bif_SUITE.erl21
2 files changed, 28 insertions, 2 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index a42ce1c9f1..faf496a030 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -6752,6 +6752,15 @@ erts_is_builtin(Eterm Mod, Eterm Name, int arity)
Export e;
Export* ep;
+ if (Mod == am_erlang && Name == am_apply && arity == 3) {
+ /*
+ * Special case. apply/3 is built-in (implemented in C),
+ * but implemented in a different way than all other
+ * BIFs.
+ */
+ return 1;
+ }
+
e.code[0] = Mod;
e.code[1] = Name;
e.code[2] = arity;
diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl
index d6a771e7b9..ebc4db53c4 100644
--- a/erts/emulator/test/bif_SUITE.erl
+++ b/erts/emulator/test/bif_SUITE.erl
@@ -32,7 +32,8 @@
specs/1,improper_bif_stubs/1,auto_imports/1,
t_list_to_existing_atom/1,os_env/1,otp_7526/1,
binary_to_atom/1,binary_to_existing_atom/1,
- atom_to_binary/1,min_max/1, erlang_halt/1]).
+ atom_to_binary/1,min_max/1, erlang_halt/1,
+ is_builtin/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -42,7 +43,7 @@ all() ->
t_list_to_existing_atom, os_env, otp_7526,
display,
atom_to_binary, binary_to_atom, binary_to_existing_atom,
- min_max, erlang_halt].
+ min_max, erlang_halt, is_builtin].
groups() ->
[].
@@ -716,6 +717,22 @@ wait_until_stable_size(File,PrevSz) ->
wait_until_stable_size(File,NewSz)
end.
+is_builtin(_Config) ->
+ Exp0 = [{M,F,A} || {M,_} <- code:all_loaded(),
+ {F,A} <- M:module_info(exports)],
+ Exp = ordsets:from_list(Exp0),
+
+ %% erlang:apply/3 is considered to be built-in, but is not
+ %% implemented as other BIFs.
+
+ Builtins0 = [{erlang,apply,3}|erlang:system_info(snifs)],
+ Builtins = ordsets:from_list(Builtins0),
+ NotBuiltin = ordsets:subtract(Exp, Builtins),
+ _ = [true = erlang:is_builtin(M, F, A) || {M,F,A} <- Builtins],
+ _ = [false = erlang:is_builtin(M, F, A) || {M,F,A} <- NotBuiltin],
+
+ ok.
+
%% Helpers