Skip to content

Commit fe8fc1b

Browse files
author
José Valim
committed
Inline some process and node calls, closes #1808
1 parent bcb7cff commit fe8fc1b

File tree

4 files changed

+94
-11
lines changed

4 files changed

+94
-11
lines changed

lib/elixir/lib/node.ex

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
defmodule Node do
22
@moduledoc """
3-
Functions related to Erlang nodes.
3+
Functions related to VM nodes.
4+
5+
Some of the functions in this module are inlined by the compiler,
6+
similar to functions in the `Kernel` module. When such happens,
7+
they are explicitly tagged as so.
48
"""
59

610
@type t :: atom
@@ -97,6 +101,8 @@ defmodule Node do
97101
98102
Check http://www.erlang.org/doc/man/erlang.html#spawn-2 for
99103
the list of available options.
104+
105+
Inlined by the compiler.
100106
"""
101107
@spec spawn(t, (() -> any)) :: pid
102108
def spawn(node, fun) do
@@ -109,6 +115,8 @@ defmodule Node do
109115
110116
Check http://www.erlang.org/doc/man/erlang.html#spawn_opt-3 for
111117
the list of available options.
118+
119+
Inlined by the compiler.
112120
"""
113121
@spec spawn(t, (() -> any), Process.spawn_opts) :: pid | {pid, reference}
114122
def spawn(node, fun, opts) do
@@ -122,6 +130,8 @@ defmodule Node do
122130
123131
Check http://www.erlang.org/doc/man/erlang.html#spawn-4 for
124132
the list of available options.
133+
134+
Inlined by the compiler.
125135
"""
126136
@spec spawn(t, module, atom, [any]) :: pid
127137
def spawn(node, module, fun, args) do
@@ -135,6 +145,8 @@ defmodule Node do
135145
136146
Check http://www.erlang.org/doc/man/erlang.html#spawn_opt-5 for
137147
the list of available options.
148+
149+
Inlined by the compiler.
138150
"""
139151
@spec spawn(t, module, atom, [any], Process.spawn_opts) :: pid | {pid, reference}
140152
def spawn(node, module, fun, args, opts) do
@@ -147,6 +159,8 @@ defmodule Node do
147159
new process, atomically. If `node` does not exist, a useless pid is returned
148160
(and due to the link, an exit signal with exit reason `:noconnection` will be
149161
received).
162+
163+
Inlined by the compiler.
150164
"""
151165
@spec spawn_link(t, (() -> any)) :: pid
152166
def spawn_link(node, fun) do
@@ -159,6 +173,8 @@ defmodule Node do
159173
process and the new process, atomically. If `node` does not exist, a useless
160174
pid is returned (and due to the link, an exit signal with exit reason
161175
`:noconnection` will be received).
176+
177+
Inlined by the compiler.
162178
"""
163179
@spec spawn_link(t, module, atom, [any]) :: pid
164180
def spawn_link(node, module, fun, args) do

lib/elixir/lib/process.ex

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
defmodule Process do
22
@moduledoc """
3-
This module provides convenience functions around processes and
4-
the process dictionary. In Erlang, most of these functions are
5-
auto-imported, but in Elixir they are grouped in a module for
6-
convenience. Notice that these functions, different from Erlang's,
7-
always return nil instead of undefined. You can use their Erlang
8-
version if you want the undefined value.
3+
Conveniences for working with processes and the process dictionary.
4+
5+
Some of the functions in this module are inlined by the compiler,
6+
similar to functions in the `Kernel` module. When such happens,
7+
they are explicitly tagged as so.
98
"""
109

1110
@doc """
@@ -81,16 +80,18 @@ defmodule Process do
8180
1) If pid is not trapping exits, pid will exit with the given reason;
8281
8382
2) If pid is trapping exits, the exit signal is transformed into a message
84-
{'EXIT', from, reason} and delivered to the message queue of pid;
83+
{:EXIT, from, reason} and delivered to the message queue of pid;
8584
8685
3) If reason is the atom `:normal`, pid will not exit. If it is trapping exits,
87-
the exit signal is transformed into a message {'EXIT', from, :normal} and
86+
the exit signal is transformed into a message {:EXIT, from, :normal} and
8887
delivered to its message queue;
8988
9089
4) If reason is the atom `:kill`, that is if `exit(pid, :kill)` is called, an
9190
untrappable exit signal is sent to pid which will unconditionally exit with
9291
exit reason `:killed`.
9392
93+
Inlined by the compiler.
94+
9495
## Examples
9596
9697
Process.exit(pid, :kill)
@@ -112,6 +113,8 @@ defmodule Process do
112113
@doc """
113114
Returns the pid of a new process started by the application of `fun`.
114115
It behaves exactly the same as `Kernel.spawn/1`.
116+
117+
Inlined by the compiler.
115118
"""
116119
@spec spawn((() -> any)) :: pid
117120
def spawn(fun) do
@@ -129,6 +132,8 @@ defmodule Process do
129132
130133
It also accepts extra options, for the list of available options
131134
check http://www.erlang.org/doc/man/erlang.html#spawn_opt-2
135+
136+
Inlined by the compiler.
132137
"""
133138
@spec spawn((() -> any), spawn_opts) :: pid | {pid, reference}
134139
def spawn(fun, opts) do
@@ -141,6 +146,8 @@ defmodule Process do
141146
scheduler queue and be run some time later.
142147
143148
It behaves exactly the same as the `Kernel.spawn/3` function.
149+
150+
Inlined by the compiler.
144151
"""
145152
@spec spawn(module, atom, [any]) :: pid
146153
def spawn(mod, fun, args) do
@@ -155,6 +162,7 @@ defmodule Process do
155162
It also accepts extra options, for the list of available options
156163
check http://www.erlang.org/doc/man/erlang.html#spawn_opt-4
157164
165+
Inlined by the compiler.
158166
"""
159167
@spec spawn(module, atom, [any], spawn_opts) :: pid | {pid, reference}
160168
def spawn(mod, fun, args, opts) do
@@ -165,6 +173,8 @@ defmodule Process do
165173
Returns the pid of a new process started by the application of `fun`.
166174
A link is created between the calling process and the new
167175
process, atomically.
176+
177+
Inlined by the compiler.
168178
"""
169179
@spec spawn_link((() -> any)) :: pid
170180
def spawn_link(fun) do
@@ -175,6 +185,8 @@ defmodule Process do
175185
Returns the pid of a new process started by the application of
176186
`module.function(args)`. A link is created between the calling process
177187
and the new process, atomically. Otherwise works like spawn/3.
188+
189+
Inlined by the compiler.
178190
"""
179191
@spec spawn_link(module, atom, [any]) :: pid
180192
def spawn_link(mod, fun, args) do
@@ -184,6 +196,8 @@ defmodule Process do
184196
@doc """
185197
Returns the pid of a new process started by the application of `fun`
186198
and reference for a monitor created to the new process.
199+
200+
Inlined by the compiler.
187201
"""
188202
@spec spawn_monitor((() -> any)) :: {pid, reference}
189203
def spawn_monitor(fun) do
@@ -194,6 +208,8 @@ defmodule Process do
194208
A new process is started by the application of `module.function(args)`
195209
and the process is monitored at the same time. Returns the pid and a
196210
reference for the monitor. Otherwise works like spawn/3.
211+
212+
Inlined by the compiler.
197213
"""
198214
@spec spawn_monitor(module, atom, [any]) :: {pid, reference}
199215
def spawn_monitor(mod, fun, args) do
@@ -205,6 +221,8 @@ defmodule Process do
205221
It returns the monitor reference.
206222
207223
See http://www.erlang.org/doc/man/erlang.html#monitor-2 for more info.
224+
225+
Inlined by the compiler.
208226
"""
209227
@spec monitor(pid | {reg_name :: atom, node :: atom} | reg_name :: atom) :: reference
210228
def monitor(item) do
@@ -217,6 +235,8 @@ defmodule Process do
217235
If the monitoring is already turned off, nothing happens.
218236
219237
See http://www.erlang.org/doc/man/erlang.html#demonitor-2 for more info.
238+
239+
Inlined by the compiler.
220240
"""
221241
@spec demonitor(reference) :: true
222242
@spec demonitor(reference, options :: [:flush | :info]) :: boolean
@@ -244,6 +264,8 @@ defmodule Process do
244264
(or port) `pid`, if there is not such a link already.
245265
246266
See http://www.erlang.org/doc/man/erlang.html#link-1 for more info.
267+
268+
Inlined by the compiler.
247269
"""
248270
@spec link(pid | port) :: true
249271
def link(pid) do
@@ -256,6 +278,8 @@ defmodule Process do
256278
fail, even if there is no link or `id` does not exist
257279
258280
See http://www.erlang.org/doc/man/erlang.html#unlink-1 for more info.
281+
282+
Inlined by the compiler.
259283
"""
260284
@spec unlink(pid | port) :: true
261285
def unlink(pid) do

lib/elixir/src/elixir_dispatch.erl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@
99
find_import/4, format_error/1]).
1010
-include("elixir.hrl").
1111
-import(ordsets, [is_element/2]).
12+
13+
%% Module macros
1214
-define(kernel, 'Elixir.Kernel').
15+
-define(node, 'Elixir.Node').
16+
-define(process, 'Elixir.Process').
1317

1418
default_functions() ->
1519
[ { ?kernel, elixir_imported_functions() } ].
@@ -328,6 +332,8 @@ rewrite(?kernel, elem, [Tuple, Index], 2) ->
328332
{ ok, erlang, element, [increment(Index), Tuple] };
329333
rewrite(?kernel, set_elem, [Tuple, Index, Value], 2) ->
330334
{ ok, erlang, setelement, [increment(Index), Tuple, Value] };
335+
rewrite(?process, monitor, [Arg], 1) ->
336+
{ ok, erlang, monitor, [process, Arg] };
331337
rewrite(Receiver, Name, Args, Arity) ->
332338
case inline(Receiver, Name, Arity) of
333339
{ AR, AN } -> { ok, AR, AN, Args };
@@ -421,4 +427,28 @@ inline(?kernel, tl, 1) -> { erlang, tl };
421427
inline(?kernel, trunc, 1) -> { erlang, trunc };
422428
inline(?kernel, tuple_size, 1) -> { erlang, tuple_size };
423429
inline(?kernel, tuple_to_list, 1) -> { erlang, tuple_to_list };
430+
431+
inline(?process, exit, 2) -> { erlang, exit };
432+
inline(?process, spawn, 1) -> { erlang, spawn };
433+
inline(?process, spawn, 2) -> { erlang, spawn_opt };
434+
inline(?process, spawn, 3) -> { erlang, spawn };
435+
inline(?process, spawn, 4) -> { erlang, spawn_opt };
436+
inline(?process, spawn_link, 1) -> { erlang, spawn_link };
437+
inline(?process, spawn_link, 3) -> { erlang, spawn_link };
438+
inline(?process, spawn_monitor, 1) -> { erlang, spawn_monitor };
439+
inline(?process, spawn_monitor, 3) -> { erlang, spawn_monitor };
440+
inline(?process, demonitor, 1) -> { erlang, demonitor };
441+
inline(?process, demonitor, 2) -> { erlang, demonitor };
442+
inline(?process, link, 1) -> { erlang, link };
443+
inline(?process, unlink, 1) -> { erlang, unlink };
444+
445+
inline(?node, spawn, 2) -> { erlang, spawn };
446+
inline(?node, spawn, 3) -> { erlang, spawn_opt };
447+
inline(?node, spawn, 4) -> { erlang, spawn };
448+
inline(?node, spawn, 5) -> { erlang, spawn_opt };
449+
inline(?node, spawn_link, 2) -> { erlang, spawn_link };
450+
inline(?node, spawn_link, 4) -> { erlang, spawn_link };
451+
inline(?node, spawn_monitor, 2) -> { erlang, spawn_monitor };
452+
inline(?node, spawn_monitor, 4) -> { erlang, spawn_monitor };
453+
424454
inline(_, _, _) -> false.

lib/elixir/test/elixir/process_test.exs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,26 @@ Code.require_file "test_helper.exs", __DIR__
33
defmodule ProcessTest do
44
use ExUnit.Case, async: true
55

6-
test :self do
6+
test "self/0" do
77
assert is_pid(Process.self)
88
end
99

10-
test :group_leader do
10+
test "group_leader/2 and group_leader/0" do
1111
another = spawn_link(fn -> :timer.sleep(1000) end)
1212
assert Process.group_leader(self, another)
1313
assert Process.group_leader == another
1414
end
15+
16+
test "monitoring functions are inlined by the compiler" do
17+
assert expand(quote(do: Process.monitor(pid())), __ENV__) ==
18+
quote(do: :erlang.monitor(:process, pid()))
19+
20+
assert &Process.spawn_monitor/1 == &:erlang.spawn_monitor/1
21+
assert &Process.spawn_monitor/3 == &:erlang.spawn_monitor/3
22+
end
23+
24+
defp expand(expr, env) do
25+
{ expr, _env } = :elixir_exp.expand(expr, :elixir_env.ex_to_env(env))
26+
expr
27+
end
1528
end

0 commit comments

Comments
 (0)