gecko-dev/ef/Compiler/CodeGenerator/NativeCodeCache.h

182 строки
5.6 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (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.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
NativeCodeCache
*/
#ifndef _NATIVE_CODE_CACHE_
#define _NATIVE_CODE_CACHE_
#include "ExceptionTable.h"
#include "FormatStructures.h"
#include "Pool.h"
#include "Attributes.h"
#include "InfoItem.h"
#include "HashTable.h"
#include "FieldOrMethod.h"
#include "LogModule.h"
#include "prmon.h"
//-----------------------------------------------------------------------------------------------------------
// This is the key for entries in the cache
// Currently it retainst he "fully qualified" name
// of the method.
struct MethodDescriptor
{
MethodDescriptor(Method& inMethod) :
method(&inMethod) { };
Method *method; // interned full name string describing this method
void operator=(const MethodDescriptor& inCopy) { method = inCopy.method; }
};
//-----------------------------------------------------------------------------------------------------------
struct PlatformTVector
{
Uint8* mTVector;
void
setTVector(Uint8* inTVector) { mTVector = inTVector; }
Uint8*
getFunctionAddress() const
{
#ifdef GENERATING_FOR_POWERPC
if (mTVEctor != NULL)
return (*(Uint8***)mTVector);
else
return (NULL);
#elif defined(GENERATING_FOR_X86)
return (mTVector);
#else
return (mTVector); // FIX-ME This probably is not right
#endif
}
Uint8*
getEnvironment() const
{
#ifdef GENERATING_FOR_POWERPC
return (*((Uint8***)mTVector + 1));
#else
assert(false);
return (NULL);
#endif
}
};
//-----------------------------------------------------------------------------------------------------------
// An entry in the CodeCache
// Not intended for use outside of NativeCode Cache
struct CacheEntry
{
CacheEntry(const MethodDescriptor& inMethodDescriptor) :
descriptor(inMethodDescriptor), stub(0) { }
MethodDescriptor descriptor; // unique descriptor of the method
PlatformTVector start; // default entry into the function
Uint8* end; // pointer to byte _after_ end of function
Uint8* stub; // if non-NULL this is the address of the stub function
ExceptionTable* eTable; // pointer to the exception table
mutable bool shouldBackPatch; // If true, specifies that the call site must be backpatched on compile
// FIX for now the restore policy will be kept in the NativeCodeCache, later we may want to store the restore policies elsewhere
StackFrameInfo policy; // specifies how to restore registers as stack frames are popped
Uint8* asynchVersion(Pool& pool, Uint8*& ip);
};
//-----------------------------------------------------------------------------------------------------------
class NativeCodeCache
{
PRMonitor* _mon;
public:
NativeCodeCache() :
mIndexByDescriptor(mPool),
mIndexByRange()
{ _mon = PR_NewMonitor(); }
Uint8* acquireMemory(const size_t inBytes);
void mapMemoryToMethod( const MethodDescriptor& inMethodDescriptor,
PlatformTVector inWhere,
Uint8* inEnd,
ExceptionTable* pExceptionTable,
StackFrameInfo& inPolicy );
addr lookupByDescriptor(const MethodDescriptor& inDescriptor, bool inhibitBackpatch, bool inLookupOnly = false);
CacheEntry* lookupByRange(Uint8* inAddress);
protected:
HashTable<CacheEntry*> mIndexByDescriptor; // hashtable of entrypoints to methods
Vector<CacheEntry*> mIndexByRange; // maps range -> method
public:
Pool mPool; // resource for our cache
static inline NativeCodeCache& getCache() { return (NativeCodeCache::sNativeCodeCache); }
static NativeCodeCache sNativeCodeCache;
#ifdef DEBUG
void printMethodTable(LogModuleObject &f);
#endif
static void enter() {
PR_EnterMonitor(sNativeCodeCache._mon);
}
static void exit() {
PR_ExitMonitor(sNativeCodeCache._mon);
}
};
// inCacheEntry: reference to actual CacheEntry in memory
// inCache: the cache in question
// creates a bit of code which when called compiles the method
// described by inCacheEntry.descriptor and then calls "compileAndBackPatchMethod"
// then jump to the method returned by compileAndBackPatchMethod
extern void*
generateCompileStub(NativeCodeCache& inCache, const CacheEntry& inCacheEntry);
extern void*
generateNativeStub(NativeCodeCache& inCache, const CacheEntry& inCacheEntry, void *nativeFunction);
extern void *
generateJNIGlue(NativeCodeCache& inCache,
const CacheEntry& inCacheEntry,
void *nativeFunction);
extern "C" void *
compileAndBackPatchMethod(const CacheEntry* inCacheEntry, void* inLastPC, void* inUserDefined);
// atomically backpatch a caller of a stub generated with generateCompileStub
// inMethodAddress the address of the callee
// inLastPC the next PC to be executed up return from the callee
// inUserDefined is a (probably) per platform piece of data that will be passed
// on to the backPatchMethod function.
void* backPatchMethod(void* inMethodAddress, void* inLastPC, void* inUserDefined);
void NS_EXTERN printMethodTable();
#endif // _NATIVE_CODE_CACHE_