aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2012-01-10 08:31:15 +0100
committerBjörn Gustavsson <[email protected]>2012-01-24 16:18:08 +0100
commit64ccd8c9b7a782ca777ca4649dbb1f4a1ef00bce (patch)
treea2a78c9027718de0f9976b1a174785a21b8fe06b /lib/kernel
parente71de38e077199d7d36cf5e3e6017cdd12dff1ba (diff)
downloadotp-64ccd8c9b7a782ca777ca4649dbb1f4a1ef00bce.tar.gz
otp-64ccd8c9b7a782ca777ca4649dbb1f4a1ef00bce.tar.bz2
otp-64ccd8c9b7a782ca777ca4649dbb1f4a1ef00bce.zip
beam_load.c: Allow stubs for BIFs
We want to be able to write type specifications for BIFs in the same way as for any other function. Currently, the type for BIFs need to be described in erl_bif_types. To avoid extending the compiler and Dialyzer with special directives for providing specifications for BIFs, we have decided to let the loader accept a local definition for a function which exists as a BIF. As an example, here is how a stub for lists:reverse/2 can be defined: -export([reverse/2]). -spec reverse([term()], term()) -> [term()]. reverse(_, _) -> erlang:nif_error(undef). Essentially, the loader will discard the local definition of reverse/2. Other functions in the same module must *not* do local calls to a BIF stub. If a local call to a BIF is found, the loader will refuse to load the module. That is, the following call is not allowed: reverse(List) -> reverse(List, []). but the following is: reverse(List) -> ?MODULE:reverse(List, []). A few words about the implementation. It turns out to be too complicated to actually discard the BIF stubs. Although it would be possibly with some jiggery pokery in ops.tab, the code would be difficult to maintain and it could slow down loading of modules that don't define BIFs (which are almost all modules). Therefore, the stub functions are kept in the loaded code, but their names in the func_info instruction are invalidated so that module_info(functions) can filter them out.
Diffstat (limited to 'lib/kernel')
-rw-r--r--lib/kernel/src/hipe_unified_loader.erl15
1 files changed, 10 insertions, 5 deletions
diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl
index 8b3aa0286d..1b56cd8d90 100644
--- a/lib/kernel/src/hipe_unified_loader.erl
+++ b/lib/kernel/src/hipe_unified_loader.erl
@@ -330,11 +330,16 @@ exports(ExportMap, BaseAddress) ->
exports(ExportMap, BaseAddress, [], []).
exports([Offset,M,F,A,IsClosure,IsExported|Rest], BaseAddress, MFAs, Addresses) ->
- MFA = {M,F,A},
- Address = BaseAddress + Offset,
- FunDef = #fundef{address=Address, mfa=MFA, is_closure=IsClosure,
- is_exported=IsExported},
- exports(Rest, BaseAddress, [MFA|MFAs], [FunDef|Addresses]);
+ case IsExported andalso erlang:is_builtin(M, F, A) of
+ true ->
+ exports(Rest, BaseAddress, MFAs, Addresses);
+ _false ->
+ MFA = {M,F,A},
+ Address = BaseAddress + Offset,
+ FunDef = #fundef{address=Address, mfa=MFA, is_closure=IsClosure,
+ is_exported=IsExported},
+ exports(Rest, BaseAddress, [MFA|MFAs], [FunDef|Addresses])
+ end;
exports([], _, MFAs, Addresses) ->
{MFAs, Addresses}.