VMMethod* CompiledMethod::formalize(STATE, bool ondemand) { if(!backend_method_) { VMMethod* vmm = NULL; #ifdef ENABLE_LLVM /* Controls whether we use LLVM out of the gate or not. */ if(state->config.compile_up_front) { if(ondemand) { set_executor(VMLLVMMethod::uncompiled_execute); } else { VMLLVMMethod* llvm = new VMLLVMMethod(state, this); llvm->compile(state); vmm = llvm; } } else { vmm = new VMMethod(state, this); } #else vmm = new VMMethod(state, this); #endif backend_method_ = vmm; if(!primitive()->nil_p()) { if(Symbol* name = try_as<Symbol>(primitive())) { set_executor(Primitives::resolve_primitive(state, name)); } } return vmm; } return backend_method_; }
bool Executable::resolve_primitive(STATE) { if(!primitive_->nil_p()) { if(Symbol* name = try_as<Symbol>(primitive_)) { set_executor(Primitives::resolve_primitive(state, name, &prim_index_)); return true; } } return false; }
MachineCode* CompiledCode::internalize(STATE, GCToken gct, const char** reason, int* ip) { MachineCode* mcode = machine_code_; atomic::memory_barrier(); if(mcode) return mcode; CompiledCode* self = this; OnStack<1> os(state, self); self->hard_lock(state, gct); mcode = self->machine_code_; if(!mcode) { { BytecodeVerification bv(self); if(!bv.verify(state)) { if(reason) *reason = bv.failure_reason(); if(ip) *ip = bv.failure_ip(); std::cerr << "Error validating bytecode: " << bv.failure_reason() << "\n"; return 0; } } mcode = new MachineCode(state, self); if(self->resolve_primitive(state)) { mcode->fallback = execute; } else { mcode->setup_argument_handler(); } // We need to have an explicit memory barrier here, because we need to // be sure that mcode is completely initialized before it's set. // Otherwise another thread might see a partially initialized // MachineCode. atomic::write(&self->machine_code_, mcode); set_executor(mcode->fallback); } self->hard_unlock(state, gct); return mcode; }
MachineCode* CompiledCode::internalize(STATE) { timer::StopWatch<timer::microseconds> timer( state->vm()->metrics().machine.bytecode_internalizer_us); atomic::memory_barrier(); MachineCode* mcode = machine_code(); if(mcode) return mcode; { BytecodeVerifier bytecode_verifier(this); bytecode_verifier.verify(state); } mcode = new MachineCode(state, this); if(resolve_primitive(state)) { mcode->fallback = execute; } else { mcode->setup_argument_handler(); } /* There is a race here because another Thread may have run this * CompiledCode instance and internalized it. We attempt to store our * version assuming that we are the only ones to do so and throw away our * work if someone else has beat us to it. */ MachineCode** mcode_ptr = &_machine_code_; if(atomic::compare_and_swap(reinterpret_cast<void**>(mcode_ptr), 0, mcode)) { set_executor(mcode->fallback); return mcode; } else { return machine_code(); } }
void CompiledCode::set_interpreter(executor interp) { set_executor(interp); machine_code_->fallback = interp; }
void CompiledMethod::set_interpreter(executor interp) { set_executor(interp); backend_method_->fallback = interp; }