зеркало из https://github.com/mozilla/pjs.git
First Checked In.
This commit is contained in:
Родитель
3a6017b93b
Коммит
8bc1be85a1
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
gc_fragments.cpp
|
||||
*/
|
||||
|
||||
#include "gc_fragments.h"
|
||||
#include "sym_file.h"
|
||||
#include "gc.h"
|
||||
#include "MetroNubUtils.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
struct CodeLocation {
|
||||
CodeLocation* mNext;
|
||||
char* mCodeAddr;
|
||||
UInt32 mFileOffset;
|
||||
char mFileName[256];
|
||||
|
||||
CodeLocation() : mNext(NULL), mCodeAddr(NULL), mFileOffset(0)
|
||||
{
|
||||
mFileName[0] = '\0';
|
||||
}
|
||||
};
|
||||
|
||||
static const kCodeLocationCacheSize = 256;
|
||||
|
||||
struct CodeLocationCache {
|
||||
CodeLocation mEntries[kCodeLocationCacheSize];
|
||||
CodeLocation* mLocations;
|
||||
CodeLocation** mLastLink;
|
||||
|
||||
CodeLocationCache();
|
||||
|
||||
CodeLocation* findLocation(char* codeAddr);
|
||||
void saveLocation(char* codeAddr, char fileName[256], UInt32 fileOffset);
|
||||
};
|
||||
|
||||
CodeLocationCache::CodeLocationCache()
|
||||
: mLocations(NULL), mLastLink(&mLocations)
|
||||
{
|
||||
// link all of the locations together in a list.
|
||||
int offset = kCodeLocationCacheSize;
|
||||
while (offset > 0) {
|
||||
CodeLocation* location = &mEntries[--offset];
|
||||
location->mNext = mLocations;
|
||||
mLocations = location;
|
||||
}
|
||||
}
|
||||
|
||||
CodeLocation* CodeLocationCache::findLocation(char* codeAddr)
|
||||
{
|
||||
CodeLocation** link = &mLocations;
|
||||
CodeLocation* location = *link;
|
||||
while (location != NULL && location->mCodeAddr != NULL) {
|
||||
if (location->mCodeAddr == codeAddr) {
|
||||
// move it to the head of the list.
|
||||
if (location != mLocations) {
|
||||
*link = location->mNext;
|
||||
location->mNext = mLocations;
|
||||
mLocations = location;
|
||||
}
|
||||
return location;
|
||||
}
|
||||
link = &location->mNext;
|
||||
location = *link;
|
||||
// maintain pointer to the last element in list for fast insertion.
|
||||
if (location != NULL)
|
||||
mLastLink = link;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CodeLocationCache::saveLocation(char* codeAddr, char fileName[256], UInt32 fileOffset)
|
||||
{
|
||||
CodeLocation** link = mLastLink;
|
||||
CodeLocation* location = *link;
|
||||
mLastLink = &mLocations;
|
||||
|
||||
// move it to the head of the list.
|
||||
if (location != mLocations) {
|
||||
*link = location->mNext;
|
||||
location->mNext = mLocations;
|
||||
mLocations = location;
|
||||
}
|
||||
|
||||
// save the specified location.
|
||||
location->mCodeAddr = codeAddr;
|
||||
location->mFileOffset = fileOffset;
|
||||
::strcpy(location->mFileName, fileName);
|
||||
}
|
||||
|
||||
struct CodeFragment {
|
||||
CodeFragment* mNext;
|
||||
char* mDataStart;
|
||||
char* mDataEnd;
|
||||
char* mCodeStart;
|
||||
char* mCodeEnd;
|
||||
FSSpec mFragmentSpec;
|
||||
CodeLocationCache mLocations;
|
||||
sym_file* mSymbols;
|
||||
|
||||
CodeFragment(char* dataStart, char* dataEnd,
|
||||
char* codeStart, char* codeEnd,
|
||||
const FSSpec* fragmentSpec);
|
||||
|
||||
~CodeFragment();
|
||||
};
|
||||
|
||||
CodeFragment::CodeFragment(char* dataStart, char* dataEnd,
|
||||
char* codeStart, char* codeEnd,
|
||||
const FSSpec* fragmentSpec)
|
||||
: mDataStart(dataStart), mDataEnd(dataEnd),
|
||||
mCodeStart(codeStart), mCodeEnd(codeEnd),
|
||||
mFragmentSpec(*fragmentSpec), mSymbols(NULL), mNext(NULL)
|
||||
{
|
||||
// need to eagerly open symbols file eagerly, otherwise we're in the middle of a GC!
|
||||
FSSpec symSpec = mFragmentSpec;
|
||||
UInt8 len = symSpec.name[0];
|
||||
symSpec.name[++len] = '.';
|
||||
symSpec.name[++len] = 'x';
|
||||
symSpec.name[++len] = 'S';
|
||||
symSpec.name[++len] = 'Y';
|
||||
symSpec.name[++len] = 'M';
|
||||
symSpec.name[0] = len;
|
||||
|
||||
mSymbols = open_sym_file(&symSpec);
|
||||
}
|
||||
|
||||
CodeFragment::~CodeFragment()
|
||||
{
|
||||
if (mSymbols) {
|
||||
close_sym_file(mSymbols);
|
||||
mSymbols = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static CodeFragment* theFragments = NULL;
|
||||
|
||||
static CodeFragment** find_fragment(char* codeAddr)
|
||||
{
|
||||
CodeFragment** link = &theFragments;
|
||||
CodeFragment* fragment = *link;
|
||||
while (fragment != NULL) {
|
||||
if (codeAddr >= fragment->mCodeStart && codeAddr < fragment->mCodeEnd)
|
||||
return link;
|
||||
link = &fragment->mNext;
|
||||
fragment = *link;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void GC_register_fragment(char* dataStart, char* dataEnd,
|
||||
char* codeStart, char* codeEnd,
|
||||
const FSSpec* fragmentSpec)
|
||||
{
|
||||
// register the roots.
|
||||
GC_add_roots(dataStart, dataEnd);
|
||||
|
||||
// create an entry for this fragment.
|
||||
CodeFragment* fragment = new CodeFragment(dataStart, dataEnd,
|
||||
codeStart, codeEnd,
|
||||
fragmentSpec);
|
||||
if (fragment != NULL) {
|
||||
fragment->mNext = theFragments;
|
||||
theFragments = fragment;
|
||||
}
|
||||
}
|
||||
|
||||
void GC_unregister_fragment(char* dataStart, char* dataEnd,
|
||||
char* codeStart, char* codeEnd)
|
||||
{
|
||||
// try not to crash when running under the MW debugger.
|
||||
if (!AmIBeingMWDebugged()) {
|
||||
CodeFragment** link = find_fragment(codeStart);
|
||||
if (link != NULL) {
|
||||
CodeFragment* fragment = *link;
|
||||
*link = fragment->mNext;
|
||||
delete fragment;
|
||||
}
|
||||
}
|
||||
|
||||
// remove the roots.
|
||||
GC_remove_roots(dataStart, dataEnd);
|
||||
}
|
||||
|
||||
int GC_address_to_source(char* codeAddr, char fileName[256], UInt32* fileOffset)
|
||||
{
|
||||
CodeFragment** link = find_fragment(codeAddr);
|
||||
if (link != NULL) {
|
||||
CodeFragment* fragment = *link;
|
||||
// always move this fragment to the head of the list, to speed up searches.
|
||||
if (theFragments != fragment) {
|
||||
*link = fragment->mNext;
|
||||
fragment->mNext = theFragments;
|
||||
theFragments = fragment;
|
||||
}
|
||||
// see if this is a cached location.
|
||||
CodeLocation* location = fragment->mLocations.findLocation(codeAddr);
|
||||
if (location != NULL) {
|
||||
::strcpy(fileName, location->mFileName);
|
||||
*fileOffset = location->mFileOffset;
|
||||
return 1;
|
||||
}
|
||||
sym_file* symbols = fragment->mSymbols;
|
||||
if (symbols != NULL) {
|
||||
if (get_source(symbols, UInt32(codeAddr - fragment->mCodeStart), fileName, fileOffset)) {
|
||||
// save this location in the per-fragment cache.
|
||||
fragment->mLocations.saveLocation(codeAddr, fileName, *fileOffset);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
gc_fragments.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __FILES__
|
||||
#include <Files.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void GC_register_fragment(char* dataStart, char* dataEnd,
|
||||
char* codeStart, char* codeEnd,
|
||||
const FSSpec* fragmentSpec);
|
||||
|
||||
void GC_unregister_fragment(char* dataStart, char* dataEnd,
|
||||
char* codeStart, char* codeEnd);
|
||||
|
||||
int GC_address_to_source(char* codeAddr, char fileName[256], UInt32* fileOffset);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
Загрузка…
Ссылка в новой задаче