sourcemod/sourcepawn/vm/compiled-function.cpp
2015-03-07 10:50:35 -08:00

72 lines
2.0 KiB
C++

// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#include "compiled-function.h"
#include "x86/jit_x86.h"
#include "environment.h"
using namespace sp;
CompiledFunction::CompiledFunction(void *entry_addr, size_t code_length,
cell_t pcode_offs,
FixedArray<LoopEdge> *edges,
FixedArray<CipMapEntry> *cipmap)
: entry_(entry_addr),
code_length_(code_length),
code_offset_(pcode_offs),
edges_(edges),
cip_map_(cipmap)
{
}
CompiledFunction::~CompiledFunction()
{
Environment::get()->FreeCode(entry_);
}
static int cip_map_entry_cmp(const void *a1, const void *aEntry)
{
uint32_t pcoffs = (uint32_t)a1;
const CipMapEntry *entry = reinterpret_cast<const CipMapEntry *>(aEntry);
if (pcoffs < entry->pcoffs)
return -1;
if (pcoffs == entry->pcoffs)
return 0;
return pcoffs > entry->pcoffs;
}
ucell_t
CompiledFunction::FindCipByPc(void *pc)
{
if (uintptr_t(pc) < uintptr_t(entry_))
return kInvalidCip;
uint32_t pcoffs = intptr_t(pc) - intptr_t(entry_);
if (pcoffs > code_length_)
return kInvalidCip;
void *ptr = bsearch(
(void *)pcoffs,
cip_map_->buffer(),
cip_map_->length(),
sizeof(CipMapEntry),
cip_map_entry_cmp);
assert(ptr);
if (!ptr) {
// Shouldn't happen, but fail gracefully.
return kInvalidCip;
}
return code_offset_ + reinterpret_cast<CipMapEntry *>(ptr)->cipoffs;
}