aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
authorRichard Carlsson <[email protected]>2019-01-22 21:14:01 +0100
committerRichard Carlsson <[email protected]>2019-01-28 19:09:43 +0100
commit87da7b5be69de01e65df566c6e35064381d1144d (patch)
tree13c47e4935ce89d9b66fda94db47934c1538955a /erts
parent35f51c7f057943c25ccb7997526c9d47aed0cd0b (diff)
downloadotp-87da7b5be69de01e65df566c6e35064381d1144d.tar.gz
otp-87da7b5be69de01e65df566c6e35064381d1144d.tar.bz2
otp-87da7b5be69de01e65df566c6e35064381d1144d.zip
Reinstate tuple calls support in the beam emulator
This reverts commit f2b332186a for beam_emu.c only, to enable an upgrade path for existing beam code compiled under OTP 20 with parameterized modules.
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/beam/beam_emu.c37
1 files changed, 33 insertions, 4 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index e909a0b4da..aa6e7d3de2 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -2210,6 +2210,7 @@ apply(Process* p, Eterm* reg, BeamInstr *I, Uint stack_offset)
Eterm module = reg[0];
Eterm function = reg[1];
Eterm args = reg[2];
+ Eterm this;
/*
* Check the arguments which should be of the form apply(Module,
@@ -2232,8 +2233,20 @@ apply(Process* p, Eterm* reg, BeamInstr *I, Uint stack_offset)
while (1) {
Eterm m, f, a;
-
- if (is_not_atom(module)) goto error;
+ /* The module argument may be either an atom or an abstract module
+ * (currently implemented using tuples, but this might change).
+ */
+ this = THE_NON_VALUE;
+ if (is_not_atom(module)) {
+ Eterm* tp;
+
+ if (is_not_tuple(module)) goto error;
+ tp = tuple_val(module);
+ if (arityval(tp[0]) < 1) goto error;
+ this = module;
+ module = tp[1];
+ if (is_not_atom(module)) goto error;
+ }
if (module != am_erlang || function != am_apply)
break;
@@ -2268,7 +2281,9 @@ apply(Process* p, Eterm* reg, BeamInstr *I, Uint stack_offset)
}
/*
* Walk down the 3rd parameter of apply (the argument list) and copy
- * the parameters to the x registers (reg[]).
+ * the parameters to the x registers (reg[]). If the module argument
+ * was an abstract module, add 1 to the function arity and put the
+ * module argument in the n+1st x register as a THIS reference.
*/
tmp = args;
@@ -2285,6 +2300,9 @@ apply(Process* p, Eterm* reg, BeamInstr *I, Uint stack_offset)
if (is_not_nil(tmp)) { /* Must be well-formed list */
goto error;
}
+ if (this != THE_NON_VALUE) {
+ reg[arity++] = this;
+ }
/*
* Get the index into the export table, or failing that the export
@@ -2323,7 +2341,18 @@ fixed_apply(Process* p, Eterm* reg, Uint arity,
return 0;
}
- if (is_not_atom(module)) goto error;
+ /* The module argument may be either an atom or an abstract module
+ * (currently implemented using tuples, but this might change).
+ */
+ if (is_not_atom(module)) {
+ Eterm* tp;
+ if (is_not_tuple(module)) goto error;
+ tp = tuple_val(module);
+ if (arityval(tp[0]) < 1) goto error;
+ module = tp[1];
+ if (is_not_atom(module)) goto error;
+ ++arity;
+ }
/* Handle apply of apply/3... */
if (module == am_erlang && function == am_apply && arity == 3) {