| //===------- MethodInfo.cpp - Runtime information for methods -------------===// |
| // |
| // The VMKit project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "mvm/Allocator.h" |
| #include "mvm/MethodInfo.h" |
| #include "MvmGC.h" |
| |
| #include <dlfcn.h> |
| |
| #if defined(__MACH__) |
| #define SELF_HANDLE RTLD_DEFAULT |
| #else |
| #define SELF_HANDLE 0 |
| #endif |
| |
| using namespace mvm; |
| |
| void CamlMethodInfo::scan(void* TL, void* ip, void* addr) { |
| if (!CF && InstructionPointer) { |
| MethodInfo* MI = VirtualMachine::SharedStaticFunctions.IPToMethodInfo(ip); |
| if (MI != &DefaultMethodInfo::DM) { |
| CF = ((CamlMethodInfo*)MI)->CF; |
| } |
| } |
| |
| if (CF) { |
| //uintptr_t spaddr = (uintptr_t)addr + CF->FrameSize + sizeof(void*); |
| uintptr_t spaddr = ((uintptr_t*)addr)[0]; |
| for (uint16 i = 0; i < CF->NumLiveOffsets; ++i) { |
| Collector::scanObject((void**)(spaddr + CF->LiveOffsets[i])); |
| } |
| } |
| } |
| |
| void StaticCamlMethodInfo::print(void* ip, void* addr) { |
| fprintf(stderr, "; %p in %s static method\n", ip, name); |
| } |
| |
| void DefaultMethodInfo::print(void* ip, void* addr) { |
| Dl_info info; |
| int res = dladdr(ip, &info); |
| if (res != 0) { |
| fprintf(stderr, "; %p in %s\n", ip, info.dli_sname); |
| } else { |
| fprintf(stderr, "; %p in Unknown method\n", ip); |
| } |
| } |
| |
| DefaultMethodInfo DefaultMethodInfo::DM; |
| |
| void DefaultMethodInfo::scan(void* TL, void* ip, void* addr) { |
| } |
| |
| |
| MethodInfo* StartFunctionMap::IPToMethodInfo(void* ip) { |
| FunctionMapLock.acquire(); |
| std::map<void*, MethodInfo*>::iterator E = Functions.end(); |
| std::map<void*, MethodInfo*>::iterator I = Functions.find(ip); |
| MethodInfo* MI = 0; |
| if (I == E) { |
| Dl_info info; |
| int res = dladdr(ip, &info); |
| if (res != 0) { |
| I = Functions.find(info.dli_saddr); |
| if (I == E) { |
| // The method is static, and we have no information for it. |
| // Just return the Default MethodInfo object. |
| MI = &DefaultMethodInfo::DM; |
| } else { |
| MI = I->second; |
| } |
| } else { |
| // The method is jitted, and no-one has intercepted its compilation. |
| // Just return the Default MethodInfo object. |
| MI = &DefaultMethodInfo::DM; |
| } |
| // Add it to the map, so that we don't need to call dladdr again. |
| Functions.insert(std::make_pair(ip, MI)); |
| } else { |
| MI = I->second; |
| } |
| FunctionMapLock.release(); |
| return MI; |
| } |
| |
| MethodInfo* VirtualMachine::IPToMethodInfo(void* ip) { |
| MethodInfo* MI = RuntimeFunctions.IPToMethodInfo(ip); |
| if (MI) return MI; |
| |
| MI = SharedRuntimeFunctions.IPToMethodInfo(ip); |
| if (MI) return MI; |
| |
| MI = StaticFunctions.IPToMethodInfo(ip); |
| if (MI != &DefaultMethodInfo::DM) return MI; |
| |
| MI = SharedStaticFunctions.IPToMethodInfo(ip); |
| return MI; |
| } |
| |
| |
| void SharedStartFunctionMap::initialize() { |
| CamlFrame* currentFrame = |
| (CamlFrame*)dlsym(SELF_HANDLE, "camlVmkitoptimized__frametable"); |
| |
| Dl_info info; |
| void* previousPtr = 0; |
| const char* previousName = 0; |
| CamlFrame* previousFrame = currentFrame; |
| StaticAllocator = new BumpPtrAllocator(); |
| |
| if (currentFrame) { |
| while (true) { |
| if (!currentFrame->ReturnAddress) break; |
| int res = dladdr(currentFrame->ReturnAddress, &info); |
| if (res) { |
| if (previousPtr && info.dli_saddr != previousPtr) { |
| StaticCamlMethodInfo* MI = |
| new(*StaticAllocator, "StaticCamlMethodInfo") |
| StaticCamlMethodInfo(previousFrame, previousPtr, previousName); |
| addMethodInfo(MI, previousPtr); |
| } |
| previousName = info.dli_sname; |
| previousFrame = currentFrame; |
| previousPtr = info.dli_saddr; |
| } |
| |
| currentFrame = (CamlFrame*) ((char*)currentFrame + |
| (currentFrame->NumLiveOffsets % 2) * sizeof(uint16_t) + |
| currentFrame->NumLiveOffsets * sizeof(uint16_t) + |
| sizeof(void*) + sizeof(uint16_t) + sizeof(uint16_t)); |
| } |
| } |
| } |
| |
| CamlMethodInfo::CamlMethodInfo(CamlFrame* C, void* ip) { |
| InstructionPointer = ip; |
| CF = C; |
| } |
| |
| StartEndFunctionMap VirtualMachine::SharedRuntimeFunctions; |
| SharedStartFunctionMap VirtualMachine::SharedStaticFunctions; |