void gc_scan(GarbageCollector* gc) { utilities::thread::Mutex::LockGuard guard(mutex_); for(std::list<BackgroundCompileRequest*>::iterator i = pending_requests_.begin(); i != pending_requests_.end(); ++i) { BackgroundCompileRequest* req = *i; if(Object* obj = gc->saw_object(req->method())) { req->set_method(force_as<CompiledCode>(obj)); } if(Class* receiver_class = req->receiver_class()) { req->set_receiver_class(as<Class>(gc->saw_object(receiver_class))); } if(BlockEnvironment* block_env = req->block_env()) { req->set_block_env(as<BlockEnvironment>(gc->saw_object(block_env))); } } if(current_compiler_) { jit::RuntimeDataHolder* rd = current_compiler_->context()->runtime_data_holder(); rd->set_mark(); ObjectMark mark(gc); rd->mark_all(current_req_->method(), mark); } }
virtual void perform() { for(;;) { // forever BackgroundCompileRequest* req = 0; // Lock, wait, get a request, unlock { thread::Mutex::LockGuard guard(mutex_); if(pause_) { state = cPaused; paused_ = true; pause_condition_.signal(); while(pause_) { condition_.wait(mutex_); } state = cUnknown; paused_ = false; } // If we've been asked to stop, do so now. if(stop_) return; while(pending_requests_.size() == 0) { state = cIdle; // unlock and wait... condition_.wait(mutex_); if(stop_) return; } // now locked again, shift a request req = pending_requests_.front(); pending_requests_.pop_front(); state = cRunning; } // mutex now unlock, allowing others to push more requests // LLVMCompiler* jit = new LLVMCompiler(); { timer::Running timer(ls_->time_spent); jit->compile(ls_, req->vmmethod(), req->is_block()); jit->generate_function(ls_); } if(show_machine_code_) { jit->show_machine_code(); } // Ok, compiled, generated machine code, now update MachineMethod // Ok, now we are manipulating managed memory, so make // sure the GC doesn't run. ls_->shared().gc_dependent(); req->vmmethod()->set_jitted(jit->llvm_function(), jit->code_bytes(), jit->function_pointer()); if(req->is_block()) { BlockEnvironment* be = req->block_env(); if(!be) { llvm::outs() << "Fatal error in JIT. Expected a BlockEnvironment.\n"; } else { be->set_native_function(jit->function_pointer()); } } else { MachineMethod* mm = req->machine_method(); if(!mm) { llvm::outs() << "Fatal error in JIT. Expected a MachineMethod.\n"; } else { mm->update(req->vmmethod(), jit); mm->activate(); } } int which = ls_->add_jitted_method(); if(ls_->config().jit_show_compiling) { llvm::outs() << "[[[ JIT finished background compiling " << which << (req->is_block() ? " (block)" : " (method)") << " ]]]\n"; } delete req; // We don't depend on the GC here, so let it run independent // of us. ls_->shared().gc_independent(); } }