Skip to content

Commit a745a63

Browse files
authored
Update README.md
1 parent 27e1b29 commit a745a63

1 file changed

Lines changed: 137 additions & 16 deletions

File tree

README.md

Lines changed: 137 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
Rubinius is a modern language platform that supports a number of programming languages.
66

7-
The philosophy and architecture of Rubinius are described below.
7+
The philosophy and high-level architecture of Rubinius are described below.
88

99
Rubinius runs on macOS and many Unix/Linux operating systems. Microsoft Windows is not supported.
1010

@@ -68,43 +68,144 @@ The rest of the components of the machine are described below.
6868

6969
### Instructions
7070

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.**
7285

7386
### Heaps & Garbage Collector
7487

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.**
76111

77112
### Console
78113

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.**
80117

81118
### Debugger
82119

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.**
84123

85124
### Profiler
86125

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
88131

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.
90133

91-
\<todo>
134+
**TODO: There's plenty of places to help out here if developer tools interest you.**
92135

93136
### Machine-code Compiler
94137

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.**
96141

97142
### Data Types & Functions
98143

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+
class A
173+
def m(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.**
100201

101202
### C-API
102203

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.
104205

105206
## FAQ
106207

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?**
108209

109210
A. Yes, absolutely. The sooner the better, really.
110211

@@ -114,13 +215,33 @@ A. We have a lot of respect for your abilities, whether you've ever written a li
114215

115216
Find something that interests you and dive in. If you get stuck, ask a question.
116217

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+
117222
**Q. Is there more documentation?**
118223

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.
120229

230+
```c++
231+
#include "machine.hpp"
232+
233+
int main(int argc, char** argv) {
234+
rubinius::Machine machine(argc, argv);
235+
236+
machine.boot();
237+
238+
return machine.halt();
239+
}
240+
```
241+
121242
**Q. What about the Ruby Programming language?**
122243
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.
124245
125246
Rubinius provides the standard Ruby libraries, with the following exceptions:
126247
@@ -136,10 +257,10 @@ A. Many popular Ruby applications, like Rails, may run on Rubinius, which aims t
136257
137258
**Q. How do I use RubyGems?**
138259
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:
140261
141262
$ rbx -S gem install <gem_name>
142263
143264
**Q. Why doesn't Rubinius install gem binaries in the same place as Ruby?**
144265
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

Comments
 (0)