Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 473 lines (374 sloc) 12.216 kB
d769c94 Initial work on new C++ VM
Evan Phoenix authored
1 #include "vm.hpp"
2 #include "objectmemory.hpp"
9eb4748 Flesh out Task considerable more
Evan Phoenix authored
3 #include "event.hpp"
4 #include "global_cache.hpp"
152cc4c Initial LLVM integration work.
Evan Phoenix authored
5 #include "llvm.hpp"
3a0e9a4 @rue Renamed vm/object.hpp to vm/object_utils.hpp. File/#include shuffling.
rue authored
6
7 #include "vm/object_utils.hpp"
8
6ac48bd Fixed a LOT of dependencies by stripping objects.hpp and prelude.hpp …
Ryan Davis authored
9 #include "builtin/class.hpp"
10 #include "builtin/contexts.hpp"
11 #include "builtin/fixnum.hpp"
12 #include "builtin/list.hpp"
13 #include "builtin/symbol.hpp"
14 #include "builtin/thread.hpp"
15 #include "builtin/tuple.hpp"
16 #include "builtin/string.hpp"
58f050c @brixen Ensure probe variables are initialized.
brixen authored
17 #include "builtin/taskprobe.hpp"
d769c94 Initial work on new C++ VM
Evan Phoenix authored
18
b09a24c Wire the JIT in via MachineMethod
Evan Phoenix authored
19 #include "config_parser.hpp"
8dc150e Implement ConfigParser, wire in into RUBY_CONFIG.
Evan Phoenix authored
20
feb91b4 Tons of stuff (too much probably)
Evan Phoenix authored
21 #include <iostream>
f9ec582 Add preemptive thread scheduling
Evan Phoenix authored
22 #include <signal.h>
feb91b4 Tons of stuff (too much probably)
Evan Phoenix authored
23
f5cf833 Reorganize ontology and class initialization
Evan Phoenix authored
24 // Reset macros since we're inside state
25 #undef G
26 #undef GO
27 #define G(whatever) globals.whatever.get()
28 #define GO(whatever) globals.whatever
29
d769c94 Initial work on new C++ VM
Evan Phoenix authored
30 namespace rubinius {
31ad5c2 Introduces the dynamic interpreter
Evan Phoenix authored
31 VM::VM(size_t bytes)
32 : current_mark(NULL)
33 , reuse_llvm(true)
34 , jit_timing(0)
35 , use_safe_position(false)
36 {
310a461 Cleanup stack usage and fix interpreter
Evan Phoenix authored
37 config.compile_up_front = false;
5be79de Implement simple context cache
Evan Phoenix authored
38
1615ead Refactoring of ObjectMemory's object creation
Evan Phoenix authored
39 VM::register_state(this);
40
8dc150e Implement ConfigParser, wire in into RUBY_CONFIG.
Evan Phoenix authored
41 user_config = new ConfigParser();
42
387bc2d @brixen Converted to attr_accessor for C++ member variable access.
brixen authored
43 om = new ObjectMemory(this, bytes);
8906a3f A slew of GC fixes
Evan Phoenix authored
44 probe.set(Qnil, &globals.roots);
5be79de Implement simple context cache
Evan Phoenix authored
45
46 MethodContext::initialize_cache(this);
5e917ee Move TypeInfo::init under ObjectMemory
Evan Phoenix authored
47 TypeInfo::auto_learn_fields(this);
5be79de Implement simple context cache
Evan Phoenix authored
48
d769c94 Initial work on new C++ VM
Evan Phoenix authored
49 bootstrap_ontology();
da8639a Added libev integration. 60% coverage.
Evan Phoenix authored
50
3f594b6 @rue Changed all TODO:s to @todo so that doxygen picks them up.
rue authored
51 /* @todo Using a single default loop, revisit when many loops.
52 * @todo This needs to be handled through the environment.
6767c76 @dgtized disabled EVBACKEND_EPOLL as it seems to make linux unhappy -- this sh…
dgtized authored
53 * (disabled epoll backend as it frequently caused hangs on epoll_wait)
d75d4be @rue Add forkcheck flag to event loop and init SIGCHLD handler at VM startup.
rue authored
54 */
6767c76 @dgtized disabled EVBACKEND_EPOLL as it seems to make linux unhappy -- this sh…
dgtized authored
55 signal_events = new event::Loop(EVFLAG_FORKCHECK | EVBACKEND_SELECT | EVBACKEND_POLL);
6163e2f Fix signal delivery and re-enable SIGINT
Evan Phoenix authored
56 events = signal_events;
432b29d Get send_on_signal working and couple simple fixes.
Evan Phoenix authored
57
d75d4be @rue Add forkcheck flag to event loop and init SIGCHLD handler at VM startup.
rue authored
58 signal_events->start(new event::Child::Event(this));
59
9eb4748 Flesh out Task considerable more
Evan Phoenix authored
60 global_cache = new GlobalCache;
feb91b4 Tons of stuff (too much probably)
Evan Phoenix authored
61
31ad5c2 Introduces the dynamic interpreter
Evan Phoenix authored
62 VMMethod::init(this);
63
07cabfc Make LLVM optional (and off by default)
Evan Phoenix authored
64 #ifdef ENABLE_LLVM
569fccd @drbrain Move vm/Rakefile to rakelib/vm.rake, integrate it into the base rake …
drbrain authored
65 VMLLVMMethod::init("vm/instructions.bc");
07cabfc Make LLVM optional (and off by default)
Evan Phoenix authored
66 #endif
49d27d7 Move LLVM's lazy code generation into the execute pipeline
Evan Phoenix authored
67 boot_threads();
f9ec582 Add preemptive thread scheduling
Evan Phoenix authored
68
69 // Force these back to false because creating the default Thread
70 // sets them to true.
71 interrupts.use_preempt = false;
72 interrupts.enable_preempt = false;
d769c94 Initial work on new C++ VM
Evan Phoenix authored
73 }
74
75 VM::~VM() {
004ebe7 @dgtized fixed some CompiledFile and ConfigFile memory leaks
dgtized authored
76 delete user_config;
d769c94 Initial work on new C++ VM
Evan Phoenix authored
77 delete om;
432b29d Get send_on_signal working and couple simple fixes.
Evan Phoenix authored
78 delete signal_events;
9eb4748 Flesh out Task considerable more
Evan Phoenix authored
79 delete global_cache;
07cabfc Make LLVM optional (and off by default)
Evan Phoenix authored
80 #ifdef ENABLE_LLVM
504908c 100x test time speedup by reusing LLVM setup
Evan Phoenix authored
81 if(!reuse_llvm) llvm_cleanup();
07cabfc Make LLVM optional (and off by default)
Evan Phoenix authored
82 #endif
d769c94 Initial work on new C++ VM
Evan Phoenix authored
83 }
304caf3 Bunch more work.
Evan Phoenix authored
84
bc4b80f Remove STATE argument from debug functions
Evan Phoenix authored
85 // HACK so not thread safe or anything!
86 static VM* __state = NULL;
87
88 VM* VM::current_state() {
89 return __state;
90 }
91
92 void VM::register_state(VM *vm) {
93 __state = vm;
94 }
95
feb91b4 Tons of stuff (too much probably)
Evan Phoenix authored
96 void VM::boot_threads() {
2cc2e45 @rue Update/fix Thread handling in VM. Possibly over-cautious again.
rue authored
97 Thread* thread = Thread::create(this);
feb91b4 Tons of stuff (too much probably)
Evan Phoenix authored
98
2cc2e45 @rue Update/fix Thread handling in VM. Possibly over-cautious again.
rue authored
99 thread->sleep(this, Qfalse);
100 globals.current_thread.set(thread);
101 globals.current_task.set(thread->task());
feb91b4 Tons of stuff (too much probably)
Evan Phoenix authored
102 }
103
78632ae Remove using Type::fields infavor of sizeof(Type)
Evan Phoenix authored
104 Object* VM::new_object_typed(Class* cls, size_t bytes, object_type type) {
105 return om->new_object_typed(cls, bytes, type);
106 }
107
108 Object* VM::new_object_from_type(Class* cls, TypeInfo* ti) {
109 return om->new_object_typed(cls, ti->instance_size, ti->type);
15fc505 More builtin objects, and a README file
Evan Phoenix authored
110 }
111
e8107bb Remove all traces of ::fields
Evan Phoenix authored
112 Class* VM::new_basic_class(Class* sup) {
78632ae Remove using Type::fields infavor of sizeof(Type)
Evan Phoenix authored
113 Class *cls = new_object<Class>(G(klass));
f5cf833 Reorganize ontology and class initialization
Evan Phoenix authored
114 if(sup->nil_p()) {
387bc2d @brixen Converted to attr_accessor for C++ member variable access.
brixen authored
115 cls->instance_type(this, Fixnum::from(ObjectType));
f5cf833 Reorganize ontology and class initialization
Evan Phoenix authored
116 } else {
387bc2d @brixen Converted to attr_accessor for C++ member variable access.
brixen authored
117 cls->instance_type(this, sup->instance_type()); // HACK test that this is always true
f5cf833 Reorganize ontology and class initialization
Evan Phoenix authored
118 }
387bc2d @brixen Converted to attr_accessor for C++ member variable access.
brixen authored
119 cls->superclass(this, sup);
f5cf833 Reorganize ontology and class initialization
Evan Phoenix authored
120
121 return cls;
122 }
123
124 Class* VM::new_class(const char* name) {
e8107bb Remove all traces of ::fields
Evan Phoenix authored
125 return new_class(name, G(object), G(object));
f5cf833 Reorganize ontology and class initialization
Evan Phoenix authored
126 }
127
128 Class* VM::new_class(const char* name, Class* super_class) {
e8107bb Remove all traces of ::fields
Evan Phoenix authored
129 return new_class(name, super_class, G(object));
f5cf833 Reorganize ontology and class initialization
Evan Phoenix authored
130 }
131
e8107bb Remove all traces of ::fields
Evan Phoenix authored
132 Class* VM::new_class(const char* name, Class* sup, Module* under) {
133 Class* cls = new_basic_class(sup);
f5cf833 Reorganize ontology and class initialization
Evan Phoenix authored
134 cls->setup(this, name, under);
135
136 // HACK test that we've got the MOP setup properly
137 MetaClass::attach(this, cls, sup->metaclass(this));
138 return cls;
139 }
140
141 Class* VM::new_class_under(const char* name, Module* under) {
e8107bb Remove all traces of ::fields
Evan Phoenix authored
142 return new_class(name, G(object), under);
f5cf833 Reorganize ontology and class initialization
Evan Phoenix authored
143 }
144
145 Module* VM::new_module(const char* name, Module* under) {
78632ae Remove using Type::fields infavor of sizeof(Type)
Evan Phoenix authored
146 Module *mod = new_object<Module>(G(module));
f5cf833 Reorganize ontology and class initialization
Evan Phoenix authored
147 mod->setup(this, name, under);
148 return mod;
149 }
150
151
1fdd151 @rue Changed all OBJECT, SYMBOL, FIXNUM, INTEGER to normal syntax.
rue authored
152 Symbol* VM::symbol(const char* str) {
5f2adf4 @brixen Replaced SymbolTable with native C++ class using STL.
brixen authored
153 return symbols.lookup(this, str);
304caf3 Bunch more work.
Evan Phoenix authored
154 }
155
1fdd151 @rue Changed all OBJECT, SYMBOL, FIXNUM, INTEGER to normal syntax.
rue authored
156 Symbol* VM::symbol(String* str) {
5f2adf4 @brixen Replaced SymbolTable with native C++ class using STL.
brixen authored
157 return symbols.lookup(this, str);
195ef1b @brixen Isolated access to SymbolTable behind VM methods.
brixen authored
158 }
159
1fdd151 @rue Changed all OBJECT, SYMBOL, FIXNUM, INTEGER to normal syntax.
rue authored
160 Symbol* VM::symbol(std::string str) {
58105ff @brixen Added Symbol::all_symbols primitive and fixed up Ruby Symbol code.
brixen authored
161 return symbols.lookup(this, str);
195ef1b @brixen Isolated access to SymbolTable behind VM methods.
brixen authored
162 }
163
1fdd151 @rue Changed all OBJECT, SYMBOL, FIXNUM, INTEGER to normal syntax.
rue authored
164 void type_assert(STATE, Object* obj, object_type type, const char* reason) {
a1704be @brixen Rework exceptions in the VM.
brixen authored
165 if((obj->reference_p() && obj->obj_type != type)
166 || (type == FixnumType && !obj->fixnum_p())) {
167 Exception::type_error(state, type, obj, reason);
fceff3d NativeFunction, Selector, SendSite
Evan Phoenix authored
168 }
304caf3 Bunch more work.
Evan Phoenix authored
169 }
4c08cc4 Add object cleanup post collect and on shutdown
Evan Phoenix authored
170
388b751 Wire up primitives to be resolved and executed.
Evan Phoenix authored
171 TypeInfo* VM::find_type(int type) {
172 return om->type_info[type];
173 }
174
f1fa512 @drbrain Oh yeah, C++ isn't ruby.
drbrain authored
175 Thread *VM::current_thread() {
6f546f0 @drbrain Implement VM::current_thread().
drbrain authored
176 return globals.current_thread.get();
da8639a Added libev integration. 60% coverage.
Evan Phoenix authored
177 }
f10f155 Pass in valgrind to find some GC bugs
Evan Phoenix authored
178
3dc347c Fix memory thrash and interrupt checks
Evan Phoenix authored
179 void VM::run_gc_soon() {
180 om->collect_young_now = true;
181 om->collect_mature_now = true;
182 interrupts.check = true;
183 }
184
f10f155 Pass in valgrind to find some GC bugs
Evan Phoenix authored
185 void VM::collect() {
186 om->collect_young(globals.roots);
187 om->collect_mature(globals.roots);
188 }
52c078b Fleshing out Instruction tests, more type safety
Evan Phoenix authored
189
f781b6a Move GC running into VM, remove Task::check_interrupts
Evan Phoenix authored
190 void VM::collect_maybe() {
191 if(om->collect_young_now) {
192 om->collect_young_now = false;
193 om->collect_young(globals.roots);
194 global_cache->clear();
195 }
196
197 if(om->collect_mature_now) {
198 om->collect_mature_now = false;
199 om->collect_mature(globals.roots);
200 global_cache->clear();
201 }
202
203 /* Stack Management procedures. Make sure that we don't
204 * miss object stored into the stack of a context */
205 if(G(current_task)->active()->zone == MatureObjectZone) {
206 om->remember_object(G(current_task)->active());
207 }
208
209 if(G(current_task)->home()->zone == MatureObjectZone &&
210 !G(current_task)->home()->Remember) {
211 om->remember_object(G(current_task)->home());
212 }
213 }
214
719c98f Fix Thread and Channel to interact properly
Evan Phoenix authored
215 bool VM::find_and_activate_thread() {
2cc2e45 @rue Update/fix Thread handling in VM. Possibly over-cautious again.
rue authored
216 Tuple* scheduled = globals.scheduled_threads.get();
217
218 for(std::size_t i = scheduled->num_fields() - 1; i > 0; i--) {
219 List* list = as<List>(scheduled->at(this, i));
220
221 Thread* thread = try_as<Thread>(list->shift(this));
f9ec582 Add preemptive thread scheduling
Evan Phoenix authored
222
2cc2e45 @rue Update/fix Thread handling in VM. Possibly over-cautious again.
rue authored
223 while(thread) {
224 thread->queued(this, Qfalse);
f9ec582 Add preemptive thread scheduling
Evan Phoenix authored
225
2cc2e45 @rue Update/fix Thread handling in VM. Possibly over-cautious again.
rue authored
226 /** @todo Should probably try to prevent dead threads here.. */
227 if(thread->alive() == Qfalse) {
228 thread = try_as<Thread>(list->shift(this));
d22ad2d @drbrain Skip over sleeping threads when looking for things to activate.
drbrain authored
229 continue;
230 }
231
2cc2e45 @rue Update/fix Thread handling in VM. Possibly over-cautious again.
rue authored
232 if(thread->sleep() == Qtrue) {
233 thread = try_as<Thread>(list->shift(this));
234 continue;
235 }
236
237 activate_thread(thread);
d22ad2d @drbrain Skip over sleeping threads when looking for things to activate.
drbrain authored
238 return true;
239 }
feb91b4 Tons of stuff (too much probably)
Evan Phoenix authored
240 }
241
719c98f Fix Thread and Channel to interact properly
Evan Phoenix authored
242 return false;
243 }
244
f9ec582 Add preemptive thread scheduling
Evan Phoenix authored
245 void VM::check_events() {
246 interrupts.check = true;
247 interrupts.check_events = true;
248 }
249
719c98f Fix Thread and Channel to interact properly
Evan Phoenix authored
250 bool VM::run_best_thread() {
251 events->poll();
252
253 if(!find_and_activate_thread()) {
7e7688e Fix deadlock detection
Evan Phoenix authored
254 // It's 1 because the event that looks for SIGCHLD is
255 // always registered.
256 if(events->num_of_events() == 1) {
8a25128 Clean up exception usage.
Evan Phoenix authored
257 throw DeadLock("no runnable threads, present or future.");
feb91b4 Tons of stuff (too much probably)
Evan Phoenix authored
258 }
259
f9ec582 Add preemptive thread scheduling
Evan Phoenix authored
260 interrupts.check_events = true;
719c98f Fix Thread and Channel to interact properly
Evan Phoenix authored
261 return false;
feb91b4 Tons of stuff (too much probably)
Evan Phoenix authored
262 }
719c98f Fix Thread and Channel to interact properly
Evan Phoenix authored
263 return true;
52c078b Fleshing out Instruction tests, more type safety
Evan Phoenix authored
264 }
265
1fdd151 @rue Changed all OBJECT, SYMBOL, FIXNUM, INTEGER to normal syntax.
rue authored
266 void VM::return_value(Object* val) {
52c078b Fleshing out Instruction tests, more type safety
Evan Phoenix authored
267 globals.current_task->push(val);
268 }
269
270 void VM::queue_thread(Thread* thread) {
2cc2e45 @rue Update/fix Thread handling in VM. Possibly over-cautious again.
rue authored
271 if(thread->queued() == Qtrue) {
272 return;
273 }
f9ec582 Add preemptive thread scheduling
Evan Phoenix authored
274
a1704be @brixen Rework exceptions in the VM.
brixen authored
275 List* lst = as<List>(globals.scheduled_threads->at(this,
2cc2e45 @rue Update/fix Thread handling in VM. Possibly over-cautious again.
rue authored
276 thread->priority()->to_native()));
52c078b Fleshing out Instruction tests, more type safety
Evan Phoenix authored
277 lst->append(this, thread);
719c98f Fix Thread and Channel to interact properly
Evan Phoenix authored
278
f9ec582 Add preemptive thread scheduling
Evan Phoenix authored
279 thread->queued(this, Qtrue);
52c078b Fleshing out Instruction tests, more type safety
Evan Phoenix authored
280 }
281
2cc2e45 @rue Update/fix Thread handling in VM. Possibly over-cautious again.
rue authored
282 void VM::dequeue_thread(Thread* thread) {
665be9e @rue Fix minor boo-boo. false != Qfalse..
rue authored
283 thread->queued(this, Qfalse);
2cc2e45 @rue Update/fix Thread handling in VM. Possibly over-cautious again.
rue authored
284
285 Tuple* scheduled = globals.scheduled_threads.get();
286
287 /** @todo Could it be in more than one somehow? --rue */
288 List* list = try_as<List>(scheduled->at(this, thread->priority()->to_native()));
289 (void) list->remove(this, thread);
290
291 check_events();
292 }
293
52c078b Fleshing out Instruction tests, more type safety
Evan Phoenix authored
294 void VM::activate_thread(Thread* thread) {
2cc2e45 @rue Update/fix Thread handling in VM. Possibly over-cautious again.
rue authored
295 if(thread == globals.current_thread.get()) {
665be9e @rue Fix minor boo-boo. false != Qfalse..
rue authored
296 thread->task(this, globals.current_task.get());
2cc2e45 @rue Update/fix Thread handling in VM. Possibly over-cautious again.
rue authored
297 return;
298 }
665be9e @rue Fix minor boo-boo. false != Qfalse..
rue authored
299
2cc2e45 @rue Update/fix Thread handling in VM. Possibly over-cautious again.
rue authored
300 /* May have been using Tasks directly. */
301 globals.current_thread->task(this, globals.current_task.get());
302 queue_thread(globals.current_thread.get());
303
304 thread->sleep(this, Qfalse);
52c078b Fleshing out Instruction tests, more type safety
Evan Phoenix authored
305 globals.current_thread.set(thread);
2cc2e45 @rue Update/fix Thread handling in VM. Possibly over-cautious again.
rue authored
306
387bc2d @brixen Converted to attr_accessor for C++ member variable access.
brixen authored
307 if(globals.current_task.get() != thread->task()) {
ead7263 Fix the context cache, DRY up some VM code
Evan Phoenix authored
308 activate_task(thread->task());
ba265dd Add proper Task switching, fixes backtrace
Evan Phoenix authored
309 }
52c078b Fleshing out Instruction tests, more type safety
Evan Phoenix authored
310 }
feb91b4 Tons of stuff (too much probably)
Evan Phoenix authored
311
ead7263 Fix the context cache, DRY up some VM code
Evan Phoenix authored
312 void VM::activate_task(Task* task) {
313 // Don't try and reclaim any contexts, they belong to someone else.
332ae82 Migrate over the context cache code from shotgun
Evan Phoenix authored
314 om->clamp_contexts();
ead7263 Fix the context cache, DRY up some VM code
Evan Phoenix authored
315
316 globals.current_task.set(task);
317 interrupts.check = true;
318 }
319
1fdd151 @rue Changed all OBJECT, SYMBOL, FIXNUM, INTEGER to normal syntax.
rue authored
320 Object* VM::current_block() {
387bc2d @brixen Converted to attr_accessor for C++ member variable access.
brixen authored
321 return globals.current_task->active()->block();
feb91b4 Tons of stuff (too much probably)
Evan Phoenix authored
322 }
323
da078e6 @mernen Changed VM::raise_from_errno signature to use const char*.
mernen authored
324 void VM::raise_from_errno(const char* msg) {
3f594b6 @rue Changed all TODO:s to @todo so that doxygen picks them up.
rue authored
325 // @todo implement me
4f7df71 @brixen Added stub for VM::raise_exception.
brixen authored
326 }
feb91b4 Tons of stuff (too much probably)
Evan Phoenix authored
327
4f7df71 @brixen Added stub for VM::raise_exception.
brixen authored
328 void VM::raise_exception(Exception* exc) {
3f594b6 @rue Changed all TODO:s to @todo so that doxygen picks them up.
rue authored
329 // @todo implement me
feb91b4 Tons of stuff (too much probably)
Evan Phoenix authored
330 }
331
1fdd151 @rue Changed all OBJECT, SYMBOL, FIXNUM, INTEGER to normal syntax.
rue authored
332 void VM::set_const(const char* name, Object* val) {
feb91b4 Tons of stuff (too much probably)
Evan Phoenix authored
333 globals.object->set_const(this, (char*)name, val);
334 }
879a046 A whole slew. Enhanced type-info, debugged GC.
Evan Phoenix authored
335
1fdd151 @rue Changed all OBJECT, SYMBOL, FIXNUM, INTEGER to normal syntax.
rue authored
336 void VM::set_const(Module* mod, const char* name, Object* val) {
feb91b4 Tons of stuff (too much probably)
Evan Phoenix authored
337 mod->set_const(this, (char*)name, val);
338 }
310a461 Cleanup stack usage and fix interpreter
Evan Phoenix authored
339
340 void VM::print_backtrace() {
eea8ecc Move print_backtrace() to Task, fix rbt on Thread switch
Evan Phoenix authored
341 globals.current_task.get()->print_backtrace();
310a461 Cleanup stack usage and fix interpreter
Evan Phoenix authored
342 }
343
344 Task* VM::new_task() {
345 Task* task = Task::create(this);
ead7263 Fix the context cache, DRY up some VM code
Evan Phoenix authored
346 activate_task(task);
310a461 Cleanup stack usage and fix interpreter
Evan Phoenix authored
347 return task;
348 }
349
31ad5c2 Introduces the dynamic interpreter
Evan Phoenix authored
350 void VM::raise_exception_safely(Exception* exc) {
351 safe_position_data.exc = exc;
352 siglongjmp(safe_position, cReasonException);
353 // Never reached.
354 }
355
356 void VM::raise_typeerror_safely(TypeError* err) {
357 safe_position_data.type_error = err;
358 siglongjmp(safe_position, cReasonTypeError);
359 // Never reached.
360 }
361
362 void VM::raise_assertion_safely(Assertion* err) {
363 safe_position_data.assertion = err;
364 siglongjmp(safe_position, cReasonAssertion);
365 // Never reached.
366 }
367
ba265dd Add proper Task switching, fixes backtrace
Evan Phoenix authored
368 void VM::run_and_monitor() {
31ad5c2 Introduces the dynamic interpreter
Evan Phoenix authored
369 int reason;
370
371 use_safe_position = true;
372 reason = sigsetjmp(safe_position, 0);
373 // If reason is not 0, then we're here because of a longjmp.
374 if(reason) {
375 switch(reason) {
376 case cReasonException:
377 G(current_task)->raise_exception(safe_position_data.exc);
378 break;
379 case cReasonTypeError: {
380 TypeError* exc = safe_position_data.type_error;
381 Exception* e = Exception::make_type_error(this, exc->type, exc->object, exc->reason);
382 G(current_task)->raise_exception(e);
383 delete exc;
384 safe_position_data.type_error = NULL;
385 break;
386 }
387 case cReasonAssertion:
388 throw safe_position_data.assertion;
389
390 default:
391 break;
392 // We're not sure what this is. Oh well, hopefully the longjmp
393 // user knew what they were doing.
394 }
395 }
396
ba265dd Add proper Task switching, fixes backtrace
Evan Phoenix authored
397 for(;;) {
f9ec582 Add preemptive thread scheduling
Evan Phoenix authored
398 if(interrupts.check_events) {
399 interrupts.check_events = false;
400 interrupts.enable_preempt = false;
401
402 Thread* current = G(current_thread);
403 // The current thread isn't asleep, so we're being preemptive
404 if(current->alive() == Qtrue && current->sleep() != Qtrue) {
405 // Order is important here. We poll so any threads
406 // might get woken up if they need to be.
407 events->poll();
408
409 // Only then do we reschedule the current thread if
410 // we need to. queue_thread() puts the thread at the end
411 // of the list for it's priority, so we shouldn't starve
412 // anything this way.
413 queue_thread(G(current_thread));
414 }
415
416 while(!find_and_activate_thread()) {
417 events->run_and_wait();
418 }
419
420 interrupts.enable_preempt = interrupts.use_preempt;
719c98f Fix Thread and Channel to interact properly
Evan Phoenix authored
421 }
422
f781b6a Move GC running into VM, remove Task::check_interrupts
Evan Phoenix authored
423 collect_maybe();
ba265dd Add proper Task switching, fixes backtrace
Evan Phoenix authored
424 G(current_task)->execute();
425 }
426 }
427
f9ec582 Add preemptive thread scheduling
Evan Phoenix authored
428 // Trampoline to call scheduler_loop()
429 static void* __thread_tramp__(void* arg) {
430 VM* state = static_cast<VM*>(arg);
431 state->scheduler_loop();
432 return NULL;
433 }
434
435 // Create the preemption thread and call scheduler_loop() in the new thread
436 void VM::setup_preemption() {
437 if(pthread_create(&preemption_thread, NULL, __thread_tramp__, this) != 0) {
438 std::cout << "Unable to create preemption thread!\n";
439 }
440 }
441
442 // Runs forever, telling the VM to reschedule threads ever 10 milliseconds
443 void VM::scheduler_loop() {
444 // First off, we don't want this thread ever receiving a signal.
445 sigset_t mask;
446 sigfillset(&mask);
447 if(pthread_sigmask(SIG_BLOCK, &mask, NULL) != 0) {
448 abort();
449 }
450
451 struct timespec requested;
452 struct timespec actual;
453
454 requested.tv_sec = 0;
455 requested.tv_nsec = 10000000; // 10 milliseconds
456
457 for(;;) {
458 nanosleep(&requested, &actual);
459 if(interrupts.enable_preempt) {
460 interrupts.reschedule = true;
461 interrupts.check_events = true;
462 }
463 }
464 }
465
310a461 Cleanup stack usage and fix interpreter
Evan Phoenix authored
466 /* For debugging. */
467 extern "C" {
bc4b80f Remove STATE argument from debug functions
Evan Phoenix authored
468 void __printbt__() {
469 VM::current_state()->print_backtrace();
310a461 Cleanup stack usage and fix interpreter
Evan Phoenix authored
470 }
471 }
d769c94 Initial work on new C++ VM
Evan Phoenix authored
472 };
Something went wrong with that request. Please try again.