annotate docs/extops.markdown @ 40:9b496a0c430a

merge
author anatofuz
date Tue, 27 Nov 2018 11:25:43 +0900
parents 2cf249471370
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 ## Extensions and Extension Ops [proposed/tentative]
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3 #### The MoarVM Opcodes Overview
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5 The MoarVM interpreter uses 16-bit opcodes. There are currently around 470
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 built-in ops, and it'll probably be around 500 once Rakudo's bootstrapped and
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 passing spectest. The interpreter loop currently dispatches by op number,
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 either using switch/case or cgoto where available.
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10 Many opcodes are self-contained (they don't call other C functions, and some
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 don't even make system calls), but lots and lots of them do call functions.
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 Since the ./moar binary is statically-linked (mostly), the link-time code
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 generation and optimization by modern compilers should do a pretty good job of
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 making such things optimal [please excuse the truism]. However, in the case of
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15 dynamically loaded extensions to the VM that need to dynamically load native
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 libraries with a C ABI (nearly all native libraries have a build that exposes
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
17 such a thing), the function pointers must be resolved at runtime after the
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 library is loaded. Perl 6's NativeCall module (using dyncall on parrot) can
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19 load libraries by name and enumerate/locate entry points and functions by name.
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 I propose to use the dyncall functionality to load MoarVM extensions and
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 resolve function pointers. The following is a draft design/spec doc for how
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 that might look:
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
24
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
25 ----------------------------------------------------------------
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
26
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
27 #### Representing Extension Op Calls on Disk and in Memory
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
28
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
29 In a table in the .moarvm disk representation of the bytecode, each extension
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
30 op invoked from that compilation unit has an entry with: 1. a (16-bit) index
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
31 into the string heap representing the fully-qualified (namespace included) name
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
32 of the op, and 2. the op signature, a byte for each operand, zer-padded to 8
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
33 bytes. In the in-memory (deserialized) representation of the compilation unit,
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
34 each record also has room to store the cache of the function pointer representing
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
35 the C function to which the op was resolved. Each distinct op called from that
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
36 compilation unit is encoded in the executable bytecode as its index in the extension
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
37 op table plus 1024 (the first 1024 being reserved for MoarVM itself).
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
38
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
39 #### Loading Code That Calls Extension Ops
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
40
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
41 During bytecode validation (on-demand upon first invocation of a frame), when
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
42 the validator comes across an opcode >= 1024, it subtracts 1024 and checks that
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
43 the resulting index is less than the number of extension op calls proscribed by
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
44 the compunit. Then it gets that extop call record (MVMExtOpCall) from the
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
45 table, and if the record has a function pointer, it calls it with the sole arg
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
46 (MVMThreadContext tc). If the function call slot is NULL, it means the function
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
47 pointer hasn't been resolved for this compunit, but also that the signature
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
48 hasn't yet been validated against the version of that opcode that was loaded by
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
49 its dependencies (if it was!). First the validator does a hash lookup to check
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
50 whether the extop has been loaded at all (this requires a mutex protection,
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
51 unless we're by then using a lock-free HLL hash for this), then if it hasn't,
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
52 it throws a bytecode validation exception. If it has been loaded (by itself or
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
53 by a dependency), it compares the signatures of the call in the compunit whose
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
54 frame is being validated against the signature of the loaded op by that name,
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
55 and if they don't match, throw a bytecode validation exception: "extension op
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
56 <opname> call signature mismatch - the op's old signature (xxxx) was
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
57 deprecated? You tried to load a call with signature <xxxx>." If the signatures
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
58 matched, operand type validation of the actual passed parameters (register
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
59 indexes) proceeds normally, using the extop's signature. The validator copies
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
60 the function pointer from the process-wide registry into the in-memory record
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
61 of the extop call in that compunit.
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
62
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
63 #### Loading Extensions
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
64
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
65 When a compilation unit is loaded, its "load" entry point routine calls its
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
66 INIT block (if it has one), which does something like the example below,
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
67 registering the native function pointers and their signatures with the runtime.
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
68 It communicates with the runtime via the currently-compiling compiler (as there
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
69 is generally a World-aware HLL compiler calling ModuleLoader). To start, it
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
70 simply uses NativeCall to fetch each function pointer (but there are plenty of
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
71 optimization opportunities there).
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
72
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
73 #### Examples
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
74
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
75 The below example purports to show the contents of a skeleton extension as
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
76 it would look to a developer. (please excuse incorrect syntax; it's pseudo-
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
77 code in some places. ;)
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
78
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
79 helper package (part of the MoarVM/NQP runtime) - MoarVM/CustomOps.p6:
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
80
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
81 ```Perl
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
82 package MoarVM::CustomOps;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
83 use NativeCall;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
84
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
85 # If we're compiling the innermost layer (and not just loading it at INIT time)
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
86 # at *compile-time* of the compilation unit surrounding the INIT block we
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
87 # assume we are in, inject the symbol into the innermost World outside of us.
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
88 # ALSO, do the same thing at INIT-time (using nqp::extop_install) when we have
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
89 # already been compiled, as well as when we're compiling.
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
90
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
91 sub install_ops($library_file, $c_prefix, $op_prefix, $names_sigs) is export {
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
92 my $world = nqp::hllcompilerworld;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
93 my $opslib = native_lib($library_file);
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
94 -> $name, $sig {
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
95 my $fqon = "$op_prefix::$name";
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
96 nqp::extop_install($opslib, $fqon, "$c_prefix$name", $sig);
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
97 $world.extop_compile($fqon, $sig)
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
98 if $world.is_compiling;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
99 } for $names_sigs;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
100 }
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
101 ```
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
102
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
103 Above, the nqp::hllcompilerworld op simply retrieves an appropriately named
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
104 dynamic lexical of the current in-flight World object. That class will have an
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
105 HLL method named extop_compile, detailed below.
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
106
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
107 Notice the helper package uses NativeCall to find the function pointers via the
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
108 native_function (or whatever it's named) routine. When each function pointer
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
109 is passed to the extop_compile method of the in-flight World object, that
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
110 method in the HLL compiler will pass the function pointer to a special internal
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
111 opcode (nqp::extop_install) that takes the NativeCall library object, the fully
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
112 qualified name of the op as it will appear in the HLL source code (namespace
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
113 ::opname), and a string representing the register signature (a la parrot's op
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
114 signatures), so the bytecode validator knows how to validate its register args.
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
115
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
116 ```Perl
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
117 class World { # NQP snippet
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
118
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
119 # at *compile-time* of the compilation unit surrounding the INIT block
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
120 # we assume we are in, inject the symbol into the innermost World outside of
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
121 # us.
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
122
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
123 method extop_compile($fqon, $addr, $sig) {
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
124 my $cu := self.current_compunit;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
125 my %extops := $cu.extop_calls;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
126 nqp::die("op $fqon already installed!")
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
127 if nqp::has_key(%extops, $fqon);
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
128 nqp::push($cu.extop_table, $fqon);
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
129 %extops{$fqon} := $cu.next_extop++;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
130 }
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
131 ```
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
132
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
133 Since the custom ops are resolved "by name" (sort of) upon bytecode loading,
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
134 we don't have to worry about Rakudo bootstrapping, since in order to install
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
135 the custom ops for Rakudo, we can simply rely on the compiler (in NQP) to
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
136 generate the appropriate loading/installing code.
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
137
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
138 core/bytecode.c excerpt - nqp::extop_install:
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
139
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
140 ```C
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
141 #include "moar.h"
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
142
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
143 typedef struct _MVMExtOpRecord {
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
144
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
145 /* name of the op, including namespace:: prefix */
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
146 MVMString *opname;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
147
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
148 /* string representing signature */
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
149 MVMString *signature;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
150
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
151 /* the function pointer (see below for signature/macro) */
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
152 MVMCustomOp *function_ptr;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
153
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
154 /* number of bytes the interpreter should advance the cur_op pointer */
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
155 MVMint32 op_size;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
156
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
157 /* (speculative/future) function pointer to the code in C
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
158 that the JIT can call to generate an AST for the
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
159 operation, for super-ultra-awesome optimization
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
160 possibilities (when pigs fly! ;) */
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
161 /* MVMCustomOpJITtoMAST * jittomast_ptr; */
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
162
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
163 /* so the record can be in a hash too (so a compiler or JIT
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
164 can access the upper code at runtime in order to inline
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
165 or optimize stuff) */
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
166 UT_hash_handle hash_handle;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
167 } MVMExtOpRecord;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
168
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
169 /* Resolve the function pointer and nstall the op at runtime. */
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
170 void MVM_bytecode_extop_install(MVMThreadContext *tc, MVMObject *library,
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
171 MVMString *opname, MVMString *funcname, MVMString *signature) {
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
172
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
173 /* TODO: protect with a mutex */
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
174 /* must also grab thread creation mutex b/c we have to
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
175 update the tc->interp_customops pointer of all the threads */
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
176
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
177 MVMCustomOp *function_ptr = NULL;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
178 MVMExtOpRecord *customops, *customop;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
179 MVMuint16 opidx = tc->instance->nextcustomop++;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
180 void *kdata;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
181 size_t klen;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
182
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
183 MVM_HASH_GET(tc, tc->instance->customops_hash, opname, customop);
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
184 if (customop)
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
185 MVM_panic(tc, "already installed custom op by this name");
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
186
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
187 customops = tc->instance->customops;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
188
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
189 if (customops == NULL) {
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
190 customops = tc->instance->customops =
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
191 calloc( sizeof(MVMExtOpRecord),
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
192 (tc->instance->customops_size = 256));
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
193 }
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
194 else if (opidx == tc->instance->customops_size) {
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
195 customops = tc->instance->customops =
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
196 realloc(tc->instance->customops,
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
197 (tc->instance->customops_size *= 2));
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
198 memset(tc->instance->customops + tc->instance->customops_size/2,
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
199 0, tc->instance->customops_size / 2 * sizeof(MVMExtOpRecord));
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
200 }
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
201
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
202 customop = customops + opidx;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
203 customop->opname = opname;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
204 customop->signature = signature;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
205 customop->op_size = MVM_bytecode_extop_compute_opsize(tc, signature);
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
206
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
207 /* use the NativeCall API directly to grab the function pointer
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
208 using the cached library object */
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
209 customop->function_ptr =
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
210 MVM_nativecall_function_ptr(tc, library, funcname);
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
211
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
212 /* the name strings should always be in a string heap already,
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
213 so don't need GC root */
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
214 HASH_ADD_KEYPTR(hash_handle, tc->instance->customops_hash, kdata, klen,
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
215 customop);
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
216 }
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
217 ```
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
218
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
219 core/interp.c excerpt - the invocation of nqp::customopcall's replacements:
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
220
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
221 ```C
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
222 MVMExtOpRecord *customops = tc->instance->customops;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
223 tc->interp_customops = &customops;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
224
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
225 #define EXTOP_OFFSET 4096
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
226
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
227 <snip>
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
228
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
229 case MVM_OP_BANK_16:
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
230 case MVM_OP_BANK_17:
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
231 ...
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
232 case MVM_OP_BANK_126:
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
233 case MVM_OP_BANK_127:
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
234 {
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
235 MVMExtOpRecord *op_record =
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
236 &customops[*(MVMuint16 *)cur_op++ - EXTOP_OFFSET];
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
237 MVMCustomOp *function_ptr = op_record->function_ptr;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
238 function_ptr(tc);
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
239 cur_op += op_record->op_size;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
240 break;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
241 }
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
242 ```
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
243
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
244 example extension (loading the rakudo ops dynamically) - Rakudo/Ops.p6 (or NQP):
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
245
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
246 ```Perl
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
247 package Rakudo::Ops;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
248
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
249 INIT {
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
250 use MoarVM::CustomOps;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
251 install_ops('rakudo_ops.lib', 'MVM_rakudo_op_', 'rakudo', [
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
252 'additivitation', 'iii',
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
253 'concatenationize', 'sss',
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
254 ]);
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
255 }
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
256
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
257 # Both at compile-time and run-time of the below code, INIT will have run
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
258 # and the following ops are installed the right namespaces and such.
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
259
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
260 my $z = rakudo::concatenationize(rakudo::additivitation(44, 66), "blah");
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
261
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
262 # note: since the types of the custom ops' operands are known to the
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
263 # HLL compiler, it just does its normal thing of generating code to
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
264 # auto-coerce the resulting integer from the addition to a string
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
265 # for the concat custom op.
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
266 ```
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
267
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
268 moar.h excerpt (note the injecting of 1 offset if it's not the result reg):
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
269
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
270 ```C
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
271 #define REG(idx) \
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
272 (reg_base[*((MVMuint16 *)(cur_op + ((idx) > 0 ? idx + 1 : 0)))])
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
273
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
274 ```
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
275
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
276 Note: The type checks should be compile-time optimized-away by all but the
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
277 stupidest of C compilers. Though they fail at runtime, I consider that
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
278 "fail fast" enough, as this is simply a best-effort attempt at a coder
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
279 convenience type-check, not a rigorous one to actually enforce that the
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
280 register type signature passed to the runtime opcode installation routine
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
281 in the HLL code actually matches the one defined/used in the C source code.
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
282
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
283 moar.h excerpt (continued):
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
284
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
285 ```C
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
286
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
287 #define MVM_CUSTOM_OP(opname, block) \
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
288 \
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
289 void opname(MVMThreadContext *tc) { \
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
290 MVMuint8 *cur_op = *tc->interp_cur_op; \
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
291 MVMRegister *reg_base = *tc->interp_reg_base; \
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
292 MVMCompUnit *cu = *tc->interp_cu; \
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
293 block; \
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
294 }
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
295 typedef MVM_CUSTOM_OP((*MVMCustomOp));
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
296 ```
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
297
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
298 rakudo_ops.c
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
299
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
300 ```C
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
301 #include "moar.h"
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
302
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
303 MVM_CUSTOM_OP(MVM_rakudo_op_additivitation, {
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
304 REG(0).i = REG(1).i + REG(2).i;
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
305 })
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
306
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
307 MVM_CUSTOM_OP(MVM_rakudo_op_concatenationize, {
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
308 REG(0).s = MVM_string_concatenate(tc, REG(1).s, REG(2).s);
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
309 })
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
310 ```
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
311
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
312 validation.c excerpt (verify extop arg types and inline the real
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
313 oprecord offsets):
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
314
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
315 ```C
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
316 /* similar to the actual interpreter, grab the MVMExtOpRecord, but
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
317 simply validate each operand type specified for the extop with
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
318 the types and count of the registers specified in the bytecode, by
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
319 enumerating each character in the signature. If
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
320 it hasn't been checked already, compare the signature of the loaded
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
321 extop by that name against the signature of the extop by that
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
322 name that was stored in the compilation unit when it was loaded from
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
323 disk, if it was. Cache the function pointer if it wasn't already. */
2cf249471370 convert mercurial for git
Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
324 ```