зеркало из https://github.com/mozilla/gecko-dev.git
139 строки
4.9 KiB
C++
139 строки
4.9 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):
|
|
*/
|
|
#ifndef InterfaceDispatchTable_H
|
|
#define InterfaceDispatchTable_H
|
|
|
|
/* Efficient mapping from {Class, Interface} to vtable offset */
|
|
|
|
#include "Vector.h"
|
|
#include "HashTable.h"
|
|
|
|
/* A type used to hold the offset, in bytes, into a vtable */
|
|
typedef Uint32 VTableOffset;
|
|
|
|
struct InterfaceVIndexPair {
|
|
Uint32 interfaceNumber; // Unique serial number of interface
|
|
Uint32 baseVOffset; // Offset, in bytes, to first entry in interface's vtable
|
|
};
|
|
typedef Vector<InterfaceVIndexPair> InterfaceList;
|
|
typedef InterfaceList *InterfaceListPtr;
|
|
|
|
struct InterfaceListKeyOps {
|
|
static bool equals(InterfaceList * userKey, InterfaceList * hashTableKey);
|
|
|
|
static InterfaceList *copyKey(Pool &/*pool*/, InterfaceList* userKey) {
|
|
return userKey;
|
|
}
|
|
|
|
static Uint32 hashCode(InterfaceList * userKey);
|
|
};
|
|
|
|
class InterfaceDispatchTable;
|
|
typedef InterfaceDispatchTable *InterfaceDispatchTablePtr;
|
|
typedef HashTable<InterfaceDispatchTablePtr, InterfaceListPtr, InterfaceListKeyOps> InterfaceSetHashTable;
|
|
|
|
class InterfaceDispatchTable {
|
|
public:
|
|
/* Maximum number of simultaneously loaded interfaces in the entire VM.
|
|
If we exceed this limit, we throw an error during compilation.
|
|
This is only an enum because const class members suck in C++ */
|
|
enum {maxInterfaces = 2048};
|
|
|
|
/* Arbitrary upper bound for global lookup table sizes.
|
|
If we blow out these limits, we throw an error during compilation.
|
|
This is only an enum because const members suck in C++ */
|
|
enum {interfaceDispatchTableSize = 4096};
|
|
enum {interfaceAssignabilityTableSize = 8192};
|
|
|
|
private:
|
|
|
|
/* The system-wide table used for mapping {class,interface} to a sub-vtable */
|
|
static VTableOffset VOffsetTable[interfaceDispatchTableSize];
|
|
|
|
/* Class-specific offset to add to interfaceNumber when accessing VIndexTable */
|
|
Uint16 vShift;
|
|
|
|
/* The system-wide table used for performing instanceof and checkcast
|
|
operations on interface types */
|
|
static Uint16 assignabilityTable[interfaceAssignabilityTableSize];
|
|
|
|
/* Class-specific offset to add to interfaceNumber when accessing assignabilityTable */
|
|
Uint16 aShift;
|
|
|
|
/* Hashtable keyed by the set of interfaces that are implemented by a class */
|
|
static InterfaceSetHashTable *hashTable;
|
|
|
|
/* List of interface/VIndex pairs */
|
|
InterfaceList *interfaceList;
|
|
|
|
/* Internal helper functions */
|
|
bool tryFitVOffset(Uint32 shift);
|
|
bool packIntoVOffsetTable();
|
|
bool tryFitAssignability(Uint32 shift);
|
|
bool packIntoAssignabilityTable();
|
|
void mergeInterfaceLists();
|
|
|
|
/* Unique number used for */
|
|
Uint16 assignabilityColor;
|
|
|
|
/* Counter used to assign unique values to assignability color, above */
|
|
static Uint16 sColorCounter;
|
|
|
|
InterfaceDispatchTable *inheritedInterfaceTable;
|
|
|
|
public:
|
|
static void staticInit(Pool &pool);
|
|
|
|
/* After building up the list of all implemented interfaces using
|
|
interfaceDispatchTable::add(), the build method is used to integrate
|
|
that list into the global interface/class lookup table in a
|
|
space-efficient manner. */
|
|
InterfaceDispatchTable *build();
|
|
|
|
InterfaceDispatchTable(): vShift(0), aShift(0), interfaceList(NULL),
|
|
assignabilityColor(0), inheritedInterfaceTable(0) {}
|
|
|
|
/* Add an interface to the set of interfaces that is implemented,
|
|
with a sub-vtable that begins at a byte offset of baseVOffset in
|
|
the enclosing vtable. */
|
|
void add(Uint32 interfaceNumber, Uint32 baseVOffset);
|
|
|
|
/* Same as above, but for an interface that has no methods. */
|
|
void add(Uint32 interfaceNumber) {add(interfaceNumber, 0);}
|
|
|
|
void inherit(InterfaceDispatchTable *inheritedTable);
|
|
|
|
/* Return the table addresses to be stored in the Type object for a class. */
|
|
VTableOffset *getVOffsetTableBaseAddress() {return &VOffsetTable[vShift];};
|
|
Uint16 *getAssignableTableBaseAddress() {return &assignabilityTable[aShift];};
|
|
|
|
/* Return the value which must be found in an interface's assignment
|
|
table entry to indicate that an object is assignable
|
|
to that interface type. */
|
|
Uint16 getAssignableMatchValue() const {return assignabilityColor;}
|
|
};
|
|
|
|
bool build(InterfaceDispatchTable * &interfaceDispatchTable);
|
|
|
|
|
|
#endif /* InterfaceDispatchTable_H */
|