Skip to content

Commit 1a0d3cb

Browse files
committedMar 28, 2016
Merge remote-tracking branch 'origin' into mcjit
2 parents 2dd51a1 + ffd3943 commit 1a0d3cb

19 files changed

+200
-85
lines changed
 

‎core/rubinius.rb

+1
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ def self.version
288288
end
289289
end
290290

291+
extra << "C" if Rubinius::CONCURRENT_GC
291292
extra << "D" if Rubinius::DEBUG_BUILD
292293

293294
rev = BUILD_REV[0..7]

‎machine/builtin/code_db.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "memory.hpp"
44
#include "object_utils.hpp"
5+
#include "on_stack.hpp"
56
#include "ontology.hpp"
67
#include "marshal.hpp"
78
#include "thread_phase.hpp"
@@ -130,6 +131,8 @@ namespace rubinius {
130131
if(m_id.empty()) break;
131132

132133
CompiledCode* code = load(state, m_id.c_str());
134+
OnStack<1> os(state, code);
135+
133136
if(code->nil_p()) {
134137
Exception::raise_runtime_error(state, "unable to resolve method in CodeDB initialize");
135138
}

‎machine/builtin/string.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -768,8 +768,12 @@ namespace rubinius {
768768
ascii_only(state, cFalse);
769769
}
770770

771-
if(CBOOL(valid_encoding_) && !CBOOL(other->valid_encoding_p(state))) {
772-
valid_encoding(state, cFalse);
771+
if(!CBOOL(other->valid_encoding_p(state))) {
772+
if(CBOOL(valid_encoding_)) {
773+
valid_encoding(state, cFalse);
774+
} else {
775+
valid_encoding(state, cNil);
776+
}
773777
}
774778

775779
if(unlikely(length > data_length)) {

‎machine/builtin/system.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ namespace rubinius {
394394
int pid;
395395

396396
state->vm()->become_managed();
397+
state->memory()->set_interrupt();
397398

398399
{
399400
LockPhase locked(state);
@@ -825,6 +826,7 @@ namespace rubinius {
825826
utilities::thread::SpinLock::LockGuard guard(state->shared().env()->fork_exec_lock());
826827

827828
state->shared().internal_threads()->before_fork(state);
829+
state->memory()->set_interrupt();
828830

829831
LockPhase locked(state);
830832

‎machine/builtin/thread.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ namespace rubinius {
156156
call_frame->line(state));
157157

158158
if(!thread->send(state, state->symbol("initialize"), args, block, true)) {
159+
thread->vm()->set_zombie(state);
159160
return NULL;
160161
}
161162

@@ -175,6 +176,7 @@ namespace rubinius {
175176
call_frame->line(state));
176177

177178
if(!thread->send(state, state->symbol("__thread_initialize__"), args, block, true)) {
179+
thread->vm()->set_zombie(state);
178180
return NULL;
179181
}
180182

‎machine/bytecode_verification.cpp

+14-7
Original file line numberDiff line numberDiff line change
@@ -40,27 +40,27 @@ namespace rubinius {
4040
if(Fixnum* fix = try_as<Fixnum>(method_->local_count())) {
4141
locals_ = fix->to_native();
4242
} else {
43-
fail("method not initialized properly", -1);
43+
fail("local_count is not a Fixnum", -1);
4444
return false;
4545
}
4646

4747
InstructionSequence* iseq = try_as<InstructionSequence>(method_->iseq());
4848
if(!iseq) {
49-
fail("method not initialized properly", -1);
49+
fail("iseq is not an InstructionSequence", -1);
5050
return false;
5151
}
5252

5353
if(Tuple* tup = try_as<Tuple>(iseq->opcodes())) {
5454
ops_ = tup;
5555
} else {
56-
fail("method not initialized properly", -1);
56+
fail("opcodes is not a Tuple", -1);
5757
return false;
5858
}
5959

6060
if(Fixnum* fix = try_as<Fixnum>(method_->stack_size())) {
6161
max_stack_allowed_ = fix->to_native();
6262
} else {
63-
fail("method not initialized properly", -1);
63+
fail("stack_size is not a Fixnum", -1);
6464
return false;
6565
}
6666

@@ -72,11 +72,18 @@ namespace rubinius {
7272
}
7373

7474
Fixnum* tot = try_as<Fixnum>(method_->total_args());
75+
if(!tot) {
76+
fail("total_args is not a Fixnum", -1);
77+
return false;
78+
}
7579
Fixnum* req = try_as<Fixnum>(method_->required_args());
80+
if(!req) {
81+
fail("required_args is not a Fixnum", -1);
82+
return false;
83+
}
7684
Fixnum* post = try_as<Fixnum>(method_->post_args());
77-
78-
if(!tot || !req || !post) {
79-
fail("method not initialized properly (missing arg counts)", -1);
85+
if(!post) {
86+
fail("post_args is not a Fixnum", -1);
8087
return false;
8188
}
8289

‎machine/memory.cpp

+40-12
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ namespace rubinius {
7171
, mature_mark_concurrent_(shared.config.gc_immix_concurrent)
7272
, mature_gc_in_progress_(false)
7373
, slab_size_(4096)
74+
, interrupt_flag_(false)
7475
, collect_young_flag_(false)
7576
, collect_full_flag_(false)
7677
, shared_(vm->shared)
@@ -519,6 +520,7 @@ namespace rubinius {
519520
if(!can_gc()) {
520521
collect_young_flag_ = false;
521522
collect_full_flag_ = false;
523+
interrupt_flag_ = false;
522524
return;
523525
}
524526

@@ -543,6 +545,9 @@ namespace rubinius {
543545
} else {
544546
collect_young(state, &gc_data);
545547
}
548+
549+
if(!collect_full_flag_) interrupt_flag_ = false;
550+
546551
RUBINIUS_GC_END(0);
547552
}
548553

@@ -610,12 +615,12 @@ namespace rubinius {
610615
}
611616

612617
void Memory::collect_full(STATE) {
613-
timer::StopWatch<timer::milliseconds> timerx(
614-
state->vm()->metrics().gc.immix_concurrent_ms);
615-
616618
// If we're already collecting, ignore this request
617619
if(mature_gc_in_progress_) return;
618620

621+
timer::StopWatch<timer::milliseconds> timerx(
622+
state->vm()->metrics().gc.immix_stop_ms);
623+
619624
if(state->shared().config.memory_collection_log.value) {
620625
logger::write("memory: full collection");
621626
}
@@ -624,21 +629,34 @@ namespace rubinius {
624629

625630
immix_->reset_stats();
626631

627-
// TODO: GC hacks hacks hacks fix fix fix.
628-
if(mature_mark_concurrent_) {
629-
memory::GCData* data = new memory::GCData(state->vm());
630-
631-
clear_fiber_marks(data);
632-
immix_->start_marker(state);
633-
immix_->collect_start(data);
634-
mature_gc_in_progress_ = true;
635-
} else {
632+
{
636633
memory::GCData data(state->vm());
637634

638635
clear_fiber_marks(&data);
639636
immix_->collect(&data);
640637
collect_full_finish(state, &data);
641638
}
639+
640+
if(mature_mark_concurrent_) {
641+
memory::GCData* data = new memory::GCData(state->vm());
642+
643+
mature_gc_in_progress_ = true;
644+
645+
immix_->collect_start(data);
646+
immix_->start_marker(state, data);
647+
}
648+
}
649+
650+
void Memory::collect_full_restart(STATE, memory::GCData* data) {
651+
if(state->shared().config.memory_collection_log.value) {
652+
logger::write("memory: concurrent collection restart");
653+
}
654+
655+
code_manager_.clear_marks();
656+
657+
immix_->reset_stats();
658+
659+
immix_->collect_start(data);
642660
}
643661

644662
void Memory::collect_full_finish(STATE, memory::GCData* data) {
@@ -672,6 +690,7 @@ namespace rubinius {
672690
}
673691

674692
collect_full_flag_ = false;
693+
interrupt_flag_ = false;
675694

676695
RUBINIUS_GC_END(1);
677696
}
@@ -783,6 +802,15 @@ namespace rubinius {
783802
schedule_full_collection(
784803
"mature region allocate object",
785804
state->vm()->metrics().gc.immix_set);
805+
806+
if(mature_mark_concurrent_) {
807+
/* Spilling allocations to the Large Object Space can be costly
808+
* because that region and collector are less efficient. To mitigate
809+
* spilling, we sleep for a very small random interval to allow the
810+
* concurrent marking thread to catch up and complete the GC cycle.
811+
*/
812+
state->vm()->blocking_suspend(state, state->vm()->metrics().memory.suspend_ms);
813+
}
786814
}
787815

788816
collect_flag = false;

‎machine/memory.hpp

+26-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "memory/write_barrier.hpp"
1919
#include "memory/immix_collector.hpp"
2020

21+
#include "util/atomic.hpp"
2122
#include "util/thread.hpp"
2223

2324
#include "shared_state.hpp"
@@ -117,6 +118,9 @@ namespace rubinius {
117118
/// allocations.
118119
size_t slab_size_;
119120

121+
/// Flag indicating that a Memory condition exists
122+
bool interrupt_flag_;
123+
120124
/// Flag indicating whether a young collection should be performed soon
121125
bool collect_young_flag_;
122126

@@ -188,7 +192,7 @@ namespace rubinius {
188192

189193
// Don't trigger GC if currently prohibited so we don't thrash checking.
190194
if(can_gc()) {
191-
collect_young_flag_ = true;
195+
interrupt_flag_ = collect_young_flag_ = true;
192196
shared_.thread_nexus()->set_stop();
193197
}
194198
}
@@ -208,7 +212,7 @@ namespace rubinius {
208212
}
209213

210214
if(can_gc()) {
211-
collect_full_flag_ = true;
215+
interrupt_flag_ = collect_full_flag_ = true;
212216
shared_.thread_nexus()->set_stop();
213217
} else if(shared_.config.memory_collection_log.value) {
214218
logger::write("memory: collection: disabled");
@@ -538,6 +542,7 @@ namespace rubinius {
538542
void collect(STATE) {
539543
collect_young_flag_ = true;
540544
collect_full_flag_ = true;
545+
interrupt_flag_ = true;
541546
collect_maybe(state);
542547
}
543548

@@ -568,12 +573,30 @@ namespace rubinius {
568573

569574
memory::MarkStack& mature_mark_stack();
570575

571-
bool& collect_young_flag() {
576+
void set_interrupt() {
577+
interrupt_flag_ = true;
578+
atomic::memory_barrier();
579+
}
580+
581+
void reset_interrupt() {
582+
interrupt_flag_ = false;
583+
}
584+
585+
bool& interrupt_p() {
586+
return interrupt_flag_;
587+
}
588+
589+
bool& collect_young_p() {
572590
return collect_young_flag_;
573591
}
574592

593+
bool& collect_full_p() {
594+
return collect_full_flag_;
595+
}
596+
575597
void collect_young(STATE, memory::GCData* data);
576598
void collect_full(STATE);
599+
void collect_full_restart(STATE, memory::GCData* data);
577600
void collect_full_finish(STATE, memory::GCData* data);
578601

579602
public:

‎machine/memory/immix_collector.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,6 @@ namespace memory {
200200
void ImmixGC::collect_start(GCData* data) {
201201
gc_.clear_marks();
202202
collect_scan(data);
203-
marker_->concurrent_mark(data);
204203
}
205204

206205
void ImmixGC::collect_scan(GCData* data) {
@@ -361,9 +360,9 @@ namespace memory {
361360
diagnostics_.total_bytes_ - diagnostics_.bytes_);
362361
}
363362

364-
void ImmixGC::start_marker(STATE) {
363+
void ImmixGC::start_marker(STATE, GCData* data) {
365364
if(!marker_) {
366-
marker_ = new ImmixMarker(state, this);
365+
marker_ = new ImmixMarker(state, this, data);
367366
}
368367
}
369368

‎machine/memory/immix_collector.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ namespace memory {
172172
return diagnostics_;
173173
}
174174

175-
void start_marker(STATE);
175+
void start_marker(STATE, GCData* data);
176176
bool process_mark_stack();
177177
bool process_mark_stack(bool& exit);
178178
MarkStack& mark_stack();

0 commit comments

Comments
 (0)