| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| |
| #ifndef IMPALA_CODEGEN_MCJIT_MEM_MGR_H |
| #define IMPALA_CODEGEN_MCJIT_MEM_MGR_H |
| |
| #include <llvm/ExecutionEngine/SectionMemoryManager.h> |
| |
| extern void *__dso_handle __attribute__ ((__visibility__ ("hidden"))); |
| |
| namespace impala { |
| |
| /// Custom memory manager. It is needed for a couple of purposes. |
| /// |
| /// We use it as a way to resolve references to __dso_handle in cross-compiled IR. |
| /// This uses the same approach as the legacy llvm JIT to handle __dso_handle. MCJIT |
| /// doesn't handle those for us: see LLVM issue 18062. |
| /// TODO: get rid of this by purging the cross-compiled IR of references to __dso_handle, |
| /// which come from global variables with destructors. |
| /// |
| /// We also use it to track how much memory is allocated for compiled code. |
| class ImpalaMCJITMemoryManager : public llvm::SectionMemoryManager { |
| public: |
| ImpalaMCJITMemoryManager() : bytes_allocated_(0), bytes_tracked_(0){} |
| |
| virtual uint64_t getSymbolAddress(const std::string& name) override { |
| if (name == "__dso_handle") return reinterpret_cast<uint64_t>(&__dso_handle); |
| return SectionMemoryManager::getSymbolAddress(name); |
| } |
| |
| virtual uint8_t* allocateCodeSection(uintptr_t size, unsigned alignment, |
| unsigned section_id, llvm::StringRef section_name) override { |
| bytes_allocated_ += size; |
| return llvm::SectionMemoryManager::allocateCodeSection( |
| size, alignment, section_id, section_name); |
| } |
| |
| virtual uint8_t* allocateDataSection(uintptr_t size, unsigned alignment, |
| unsigned section_id, llvm::StringRef section_name, bool is_read_only) override { |
| bytes_allocated_ += size; |
| return llvm::SectionMemoryManager::allocateDataSection( |
| size, alignment, section_id, section_name, is_read_only); |
| } |
| |
| int64_t bytes_allocated() const { return bytes_allocated_; } |
| int64_t bytes_tracked() const { return bytes_tracked_; } |
| void set_bytes_tracked(int64_t bytes_tracked) { |
| DCHECK_LE(bytes_tracked, bytes_allocated_); |
| bytes_tracked_ = bytes_tracked; |
| } |
| |
| private: |
| /// Total bytes allocated for the compiled code. |
| int64_t bytes_allocated_; |
| |
| /// Total bytes already tracked by MemTrackers. <= 'bytes_allocated_'. |
| /// Needed to release the correct amount from the MemTracker when done. |
| int64_t bytes_tracked_; |
| }; |
| } |
| |
| #endif |