[Lldb-commits] [lldb] r177364 - Refactored the expression parser so that the IR

Malea, Daniel daniel.malea at intel.com
Thu Apr 18 14:53:42 PDT 2013


Hi Sean,

After some back-and-forth on IRC, I think there is a slight data race in
this function around m_did_jit. It's atomicity doesn't prevent it from
being read on line 254 before (another thread) writes to it on line 262.
Also, the weak_ptr::lock does not guarantee that multiple threads don't
enter the function -- can you please take a look?

I think jit_mutex_locker needs to be moved up one scope.

Thanks Carlo for spotting this one!


Cheers,
Dan


On 2013-03-18 8:10 PM, "Sean Callanan" <scallanan at apple.com> wrote:

>
>+void
>+IRExecutionUnit::GetRunnableInfo(Error &error,
>+                                 lldb::addr_t &func_addr,
>+                                 lldb::addr_t &func_end)
>+{
>+    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet
>(LIBLLDB_LOG_EXPRESSIONS));
>+    lldb::ProcessSP process_sp(m_process_wp.lock());
>+    
>+    func_addr = LLDB_INVALID_ADDRESS;
>+    func_end = LLDB_INVALID_ADDRESS;
>+    
>+    if (!process_sp)
>+    {
>+        error.SetErrorToGenericError();
>+        error.SetErrorString("Couldn't write the JIT compiled code into
>the process because the process is invalid");
>+        return;
>+    }
>+    
>+    if (m_did_jit)
>+    {
>+        func_addr = m_function_load_addr;
>+        func_end = m_function_end_load_addr;
>+        
>+        return;
>+    }; // someone else may have gotten the mutex first
>+    
>+    {
>+        Mutex::Locker jit_mutex_locker(m_jit_mutex);
>+        
>+        if (m_did_jit)
>+        {
>+            func_addr = m_function_load_addr;
>+            func_end = m_function_end_load_addr;
>+            
>+            return;
>+        }; // someone else may have gotten the mutex first
>+        
>+        m_did_jit = true;
>+        
>+        lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet
>(LIBLLDB_LOG_EXPRESSIONS));
>+        
>+        std::string error_string;
>+        
>+        if (log)
>+        {
>+            std::string s;
>+            llvm::raw_string_ostream oss(s);
>+            
>+            m_module->print(oss, NULL);
>+            
>+            oss.flush();
>+            
>+            log->Printf ("Module being sent to JIT: \n%s", s.c_str());
>+        }
>+        
>+        llvm::Triple triple(m_module->getTargetTriple());
>+        llvm::Function *function = m_module->getFunction
>(m_name.AsCString());
>+        llvm::Reloc::Model relocModel;
>+        llvm::CodeModel::Model codeModel;
>+        
>+        if (triple.isOSBinFormatELF())
>+        {
>+            relocModel = llvm::Reloc::Static;
>+            // This will be small for 32-bit and large for 64-bit.
>+            codeModel = llvm::CodeModel::JITDefault;
>+        }
>+        else
>+        {
>+            relocModel = llvm::Reloc::PIC_;
>+            codeModel = llvm::CodeModel::Small;
>+        }
>+        
>+        llvm::EngineBuilder builder(m_module_ap.get());
>+        
>+        builder.setEngineKind(llvm::EngineKind::JIT)
>+        .setErrorStr(&error_string)
>+        .setRelocationModel(relocModel)
>+        .setJITMemoryManager(new MemoryManager(*this))
>+        .setOptLevel(llvm::CodeGenOpt::Less)
>+        .setAllocateGVsWithCode(true)
>+        .setCodeModel(codeModel)
>+        .setUseMCJIT(true);
>+        
>+        llvm::StringRef mArch;
>+        llvm::StringRef mCPU;
>+        llvm::SmallVector<std::string, 0> mAttrs;
>+        
>+        for (std::string &feature : m_cpu_features)
>+            mAttrs.push_back(feature);
>+        
>+        llvm::TargetMachine *target_machine =
>builder.selectTarget(triple,
>+                                                                   mArch,
>+                                                                   mCPU,
>+                 
>mAttrs);
>+        
>+        m_execution_engine_ap.reset(builder.create(target_machine));
>+        
>+        if (!m_execution_engine_ap.get())
>+        {
>+            error.SetErrorToGenericError();
>+            error.SetErrorStringWithFormat("Couldn't JIT the function:
>%s", error_string.c_str());
>+            return;
>+        }
>+        else
>+        {
>+            m_module_ap.release(); // ownership was transferred
>+        }
>+        
>+        m_execution_engine_ap->DisableLazyCompilation();
>+        
>+        // We don't actually need the function pointer here, this just
>forces it to get resolved.
>+        
>+        void *fun_ptr =
>m_execution_engine_ap->getPointerToFunction(function);
>+        
>+        // Errors usually cause failures in the JIT, but if we're lucky
>we get here.
>+        
>+        if (!function)
>+        {
>+            error.SetErrorToGenericError();
>+            error.SetErrorStringWithFormat("Couldn't find '%s' in the
>JITted module", m_name.AsCString());
>+            return;
>+        }
>+        
>+        if (!fun_ptr)
>+        {
>+            error.SetErrorToGenericError();
>+            error.SetErrorStringWithFormat("'%s' was in the JITted
>module but wasn't lowered", m_name.AsCString());
>+            return;
>+        }
>+        
>+        m_jitted_functions.push_back (JittedFunction(m_name.AsCString(),
>(lldb::addr_t)fun_ptr));
>+        
>+        CommitAllocations(process_sp);
>+        ReportAllocations(*m_execution_engine_ap);
>+        WriteData(process_sp);
>+                
>+        for (JittedFunction &jitted_function : m_jitted_functions)
>+        {
>+            jitted_function.m_remote_addr = GetRemoteAddressForLocal
>(jitted_function.m_local_addr);
>+            
>+            if (!jitted_function.m_name.compare(m_name.AsCString()))
>+            {
>+                AddrRange func_range =
>GetRemoteRangeForLocal(jitted_function.m_local_addr);
>+                m_function_end_load_addr = func_range.first +
>func_range.second;
>+                m_function_load_addr = jitted_function.m_remote_addr;
>+            }
>+        }
>+        
>+        if (log)
>+        {
>+            log->Printf("Code can be run in the target.");
>+            
>+            StreamString disassembly_stream;
>+            
>+            Error err = DisassembleFunction(disassembly_stream,
>process_sp);
>+            
>+            if (!err.Success())
>+            {
>+                log->Printf("Couldn't disassemble function : %s",
>err.AsCString("unknown error"));
>+            }
>+            else
>+            {
>+                log->Printf("Function disassembly:\n%s",
>disassembly_stream.GetData());
>+            }
>+        }
>+        
>+        func_addr = m_function_load_addr;
>+        func_end = m_function_end_load_addr;
>+        
>+        return;
>+    }
>+}
>+





More information about the lldb-commits mailing list