You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Rubinius is a modern language platform that supports a number of programming languages.
6
6
7
-
The philosophy and architecture of Rubinius are described below.
7
+
The philosophy and high-level architecture of Rubinius are described below.
8
8
9
9
Rubinius runs on macOS and many Unix/Linux operating systems. Microsoft Windows is not supported.
10
10
@@ -68,43 +68,144 @@ The rest of the components of the machine are described below.
68
68
69
69
### Instructions
70
70
71
-
\<todo>
71
+
The Rubinius instruction set includes different categories of instructions. One key aspect of the Rubinius philosophy is that the instruction set should represent any machine semantic. This contrasts with the way Rubinius has been implemented historically, which relied heavily on C++ "primitives" modeled on the Smalltalk 80 virtual machine. All the primitives are being replaced as the instruction set evolves richer capabilities.
72
+
73
+
The categories of instructions are:
74
+
75
+
1.*Stack* instructions that push, pop, and get operands from a stack;
76
+
2.*Register* instructions that read from and write to a set of registers;
77
+
3.*Assertion* instructions that can halt execution but cannot change the semantics of the program;
78
+
4.*Instrumentation* instructions that cannot change the semantics of the program but can emit data from the program;
79
+
5.*Parsing Expression Grammar* (PEG) instructions. PEGs are an elegant formalism for describing recognizers;
80
+
6.*Foreign Function Interface* (FFI) instructions for binding and calling external functions;
81
+
7.*Concurrency* instructions for execution threads and concurrent data;
82
+
8.*System* instructions for accessing files, directories, and other systam capabilities.
83
+
84
+
**TODO: There's plenty of places to help out here if parsers, compilers, and instruction sets interest you.**
72
85
73
86
### Heaps & Garbage Collector
74
87
75
-
\<todo>
88
+
Rubinius has two kinds of managed objects: object-oriented ones that can support inheriting from a superclass, and data objects that have no concept of object-orientation.
89
+
90
+
Rubinius has three concepts for heaps, the space where managed objects live:
91
+
92
+
1. The *open* heap is one where any object in the heap can contain a reference to any other object. Think normal Ruby land;
93
+
2. The *closed* heap is one where an object in the heap can contain a reference to an object outside the closed heap, but no object outside can contain a reference to an object in the closed heap;
94
+
3. The *isolated* heap is one where no object in the isolated heap can contain a reference to an object outside the heap, and no object outside can contain a reference to an object in the isolated heap.
95
+
96
+
Threads that use isolated heaps can execute fully independent of any other thread and only must synchronize with the process during boot, fork, and halt. The garbage collector for isolated heaps is run in that thread.
97
+
98
+
Rubinius uses a single mechanism for garbage collection, the [Immix mark-region collector](http://www.cs.williams.edu/~dbarowy/cs334s18/assets/immix-pldi-2008.pdf).
99
+
100
+
The Rubinius garbage collector currently runs on a single separate thread and must fully synchronize all threads that mutate managed memory (ie it stops the world). In the future, the single open heap will introduce a second generational area, and the isolated heaps will provide for parallel collection.
101
+
102
+
**TODO: There's plenty of places to help out here if garbage collectors interest you.**
103
+
104
+
### CodeDB
105
+
106
+
The Rubinius CodeDB is where all compiled code for the core and standard libraries is stored. Every executable context (in Ruby, these are scripts, class & module bodies, methods, and blocks) has a unique ID and is cached in the CodeDB. In the future, all user code will also be cached in the CodeDB.
107
+
108
+
The unique ID of every executable context allows for associating arbitrary dimensions of data with that instance of executable code. For example, type information seen at run time, profile and coverage information, call graphs, and memory allocations data can all be associated with the executable code.
109
+
110
+
**TODO: There's plenty of places to help out here if databases and code analytics interest you.**
76
111
77
112
### Console
78
113
79
-
\<todo>
114
+
The Console is an interprocess communication (IPC) mechanism. In contrast to Ruby's IRB, which executes in the same process, the Rubinius Console is intended to be a general purpose mechanism to interact with the virtual machine. The capabilities of the Console include the ability to execute code and return the result, start/step/stop the Debugger, start/stop the Profiler, access data from the Profiler and Diagnostics, and fetch the call graph and object graph data.
115
+
116
+
**TODO: There's plenty of places to help out here if developer tools interest you.**
80
117
81
118
### Debugger
82
119
83
-
\<todo>
120
+
The Debugger uses instruction replacement (ie substituting the debug instruction for the existing instruction at that point in the instruction sequence) to cause an executing instance of code to stop and allow you to inspect values and step to the next instruction, or step into or out of another instance of code (eg a method, function, or block).
121
+
122
+
**TODO: There's plenty of places to help out here if developer tools interest you.**
84
123
85
124
### Profiler
86
125
87
-
\<todo>
126
+
The Profiler is a randomized-interval sampling profiler that is always running. At a randomized interval, the code instances that are currently executing in a thread have their sample count incremented. In addition, all code instances have a call count that is incremented each time they are invoked. At every call site, the number of times the call site executes is tracked for each type of object seen. The call sites enable deriving the call graph for the program from the object graph because the call sites have a normal (Ruby) object interface.
127
+
128
+
**TODO: There's plenty of places to help out here if developer tools interest you.**
129
+
130
+
### Diagnostics & Logging
88
131
89
-
###Diagnostics
132
+
The Diagnostics facility provides metrics on all components of the virtual machine. The logging facility includes different log levels (ie debug, info, warn, error) and provides a descriptive account of virtual machine lifecycle events.
90
133
91
-
\<todo>
134
+
**TODO: There's plenty of places to help out here if developer tools interest you.**
92
135
93
136
### Machine-code Compiler
94
137
95
-
\<todo>
138
+
The machine-code compiler is based on LLVM and compiles a managed code instance to machine code. The first generation Rubinius JIT (just-in-time compiler) included type inference, custom code passes, and inlining facilities all implemented in C++. The next generation compiler uses a [nanopass](http://nanopass.org) architecture and builds a single managed code instance that can be compiled to native machine code.
139
+
140
+
**TODO: There's plenty of places to help out here if native machine code compilers interest you.**
96
141
97
142
### Data Types & Functions
98
143
99
-
\<todo>
144
+
Rubinius has functions. No, really.
145
+
146
+
```
147
+
$ bin/rbx compile -N plus -B -e 'fun plus(a, b) a + b end'
148
+
149
+
================ :plus =================
150
+
Arguments: 2 required, 0 post, 2 total
151
+
Arity: 2
152
+
Locals: 2: a, b
153
+
Stack size: 4
154
+
Registers: 0
155
+
Literals: 1: :+
156
+
Line: 1
157
+
Lines to IP:
158
+
159
+
0000: push_local 0 # a
160
+
0002: push_local 1 # b
161
+
0004: send_stack :+, 1
162
+
0007: unwind 0
163
+
0009: ret 0
164
+
----------------------------------------
165
+
```
166
+
167
+
There are several ways that types can be added. First, it's important to distinguish the "behavior" of object-oriented code from the "types" of data. See [Objects are for interactions, functions are for data](https://medium.com/metalanguage/objects-are-for-interactions-functions-are-for-data-936e044cc729).
168
+
169
+
For objects, instead of types, we want to be able to easily convey that objects should represent themselves differently:
170
+
171
+
```ruby
172
+
classA
173
+
defm(a:Integer(2), b:Integer(3))
174
+
# If the values passed for a and b are not Integers,
175
+
# the Integer() constructor will be called on them.
176
+
# If a value isn't passed for a, the default value is 2.
177
+
# Similarly for b, the default value is 3.
178
+
end
179
+
end
180
+
```
181
+
182
+
For functions, the situation is similar, but different:
183
+
184
+
```ruby
185
+
type :int, fun +(a: int, b: int)
186
+
# The type of a and b must be machine integers.
187
+
# The return type is specified by an annotation
188
+
end
189
+
190
+
fun +(a: int, b: int, return: int)
191
+
# The type of the return value is int.
192
+
# The 'return' argument is elided.
193
+
end
194
+
195
+
fun +(a: int, b: int): int
196
+
# This form would require modifying the parser.
197
+
end
198
+
```
199
+
200
+
**TODO: There's plenty of places to help out here if functions and data types interest you.**
100
201
101
202
### C-API
102
203
103
-
\<todo>
204
+
The C-API provides an element of compatibility with Ruby C-extensions. However, the C-API is deprecated and will likely eventually be removed.
104
205
105
206
## FAQ
106
207
107
-
**Q. There's this other <programming language, project, concept, application> that seems <better, faster, cheaper>, shouldn't I use that instead?**
208
+
**Q. There's this other \<programming language, project, concept, application> that seems \<better, faster, cheaper>, shouldn't I use that instead?**
108
209
109
210
A. Yes, absolutely. The sooner the better, really.
110
211
@@ -114,13 +215,33 @@ A. We have a lot of respect for your abilities, whether you've ever written a li
114
215
115
216
Find something that interests you and dive in. If you get stuck, ask a question.
116
217
218
+
**Q. Why isn't \<my pet feature> done already? When will it be done?**
219
+
220
+
**A.** Do you have 1,000,000 USD? No, really.
221
+
117
222
**Q. Is there more documentation?**
118
223
119
-
A. Yes, there is a [book](https://rubinius.com/book/) that needs a lot of love and attention.
224
+
**A.** Yes, there is a [book](https://rubinius.com/book/) that needs a lot of love and attention.
225
+
226
+
**Q. Can I embed Rubinius into my favorite C/C++ application?**
227
+
228
+
**A.** Yes, you can! More of the facilities to support interacting with the Machine will be added over time.
120
229
230
+
```c++
231
+
#include"machine.hpp"
232
+
233
+
intmain(int argc, char** argv) {
234
+
rubinius::Machine machine(argc, argv);
235
+
236
+
machine.boot();
237
+
238
+
return machine.halt();
239
+
}
240
+
```
241
+
121
242
**Q. What about the Ruby Programming language?**
122
243
123
-
A. Many popular Ruby applications, like Rails, may run on Rubinius, which aims to be compatible with the most recent stable Ruby version.
244
+
**A.** Many popular Ruby applications, like Rails, may run on Rubinius, which aims to be compatible with the most recent stable Ruby version.
124
245
125
246
Rubinius provides the standard Ruby libraries, with the following exceptions:
126
247
@@ -136,10 +257,10 @@ A. Many popular Ruby applications, like Rails, may run on Rubinius, which aims t
136
257
137
258
**Q. How do I use RubyGems?**
138
259
139
-
A. Rubinius comes with RubyGems built-in. To install a gem, run the following:
260
+
**A.** Rubinius comes with RubyGems built-in. To install a gem, run the following:
140
261
141
262
$ rbx -S gem install <gem_name>
142
263
143
264
**Q. Why doesn't Rubinius install gem binaries in the same place as Ruby?**
144
265
145
-
A. Rubinius is intended to be installed alongside Ruby without causing conflicts. Only the main executable, `rbx`, should be installed into a system directory. Edit your shell PATH to include the directories listed when Rubinius is installed to access other executables like gem binaries.
266
+
**A.** Rubinius is intended to be installed alongside Ruby without causing conflicts. Only the main executable, `rbx`, should be installed into a system directory. Edit your shell PATH to include the directories listed when Rubinius is installed to access other executables like gem binaries.
0 commit comments