Bug 1444745 - Part 1: Clear out xptinfo and typelib to make way for the this patch, r=mccr8

Unfortunately, I wasn't able to figure out a way to make firefox build & run in
the intermediate stages of these commits. Because of this, I am going to just
delete most of the code which I am deleting in the first patch, as I figure that
those are somewhat uninteresting changes, and then make the other changes in the
following patches.

In total, the following things are deleted:
1. All of xpcom/typelib, except for `xpt/tools` - this directory is being
subsumed entirely into xpcom/reflect/xptinfo.
2. Most of the code in xpcom/reflect/xptinfo, it is being rewritten to avoid
allocating and contain all of the necessary data structures.
3. idl-parser's typelib.py XPT generator, as it will be replaced.
4. Most includes of files which have been deleted.

NOTE: xpcom/typelib/xpt/tools/xpt.py was not removed, as it is used by bundling
code & bundling tests, which we don't want to remove yet.
This commit is contained in:
Nika Layzell 2018-04-04 15:55:09 -04:00
parent 0405ef5fa2
commit f5f86c989e
66 changed files with 4 additions and 2909 deletions

View File

@ -155,6 +155,10 @@ configure:: $(configure-preqs)
ifneq (,$(MAKEFILE))
$(OBJDIR)/Makefile: $(OBJDIR)/config.status
$(OBJDIR)/config.status: $(CONFIG_STATUS_DEPS)
else
$(OBJDIR)/Makefile: $(CONFIG_STATUS_DEPS)

View File

@ -28,15 +28,12 @@
#include "nsXBLPrototypeBinding.h"
#include "nsXBLContentSink.h"
#include "xptinfo.h"
#include "nsIInterfaceInfoManager.h"
#include "nsIDocumentObserver.h"
#include "nsGkAtoms.h"
#include "nsXBLProtoImpl.h"
#include "nsCRT.h"
#include "nsContentUtils.h"
#include "nsTextFragment.h"
#include "nsTextNode.h"
#include "nsIInterfaceInfo.h"
#include "nsIScriptError.h"
#include "nsXBLResourceLoader.h"

View File

@ -23,7 +23,6 @@
#include "mozilla/TimeStamp.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/URLPreloader.h"
#include "mozilla/XPTInterfaceInfoManager.h"
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/DOMExceptionBinding.h"
#include "mozilla/dom/BindingUtils.h"
@ -32,7 +31,6 @@
#include "mozilla/Scheduler.h"
#include "nsZipArchive.h"
#include "nsWindowMemoryReporter.h"
#include "ShimInterfaceInfo.h"
#include "nsIException.h"
#include "nsIScriptError.h"
#include "nsISimpleEnumerator.h"
@ -115,8 +113,6 @@ public:
private:
virtual ~nsXPCComponents_Interfaces();
nsCOMArray<nsIInterfaceInfo> mInterfaces;
};
NS_IMETHODIMP
@ -311,8 +307,6 @@ public:
private:
virtual ~nsXPCComponents_InterfacesByID();
nsCOMArray<nsIInterfaceInfo> mInterfaces;
};
/***************************************************************************/

View File

@ -10,7 +10,6 @@
#include "js/Wrapper.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/XPTInterfaceInfoManager.h"
#include "nsIScriptError.h"
#include "nsPrintfCString.h"
#include "nsPointerHashKeys.h"

View File

@ -58,7 +58,6 @@ LOCAL_INCLUDES += [
'/dom/svg',
'/layout/base',
'/layout/style',
'/xpcom/reflect/xptinfo',
]
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):

View File

@ -30,7 +30,6 @@
#include "nsDOMMutationObserver.h"
#include "nsICycleCollectorListener.h"
#include "mozilla/XPTInterfaceInfoManager.h"
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
#include "nsScriptSecurityManager.h"

View File

@ -108,7 +108,6 @@
#include "nsISupportsPrimitives.h"
#include "nsMemory.h"
#include "nsIXPConnect.h"
#include "nsIInterfaceInfo.h"
#include "nsIXPCScriptable.h"
#include "nsIObserver.h"
#include "nsWeakReference.h"

View File

@ -101,8 +101,6 @@
present.places = true;
} else if (aPath.search(/^explicit\/images/) >= 0) {
present.images = true;
} else if (aPath.search(/^explicit\/xpti-working-set$/) >= 0) {
present.xptiWorkingSet = true;
} else if (aPath.search(/^explicit\/atoms\/dynamic\/atom-objects$/) >= 0) {
present.dynamicAtomObjects = true;
} else if (/\[System Principal\].*this-is-a-sandbox-name/.test(aPath)) {
@ -260,7 +258,6 @@
ok(present.windowObjectsJsCompartments, "window-objects/.../js compartments are present");
ok(present.places, "places is present");
ok(present.images, "images is present");
ok(present.xptiWorkingSet, "xpti-working-set is present");
ok(present.dynamicAtomObjects, "dynamic/atom-objects is present");
ok(present.sandboxLocation, "sandbox locations are present");
ok(present.bigString, "large string is present");

View File

@ -54,9 +54,6 @@
#include "nsThreadPool.h"
#include "xptinfo.h"
#include "nsIInterfaceInfoManager.h"
#include "xptiprivate.h"
#include "mozilla/XPTInterfaceInfoManager.h"
#include "nsTimerImpl.h"
#include "TimerThread.h"

View File

@ -55,7 +55,6 @@
COMPONENT(MULTIPLEXINPUTSTREAM, nsMultiplexInputStreamConstructor)
COMPONENT(VARIANT, nsVariantCCConstructor)
COMPONENT(INTERFACEINFOMANAGER_SERVICE, nsXPTIInterfaceInfoManagerGetSingleton)
COMPONENT(HASH_PROPERTY_BAG, nsHashPropertyBagCCConstructor)

View File

@ -91,7 +91,6 @@ LOCAL_INCLUDES += [
'../ds',
'../glue',
'../io',
'../reflect/xptinfo',
'../threads',
'/chrome',
'/docshell/base',

View File

@ -46,7 +46,6 @@ LOCAL_INCLUDES += [
'../base',
'../build',
'../ds',
'../reflect/xptinfo',
'/chrome',
'/modules/libjar',
]

View File

@ -1,307 +0,0 @@
#!/usr/bin/env python
# typelib.py - Generate XPCOM typelib files from IDL.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
"""Generate an XPIDL typelib for the IDL files specified on the command line"""
import os
import sys
import xpidl
import xpt
# A map of xpidl.py types to xpt.py types
TypeMap = {
# nsresult is not strictly an xpidl.py type, but it's useful here
'nsresult': xpt.Type.Tags.uint32,
# builtins
'boolean': xpt.Type.Tags.boolean,
'void': xpt.Type.Tags.void,
'int16_t': xpt.Type.Tags.int16,
'int32_t': xpt.Type.Tags.int32,
'int64_t': xpt.Type.Tags.int64,
'uint8_t': xpt.Type.Tags.uint8,
'uint16_t': xpt.Type.Tags.uint16,
'uint32_t': xpt.Type.Tags.uint32,
'uint64_t': xpt.Type.Tags.uint64,
'octet': xpt.Type.Tags.uint8,
'short': xpt.Type.Tags.int16,
'long': xpt.Type.Tags.int32,
'long long': xpt.Type.Tags.int64,
'unsigned short': xpt.Type.Tags.uint16,
'unsigned long': xpt.Type.Tags.uint32,
'unsigned long long': xpt.Type.Tags.uint64,
'float': xpt.Type.Tags.float,
'double': xpt.Type.Tags.double,
'char': xpt.Type.Tags.char,
'string': xpt.Type.Tags.char_ptr,
'wchar': xpt.Type.Tags.wchar_t,
'wstring': xpt.Type.Tags.wchar_t_ptr,
# special types
'nsid': xpt.Type.Tags.nsIID,
'domstring': xpt.Type.Tags.DOMString,
'astring': xpt.Type.Tags.AString,
'utf8string': xpt.Type.Tags.UTF8String,
'cstring': xpt.Type.Tags.CString,
'jsval': xpt.Type.Tags.jsval
}
# XXXkhuey dipper types should go away (bug 677784)
def isDipperType(type):
return type == xpt.Type.Tags.DOMString or type == xpt.Type.Tags.AString or type == xpt.Type.Tags.CString or type == xpt.Type.Tags.UTF8String
def build_interface(iface, ifaces):
def get_type(type, calltype, iid_is=None, size_is=None):
""" Return the appropriate xpt.Type object for this param """
while isinstance(type, xpidl.Typedef):
type = type.realtype
if isinstance(type, xpidl.Builtin):
if type.name == 'string' and size_is is not None:
return xpt.StringWithSizeType(size_is, size_is)
elif type.name == 'wstring' and size_is is not None:
return xpt.WideStringWithSizeType(size_is, size_is)
else:
tag = TypeMap[type.name]
isPtr = (tag == xpt.Type.Tags.char_ptr or tag == xpt.Type.Tags.wchar_t_ptr)
return xpt.SimpleType(tag,
pointer=isPtr,
reference=False)
if isinstance(type, xpidl.Array):
# NB: For an Array<T> we pass down the iid_is to get the type of T.
# This allows Arrays of InterfaceIs types to work.
return xpt.ArrayType(get_type(type.type, calltype, iid_is), size_is,
#XXXkhuey length_is duplicates size_is (bug 677788),
size_is)
if isinstance(type, xpidl.Interface) or isinstance(type, xpidl.Forward):
xptiface = None
for i in ifaces:
if i.name == type.name:
xptiface = i
if not xptiface:
xptiface = xpt.Interface(name=type.name)
ifaces.append(xptiface)
return xpt.InterfaceType(xptiface)
if isinstance(type, xpidl.Native):
if type.specialtype:
# XXXkhuey jsval is marked differently in the typelib and in the headers :-(
isPtr = (type.isPtr(calltype) or type.isRef(calltype)) and not type.specialtype == 'jsval'
isRef = type.isRef(calltype) and not type.specialtype == 'jsval'
return xpt.SimpleType(TypeMap[type.specialtype],
pointer=isPtr,
reference=isRef)
elif iid_is is not None:
return xpt.InterfaceIsType(iid_is)
else:
# void ptr
return xpt.SimpleType(TypeMap['void'],
pointer=True,
reference=False)
raise Exception("Unknown type!")
def get_nsresult():
return xpt.SimpleType(TypeMap['nsresult'])
def build_nsresult_param():
return xpt.Param(get_nsresult())
def get_result_type(m):
if not m.notxpcom:
return get_nsresult()
return get_type(m.realtype, '')
def build_result_param(m):
return xpt.Param(get_result_type(m))
def build_retval_param(m):
type = get_type(m.realtype, 'out')
if isDipperType(type.tag):
# NB: The retval bit needs to be set here, contrary to what the
# xpt spec says.
return xpt.Param(type, in_=True, retval=True, dipper=True)
return xpt.Param(type, in_=False, out=True, retval=True)
def build_attr_param(a, getter=False, setter=False):
if not (getter or setter):
raise Exception("Attribute param must be for a getter or a setter!")
type = get_type(a.realtype, getter and 'out' or 'in')
if setter:
return xpt.Param(type)
else:
if isDipperType(type.tag):
# NB: The retval bit needs to be set here, contrary to what the
# xpt spec says.
return xpt.Param(type, in_=True, retval=True, dipper=True)
return xpt.Param(type, in_=False, out=True, retval=True)
if iface.namemap is None:
raise Exception("Interface was not resolved.")
consts = []
methods = []
def build_const(c):
consts.append(xpt.Constant(c.name, get_type(c.basetype, ''), c.getValue()))
def build_method(m):
params = []
def build_param(p):
def findattr(p, attr):
if hasattr(p, attr) and getattr(p, attr):
for i, param in enumerate(m.params):
if param.name == getattr(p, attr):
return i
return None
iid_is = findattr(p, 'iid_is')
size_is = findattr(p, 'size_is')
in_ = p.paramtype.count("in")
out = p.paramtype.count("out")
dipper = False
type = get_type(p.realtype, p.paramtype, iid_is=iid_is, size_is=size_is)
if out and isDipperType(type.tag):
out = False
dipper = True
return xpt.Param(type, in_, out, p.retval, p.shared, dipper, p.optional)
for p in m.params:
params.append(build_param(p))
if not m.notxpcom and m.realtype.name != 'void':
params.append(build_retval_param(m))
methods.append(xpt.Method(m.name, build_result_param(m), params,
getter=False, setter=False, notxpcom=m.notxpcom,
constructor=False, hidden=m.noscript,
optargc=m.optional_argc,
implicit_jscontext=m.implicit_jscontext))
def build_attr(a):
# Write the getter
methods.append(xpt.Method(a.name, build_nsresult_param(),
[build_attr_param(a, getter=True)],
getter=True, setter=False,
constructor=False, hidden=a.noscript,
optargc=False,
implicit_jscontext=a.implicit_jscontext))
# And maybe the setter
if not a.readonly:
methods.append(xpt.Method(a.name, build_nsresult_param(),
[build_attr_param(a, setter=True)],
getter=False, setter=True,
constructor=False, hidden=a.noscript,
optargc=False,
implicit_jscontext=a.implicit_jscontext))
for member in iface.members:
if isinstance(member, xpidl.ConstMember):
build_const(member)
elif isinstance(member, xpidl.Attribute):
build_attr(member)
elif isinstance(member, xpidl.Method):
build_method(member)
elif isinstance(member, xpidl.CDATA):
pass
else:
raise Exception("Unexpected interface member: %s" % member)
parent = None
if iface.base:
for i in ifaces:
if i.name == iface.base:
parent = i
if not parent:
parent = xpt.Interface(name=iface.base)
ifaces.append(parent)
return xpt.Interface(iface.name, iface.attributes.uuid, methods=methods,
constants=consts, resolved=True, parent=parent,
scriptable=iface.attributes.scriptable,
function=iface.attributes.function,
builtinclass=iface.attributes.builtinclass,
main_process_scriptable_only=iface.attributes.main_process_scriptable_only)
def write_typelib(idl, fd, filename):
""" Generate the typelib. """
# We only care about interfaces that are scriptable.
ifaces = []
for p in idl.productions:
if p.kind == 'interface' and p.attributes.scriptable:
ifaces.append(build_interface(p, ifaces))
typelib = xpt.Typelib(interfaces=ifaces)
typelib.writefd(fd)
if __name__ == '__main__':
from optparse import OptionParser
o = OptionParser()
o.add_option('-I', action='append', dest='incdirs', default=['.'],
help="Directory to search for imported files")
o.add_option('--cachedir', dest='cachedir', default=None,
help="Directory in which to cache lex/parse tables.")
o.add_option('-o', dest='outfile', default=None,
help="Output file")
o.add_option('-d', dest='depfile', default=None,
help="Generate a make dependency file")
o.add_option('--regen', action='store_true', dest='regen', default=False,
help="Regenerate IDL Parser cache")
options, args = o.parse_args()
file = args[0] if args else None
if options.cachedir is not None:
if not os.path.isdir(options.cachedir):
os.mkdir(options.cachedir)
sys.path.append(options.cachedir)
if options.regen:
if options.cachedir is None:
print >>sys.stderr, "--regen requires --cachedir"
sys.exit(1)
p = xpidl.IDLParser(outputdir=options.cachedir, regen=True)
sys.exit(0)
if options.depfile is not None and options.outfile is None:
print >>sys.stderr, "-d requires -o"
sys.exit(1)
if options.outfile is not None:
outfd = open(options.outfile, 'wb')
closeoutfd = True
else:
raise "typelib generation requires an output file"
p = xpidl.IDLParser(outputdir=options.cachedir)
idl = p.parse(open(file).read(), filename=file)
idl.resolve(options.incdirs, p)
write_typelib(idl, outfd, file)
if closeoutfd:
outfd.close()
if options.depfile is not None:
depfd = open(options.depfile, 'w')
deps = [dep.replace('\\', '/') for dep in idl.deps]
print >>depfd, "%s: %s" % (options.outfile, " ".join(deps))
for dep in deps:
print >>depfd, "%s:" % dep

View File

@ -36,7 +36,6 @@ TEST_DIRS += [
# Can't build internal xptcall tests that use symbols which are not exported.
#TEST_DIRS += [
# 'reflect/xptinfo/tests',
# 'reflect/xptcall/tests,
#]

View File

@ -330,5 +330,4 @@ FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'../..',
'/xpcom/reflect/xptinfo',
]

View File

@ -4,7 +4,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "xptcprivate.h"
#include "xptiprivate.h"
#ifndef __AARCH64EL__
#error "Only little endian compatibility was tested"

View File

@ -6,7 +6,6 @@
/* Implement shared vtbl methods. */
#include "xptcprivate.h"
#include "xptiprivate.h"
/* Prototype specifies unmangled function name and disables unused warning */
static nsresult

View File

@ -6,7 +6,6 @@
/* Implement shared vtbl methods. */
#include "xptcprivate.h"
#include "xptiprivate.h"
#if !defined(__arm__) && !(defined(LINUX) || defined(ANDROID) || defined(XP_DARWIN))
#error "This code is for Linux/iOS ARM only. Please check if it works for you, too.\nDepends strongly on gcc behaviour."

View File

@ -6,7 +6,6 @@
/* Implement shared vtbl methods. */
#include "xptcprivate.h"
#include "xptiprivate.h"
#ifdef __GNUC__
/* This tells gcc3.4+ not to optimize away symbols.

View File

@ -6,7 +6,6 @@
/* Implement shared vtbl methods. */
#include "xptcprivate.h"
#include "xptiprivate.h"
#include "xptc_gcc_x86_unix.h"
extern "C" {

View File

@ -7,7 +7,6 @@
#include "xptcprivate.h"
#include "xptiprivate.h"
#include <stddef.h>
#include <stdlib.h>

View File

@ -7,7 +7,6 @@
#include "xptcprivate.h"
#include "xptiprivate.h"
#include <stddef.h>
#include <stdlib.h>

View File

@ -6,7 +6,6 @@
/* Implement shared vtbl methods. */
#include "xptcprivate.h"
#include "xptiprivate.h"
/* Prototype specifies unmangled function name and disables unused warning */
static nsresult

View File

@ -6,7 +6,6 @@
/* Implement shared vtbl methods. */
#include "xptcprivate.h"
#include "xptiprivate.h"
extern "C" {
nsresult ATTRIBUTE_USED

View File

@ -7,7 +7,6 @@
/* Implement shared vtbl methods. */
#include "xptcprivate.h"
#include "xptiprivate.h"
static nsresult ATTRIBUTE_USED
PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,

View File

@ -7,7 +7,6 @@
/* Implement shared vtbl methods. */
#include "xptcprivate.h"
#include "xptiprivate.h"
static nsresult ATTRIBUTE_USED
PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,

View File

@ -6,7 +6,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "xptcprivate.h"
#include "xptiprivate.h"
#include <stdint.h>

View File

@ -4,7 +4,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "xptcprivate.h"
#include "xptiprivate.h"
#if (_MIPS_SIM != _ABIN32) && (_MIPS_SIM != _ABI64)
#error "This code is for MIPS n32/n64 only"

View File

@ -8,7 +8,6 @@
/* Implement shared vtbl methods. */
#include "xptcprivate.h"
#include "xptiprivate.h"
#if _HPUX
#error "This code is for HP-PA RISC 32 bit mode only"

View File

@ -6,7 +6,6 @@
// Implement shared vtbl methods.
#include "xptcprivate.h"
#include "xptiprivate.h"
// The Linux/PPC64 ABI passes the first 8 integral
// parameters and the first 13 floating point parameters in registers

View File

@ -6,7 +6,6 @@
/* Implement shared vtbl methods. */
#include "xptcprivate.h"
#include "xptiprivate.h"
#if defined(AIX)

View File

@ -5,7 +5,6 @@
/* Implement shared vtbl methods. */
#include "xptcprivate.h"
#include "xptiprivate.h"
#if defined(AIX)

View File

@ -6,7 +6,6 @@
// Implement shared vtbl methods.
#include "xptcprivate.h"
#include "xptiprivate.h"
// The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral
// parameters and the first 8 floating point parameters in registers

View File

@ -6,7 +6,6 @@
// Implement shared vtbl methods.
#include "xptcprivate.h"
#include "xptiprivate.h"
// The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral
// parameters and the first 8 floating point parameters in registers

View File

@ -4,7 +4,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "xptcprivate.h"
#include "xptiprivate.h"
/* Under the Mac OS X PowerPC ABI, the first 8 integer and 13 floating point
* parameters are delivered in registers and are not on the stack, although

View File

@ -7,7 +7,6 @@
/* Implement shared vtbl methods. */
#include "xptcprivate.h"
#include "xptiprivate.h"
#if defined(sparc) || defined(__sparc__)

View File

@ -6,7 +6,6 @@
/* Implement shared vtbl methods. */
#include "xptcprivate.h"
#include "xptiprivate.h"
#if defined(sparc) || defined(__sparc__)

View File

@ -7,7 +7,6 @@
/* Implement shared vtbl methods. */
#include "xptcprivate.h"
#include "xptiprivate.h"
#if defined(sparc) || defined(__sparc__)

View File

@ -9,7 +9,6 @@
// Keep this in sync with the linux version.
#include "xptcprivate.h"
#include "xptiprivate.h"
// The Darwin/x86-64 ABI passes the first 6 integer parameters and the
// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx,

View File

@ -9,7 +9,6 @@
// Keep this in sync with the darwin version.
#include "xptcprivate.h"
#include "xptiprivate.h"
// The Linux/x86-64 ABI passes the first 6 integer parameters and the
// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx,

View File

@ -9,7 +9,6 @@
// Keep this in sync with the darwin version.
#include "xptcprivate.h"
#include "xptiprivate.h"
// The Linux/x86-64 ABI passes the first 6 integer parameters and the
// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx,

View File

@ -7,7 +7,6 @@
/* Implement shared vtbl methods. */
#include "xptcprivate.h"
#include "xptiprivate.h"
nsresult ATTRIBUTE_USED
PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)

View File

@ -40,5 +40,4 @@ FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'../..',
'/xpcom/reflect/xptinfo',
]

View File

@ -6,7 +6,6 @@
/* Implement shared vtbl methods. */
#include "xptcprivate.h"
#include "xptiprivate.h"
#ifndef WIN32
#error "This code is for Win32 only"

View File

@ -6,7 +6,6 @@
/* Implement shared vtbl methods. */
#include "xptcprivate.h"
#include "xptiprivate.h"
/*
* This is for Windows XP 64-Bit Edition / Server 2003 for AMD64 or later.

View File

@ -5,7 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "xptcprivate.h"
#include "xptiprivate.h"
/*
* This is for Windows 64 bit (x86_64) using GCC syntax

View File

@ -17,8 +17,4 @@ EXPORTS += [
'xptcstubsdef.inc',
]
LOCAL_INCLUDES += [
'/xpcom/reflect/xptinfo',
]
FINAL_LIBRARY = 'xul'

View File

@ -6,8 +6,6 @@
/* entry point wrappers. */
#include "xptcprivate.h"
#include "xptiprivate.h"
#include "mozilla/XPTInterfaceInfoManager.h"
#include "nsPrintfCString.h"
using namespace mozilla;

View File

@ -10,7 +10,6 @@
#include "nscore.h"
#include "nsISupports.h"
#include "xpt_struct.h"
#include "xptinfo.h"
#include "js/Value.h"
#include "mozilla/MemoryReporting.h"

View File

@ -12,8 +12,6 @@
#include "nsAutoPtr.h"
#include "mozilla/Attributes.h"
class xptiInterfaceEntry;
#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__) && !defined(__FreeBSD__))
#define STUB_ENTRY(n) NS_IMETHOD Stub##n() = 0;
#else

View File

@ -1,360 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sw=4 et tw=78:
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ShimInterfaceInfo.h"
#include "nsIDOMDOMRequest.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDocumentFragment.h"
#include "nsIDOMElement.h"
#include "nsIDOMEvent.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOMGeoPositionError.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsIDOMNode.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMOfflineResourceList.h"
#include "nsIDOMParser.h"
#include "nsIDOMRange.h"
#include "nsIListBoxObject.h"
#include "nsIMessageManager.h"
#include "nsISelection.h"
#include "nsITreeBoxObject.h"
#include "mozilla/dom/CSSPrimitiveValueBinding.h"
#include "mozilla/dom/CSSStyleDeclarationBinding.h"
#include "mozilla/dom/CSSStyleSheetBinding.h"
#include "mozilla/dom/CSSValueBinding.h"
#include "mozilla/dom/CSSValueListBinding.h"
#include "mozilla/dom/DOMParserBinding.h"
#include "mozilla/dom/DOMRequestBinding.h"
#include "mozilla/dom/DocumentBinding.h"
#include "mozilla/dom/DocumentFragmentBinding.h"
#include "mozilla/dom/ElementBinding.h"
#include "mozilla/dom/EventBinding.h"
#include "mozilla/dom/EventTargetBinding.h"
#include "mozilla/dom/HTMLAnchorElementBinding.h"
#include "mozilla/dom/HTMLAreaElementBinding.h"
#include "mozilla/dom/HTMLButtonElementBinding.h"
#include "mozilla/dom/HTMLFrameSetElementBinding.h"
#include "mozilla/dom/HTMLHtmlElementBinding.h"
#include "mozilla/dom/HTMLInputElementBinding.h"
#include "mozilla/dom/ListBoxObjectBinding.h"
#include "mozilla/dom/MediaListBinding.h"
#include "mozilla/dom/MessageEventBinding.h"
#include "mozilla/dom/MessageManagerBinding.h"
#include "mozilla/dom/NodeListBinding.h"
#include "mozilla/dom/NodeBinding.h"
#include "mozilla/dom/EventBinding.h"
#include "mozilla/dom/OfflineResourceListBinding.h"
#include "mozilla/dom/PositionErrorBinding.h"
#include "mozilla/dom/RangeBinding.h"
#include "mozilla/dom/SelectionBinding.h"
#include "mozilla/dom/StorageEventBinding.h"
#include "mozilla/dom/StyleSheetBinding.h"
#include "mozilla/dom/StyleSheetListBinding.h"
#include "mozilla/dom/SVGElementBinding.h"
#include "mozilla/dom/TimeEventBinding.h"
#include "mozilla/dom/TreeBoxObjectBinding.h"
#include "mozilla/dom/XULDocumentBinding.h"
using namespace mozilla;
struct ComponentsInterfaceShimEntry {
constexpr
ComponentsInterfaceShimEntry(const char* aName, const nsIID& aIID,
const dom::NativePropertyHooks* aNativePropHooks)
: geckoName(aName), iid(aIID), nativePropHooks(aNativePropHooks) {}
const char *geckoName;
const nsIID& iid;
const dom::NativePropertyHooks* nativePropHooks;
};
#define DEFINE_SHIM_WITH_CUSTOM_INTERFACE(geckoName, domName) \
{ #geckoName, NS_GET_IID(geckoName), \
mozilla::dom::domName ## Binding::sNativePropertyHooks }
#define DEFINE_SHIM(name) \
DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOM ## name, name)
/**
* These shim entries allow us to make old XPIDL interfaces implementing DOM
* APIs as non-scriptable in order to save some runtime memory on Firefox OS,
* without breaking the entries under Components.interfaces which might both
* be used by our code and add-ons. Specifically, the shim entries provide
* the following:
*
* * Components.interfaces.nsIFoo entries. These entries basically work
* almost exactly as the usual ones that you would get through the
* XPIDL machinery. Specifically, they have the right name, they reflect
* the right IID, and they will work properly when passed to QueryInterface.
*
* * Components.interfaces.nsIFoo.CONSTANT values. These entries will have
* the right name and the right value for most integer types. Note that
* support for non-numerical constants is untested and will probably not
* work out of the box.
*
* FAQ:
* * When should I add an entry to the list here?
* Only if you're making an XPIDL interfaces which has a corresponding
* WebIDL interface non-scriptable.
* * When should I remove an entry from this list?
* If you are completely removing an XPIDL interface from the code base. If
* you forget to do so, the compiler will remind you.
* * How should I add an entry to the list here?
* First, make sure that the XPIDL interface in question is non-scriptable
* and also has a corresponding WebIDL interface. Then, add two include
* entries above, one for the XPIDL interface and one for the WebIDL
* interface, and add a shim entry below. If the name of the XPIDL
* interface only has an "nsIDOM" prefix prepended to the WebIDL name, you
* can use the DEFINE_SHIM macro and pass in the name of the WebIDL
* interface. Otherwise, use DEFINE_SHIM_WITH_CUSTOM_INTERFACE.
*/
const ComponentsInterfaceShimEntry kComponentsInterfaceShimMap[] =
{
DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIContentFrameMessageManager, ContentFrameMessageManager),
DEFINE_SHIM(DOMRequest),
DEFINE_SHIM(Document),
DEFINE_SHIM(DocumentFragment),
DEFINE_SHIM(Element),
DEFINE_SHIM(Event),
DEFINE_SHIM(EventTarget),
DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMGeoPositionError, PositionError),
DEFINE_SHIM(HTMLInputElement),
DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIListBoxObject, ListBoxObject),
DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIMessageSender, MessageSender),
DEFINE_SHIM(NodeList),
DEFINE_SHIM(Node),
DEFINE_SHIM(OfflineResourceList),
DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMParser, DOMParser),
DEFINE_SHIM(Range),
DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsITreeBoxObject, TreeBoxObject),
DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsISelection, Selection),
};
#undef DEFINE_SHIM
#undef DEFINE_SHIM_WITH_CUSTOM_INTERFACE
NS_IMPL_ISUPPORTS(ShimInterfaceInfo, nsISupports, nsIInterfaceInfo)
already_AddRefed<ShimInterfaceInfo>
ShimInterfaceInfo::MaybeConstruct(const char* aName, JSContext* cx)
{
RefPtr<ShimInterfaceInfo> info;
for (uint32_t i = 0; i < ArrayLength(kComponentsInterfaceShimMap); ++i) {
if (!strcmp(aName, kComponentsInterfaceShimMap[i].geckoName)) {
const ComponentsInterfaceShimEntry& shimEntry =
kComponentsInterfaceShimMap[i];
info = new ShimInterfaceInfo(shimEntry.iid,
shimEntry.geckoName,
shimEntry.nativePropHooks);
break;
}
}
return info.forget();
}
ShimInterfaceInfo::ShimInterfaceInfo(const nsIID& aIID,
const char* aName,
const mozilla::dom::NativePropertyHooks* aNativePropHooks)
: mIID(aIID)
, mName(aName)
, mNativePropHooks(aNativePropHooks)
{
}
NS_IMETHODIMP
ShimInterfaceInfo::GetName(char** aName)
{
*aName = ToNewCString(mName);
return NS_OK;
}
NS_IMETHODIMP
ShimInterfaceInfo::IsScriptable(bool* aRetVal)
{
// This class should pretend that the interface is scriptable because
// that's what nsJSIID assumes.
*aRetVal = true;
return NS_OK;
}
NS_IMETHODIMP
ShimInterfaceInfo::IsBuiltinClass(bool* aRetVal)
{
*aRetVal = true;
return NS_OK;
}
NS_IMETHODIMP
ShimInterfaceInfo::IsMainProcessScriptableOnly(bool* aRetVal)
{
*aRetVal = false;
return NS_OK;
}
NS_IMETHODIMP
ShimInterfaceInfo::GetParent(nsIInterfaceInfo** aParent)
{
*aParent = nullptr;
return NS_OK;
}
NS_IMETHODIMP
ShimInterfaceInfo::GetMethodCount(uint16_t* aCount)
{
// Pretend we don't have any methods.
*aCount = 0;
return NS_OK;
}
NS_IMETHODIMP
ShimInterfaceInfo::GetConstantCount(uint16_t* aCount)
{
// We assume that we never have interfaces with more than UINT16_MAX
// constants defined on them.
uint16_t count = 0;
// NOTE: The structure of this loop must be kept in sync with the loop
// in GetConstant.
const mozilla::dom::NativePropertyHooks* propHooks = mNativePropHooks;
do {
const mozilla::dom::NativeProperties* props[] = {
propHooks->mNativeProperties.regular,
propHooks->mNativeProperties.chromeOnly
};
for (size_t i = 0; i < ArrayLength(props); ++i) {
auto prop = props[i];
if (prop && prop->HasConstants()) {
for (auto cs = prop->Constants()->specs; cs->name; ++cs) {
// We have found one constant here. We explicitly do not
// bother calling isEnabled() here because it's OK to define
// potentially extra constants on these shim interfaces.
++count;
}
}
}
} while ((propHooks = propHooks->mProtoHooks));
*aCount = count;
return NS_OK;
}
NS_IMETHODIMP
ShimInterfaceInfo::GetMethodInfo(uint16_t aIndex, const nsXPTMethodInfo** aInfo)
{
MOZ_ASSERT(false, "This should never be called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ShimInterfaceInfo::GetMethodInfoForName(const char* aName, uint16_t* aIndex, const nsXPTMethodInfo** aInfo)
{
MOZ_ASSERT(false, "This should never be called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ShimInterfaceInfo::GetConstant(uint16_t aIndex, JS::MutableHandleValue aConstant,
char** aName)
{
// We assume that we never have interfaces with more than UINT16_MAX
// constants defined on them.
uint16_t index = 0;
// NOTE: The structure of this loop must be kept in sync with the loop
// in GetConstantCount.
const mozilla::dom::NativePropertyHooks* propHooks = mNativePropHooks;
do {
const mozilla::dom::NativeProperties* props[] = {
propHooks->mNativeProperties.regular,
propHooks->mNativeProperties.chromeOnly
};
for (size_t i = 0; i < ArrayLength(props); ++i) {
auto prop = props[i];
if (prop && prop->HasConstants()) {
for (auto cs = prop->Constants()->specs; cs->name; ++cs) {
// We have found one constant here. We explicitly do not
// bother calling isEnabled() here because it's OK to define
// potentially extra constants on these shim interfaces.
if (index == aIndex) {
aConstant.set(cs->value);
*aName = ToNewCString(nsDependentCString(cs->name));
return NS_OK;
}
++index;
}
}
}
} while ((propHooks = propHooks->mProtoHooks));
// aIndex was bigger than the number of constants we have.
return NS_ERROR_INVALID_ARG;
}
NS_IMETHODIMP
ShimInterfaceInfo::GetTypeForParam(uint16_t aInex, const nsXPTParamInfo* aParam, uint16_t aDimension, nsXPTType* aRetVal)
{
MOZ_ASSERT(false, "This should never be called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ShimInterfaceInfo::GetSizeIsArgNumberForParam(uint16_t aInex, const nsXPTParamInfo* aParam, uint16_t aDimension, uint8_t* aRetVal)
{
MOZ_ASSERT(false, "This should never be called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ShimInterfaceInfo::GetInterfaceIsArgNumberForParam(uint16_t aInex, const nsXPTParamInfo* aParam, uint8_t* aRetVal)
{
MOZ_ASSERT(false, "This should never be called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ShimInterfaceInfo::IsIID(const nsIID* aIID, bool* aRetVal)
{
*aRetVal = mIID.Equals(*aIID);
return NS_OK;
}
NS_IMETHODIMP
ShimInterfaceInfo::GetNameShared(const char** aName)
{
*aName = mName.get();
return NS_OK;
}
NS_IMETHODIMP
ShimInterfaceInfo::GetIIDShared(const nsIID** aIID)
{
*aIID = &mIID;
return NS_OK;
}
NS_IMETHODIMP
ShimInterfaceInfo::IsFunction(bool* aRetVal)
{
*aRetVal = false;
return NS_OK;
}
NS_IMETHODIMP
ShimInterfaceInfo::HasAncestor(const nsIID* aIID, bool* aRetVal)
{
*aRetVal = false;
return NS_OK;
}
NS_IMETHODIMP_(nsresult)
ShimInterfaceInfo::GetIIDForParamNoAlloc(uint16_t aIndex, const nsXPTParamInfo* aInfo, nsIID* aIID)
{
MOZ_ASSERT(false, "This should never be called");
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@ -1,50 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef ShimInterfaceInfo_h
#define ShimInterfaceInfo_h
#include "mozilla/Attributes.h"
#include "nsIInterfaceInfo.h"
#include "nsString.h"
#include "nsID.h"
#include "nsTArray.h"
#include "xptinfo.h"
#include "nsAutoPtr.h"
#include "js/RootingAPI.h"
namespace mozilla {
namespace dom {
struct NativePropertyHooks;
} // namespace dom
} // namespace mozilla
class ShimInterfaceInfo final : public nsIInterfaceInfo
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIINTERFACEINFO
// Construct a ShimInterfaceInfo object if we have a shim available for aName.
// Otherwise, returns nullptr.
static already_AddRefed<ShimInterfaceInfo>
MaybeConstruct(const char* aName, JSContext* cx);
private:
ShimInterfaceInfo(const nsIID& aIID,
const char* aName,
const mozilla::dom::NativePropertyHooks* aNativePropHooks);
~ShimInterfaceInfo() {}
private:
nsIID mIID;
nsAutoCString mName;
const mozilla::dom::NativePropertyHooks* mNativePropHooks;
};
#endif

View File

@ -1,20 +0,0 @@
/* jband - 03/24/00 - */
- DOCS
- improve error handling
- should some errors really be warnings?
- should autoreg support additional channel to receive warnings so that
an installer can decide whether or not to accept the consequences of
leaving the newly installed files in place?
- verification of interfaces (warnings and/or errors)
- verify that repeated interfaces are identical in all ways
- verify that interface names are always one-to-one with iids
- check for truncated xpt files and version problems
- http://bugzilla.mozilla.org/show_bug.cgi?id=33193
- TESTS!
- e.g. verify the merge stuff really works for various inputs.
- we really need a set of .xpt and .zip files and code that does an array
of autoreg and interfaceinof use activitities to test various corners
of the system.
- better autoreg logging
- use only 32 bits for file size?

View File

@ -1,93 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=4 et sw=4 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_XPTInterfaceInfoManager_h_
#define mozilla_XPTInterfaceInfoManager_h_
#include "nsIInterfaceInfoManager.h"
#include "nsIMemoryReporter.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Mutex.h"
#include "mozilla/ReentrantMonitor.h"
#include "nsDataHashtable.h"
template<typename T> class nsCOMArray;
class nsIMemoryReporter;
struct XPTInterfaceDescriptor;
class xptiInterfaceEntry;
class xptiInterfaceInfo;
class xptiTypelibGuts;
namespace mozilla {
class XPTInterfaceInfoManager final
: public nsIInterfaceInfoManager
, public nsIMemoryReporter
{
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINTERFACEINFOMANAGER
NS_DECL_NSIMEMORYREPORTER
public:
// GetSingleton() is infallible
static XPTInterfaceInfoManager* GetSingleton();
static void FreeInterfaceInfoManager();
void GetScriptableInterfaces(nsCOMArray<nsIInterfaceInfo>& aInterfaces);
static Mutex& GetResolveLock()
{
return GetSingleton()->mResolveLock;
}
xptiInterfaceEntry* GetInterfaceEntryForIID(const nsIID *iid);
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
private:
XPTInterfaceInfoManager();
~XPTInterfaceInfoManager();
void InitMemoryReporter();
// idx is the index of this interface in the XPTHeader
void VerifyAndAddEntryIfNew(const XPTInterfaceDescriptor* iface,
uint16_t idx,
xptiTypelibGuts* typelib);
private:
class xptiWorkingSet
{
public:
xptiWorkingSet();
~xptiWorkingSet();
void InvalidateInterfaceInfos();
// XXX make these private with accessors
// mTableMonitor must be held across:
// * any read from or write to mIIDTable or mNameTable
// * any writing to the links between an xptiInterfaceEntry
// and its xptiInterfaceInfo (mEntry/mInfo)
mozilla::ReentrantMonitor mTableReentrantMonitor;
nsDataHashtable<nsIDHashKey, xptiInterfaceEntry*> mIIDTable;
nsDataHashtable<nsDepCharHashKey, xptiInterfaceEntry*> mNameTable;
};
// XXX xptiInterfaceInfo want's to poke at the working set itself
friend class ::xptiInterfaceInfo;
friend class ::xptiInterfaceEntry;
friend class ::xptiTypelibGuts;
xptiWorkingSet mWorkingSet;
Mutex mResolveLock;
};
} // namespace mozilla
#endif

View File

@ -5,33 +5,11 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [
'ShimInterfaceInfo.cpp',
'xptiInterfaceInfo.cpp',
'xptiInterfaceInfoManager.cpp',
'xptiTypelibGuts.cpp',
'xptiWorkingSet.cpp',
]
XPIDL_SOURCES += [
'nsIInterfaceInfo.idl',
'nsIInterfaceInfoManager.idl',
]
XPIDL_MODULE = 'xpcom_xpti'
EXPORTS += [
'xptinfo.h',
]
EXPORTS.mozilla += [
'XPTInterfaceInfoManager.h',
]
LOCAL_INCLUDES += [
'/dom/base',
]
FINAL_LIBRARY = 'xul'
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
CXXFLAGS += ['-Wno-error=shadow']

View File

@ -1,88 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* The nsIInterfaceInfo public declaration. */
#include "nsISupports.idl"
// forward declaration of non-XPCOM types
[ptr] native nsXPTMethodInfoPtr(nsXPTMethodInfo);
[ptr] native nsXPTParamInfoPtr(nsXPTParamInfo);
native nsXPTType(nsXPTType);
// We bend the rules to do a [shared] nsIID (but this is never scriptable)
[ptr] native nsIIDPtrShared(nsIID);
%{C++
class nsXPTMethodInfo;
class nsXPTParamInfo;
class nsXPTType;
%}
[builtinclass, uuid(3820e663-8e22-4789-b470-56bcf7083f2b)]
interface nsIInterfaceInfo : nsISupports
{
readonly attribute string name;
boolean isScriptable();
boolean isBuiltinClass();
readonly attribute nsIInterfaceInfo parent;
/**
* These include counts for parent (and all ancestors).
*/
readonly attribute uint16_t methodCount;
readonly attribute uint16_t constantCount;
/**
* These include methods and constants for parent (and all ancestors).
*
* These do *not* make copies ***explicit bending of XPCOM rules***.
*/
void getMethodInfo(in uint16_t index,
[shared, retval] out nsXPTMethodInfoPtr info);
void getMethodInfoForName(in string methodName, out uint16_t index,
[shared, retval] out nsXPTMethodInfoPtr info);
void getConstant(in uint16_t index,
out jsval constant,
out string name);
/**
* These do *not* make copies ***explicit bending of XPCOM rules***.
*/
nsXPTType getTypeForParam(in uint16_t methodIndex,
[const] in nsXPTParamInfoPtr param,
in uint16_t dimension);
uint8_t getSizeIsArgNumberForParam(in uint16_t methodIndex,
[const] in nsXPTParamInfoPtr param,
in uint16_t dimension);
uint8_t getInterfaceIsArgNumberForParam(in uint16_t methodIndex,
[const] in nsXPTParamInfoPtr param);
boolean isIID(in nsIIDPtr IID);
void getNameShared([shared,retval] out string name);
void getIIDShared([shared,retval] out nsIIDPtrShared iid);
boolean isFunction();
boolean hasAncestor(in nsIIDPtr iid);
[notxpcom] nsresult getIIDForParamNoAlloc(in uint16_t methodIndex,
[const] in nsXPTParamInfoPtr param,
out nsIID iid);
boolean isMainProcessScriptableOnly();
};

View File

@ -1,28 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* The nsIInterfaceInfoManager public declaration. */
#include "nsISupports.idl"
interface nsIInterfaceInfo;
[builtinclass, uuid(1d53d8d9-1d92-428f-b5cc-198b55e897d7)]
interface nsIInterfaceInfoManager : nsISupports
{
nsIInterfaceInfo getInfoForIID(in nsIIDPtr iid);
nsIInterfaceInfo getInfoForName(in string name);
};
%{C++
#define NS_INTERFACEINFOMANAGER_SERVICE_CID \
{ /* 13bef784-f8e0-4f96-85c1-09f9ef4f9a19 */ \
0x13bef784, 0xf8e0, 0x4f96, \
{0x85, 0xc1, 0x09, 0xf9, 0xef, 0x4f, 0x9a, 0x19} }
#define NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID \
"@mozilla.org/xpti/interfaceinfomanager-service;1"
%}

View File

@ -1,680 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Implementation of xptiInterfaceEntry and xptiInterfaceInfo. */
#include "xptiprivate.h"
#include "xpt_arena.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/XPTInterfaceInfoManager.h"
#include "mozilla/PodOperations.h"
#include "jsapi.h"
using namespace mozilla;
/* static */ xptiInterfaceEntry*
xptiInterfaceEntry::Create(const XPTInterfaceDescriptor* aIface,
xptiTypelibGuts* aTypelib)
{
void* place = XPT_CALLOC8(gXPTIStructArena, sizeof(xptiInterfaceEntry));
if (!place) {
return nullptr;
}
return new (place) xptiInterfaceEntry(aIface, aTypelib);
}
xptiInterfaceEntry::xptiInterfaceEntry(const XPTInterfaceDescriptor* aIface,
xptiTypelibGuts* aTypelib)
: mIID(aIface->mIID)
, mDescriptor(aIface)
, mTypelib(aTypelib)
, mParent(nullptr)
, mInfo(nullptr)
, mMethodBaseIndex(0)
, mConstantBaseIndex(0)
, mFlags(0)
, mName(aIface->Name())
{
SetResolvedState(PARTIALLY_RESOLVED);
SetScriptableFlag(aIface->IsScriptable());
SetBuiltinClassFlag(aIface->IsBuiltinClass());
SetMainProcessScriptableOnlyFlag(aIface->IsMainProcessScriptableOnly());
}
bool
xptiInterfaceEntry::Resolve()
{
MutexAutoLock lock(XPTInterfaceInfoManager::GetResolveLock());
return ResolveLocked();
}
bool
xptiInterfaceEntry::ResolveLocked()
{
int resolvedState = GetResolveState();
if(resolvedState == FULLY_RESOLVED)
return true;
if(resolvedState == RESOLVE_FAILED)
return false;
NS_ASSERTION(GetResolveState() == PARTIALLY_RESOLVED, "bad state!");
// Finish out resolution by finding parent and Resolving it so
// we can set the info we get from it.
uint16_t parent_index = mDescriptor->mParentInterface;
if(parent_index)
{
xptiInterfaceEntry* parent =
mTypelib->GetEntryAt(parent_index - 1);
if(!parent || !parent->EnsureResolvedLocked())
{
SetResolvedState(RESOLVE_FAILED);
return false;
}
mParent = parent;
if (parent->GetHasNotXPCOMFlag()) {
SetHasNotXPCOMFlag();
} else {
for (uint16_t idx = 0; idx < mDescriptor->mNumMethods; ++idx) {
const nsXPTMethodInfo* method = static_cast<const nsXPTMethodInfo*>(
&mDescriptor->Method(idx));
if (method->IsNotXPCOM()) {
SetHasNotXPCOMFlag();
break;
}
}
}
mMethodBaseIndex =
parent->mMethodBaseIndex +
parent->mDescriptor->mNumMethods;
mConstantBaseIndex =
parent->mConstantBaseIndex +
parent->mDescriptor->mNumConstants;
}
SetResolvedState(FULLY_RESOLVED);
return true;
}
/**************************************************/
// These non-virtual methods handle the delegated nsIInterfaceInfo methods.
nsresult
xptiInterfaceEntry::GetName(char **name)
{
// It is not necessary to Resolve because this info is read from manifest.
*name = moz_xstrdup(mName);
return NS_OK;
}
nsresult
xptiInterfaceEntry::GetIID(nsIID **iid)
{
// It is not necessary to Resolve because this info is read from manifest.
*iid = mIID.Clone();
return NS_OK;
}
nsresult
xptiInterfaceEntry::IsScriptable(bool* result)
{
// It is not necessary to Resolve because this info is read from manifest.
*result = GetScriptableFlag();
return NS_OK;
}
nsresult
xptiInterfaceEntry::IsFunction(bool* result)
{
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
*result = mDescriptor->IsFunction();
return NS_OK;
}
nsresult
xptiInterfaceEntry::GetMethodCount(uint16_t* count)
{
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
*count = mMethodBaseIndex +
mDescriptor->mNumMethods;
return NS_OK;
}
nsresult
xptiInterfaceEntry::GetConstantCount(uint16_t* count)
{
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
if(!count)
return NS_ERROR_UNEXPECTED;
*count = mConstantBaseIndex +
mDescriptor->mNumConstants;
return NS_OK;
}
nsresult
xptiInterfaceEntry::GetMethodInfo(uint16_t index, const nsXPTMethodInfo** info)
{
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
if(index < mMethodBaseIndex)
return mParent->GetMethodInfo(index, info);
if(index >= mMethodBaseIndex +
mDescriptor->mNumMethods)
{
NS_ERROR("bad param");
*info = nullptr;
return NS_ERROR_INVALID_ARG;
}
// else...
*info = static_cast<const nsXPTMethodInfo*>
(&mDescriptor->Method(index - mMethodBaseIndex));
return NS_OK;
}
nsresult
xptiInterfaceEntry::GetMethodInfoForName(const char* methodName, uint16_t *index,
const nsXPTMethodInfo** result)
{
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
// This is a slow algorithm, but this is not expected to be called much.
for(uint16_t i = 0; i < mDescriptor->mNumMethods; ++i)
{
const nsXPTMethodInfo* info;
info = static_cast<const nsXPTMethodInfo*>(&mDescriptor->Method(i));
if (PL_strcmp(methodName, info->GetName()) == 0) {
*index = i + mMethodBaseIndex;
*result = info;
return NS_OK;
}
}
if(mParent)
return mParent->GetMethodInfoForName(methodName, index, result);
else
{
*index = 0;
*result = 0;
return NS_ERROR_INVALID_ARG;
}
}
nsresult
xptiInterfaceEntry::GetConstant(uint16_t index, JS::MutableHandleValue constant,
char** name)
{
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
if(index < mConstantBaseIndex)
return mParent->GetConstant(index, constant, name);
if(index >= mConstantBaseIndex +
mDescriptor->mNumConstants)
{
NS_PRECONDITION(0, "bad param");
return NS_ERROR_INVALID_ARG;
}
const auto& c = mDescriptor->Const(index - mConstantBaseIndex);
AutoJSContext cx;
JS::Rooted<JS::Value> v(cx);
v.setUndefined();
switch (c.mType.mPrefix.mFlags) {
case nsXPTType::T_I16:
{
v.setInt32(c.mValue.i16);
break;
}
case nsXPTType::T_U16:
{
v.setInt32(c.mValue.ui16);
break;
}
case nsXPTType::T_I32:
{
v = JS_NumberValue(c.mValue.i32);
break;
}
case nsXPTType::T_U32:
{
v = JS_NumberValue(c.mValue.ui32);
break;
}
default:
{
MOZ_ASSERT(false, "Invalid constant type found in interface");
}
}
constant.set(v);
*name = ToNewCString(nsDependentCString(c.Name()));
return NS_OK;
}
// this is a private helper
nsresult
xptiInterfaceEntry::GetInterfaceIndexForParam(uint16_t methodIndex,
const nsXPTParamInfo* param,
uint16_t* interfaceIndex)
{
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
if(methodIndex < mMethodBaseIndex)
return mParent->GetInterfaceIndexForParam(methodIndex, param,
interfaceIndex);
if(methodIndex >= mMethodBaseIndex +
mDescriptor->mNumMethods)
{
NS_ERROR("bad param");
return NS_ERROR_INVALID_ARG;
}
const XPTTypeDescriptor *td = &param->mType;
while (td->Tag() == TD_ARRAY) {
td = td->ArrayElementType();
}
if (td->Tag() != TD_INTERFACE_TYPE) {
NS_ERROR("not an interface");
return NS_ERROR_INVALID_ARG;
}
*interfaceIndex = td->InterfaceIndex();
return NS_OK;
}
nsresult
xptiInterfaceEntry::GetEntryForParam(uint16_t methodIndex,
const nsXPTParamInfo * param,
xptiInterfaceEntry** entry)
{
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
if(methodIndex < mMethodBaseIndex)
return mParent->GetEntryForParam(methodIndex, param, entry);
uint16_t interfaceIndex = 0;
nsresult rv = GetInterfaceIndexForParam(methodIndex, param,
&interfaceIndex);
if (NS_FAILED(rv)) {
return rv;
}
xptiInterfaceEntry* theEntry = mTypelib->GetEntryAt(interfaceIndex - 1);
// This can happen if a declared interface is not available at runtime.
if(!theEntry)
{
*entry = nullptr;
return NS_ERROR_FAILURE;
}
*entry = theEntry;
return NS_OK;
}
already_AddRefed<ShimInterfaceInfo>
xptiInterfaceEntry::GetShimForParam(uint16_t methodIndex,
const nsXPTParamInfo* param)
{
if(methodIndex < mMethodBaseIndex) {
return mParent->GetShimForParam(methodIndex, param);
}
uint16_t interfaceIndex = 0;
nsresult rv = GetInterfaceIndexForParam(methodIndex, param,
&interfaceIndex);
if (NS_FAILED(rv)) {
return nullptr;
}
const char* shimName = mTypelib->GetEntryNameAt(interfaceIndex - 1);
RefPtr<ShimInterfaceInfo> shim =
ShimInterfaceInfo::MaybeConstruct(shimName, nullptr);
return shim.forget();
}
nsresult
xptiInterfaceEntry::GetIIDForParamNoAlloc(uint16_t methodIndex,
const nsXPTParamInfo * param,
nsIID *iid)
{
xptiInterfaceEntry* entry;
nsresult rv = GetEntryForParam(methodIndex, param, &entry);
if (NS_FAILED(rv)) {
RefPtr<ShimInterfaceInfo> shim = GetShimForParam(methodIndex, param);
if (!shim) {
return rv;
}
const nsIID* shimIID;
DebugOnly<nsresult> rv2 = shim->GetIIDShared(&shimIID);
MOZ_ASSERT(NS_SUCCEEDED(rv2));
*iid = *shimIID;
return NS_OK;
}
*iid = entry->mIID;
return NS_OK;
}
// this is a private helper
nsresult
xptiInterfaceEntry::GetTypeInArray(const nsXPTParamInfo* param,
uint16_t dimension,
const XPTTypeDescriptor** type)
{
NS_ASSERTION(IsFullyResolved(), "bad state");
const XPTTypeDescriptor *td = &param->mType;
for (uint16_t i = 0; i < dimension; i++) {
if (td->Tag() != TD_ARRAY) {
NS_ERROR("bad dimension");
return NS_ERROR_INVALID_ARG;
}
td = td->ArrayElementType();
}
*type = td;
return NS_OK;
}
nsresult
xptiInterfaceEntry::GetTypeForParam(uint16_t methodIndex,
const nsXPTParamInfo* param,
uint16_t dimension,
nsXPTType* type)
{
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
if(methodIndex < mMethodBaseIndex)
return mParent->
GetTypeForParam(methodIndex, param, dimension, type);
if(methodIndex >= mMethodBaseIndex +
mDescriptor->mNumMethods)
{
NS_ERROR("bad index");
return NS_ERROR_INVALID_ARG;
}
const XPTTypeDescriptor *td;
if(dimension) {
nsresult rv = GetTypeInArray(param, dimension, &td);
if(NS_FAILED(rv))
return rv;
}
else
td = &param->mType;
*type = nsXPTType(td->mPrefix);
return NS_OK;
}
nsresult
xptiInterfaceEntry::GetSizeIsArgNumberForParam(uint16_t methodIndex,
const nsXPTParamInfo* param,
uint16_t dimension,
uint8_t* argnum)
{
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
if(methodIndex < mMethodBaseIndex)
return mParent->
GetSizeIsArgNumberForParam(methodIndex, param, dimension, argnum);
if(methodIndex >= mMethodBaseIndex +
mDescriptor->mNumMethods)
{
NS_ERROR("bad index");
return NS_ERROR_INVALID_ARG;
}
const XPTTypeDescriptor *td;
if(dimension) {
nsresult rv = GetTypeInArray(param, dimension, &td);
if(NS_FAILED(rv))
return rv;
}
else
td = &param->mType;
// verify that this is a type that has size_is
switch (td->Tag()) {
case TD_ARRAY:
case TD_PSTRING_SIZE_IS:
case TD_PWSTRING_SIZE_IS:
*argnum = td->ArgNum();
break;
default:
NS_ERROR("not a size_is");
return NS_ERROR_INVALID_ARG;
}
return NS_OK;
}
nsresult
xptiInterfaceEntry::GetInterfaceIsArgNumberForParam(uint16_t methodIndex,
const nsXPTParamInfo* param,
uint8_t* argnum)
{
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
if(methodIndex < mMethodBaseIndex)
return mParent->
GetInterfaceIsArgNumberForParam(methodIndex, param, argnum);
if(methodIndex >= mMethodBaseIndex +
mDescriptor->mNumMethods)
{
NS_ERROR("bad index");
return NS_ERROR_INVALID_ARG;
}
const XPTTypeDescriptor *td = &param->mType;
while (td->Tag() == TD_ARRAY) {
td = td->ArrayElementType();
}
if (td->Tag() != TD_INTERFACE_IS_TYPE) {
NS_ERROR("not an iid_is");
return NS_ERROR_INVALID_ARG;
}
*argnum = td->ArgNum();
return NS_OK;
}
nsresult
xptiInterfaceEntry::IsIID(const nsIID * iid, bool *_retval)
{
// It is not necessary to Resolve because this info is read from manifest.
*_retval = mIID.Equals(*iid);
return NS_OK;
}
nsresult
xptiInterfaceEntry::GetNameShared(const char **name)
{
// It is not necessary to Resolve because this info is read from manifest.
*name = mName;
return NS_OK;
}
nsresult
xptiInterfaceEntry::GetIIDShared(const nsIID * *iid)
{
// It is not necessary to Resolve because this info is read from manifest.
*iid = &mIID;
return NS_OK;
}
nsresult
xptiInterfaceEntry::HasAncestor(const nsIID * iid, bool *_retval)
{
*_retval = false;
for(xptiInterfaceEntry* current = this;
current;
current = current->mParent)
{
if(current->mIID.Equals(*iid))
{
*_retval = true;
break;
}
if(!current->EnsureResolved())
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
/***************************************************/
already_AddRefed<xptiInterfaceInfo>
xptiInterfaceEntry::InterfaceInfo()
{
#ifdef DEBUG
XPTInterfaceInfoManager::GetSingleton()->mWorkingSet.mTableReentrantMonitor.
AssertCurrentThreadIn();
#endif
if(!mInfo)
{
mInfo = new xptiInterfaceInfo(this);
}
RefPtr<xptiInterfaceInfo> info = mInfo;
return info.forget();
}
void
xptiInterfaceEntry::LockedInvalidateInterfaceInfo()
{
if(mInfo)
{
mInfo->Invalidate();
mInfo = nullptr;
}
}
bool
xptiInterfaceInfo::BuildParent()
{
mozilla::ReentrantMonitorAutoEnter monitor(XPTInterfaceInfoManager::GetSingleton()->
mWorkingSet.mTableReentrantMonitor);
NS_ASSERTION(mEntry &&
mEntry->IsFullyResolved() &&
!mParent &&
mEntry->Parent(),
"bad BuildParent call");
mParent = mEntry->Parent()->InterfaceInfo();
return true;
}
/***************************************************************************/
NS_IMPL_QUERY_INTERFACE(xptiInterfaceInfo, nsIInterfaceInfo)
xptiInterfaceInfo::xptiInterfaceInfo(xptiInterfaceEntry* entry)
: mEntry(entry)
{
}
xptiInterfaceInfo::~xptiInterfaceInfo()
{
NS_ASSERTION(!mEntry, "bad state in dtor");
}
void
xptiInterfaceInfo::Invalidate()
{
mParent = nullptr;
mEntry = nullptr;
}
MozExternalRefCountType
xptiInterfaceInfo::AddRef(void)
{
nsrefcnt cnt = ++mRefCnt;
NS_LOG_ADDREF(this, cnt, "xptiInterfaceInfo", sizeof(*this));
return cnt;
}
MozExternalRefCountType
xptiInterfaceInfo::Release(void)
{
xptiInterfaceEntry* entry = mEntry;
nsrefcnt cnt = --mRefCnt;
NS_LOG_RELEASE(this, cnt, "xptiInterfaceInfo");
if(!cnt)
{
mozilla::ReentrantMonitorAutoEnter monitor(XPTInterfaceInfoManager::
GetSingleton()->mWorkingSet.
mTableReentrantMonitor);
// If InterfaceInfo added and *released* a reference before we
// acquired the monitor then 'this' might already be dead. In that
// case we would not want to try to access any instance data. We
// would want to bail immediately. If 'this' is already dead then the
// entry will no longer have a pointer to 'this'. So, we can protect
// ourselves from danger without more aggressive locking.
if(entry && !entry->InterfaceInfoEquals(this))
return 0;
// If InterfaceInfo added a reference before we acquired the monitor
// then we want to bail out of here without destorying the object.
if(mRefCnt)
return 1;
if(mEntry)
{
mEntry->LockedInterfaceInfoDeathNotification();
mEntry = nullptr;
}
delete this;
return 0;
}
return cnt;
}
/***************************************************************************/

View File

@ -1,206 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Implementation of xptiInterfaceInfoManager. */
#include "mozilla/XPTInterfaceInfoManager.h"
#include "mozilla/FileUtils.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/StaticPtr.h"
#include "xptiprivate.h"
#include "nsDependentString.h"
#include "nsString.h"
#include "nsArrayEnumerator.h"
#include "nsDirectoryService.h"
#include "nsIMemoryReporter.h"
using namespace mozilla;
NS_IMPL_ISUPPORTS(
XPTInterfaceInfoManager,
nsIInterfaceInfoManager,
nsIMemoryReporter)
static StaticRefPtr<XPTInterfaceInfoManager> gInterfaceInfoManager;
size_t
XPTInterfaceInfoManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
{
size_t n = aMallocSizeOf(this);
ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
// The entries themselves are allocated out of an arena accounted
// for elsewhere, so don't measure them
n += mWorkingSet.mIIDTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
n += mWorkingSet.mNameTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
return n;
}
MOZ_DEFINE_MALLOC_SIZE_OF(XPTIMallocSizeOf)
NS_IMETHODIMP
XPTInterfaceInfoManager::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData, bool aAnonymize)
{
size_t amount = SizeOfIncludingThis(XPTIMallocSizeOf);
// Measure gXPTIStructArena here, too. This is a bit grotty because it
// doesn't belong to the XPTIInterfaceInfoManager, but there's no
// obviously better place to measure it.
amount += XPT_SizeOfArenaIncludingThis(gXPTIStructArena, XPTIMallocSizeOf);
MOZ_COLLECT_REPORT(
"explicit/xpti-working-set", KIND_HEAP, UNITS_BYTES, amount,
"Memory used by the XPCOM typelib system.");
return NS_OK;
}
// static
XPTInterfaceInfoManager*
XPTInterfaceInfoManager::GetSingleton()
{
if (!gInterfaceInfoManager) {
gInterfaceInfoManager = new XPTInterfaceInfoManager();
gInterfaceInfoManager->InitMemoryReporter();
}
return gInterfaceInfoManager;
}
void
XPTInterfaceInfoManager::FreeInterfaceInfoManager()
{
gInterfaceInfoManager = nullptr;
}
XPTInterfaceInfoManager::XPTInterfaceInfoManager()
: mWorkingSet(),
mResolveLock("XPTInterfaceInfoManager.mResolveLock")
{
xptiTypelibGuts* typelib = xptiTypelibGuts::Create();
ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
for (uint16_t k = 0; k < XPTHeader::kNumInterfaces; k++) {
VerifyAndAddEntryIfNew(XPTHeader::kInterfaces + k, k, typelib);
}
}
XPTInterfaceInfoManager::~XPTInterfaceInfoManager()
{
// We only do this on shutdown of the service.
mWorkingSet.InvalidateInterfaceInfos();
UnregisterWeakMemoryReporter(this);
}
void
XPTInterfaceInfoManager::InitMemoryReporter()
{
RegisterWeakMemoryReporter(this);
}
void
XPTInterfaceInfoManager::VerifyAndAddEntryIfNew(const XPTInterfaceDescriptor* iface,
uint16_t idx,
xptiTypelibGuts* typelib)
{
static const nsID zeroIID =
{ 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } };
if (iface->mIID.Equals(zeroIID)) {
return;
}
// The number of maximum methods is not arbitrary. It is the same value as
// in xpcom/reflect/xptcall/genstubs.pl; do not change this value
// without changing that one or you WILL see problems.
if (iface->mNumMethods > 250 && !iface->IsBuiltinClass()) {
NS_ASSERTION(0, "Too many methods to handle for the stub, cannot load");
fprintf(stderr, "ignoring too large interface: %s\n", iface->Name());
return;
}
mWorkingSet.mTableReentrantMonitor.AssertCurrentThreadIn();
xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(iface->mIID);
if (entry) {
// XXX validate this info to find possible inconsistencies
return;
}
// Build a new xptiInterfaceEntry object and hook it up.
entry = xptiInterfaceEntry::Create(iface, typelib);
if (!entry)
return;
mWorkingSet.mIIDTable.Put(entry->IID(), entry);
mWorkingSet.mNameTable.Put(entry->GetTheName(), entry);
typelib->SetEntryAt(idx, entry);
}
// this is a private helper
static nsresult
EntryToInfo(xptiInterfaceEntry* entry, nsIInterfaceInfo **_retval)
{
if (!entry) {
*_retval = nullptr;
return NS_ERROR_FAILURE;
}
RefPtr<xptiInterfaceInfo> info = entry->InterfaceInfo();
info.forget(_retval);
return NS_OK;
}
xptiInterfaceEntry*
XPTInterfaceInfoManager::GetInterfaceEntryForIID(const nsIID *iid)
{
ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
return mWorkingSet.mIIDTable.Get(*iid);
}
NS_IMETHODIMP
XPTInterfaceInfoManager::GetInfoForIID(const nsIID * iid, nsIInterfaceInfo **_retval)
{
NS_ASSERTION(iid, "bad param");
NS_ASSERTION(_retval, "bad param");
ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(*iid);
return EntryToInfo(entry, _retval);
}
NS_IMETHODIMP
XPTInterfaceInfoManager::GetInfoForName(const char *name, nsIInterfaceInfo **_retval)
{
NS_ASSERTION(name, "bad param");
NS_ASSERTION(_retval, "bad param");
ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
xptiInterfaceEntry* entry = mWorkingSet.mNameTable.Get(name);
return EntryToInfo(entry, _retval);
}
void
XPTInterfaceInfoManager::GetScriptableInterfaces(nsCOMArray<nsIInterfaceInfo>& aInterfaces)
{
// I didn't want to incur the size overhead of using nsHashtable just to
// make building an enumerator easier. So, this code makes a snapshot of
// the table using an nsCOMArray and builds an enumerator for that.
// We can afford this transient cost.
ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
aInterfaces.SetCapacity(mWorkingSet.mNameTable.Count());
for (auto iter = mWorkingSet.mNameTable.Iter(); !iter.Done(); iter.Next()) {
xptiInterfaceEntry* entry = iter.UserData();
if (entry->GetScriptableFlag()) {
nsCOMPtr<nsIInterfaceInfo> ii = entry->InterfaceInfo();
aInterfaces.AppendElement(ii);
}
}
}

View File

@ -1,72 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Implementation of xptiTypelibGuts. */
#include "xptiprivate.h"
#include "xpt_arena.h"
#include "mozilla/XPTInterfaceInfoManager.h"
using namespace mozilla;
// Ensure through static analysis that xptiTypelibGuts won't have a vtable.
template <class T>
class MOZ_NEEDS_NO_VTABLE_TYPE CheckNoVTable
{
};
CheckNoVTable<xptiTypelibGuts> gChecker;
// static
xptiTypelibGuts*
xptiTypelibGuts::Create()
{
size_t n = sizeof(xptiTypelibGuts) +
sizeof(xptiInterfaceEntry*) * (XPTHeader::kNumInterfaces - 1);
void* place = XPT_CALLOC8(gXPTIStructArena, n);
if (!place)
return nullptr;
return new(place) xptiTypelibGuts();
}
xptiInterfaceEntry*
xptiTypelibGuts::GetEntryAt(uint16_t i)
{
static const nsID zeroIID =
{ 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } };
NS_ASSERTION(i < GetEntryCount(), "bad index");
xptiInterfaceEntry* r = mEntryArray[i];
if (r)
return r;
const XPTInterfaceDescriptor* iface = XPTHeader::kInterfaces + i;
XPTInterfaceInfoManager::xptiWorkingSet& set =
XPTInterfaceInfoManager::GetSingleton()->mWorkingSet;
{
ReentrantMonitorAutoEnter monitor(set.mTableReentrantMonitor);
if (iface->mIID.Equals(zeroIID))
r = set.mNameTable.Get(iface->Name());
else
r = set.mIIDTable.Get(iface->mIID);
}
if (r)
SetEntryAt(i, r);
return r;
}
const char*
xptiTypelibGuts::GetEntryNameAt(uint16_t i)
{
NS_ASSERTION(i < GetEntryCount(), "bad index");
const XPTInterfaceDescriptor* iface = XPTHeader::kInterfaces + i;
return iface->Name();
}

View File

@ -1,53 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Implementation of xptiWorkingSet. */
#include "mozilla/XPTInterfaceInfoManager.h"
#include "xptiprivate.h"
#include "nsString.h"
using namespace mozilla;
static const size_t XPTI_ARENA8_BLOCK_SIZE = 16 * 1024;
static const size_t XPTI_ARENA1_BLOCK_SIZE = 8 * 1024;
static const uint32_t XPTI_HASHTABLE_LENGTH = 1024;
XPTInterfaceInfoManager::xptiWorkingSet::xptiWorkingSet()
: mTableReentrantMonitor("xptiWorkingSet::mTableReentrantMonitor")
, mIIDTable(XPTI_HASHTABLE_LENGTH)
, mNameTable(XPTI_HASHTABLE_LENGTH)
{
MOZ_COUNT_CTOR(xptiWorkingSet);
gXPTIStructArena = XPT_NewArena(XPTI_ARENA8_BLOCK_SIZE,
XPTI_ARENA1_BLOCK_SIZE);
}
void
XPTInterfaceInfoManager::xptiWorkingSet::InvalidateInterfaceInfos()
{
ReentrantMonitorAutoEnter monitor(mTableReentrantMonitor);
for (auto iter = mNameTable.Iter(); !iter.Done(); iter.Next()) {
xptiInterfaceEntry* entry = iter.UserData();
entry->LockedInvalidateInterfaceInfo();
}
}
XPTInterfaceInfoManager::xptiWorkingSet::~xptiWorkingSet()
{
MOZ_COUNT_DTOR(xptiWorkingSet);
// Only destroy the arena if we're doing leak stats. Why waste shutdown
// time touching pages if we don't have to?
#ifdef NS_FREE_PERMANENT_DATA
XPT_DestroyArena(gXPTIStructArena);
#endif
}
XPTArena* gXPTIStructArena;

View File

@ -1,363 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Library-private header for Interface Info system. */
#ifndef xptiprivate_h___
#define xptiprivate_h___
#include "nscore.h"
#include <new>
#include "nsISupports.h"
// this after nsISupports, to pick up IID
// so that xpt stuff doesn't try to define it itself...
#include "xpt_struct.h"
#include "nsIInterfaceInfo.h"
#include "nsIInterfaceInfoManager.h"
#include "xptinfo.h"
#include "ShimInterfaceInfo.h"
#include "nsIServiceManager.h"
#include "nsIFile.h"
#include "nsIDirectoryService.h"
#include "nsDirectoryServiceDefs.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsIWeakReference.h"
#include "mozilla/ReentrantMonitor.h"
#include "mozilla/Mutex.h"
#include "mozilla/Attributes.h"
#include "js/TypeDecls.h"
#include "nsCRT.h"
#include "nsMemory.h"
#include "nsCOMArray.h"
#include "nsQuickSort.h"
#include "nsString.h"
#include "nsIInputStream.h"
#include "nsHashKeys.h"
#include "nsDataHashtable.h"
#include "plstr.h"
#include "prprf.h"
#include "prio.h"
#include "prtime.h"
#include "prenv.h"
#include <stdio.h>
#include <stdarg.h>
/***************************************************************************/
class xptiInterfaceInfo;
class xptiInterfaceEntry;
class xptiTypelibGuts;
struct XPTArena;
extern XPTArena* gXPTIStructArena;
/***************************************************************************/
/***************************************************************************/
// No virtuals.
// These are always constructed in the struct arena using placement new.
// dtor need not be called.
class xptiTypelibGuts
{
public:
static xptiTypelibGuts* Create();
uint16_t GetEntryCount() const { return XPTHeader::kNumInterfaces; }
void SetEntryAt(uint16_t i, xptiInterfaceEntry* ptr)
{
NS_ASSERTION(i < GetEntryCount(),"bad param!");
mEntryArray[i] = ptr;
}
xptiInterfaceEntry* GetEntryAt(uint16_t i);
const char* GetEntryNameAt(uint16_t i);
private:
xptiTypelibGuts() = default;
~xptiTypelibGuts();
private:
xptiInterfaceEntry* mEntryArray[1]; // Always last. Sized to fit.
};
/***************************************************************************/
/***************************************************************************/
// This class exists to help xptiInterfaceInfo store a 4-state (2 bit) value
// and a set of bitflags in one 8bit value. See below.
class xptiInfoFlags
{
enum {STATE_MASK = 3};
public:
explicit xptiInfoFlags(uint8_t n) : mData(n) {}
xptiInfoFlags(const xptiInfoFlags& r) : mData(r.mData) {}
static uint8_t GetStateMask()
{return uint8_t(STATE_MASK);}
void Clear()
{mData = 0;}
uint8_t GetData() const
{return mData;}
uint8_t GetState() const
{return mData & GetStateMask();}
void SetState(uint8_t state)
{mData &= ~GetStateMask(); mData |= state;}
void SetFlagBit(uint8_t flag, bool on)
{if(on)
mData |= ~GetStateMask() & flag;
else
mData &= GetStateMask() | ~flag;}
bool GetFlagBit(uint8_t flag) const
{return (mData & flag) ? true : false;}
private:
uint8_t mData;
};
/****************************************************/
// No virtual methods.
// We always create in the struct arena and construct using "placement new".
// No members need dtor calls.
class xptiInterfaceEntry
{
public:
static xptiInterfaceEntry* Create(const XPTInterfaceDescriptor* aIface,
xptiTypelibGuts* aTypelib);
enum {
PARTIALLY_RESOLVED = 1,
FULLY_RESOLVED = 2,
RESOLVE_FAILED = 3
};
// Additional bit flags...
enum {SCRIPTABLE = 4, BUILTINCLASS = 8, HASNOTXPCOM = 16,
MAIN_PROCESS_SCRIPTABLE_ONLY = 32};
uint8_t GetResolveState() const {return mFlags.GetState();}
bool IsFullyResolved() const
{return GetResolveState() == (uint8_t) FULLY_RESOLVED;}
void SetScriptableFlag(bool on)
{mFlags.SetFlagBit(uint8_t(SCRIPTABLE),on);}
bool GetScriptableFlag() const
{return mFlags.GetFlagBit(uint8_t(SCRIPTABLE));}
void SetBuiltinClassFlag(bool on)
{mFlags.SetFlagBit(uint8_t(BUILTINCLASS),on);}
bool GetBuiltinClassFlag() const
{return mFlags.GetFlagBit(uint8_t(BUILTINCLASS));}
void SetMainProcessScriptableOnlyFlag(bool on)
{mFlags.SetFlagBit(uint8_t(MAIN_PROCESS_SCRIPTABLE_ONLY),on);}
bool GetMainProcessScriptableOnlyFlag() const
{return mFlags.GetFlagBit(uint8_t(MAIN_PROCESS_SCRIPTABLE_ONLY));}
// AddRef/Release are special and are not considered for the NOTXPCOM flag.
void SetHasNotXPCOMFlag()
{
mFlags.SetFlagBit(HASNOTXPCOM, true);
}
bool GetHasNotXPCOMFlag() const
{
return mFlags.GetFlagBit(HASNOTXPCOM);
}
const nsID* GetTheIID() const {return &mIID;}
const char* GetTheName() const {return mName;}
bool EnsureResolved()
{return IsFullyResolved() ? true : Resolve();}
already_AddRefed<xptiInterfaceInfo> InterfaceInfo();
bool InterfaceInfoEquals(const xptiInterfaceInfo* info) const
{return info == mInfo;}
void LockedInvalidateInterfaceInfo();
void LockedInterfaceInfoDeathNotification() {mInfo = nullptr;}
xptiInterfaceEntry* Parent() const {
NS_ASSERTION(IsFullyResolved(), "Parent() called while not resolved?");
return mParent;
}
const nsID& IID() const { return mIID; }
//////////////////////
// These non-virtual methods handle the delegated nsIInterfaceInfo methods.
nsresult GetName(char * *aName);
nsresult GetIID(nsIID * *aIID);
nsresult IsScriptable(bool *_retval);
nsresult IsBuiltinClass(bool *_retval) {
*_retval = GetBuiltinClassFlag();
return NS_OK;
}
nsresult IsMainProcessScriptableOnly(bool *_retval) {
*_retval = GetMainProcessScriptableOnlyFlag();
return NS_OK;
}
// Except this one.
//nsresult GetParent(nsIInterfaceInfo * *aParent);
nsresult GetMethodCount(uint16_t *aMethodCount);
nsresult GetConstantCount(uint16_t *aConstantCount);
nsresult GetMethodInfo(uint16_t index, const nsXPTMethodInfo * *info);
nsresult GetMethodInfoForName(const char *methodName, uint16_t *index, const nsXPTMethodInfo * *info);
nsresult GetConstant(uint16_t index, JS::MutableHandleValue, char** constant);
nsresult GetTypeForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, nsXPTType *_retval);
nsresult GetSizeIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, uint8_t *_retval);
nsresult GetInterfaceIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint8_t *_retval);
nsresult IsIID(const nsIID * IID, bool *_retval);
nsresult GetNameShared(const char **name);
nsresult GetIIDShared(const nsIID * *iid);
nsresult IsFunction(bool *_retval);
nsresult HasAncestor(const nsIID * iid, bool *_retval);
nsresult GetIIDForParamNoAlloc(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID *iid);
private:
xptiInterfaceEntry(const XPTInterfaceDescriptor* aIface,
xptiTypelibGuts* aTypelib);
~xptiInterfaceEntry();
void SetResolvedState(int state)
{mFlags.SetState(uint8_t(state));}
bool Resolve();
// We only call these "*Locked" variants after locking. This is done to
// allow reentrace as files are loaded and various interfaces resolved
// without having to worry about the locked state.
bool EnsureResolvedLocked()
{return IsFullyResolved() ? true : ResolveLocked();}
bool ResolveLocked();
// private helpers
nsresult GetEntryForParam(uint16_t methodIndex,
const nsXPTParamInfo * param,
xptiInterfaceEntry** entry);
nsresult GetTypeInArray(const nsXPTParamInfo* param,
uint16_t dimension,
const XPTTypeDescriptor** type);
nsresult GetInterfaceIndexForParam(uint16_t methodIndex,
const nsXPTParamInfo* param,
uint16_t* interfaceIndex);
already_AddRefed<ShimInterfaceInfo>
GetShimForParam(uint16_t methodIndex, const nsXPTParamInfo* param);
private:
nsID mIID;
const XPTInterfaceDescriptor* mDescriptor;
xptiTypelibGuts* mTypelib;
xptiInterfaceEntry* mParent; // Valid only when fully resolved
xptiInterfaceInfo* MOZ_UNSAFE_REF("The safety of this pointer is ensured "
"by the semantics of xptiWorkingSet.")
mInfo; // May come and go.
uint16_t mMethodBaseIndex;
uint16_t mConstantBaseIndex;
xptiInfoFlags mFlags;
const char* mName;
};
class xptiInterfaceInfo final : public nsIInterfaceInfo
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
// Use delegation to implement (most!) of nsIInterfaceInfo.
NS_IMETHOD GetName(char * *aName) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetName(aName); }
NS_IMETHOD IsScriptable(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsScriptable(_retval); }
NS_IMETHOD IsBuiltinClass(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsBuiltinClass(_retval); }
NS_IMETHOD IsMainProcessScriptableOnly(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsMainProcessScriptableOnly(_retval); }
// Except this one.
NS_IMETHOD GetParent(nsIInterfaceInfo * *aParent) override
{
if(!EnsureResolved() || !EnsureParent())
return NS_ERROR_UNEXPECTED;
NS_IF_ADDREF(*aParent = mParent);
return NS_OK;
}
NS_IMETHOD GetMethodCount(uint16_t *aMethodCount) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodCount(aMethodCount); }
NS_IMETHOD GetConstantCount(uint16_t *aConstantCount) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstantCount(aConstantCount); }
NS_IMETHOD GetMethodInfo(uint16_t index, const nsXPTMethodInfo * *info) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfo(index, info); }
NS_IMETHOD GetMethodInfoForName(const char *methodName, uint16_t *index, const nsXPTMethodInfo * *info) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfoForName(methodName, index, info); }
NS_IMETHOD GetConstant(uint16_t index, JS::MutableHandleValue constant, char** name) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstant(index, constant, name); }
NS_IMETHOD GetTypeForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, nsXPTType *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetTypeForParam(methodIndex, param, dimension, _retval); }
NS_IMETHOD GetSizeIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, uint8_t *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetSizeIsArgNumberForParam(methodIndex, param, dimension, _retval); }
NS_IMETHOD GetInterfaceIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint8_t *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInterfaceIsArgNumberForParam(methodIndex, param, _retval); }
NS_IMETHOD IsIID(const nsIID * IID, bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsIID(IID, _retval); }
NS_IMETHOD GetNameShared(const char **name) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetNameShared(name); }
NS_IMETHOD GetIIDShared(const nsIID * *iid) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDShared(iid); }
NS_IMETHOD IsFunction(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsFunction(_retval); }
NS_IMETHOD HasAncestor(const nsIID * iid, bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->HasAncestor(iid, _retval); }
NS_IMETHOD GetIIDForParamNoAlloc(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID *iid) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParamNoAlloc(methodIndex, param, iid); }
public:
explicit xptiInterfaceInfo(xptiInterfaceEntry* entry);
void Invalidate();
private:
~xptiInterfaceInfo();
// Note that mParent might still end up as nullptr if we don't have one.
bool EnsureParent()
{
NS_ASSERTION(mEntry && mEntry->IsFullyResolved(), "bad EnsureParent call");
return mParent || !mEntry->Parent() || BuildParent();
}
bool EnsureResolved()
{
return mEntry && mEntry->EnsureResolved();
}
bool BuildParent();
xptiInterfaceInfo(); // not implemented
private:
xptiInterfaceEntry* mEntry;
RefPtr<xptiInterfaceInfo> mParent;
};
/***************************************************************************/
#endif /* xptiprivate_h___ */

View File

@ -4,31 +4,4 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
Library('xpt')
DIRS += ['tools']
UNIFIED_SOURCES += [
'xpt_arena.cpp',
]
SOURCES += [
'!XPTInfo.cpp',
]
EXPORTS += [
'xpt_arena.h',
'xpt_struct.h',
]
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'!/xpcom/base',
'/xpcom/base',
]
if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'):
CFLAGS += ['-Zl']
DIST_INSTALL = True

View File

@ -1,188 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Quick arena hack for xpt. */
/* XXX This exists because we don't want to drag in NSPR. It *seemed*
* to make more sense to write a quick and dirty arena than to clone
* plarena (like js/src did). This is not optimal, but it works.
*/
#include "xpt_arena.h"
#include "mozilla/Assertions.h"
#include "mozilla/MemoryReporting.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/****************************************************/
/* Block header for each block in the arena */
struct BLK_HDR
{
BLK_HDR *next;
};
#define XPT_MIN_BLOCK_SIZE 32
/* XXX this is lame. Should clone the code to do this bitwise */
#define ALIGN_RND(s,a) ((a)==1?(s):((((s)+(a)-1)/(a))*(a)))
struct XPTSubArena
{
BLK_HDR *first;
uint8_t *next;
size_t space;
size_t block_size;
};
struct XPTArena
{
// We have one sub-arena with 8-byte alignment for most allocations, and
// one with 1-byte alignment for C string allocations. The latter sub-arena
// avoids significant amounts of unnecessary padding between C strings.
XPTSubArena subarena8;
XPTSubArena subarena1;
};
XPTArena*
XPT_NewArena(size_t block_size8, size_t block_size1)
{
XPTArena *arena = static_cast<XPTArena*>(calloc(1, sizeof(XPTArena)));
if (arena) {
if (block_size8 < XPT_MIN_BLOCK_SIZE)
block_size8 = XPT_MIN_BLOCK_SIZE;
arena->subarena8.block_size = ALIGN_RND(block_size8, 8);
if (block_size1 < XPT_MIN_BLOCK_SIZE)
block_size1 = XPT_MIN_BLOCK_SIZE;
arena->subarena1.block_size = block_size1;
}
return arena;
}
static void
DestroySubArena(XPTSubArena *subarena)
{
BLK_HDR* cur = subarena->first;
while (cur) {
BLK_HDR* next = cur->next;
free(cur);
cur = next;
}
}
void
XPT_DestroyArena(XPTArena *arena)
{
DestroySubArena(&arena->subarena8);
DestroySubArena(&arena->subarena1);
free(arena);
}
/*
* Our alignment rule is that we always round up the size of each allocation
* so that the 'arena->next' pointer one will point to properly aligned space.
*/
void*
XPT_ArenaCalloc(XPTArena *arena, size_t size, size_t alignment)
{
if (!size)
return NULL;
if (!arena) {
MOZ_ASSERT(false);
return NULL;
}
XPTSubArena *subarena;
if (alignment == 8) {
subarena = &arena->subarena8;
} else if (alignment == 1) {
subarena = &arena->subarena1;
} else {
MOZ_ASSERT(false);
return NULL;
}
size_t bytes = ALIGN_RND(size, alignment);
if (bytes > subarena->space) {
BLK_HDR* new_block;
size_t block_header_size = ALIGN_RND(sizeof(BLK_HDR), alignment);
size_t new_space = subarena->block_size;
while (bytes > new_space - block_header_size)
new_space += subarena->block_size;
new_block =
static_cast<BLK_HDR*>(calloc(new_space / alignment, alignment));
if (!new_block) {
subarena->next = NULL;
subarena->space = 0;
return NULL;
}
/* link block into the list of blocks for use when we destroy */
new_block->next = subarena->first;
subarena->first = new_block;
/* set info for current block */
subarena->next =
reinterpret_cast<uint8_t*>(new_block) + block_header_size;
subarena->space = new_space - block_header_size;
#ifdef DEBUG
/* mark block for corruption check */
memset(subarena->next, 0xcd, subarena->space);
#endif
}
#ifdef DEBUG
{
/* do corruption check */
size_t i;
for (i = 0; i < bytes; ++i) {
MOZ_ASSERT(subarena->next[i] == 0xcd);
}
/* we guarantee that the block will be filled with zeros */
memset(subarena->next, 0, bytes);
}
#endif
uint8_t* p = subarena->next;
subarena->next += bytes;
subarena->space -= bytes;
return p;
}
/***************************************************************************/
static size_t
SizeOfSubArenaExcludingThis(XPTSubArena *subarena, MozMallocSizeOf mallocSizeOf)
{
size_t n = 0;
BLK_HDR* cur = subarena->first;
while (cur) {
BLK_HDR* next = cur->next;
n += mallocSizeOf(cur);
cur = next;
}
return n;
}
size_t
XPT_SizeOfArenaIncludingThis(XPTArena *arena, MozMallocSizeOf mallocSizeOf)
{
size_t n = mallocSizeOf(arena);
n += SizeOfSubArenaExcludingThis(&arena->subarena8, mallocSizeOf);
n += SizeOfSubArenaExcludingThis(&arena->subarena1, mallocSizeOf);
return n;
}

View File

@ -1,45 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Simple arena allocator for xpt (which avoids using NSPR).
*/
#ifndef __xpt_arena_h__
#define __xpt_arena_h__
#include <stdlib.h>
#include "mozilla/Attributes.h"
#include "mozilla/MemoryReporting.h"
#include <stdint.h>
/*
* Simple Arena support. Use with caution!
*/
struct XPTArena;
XPTArena*
XPT_NewArena(size_t block_size8, size_t block_size1);
void
XPT_DestroyArena(XPTArena *arena);
void*
XPT_ArenaCalloc(XPTArena *arena, size_t size, size_t alignment);
size_t
XPT_SizeOfArenaIncludingThis(XPTArena *arena, MozMallocSizeOf mallocSizeOf);
/* --------------------------------------------------------- */
#define XPT_CALLOC8(_arena, _bytes) XPT_ArenaCalloc((_arena), (_bytes), 8)
#define XPT_CALLOC1(_arena, _bytes) XPT_ArenaCalloc((_arena), (_bytes), 1)
#define XPT_NEWZAP(_arena, _struct) ((_struct *) XPT_CALLOC8((_arena), sizeof(_struct)))
/* --------------------------------------------------------- */
#endif /* __xpt_arena_h__ */

View File

@ -1,243 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/*
* Structures for representing typelib structures in memory.
* http://www.mozilla.org/scriptable/typelib_file.html
*/
#ifndef xpt_struct_h
#define xpt_struct_h
#include "nsID.h"
#include <stdint.h>
#include "mozilla/Assertions.h"
struct XPTInterfaceDescriptor;
struct XPTConstDescriptor;
struct XPTMethodDescriptor;
struct XPTParamDescriptor;
struct XPTTypeDescriptor;
struct XPTTypeDescriptorPrefix;
struct XPTHeader {
static const uint16_t kNumInterfaces;
static const XPTInterfaceDescriptor kInterfaces[];
static const XPTTypeDescriptor kTypes[];
static const XPTParamDescriptor kParams[];
static const XPTMethodDescriptor kMethods[];
static const XPTConstDescriptor kConsts[];
// All of the strings for this header, including their null
// terminators, concatenated into a single string.
static const char kStrings[];
};
/*
* An InterfaceDescriptor describes a single XPCOM interface, including all of
* its methods.
*/
struct XPTInterfaceDescriptor {
static const uint8_t kScriptableMask = 0x80;
static const uint8_t kFunctionMask = 0x40;
static const uint8_t kBuiltinClassMask = 0x20;
static const uint8_t kMainProcessScriptableOnlyMask = 0x10;
bool IsScriptable() const { return !!(mFlags & kScriptableMask); }
bool IsFunction() const { return !!(mFlags & kFunctionMask); }
bool IsBuiltinClass() const { return !!(mFlags & kBuiltinClassMask); }
bool IsMainProcessScriptableOnly() const { return !!(mFlags & kMainProcessScriptableOnlyMask); }
inline const char* Name() const;
inline const XPTMethodDescriptor& Method(size_t aIndex) const;
inline const XPTConstDescriptor& Const(size_t aIndex) const;
/*
* This field ordering minimizes the size of this struct.
*/
nsID mIID;
uint32_t mName; // Index into XPTHeader::mStrings.
uint16_t mMethodDescriptors; // Index into XPTHeader::mMethods.
uint16_t mConstDescriptors; // Index into XPTHeader::mConsts.
uint16_t mParentInterface;
uint16_t mNumMethods;
uint16_t mNumConstants;
uint8_t mFlags;
};
/*
* A TypeDescriptor is a union used to identify the type of a method
* argument or return value.
*
* There are three types of TypeDescriptors:
*
* SimpleTypeDescriptor
* InterfaceTypeDescriptor
* InterfaceIsTypeDescriptor
*
* The tag field in the prefix indicates which of the variant TypeDescriptor
* records is being used, and hence which union members are valid. Values from 0
* to 17 refer to SimpleTypeDescriptors. The value 18 designates an
* InterfaceTypeDescriptor, while 19 represents an InterfaceIsTypeDescriptor.
*/
/* why bother with a struct? - other code relies on this being a struct */
struct XPTTypeDescriptorPrefix {
uint8_t TagPart() const {
static const uint8_t kFlagMask = 0xe0;
return (uint8_t) (mFlags & ~kFlagMask);
}
uint8_t mFlags;
};
/*
* The following enum maps mnemonic names to the different numeric values
* of XPTTypeDescriptor->tag.
*/
enum XPTTypeDescriptorTags {
TD_INT8 = 0,
TD_INT16 = 1,
TD_INT32 = 2,
TD_INT64 = 3,
TD_UINT8 = 4,
TD_UINT16 = 5,
TD_UINT32 = 6,
TD_UINT64 = 7,
TD_FLOAT = 8,
TD_DOUBLE = 9,
TD_BOOL = 10,
TD_CHAR = 11,
TD_WCHAR = 12,
TD_VOID = 13,
TD_PNSIID = 14,
TD_DOMSTRING = 15,
TD_PSTRING = 16,
TD_PWSTRING = 17,
TD_INTERFACE_TYPE = 18,
TD_INTERFACE_IS_TYPE = 19,
TD_ARRAY = 20,
TD_PSTRING_SIZE_IS = 21,
TD_PWSTRING_SIZE_IS = 22,
TD_UTF8STRING = 23,
TD_CSTRING = 24,
TD_ASTRING = 25,
TD_JSVAL = 26
};
struct XPTTypeDescriptor {
uint8_t Tag() const {
return mPrefix.TagPart();
}
uint8_t ArgNum() const {
MOZ_ASSERT(Tag() == TD_INTERFACE_IS_TYPE ||
Tag() == TD_PSTRING_SIZE_IS ||
Tag() == TD_PWSTRING_SIZE_IS ||
Tag() == TD_ARRAY);
return mData1;
}
const XPTTypeDescriptor* ArrayElementType() const {
MOZ_ASSERT(Tag() == TD_ARRAY);
return &XPTHeader::kTypes[mData2];
}
// We store the 16-bit iface value as two 8-bit values in order to
// avoid 16-bit alignment requirements for XPTTypeDescriptor, which
// reduces its size and also the size of XPTParamDescriptor.
uint16_t InterfaceIndex() const {
MOZ_ASSERT(Tag() == TD_INTERFACE_TYPE);
return (mData1 << 8) | mData2;
}
XPTTypeDescriptorPrefix mPrefix;
// The data for the different variants is stored in these two data fields.
// These should only be accessed via the getter methods above, which will
// assert if the tag is invalid. The memory layout here doesn't exactly match
// the on-disk format. This is to save memory. Some fields for some cases are
// smaller than they are on disk or omitted entirely.
uint8_t mData1;
uint8_t mData2;
};
/*
* A ConstDescriptor records the name and value of a scoped interface constant.
* This is allowed only for a subset of types.
*
* The type of the value record is determined by the contents of the associated
* TypeDescriptor record. For instance, if type corresponds to int16_t, then
* value is a 16-bit signed integer.
*/
union XPTConstValue {
int16_t i16;
uint16_t ui16;
int32_t i32;
uint32_t ui32;
// These constructors are needed to statically initialize different cases of
// the union because MSVC does not support the use of designated initializers
// in C++ code. They need to be constexpr to ensure that no initialization code
// is run at startup, to enable sharing of this memory between Firefox processes.
explicit constexpr XPTConstValue(int16_t aInt) : i16(aInt) {}
explicit constexpr XPTConstValue(uint16_t aInt) : ui16(aInt) {}
explicit constexpr XPTConstValue(int32_t aInt) : i32(aInt) {}
explicit constexpr XPTConstValue(uint32_t aInt) : ui32(aInt) {}
};
struct XPTConstDescriptor {
const char* Name() const {
return &XPTHeader::kStrings[mName];
}
uint32_t mName; // Index into XPTHeader::mStrings.
XPTTypeDescriptor mType;
XPTConstValue mValue;
};
/*
* A ParamDescriptor is used to describe either a single argument to a method or
* a method's result.
*/
struct XPTParamDescriptor {
uint8_t mFlags;
XPTTypeDescriptor mType;
};
/*
* A MethodDescriptor is used to describe a single interface method.
*/
struct XPTMethodDescriptor {
const char* Name() const {
return &XPTHeader::kStrings[mName];
}
const XPTParamDescriptor& Param(uint8_t aIndex) const {
return XPTHeader::kParams[mParams + aIndex];
}
uint32_t mName; // Index into XPTHeader::mStrings.
uint32_t mParams; // Index into XPTHeader::mParams.
uint8_t mFlags;
uint8_t mNumArgs;
};
const char*
XPTInterfaceDescriptor::Name() const {
return &XPTHeader::kStrings[mName];
}
const XPTMethodDescriptor&
XPTInterfaceDescriptor::Method(size_t aIndex) const {
return XPTHeader::kMethods[mMethodDescriptors + aIndex];
}
const XPTConstDescriptor&
XPTInterfaceDescriptor::Const(size_t aIndex) const {
return XPTHeader::kConsts[mConstDescriptors + aIndex];
}
#endif /* xpt_struct_h */