зеркало из https://github.com/mozilla/pjs.git
Remove tracer from XPConnect (bug 698201 part 6, r=bholley).
This commit is contained in:
Родитель
4a2dbc9ddd
Коммит
195a08ec39
|
@ -91,9 +91,8 @@
|
|||
#undef JS_INTPTR_TYPE
|
||||
#undef JS_BYTES_PER_WORD
|
||||
|
||||
/* Some mozilla code uses JS-friend APIs that depend on JS_TRACER and
|
||||
JS_METHODJIT being correct. */
|
||||
#undef JS_TRACER
|
||||
/* Some mozilla code uses JS-friend APIs that depend on JS_METHODJIT being
|
||||
correct. */
|
||||
#undef JS_METHODJIT
|
||||
|
||||
#endif /* js_config_h___ */
|
||||
|
|
|
@ -94,7 +94,6 @@ LOCAL_INCLUDES = \
|
|||
-I$(srcdir)/../wrappers \
|
||||
-I$(srcdir)/../loader \
|
||||
-I$(topsrcdir)/js/src \
|
||||
-I$(topsrcdir)/js/src/nanojit \
|
||||
-I$(topsrcdir)/caps/include \
|
||||
-I$(topsrcdir)/content/base/src \
|
||||
-I$(topsrcdir)/content/html/content/src \
|
||||
|
@ -119,24 +118,6 @@ DEFINES += \
|
|||
-DEXPORT_XPC_API \
|
||||
$(NULL)
|
||||
|
||||
CONFIG := $(shell cat $(DEPTH)/js/src/js-confdefs.h)
|
||||
|
||||
ENABLE_JIT = $(filter JS_TRACER, $(CONFIG))
|
||||
|
||||
ifneq (,$(ENABLE_JIT))
|
||||
|
||||
# Ugly! We need the AVMPLUS defines out of js/src/js-confdefs.h to make the
|
||||
# nanojit headers happy. Gotta figure out a better way to get them, bug 483677.
|
||||
DEFINES += \
|
||||
-DJS_TRACER=1 \
|
||||
-DFEATURE_NANOJIT=1 \
|
||||
$(addprefix -D,$(filter AVMPLUS%,$(CONFIG))) \
|
||||
$(NULL)
|
||||
|
||||
ENABLE_TRACEABLE_FLAGS = --enable-traceables
|
||||
|
||||
endif # ENABLE_JIT
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
ifndef GNU_CXX
|
||||
ifeq (,$(filter-out 1200 1300 1310,$(_MSC_VER)))
|
||||
|
|
|
@ -4069,7 +4069,6 @@ GENERATE_JSOPTION_GETTER_SETTER(Werror, JSOPTION_WERROR)
|
|||
GENERATE_JSOPTION_GETTER_SETTER(Atline, JSOPTION_ATLINE)
|
||||
GENERATE_JSOPTION_GETTER_SETTER(Xml, JSOPTION_XML)
|
||||
GENERATE_JSOPTION_GETTER_SETTER(Relimit, JSOPTION_RELIMIT)
|
||||
GENERATE_JSOPTION_GETTER_SETTER(Tracejit, JSOPTION_JIT)
|
||||
GENERATE_JSOPTION_GETTER_SETTER(Methodjit, JSOPTION_METHODJIT)
|
||||
GENERATE_JSOPTION_GETTER_SETTER(Jitprofiling, JSOPTION_PROFILING)
|
||||
GENERATE_JSOPTION_GETTER_SETTER(Methodjit_always, JSOPTION_METHODJIT_ALWAYS)
|
||||
|
|
|
@ -1214,45 +1214,6 @@ XPCJSRuntime::~XPCJSRuntime()
|
|||
|
||||
namespace {
|
||||
|
||||
#ifdef JS_TRACER
|
||||
|
||||
PRInt64
|
||||
GetCompartmentTjitCodeSize(JSCompartment *c)
|
||||
{
|
||||
if (c->hasTraceMonitor()) {
|
||||
size_t total, frag_size, free_size;
|
||||
c->traceMonitor()->getCodeAllocStats(total, frag_size, free_size);
|
||||
return total;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRInt64
|
||||
GetCompartmentTjitDataAllocatorsMainSize(JSCompartment *c)
|
||||
{
|
||||
return c->hasTraceMonitor()
|
||||
? c->traceMonitor()->getVMAllocatorsMainSize(moz_malloc_usable_size)
|
||||
: 0;
|
||||
}
|
||||
|
||||
PRInt64
|
||||
GetCompartmentTjitDataAllocatorsReserveSize(JSCompartment *c)
|
||||
{
|
||||
return c->hasTraceMonitor()
|
||||
? c->traceMonitor()->getVMAllocatorsReserveSize(moz_malloc_usable_size)
|
||||
: 0;
|
||||
}
|
||||
|
||||
PRInt64
|
||||
GetCompartmentTjitDataTraceMonitorSize(JSCompartment *c)
|
||||
{
|
||||
return c->hasTraceMonitor()
|
||||
? c->traceMonitor()->getTraceMonitorSize(moz_malloc_usable_size)
|
||||
: 0;
|
||||
}
|
||||
|
||||
#endif // JS_TRACER
|
||||
|
||||
void
|
||||
CompartmentCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
|
||||
{
|
||||
|
@ -1270,12 +1231,6 @@ CompartmentCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
|
|||
curr->mjitCodeMethod = method;
|
||||
curr->mjitCodeRegexp = regexp;
|
||||
curr->mjitCodeUnused = unused;
|
||||
#endif
|
||||
#ifdef JS_TRACER
|
||||
curr->tjitCode = GetCompartmentTjitCodeSize(compartment);
|
||||
curr->tjitDataAllocatorsMain = GetCompartmentTjitDataAllocatorsMainSize(compartment);
|
||||
curr->tjitDataAllocatorsReserve = GetCompartmentTjitDataAllocatorsReserveSize(compartment);
|
||||
curr->tjitDataNonAllocators = GetCompartmentTjitDataTraceMonitorSize(compartment);
|
||||
#endif
|
||||
JS_GetTypeInferenceMemoryStats(cx, compartment, &curr->typeInferenceMemory,
|
||||
moz_malloc_usable_size);
|
||||
|
@ -1832,38 +1787,6 @@ ReportCompartmentStats(const CompartmentStats &stats,
|
|||
"JITScripts, native maps, and inline cache structs." SLOP_BYTES_STRING,
|
||||
callback, closure);
|
||||
#endif
|
||||
#ifdef JS_TRACER
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
|
||||
"tjit-code"),
|
||||
nsIMemoryReporter::KIND_NONHEAP, stats.tjitCode,
|
||||
"Memory used by the trace JIT to hold the compartment's generated code.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
|
||||
"tjit-data/allocators-main"),
|
||||
nsIMemoryReporter::KIND_HEAP,
|
||||
stats.tjitDataAllocatorsMain,
|
||||
"Memory used by the trace JIT to store the compartment's trace-related "
|
||||
"data. This data is allocated via the compartment's VMAllocators.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
|
||||
"tjit-data/allocators-reserve"),
|
||||
nsIMemoryReporter::KIND_HEAP,
|
||||
stats.tjitDataAllocatorsReserve,
|
||||
"Memory used by the trace JIT and held in reserve for the compartment's "
|
||||
"VMAllocators in case of OOM.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
|
||||
"tjit-data/trace-monitor"),
|
||||
nsIMemoryReporter::KIND_HEAP,
|
||||
stats.tjitDataNonAllocators,
|
||||
"Memory used by the trace JIT that is stored in the TraceMonitor. This "
|
||||
"includes the TraceMonitor object itself, plus its TraceNativeStorage, "
|
||||
"RecordAttemptMap, and LoopProfileMap.",
|
||||
callback, closure);
|
||||
#endif
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
|
||||
"type-inference/script-main"),
|
||||
|
|
|
@ -431,15 +431,6 @@ xpc_qsDefineQuickStubs(JSContext *cx, JSObject *proto, uintN flags,
|
|||
}
|
||||
}
|
||||
|
||||
const xpc_qsTraceableSpec *ts = entry->traceables;
|
||||
if (ts) {
|
||||
for (; ts->name; ts++) {
|
||||
if (!JS_DefineFunction(cx, proto, ts->name, ts->native, ts->arity,
|
||||
flags | JSFUN_STUB_GSOPS | JSFUN_TRCINFO))
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Next.
|
||||
size_t j = entry->parentInterface;
|
||||
if (j == XPC_QS_NULL_INDEX)
|
||||
|
|
|
@ -71,7 +71,6 @@ struct xpc_qsHashEntry {
|
|||
nsID iid;
|
||||
const xpc_qsPropertySpec *properties;
|
||||
const xpc_qsFunctionSpec *functions;
|
||||
const xpc_qsTraceableSpec *traceables;
|
||||
// These last two fields index to other entries in the same table.
|
||||
// XPC_QS_NULL_ENTRY indicates there are no more entries in the chain.
|
||||
size_t parentInterface;
|
||||
|
|
|
@ -1263,8 +1263,6 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
|
|||
// We use js_Invoke so that the gcthings we use as args will be rooted by
|
||||
// the engine as we do conversions and prepare to do the function call.
|
||||
|
||||
js::LeaveTrace(cx);
|
||||
|
||||
// setup stack
|
||||
|
||||
// if this isn't a function call then we don't need to push extra stuff
|
||||
|
|
|
@ -200,34 +200,18 @@ def removeStubMember(memberId, member):
|
|||
% (member.name, member.iface.name))
|
||||
member.iface.stubMembers.remove(member)
|
||||
|
||||
def addStubMember(memberId, member, traceable):
|
||||
mayTrace = False
|
||||
def addStubMember(memberId, member):
|
||||
if member.kind == 'method' and not member.implicit_jscontext and not isVariantType(member.realtype):
|
||||
# This code MUST match writeTraceableQuickStub
|
||||
haveCallee = memberNeedsCallee(member)
|
||||
# Traceable natives support up to MAX_TRACEABLE_NATIVE_ARGS
|
||||
# total arguments. We always have two prefix arguments
|
||||
# (CONTEXT and THIS) and when haveCallee is true also have
|
||||
# CALLEE. We can only output a traceable native if our number
|
||||
# of arguments is no bigger than can be handled.
|
||||
prefixArgCount = 2 + int(haveCallee);
|
||||
mayTrace = (len(member.params) <= MAX_TRACEABLE_NATIVE_ARGS - prefixArgCount)
|
||||
|
||||
for param in member.params:
|
||||
for attrname, value in vars(param).items():
|
||||
if value is True:
|
||||
# Let the tracer call the regular fastnative method if there
|
||||
# are optional arguments.
|
||||
if attrname == 'optional':
|
||||
mayTrace = False
|
||||
continue
|
||||
|
||||
raise UserError("Method %s, parameter %s: "
|
||||
"unrecognized property %r"
|
||||
% (memberId, param.name, attrname))
|
||||
|
||||
member.traceable = traceable and mayTrace
|
||||
|
||||
# Add this member to the list.
|
||||
member.iface.stubMembers.append(member)
|
||||
|
||||
|
@ -256,7 +240,7 @@ def checkStubMember(member, isCustom):
|
|||
# Check for unknown properties.
|
||||
for attrname, value in vars(member).items():
|
||||
if value is True and attrname not in ('readonly','optional_argc',
|
||||
'traceable','implicit_jscontext',
|
||||
'implicit_jscontext',
|
||||
'getter', 'stringifier'):
|
||||
raise UserError("%s %s: unrecognized property %r"
|
||||
% (member.kind.capitalize(), memberId,
|
||||
|
@ -288,7 +272,7 @@ class Configuration:
|
|||
self.customReturnInterfaces = config.get('customReturnInterfaces', [])
|
||||
self.customMethodCalls = config.get('customMethodCalls', {})
|
||||
|
||||
def readConfigFile(filename, includePath, cachedir, traceable):
|
||||
def readConfigFile(filename, includePath, cachedir):
|
||||
# Read the config file.
|
||||
conf = Configuration(filename, includePath)
|
||||
|
||||
|
@ -339,10 +323,8 @@ def readConfigFile(filename, includePath, cachedir, traceable):
|
|||
for member in iface.members:
|
||||
if member.kind in ('method', 'attribute') and not member.noscript:
|
||||
cmc = conf.customMethodCalls.get(interfaceName + "_" + header.methodNativeName(member), None)
|
||||
mayTrace = cmc is None or cmc.get('traceable', True)
|
||||
|
||||
addStubMember(iface.name + '.' + member.name, member,
|
||||
traceable and mayTrace)
|
||||
addStubMember(iface.name + '.' + member.name, member)
|
||||
|
||||
if member.iface not in stubbedInterfaces:
|
||||
stubbedInterfaces.append(member.iface)
|
||||
|
@ -360,9 +342,8 @@ def readConfigFile(filename, includePath, cachedir, traceable):
|
|||
% memberId)
|
||||
|
||||
cmc = conf.customMethodCalls.get(interfaceName + "_" + header.methodNativeName(member), None)
|
||||
mayTrace = cmc is None or cmc.get('traceable', True)
|
||||
|
||||
addStubMember(memberId, member, traceable and mayTrace)
|
||||
addStubMember(memberId, member)
|
||||
if member.iface not in stubbedInterfaces:
|
||||
stubbedInterfaces.append(member.iface)
|
||||
else:
|
||||
|
@ -1065,409 +1046,6 @@ def writeQuickStub(f, customMethodCalls, member, stubName, isSetter=False):
|
|||
if customMethodCall is not None:
|
||||
f.write(callTemplate)
|
||||
|
||||
# Only these types can be returned (note: no strings);
|
||||
# if the type isn't one of these, then defaultTraceType is used
|
||||
traceReturnTypeMap = {
|
||||
'void': ("uint32 ", "UINT32", "0"),
|
||||
'boolean': ("JSBool ", "BOOL", "JS_FALSE"),
|
||||
'short': ("int32 ", "INT32", "0"),
|
||||
'unsigned short': ("uint32 ", "UINT32", "0"),
|
||||
'long': ("int32 ", "INT32", "0"),
|
||||
'unsigned long': ("uint32 ", "UINT32", "0"),
|
||||
'long long': ("jsdouble ", "DOUBLE", "0"),
|
||||
'unsigned long long': ("jsdouble ", "DOUBLE", "0"),
|
||||
'float': ("jsdouble ", "DOUBLE", "0"),
|
||||
'double': ("jsdouble ", "DOUBLE", "0"),
|
||||
'octet': ("uint32 ", "UINT32", "0"),
|
||||
'[astring]': ("JSString *", "STRING_OR_NULL", "nsnull"),
|
||||
'[domstring]': ("JSString *", "STRING_OR_NULL", "nsnull"),
|
||||
'[cstring]': ("JSString *", "STRING_OR_NULL", "nsnull"),
|
||||
'string': ("JSString *", "STRING_OR_NULL", "nsnull"),
|
||||
'wstring': ("JSString *", "STRING_OR_NULL", "nsnull")
|
||||
}
|
||||
|
||||
# This list extends the above list, but includes types that
|
||||
# are valid for arguments only, namely strings.
|
||||
traceParamTypeMap = traceReturnTypeMap.copy()
|
||||
traceParamTypeMap.update({
|
||||
'void': ("uint32 ", "UINT32"),
|
||||
'boolean': ("JSBool ", "BOOL"),
|
||||
'short': ("int32 ", "INT32"),
|
||||
'unsigned short': ("uint32 ", "UINT32"),
|
||||
'long': ("int32 ", "INT32"),
|
||||
'unsigned long': ("uint32 ", "UINT32"),
|
||||
'long long': ("jsdouble ", "DOUBLE"),
|
||||
'unsigned long long': ("jsdouble ", "DOUBLE"),
|
||||
'float': ("jsdouble ", "DOUBLE"),
|
||||
'double': ("jsdouble ", "DOUBLE"),
|
||||
'octet': ("uint32 ", "UINT32"),
|
||||
'[astring]': ("JSString *", "STRING"),
|
||||
'[domstring]': ("JSString *", "STRING"),
|
||||
'[cstring]': ("JSString *", "STRING"),
|
||||
'string': ("JSString *", "STRING"),
|
||||
'wstring': ("JSString *", "STRING"),
|
||||
})
|
||||
|
||||
defaultReturnTraceType = ("JSObject *", "OBJECT_OR_NULL", "nsnull")
|
||||
defaultParamTraceType = ("js::ValueArgType ", "VALUE")
|
||||
|
||||
def getTraceParamType(type):
|
||||
type = getBuiltinOrNativeTypeName(type)
|
||||
assert type is not '[jsval]'
|
||||
return traceParamTypeMap.get(type, defaultParamTraceType)[0]
|
||||
|
||||
def getTraceReturnType(type):
|
||||
assert not isVariantType(type)
|
||||
type = getBuiltinOrNativeTypeName(type)
|
||||
assert type is not '[jsval]'
|
||||
return traceReturnTypeMap.get(type, defaultReturnTraceType)[0]
|
||||
|
||||
def getTraceInfoParamType(type):
|
||||
type = getBuiltinOrNativeTypeName(type)
|
||||
assert type is not '[jsval]'
|
||||
return traceParamTypeMap.get(type, defaultParamTraceType)[1]
|
||||
|
||||
def getTraceInfoReturnType(type):
|
||||
assert not isVariantType(type)
|
||||
type = getBuiltinOrNativeTypeName(type)
|
||||
assert type is not '[jsval]'
|
||||
return traceReturnTypeMap.get(type, defaultReturnTraceType)[1]
|
||||
|
||||
def getTraceInfoDefaultReturn(type):
|
||||
assert not isVariantType(type)
|
||||
type = getBuiltinOrNativeTypeName(type)
|
||||
assert type is not '[jsval]'
|
||||
return traceReturnTypeMap.get(type, defaultReturnTraceType)[2]
|
||||
|
||||
def getFailureString(retval, indent):
|
||||
assert indent > 0
|
||||
ret = " " * (4 * indent)
|
||||
ret += "js_SetTraceableNativeFailed(cx);\n"
|
||||
ret += " " * (4 * indent)
|
||||
ret += "return %s;\n" % retval
|
||||
ret += " " * (4 * (indent - 1))
|
||||
ret += "}\n"
|
||||
return ret
|
||||
|
||||
def writeFailure(f, retval, indent):
|
||||
f.write(getFailureString(retval, indent))
|
||||
|
||||
traceableArgumentConversionTemplates = {
|
||||
'octet':
|
||||
" PRUint8 ${name} = (PRUint8) ${argVal};\n",
|
||||
'short':
|
||||
" PRint16 ${name} = (PRint16) ${argVal};\n",
|
||||
'unsigned short':
|
||||
" PRUint16 ${name} = (PRUint16) ${argVal};\n",
|
||||
'long':
|
||||
" PRInt32 ${name} = (PRInt32) ${argVal};\n",
|
||||
'unsigned long':
|
||||
" PRUint32 ${name} = (PRUint32) ${argVal};\n",
|
||||
'long long':
|
||||
" PRInt64 ${name} = (PRInt64) ${argVal};\n",
|
||||
'unsigned long long':
|
||||
" PRUint64 ${name} = xpc_qsDoubleToUint64(${argVal});\n",
|
||||
'boolean':
|
||||
" bool ${name} = (bool) ${argVal};\n",
|
||||
'float':
|
||||
" float ${name} = (float) ${argVal};\n",
|
||||
'double':
|
||||
" jsdouble ${name} = ${argVal};\n",
|
||||
'[astring]':
|
||||
" XPCReadableJSStringWrapper ${name};\n"
|
||||
" if (!${name}.init(cx, ${argVal})) {\n"
|
||||
"${error}",
|
||||
'[domstring]':
|
||||
" XPCReadableJSStringWrapper ${name};\n"
|
||||
" if (!${name}.init(cx, ${argVal})) {\n"
|
||||
"${error}",
|
||||
'[utf8string]':
|
||||
" size_t ${name}_length;\n"
|
||||
" const jschar *${name}_chars = JS_GetStringCharsAndLength(cx, "
|
||||
"${argVal}, &${name}_length);\n"
|
||||
" if (!${name}_chars) {\n"
|
||||
"${error}"
|
||||
" NS_ConvertUTF16toUTF8 ${name}(${argVal}_chars, ${argVal}_length);\n",
|
||||
'string':
|
||||
" size_t ${name}_length;\n"
|
||||
" const jschar *${name}_chars = JS_GetStringCharsAndLength(cx, "
|
||||
"${argVal}, &${name}_length);\n"
|
||||
" if (!${name}_chars) {\n"
|
||||
"${error}"
|
||||
" NS_ConvertUTF16toUTF8 ${name}_utf8(${name}_chars, ${name}_length);\n"
|
||||
" const char *${name} = ${name}_utf8.get();\n",
|
||||
'wstring':
|
||||
" const jschar *${name}_chars = JS_GetStringCharsZ(cx, {argVal});\n"
|
||||
" if (!${name}_chars) {\n"
|
||||
"${error}"
|
||||
" const PRUnichar *${name} = ${name}_chars;\n",
|
||||
}
|
||||
|
||||
def writeTraceableArgumentConversion(f, member, i, name, type, haveCcx,
|
||||
rvdeclared):
|
||||
argVal = "_arg%d" % i
|
||||
|
||||
params = {
|
||||
'name': name,
|
||||
'argVal': argVal,
|
||||
'error': getFailureString(getTraceInfoDefaultReturn(member.realtype), 2)
|
||||
}
|
||||
|
||||
typeName = getBuiltinOrNativeTypeName(type)
|
||||
if typeName is not None:
|
||||
template = traceableArgumentConversionTemplates.get(typeName)
|
||||
if template is not None:
|
||||
f.write(substitute(template, params))
|
||||
return rvdeclared
|
||||
# else fall through; the type isn't supported yet.
|
||||
elif isInterfaceType(type):
|
||||
if type.name == 'nsIVariant':
|
||||
# Totally custom.
|
||||
assert haveCcx
|
||||
template = (
|
||||
" nsCOMPtr<nsIVariant> ${name}(already_AddRefed<nsIVariant>("
|
||||
"XPCVariant::newVariant(ccx, js::ValueArgToConstRef(${argVal}))));\n"
|
||||
" if (!${name}) {\n")
|
||||
f.write(substitute(template, params))
|
||||
writeFailure(f, getTraceInfoDefaultReturn(member.realtype), 2)
|
||||
return rvdeclared
|
||||
elif type.name == 'nsIAtom':
|
||||
# Should have special atomizing behavior. Fall through.
|
||||
pass
|
||||
else:
|
||||
if not rvdeclared:
|
||||
f.write(" nsresult rv;\n");
|
||||
f.write(" %s *%s;\n" % (type.name, name))
|
||||
f.write(" xpc_qsSelfRef %sref;\n" % name)
|
||||
f.write(" JS::Anchor<jsval> %sanchor;\n" % name);
|
||||
f.write(" rv = xpc_qsUnwrapArg<%s>("
|
||||
"cx, js::ValueArgToConstRef(%s), &%s, &%sref.ptr, &%sanchor.get());\n"
|
||||
% (type.name, argVal, name, name, name))
|
||||
f.write(" if (NS_FAILED(rv)) {\n")
|
||||
if haveCcx:
|
||||
f.write(" xpc_qsThrowBadArgWithCcx(ccx, rv, %d);\n" % i)
|
||||
else:
|
||||
# XXX Fix this to return a real error!
|
||||
f.write(" xpc_qsThrowBadArgWithDetails(cx, rv, %d, "
|
||||
"\"%s\", \"%s\");\n"
|
||||
% (i, member.iface.name, member.name))
|
||||
writeFailure(f, getTraceInfoDefaultReturn(member.realtype), 2)
|
||||
return True
|
||||
|
||||
print member
|
||||
warn("Unable to unbox argument of type %s (for traceable arg)" % type.name)
|
||||
f.write(" !; // TODO - Unbox argument %s = arg%d\n" % (name, i))
|
||||
return rvdeclared
|
||||
|
||||
traceableResultConvTemplates = {
|
||||
'void':
|
||||
" return 0;\n",
|
||||
'octet':
|
||||
" return uint32(result);\n",
|
||||
'short':
|
||||
" return int32(result);\n",
|
||||
'unsigned short':
|
||||
" return uint32(result);\n",
|
||||
'long':
|
||||
" return int32(result);\n",
|
||||
'unsigned long':
|
||||
" return uint32(result);\n",
|
||||
'long long':
|
||||
" return jsdouble(result);\n",
|
||||
'unsigned long long':
|
||||
" return jsdouble(result);\n",
|
||||
'boolean':
|
||||
" return result ? JS_TRUE : JS_FALSE;\n",
|
||||
'float':
|
||||
" return jsdouble(result);\n",
|
||||
'double':
|
||||
" return jsdouble(result);\n",
|
||||
'[domstring]':
|
||||
" JSString *rval;\n"
|
||||
" if (!xpc_qsStringToJsstring(cx, result, &rval)) {\n"
|
||||
" JS_ReportOutOfMemory(cx);\n${errorStr}"
|
||||
" return rval;\n",
|
||||
'[astring]':
|
||||
" JSString *rval;\n"
|
||||
" if (!xpc_qsStringToJsstring(cx, result, &rval)) {\n"
|
||||
" JS_ReportOutOfMemory(cx);\n${errorStr}"
|
||||
" return rval;\n"
|
||||
}
|
||||
|
||||
def writeTraceableResultConv(f, type):
|
||||
typeName = getBuiltinOrNativeTypeName(type)
|
||||
assert typeName is not '[jsval]'
|
||||
if typeName is not None:
|
||||
template = traceableResultConvTemplates.get(typeName)
|
||||
if template is not None:
|
||||
values = { 'errorStr': getFailureString(
|
||||
getTraceInfoDefaultReturn(type), 2) }
|
||||
f.write(substitute(template, values))
|
||||
return
|
||||
# else fall through; this type isn't supported yet
|
||||
elif isInterfaceType(type):
|
||||
if isVariantType(type):
|
||||
f.write(" jsval returnVal;\n"
|
||||
" JSBool ok = xpc_qsVariantToJsval(lccx, result, "
|
||||
"&returnVal);\n")
|
||||
else:
|
||||
f.write(" if (!result) {\n"
|
||||
" return nsnull;\n"
|
||||
" }\n"
|
||||
" nsWrapperCache* cache = xpc_qsGetWrapperCache(result);\n"
|
||||
" JSObject* wrapper =\n"
|
||||
" xpc_FastGetCachedWrapper(cache, obj);\n"
|
||||
" if (wrapper) {\n"
|
||||
" return wrapper;\n"
|
||||
" }\n"
|
||||
" // After this point do not use 'result'!\n"
|
||||
" qsObjectHelper helper(result, cache);\n"
|
||||
" jsval returnVal;\n"
|
||||
" JSBool ok = xpc_qsXPCOMObjectToJsval(lccx, "
|
||||
"helper, &NS_GET_IID(%s), &interfaces[k_%s], "
|
||||
"&returnVal);\n"
|
||||
% (type.name, type.name))
|
||||
f.write(" if (!ok) {\n");
|
||||
writeFailure(f, getTraceInfoDefaultReturn(type), 2)
|
||||
f.write(" return JSVAL_TO_OBJECT(returnVal);\n")
|
||||
return
|
||||
|
||||
warn("Unable to convert result of type %s" % typeName)
|
||||
f.write(" !; // TODO - Convert `result` to jsval, store in rval.\n")
|
||||
f.write(" return xpc_qsThrow(cx, NS_ERROR_UNEXPECTED); // FIXME\n")
|
||||
|
||||
def writeTraceableQuickStub(f, customMethodCalls, member, stubName):
|
||||
assert member.traceable
|
||||
|
||||
traceInfo = {
|
||||
'type': getTraceInfoReturnType(member.realtype) + "_FAIL",
|
||||
'params': ["CONTEXT", "THIS"]
|
||||
}
|
||||
|
||||
haveCcx = memberNeedsCcx(member)
|
||||
|
||||
customMethodCall = customMethodCalls.get(stubName, None)
|
||||
|
||||
if customMethodCall is None:
|
||||
customMethodCall = customMethodCalls.get(member.iface.name + '_', None)
|
||||
if customMethodCall is not None:
|
||||
# We don't support traceable templated quickstubs yet
|
||||
assert not 'code' in customMethodCall
|
||||
|
||||
if customMethodCall is not None and customMethodCall.get('skipgen', False):
|
||||
return
|
||||
if (customMethodCall is not None and
|
||||
not customMethodCall.get('unwrapThisFailureFatal', True)):
|
||||
raise UserError(member.iface.name + '.' + member.name + ": "
|
||||
"Unwrapping this failure must be fatal for traceable stubs")
|
||||
|
||||
# Write the function
|
||||
f.write("static %sFASTCALL\n" % getTraceReturnType(member.realtype))
|
||||
f.write("%s(JSContext *cx, JSObject *obj" % (stubName + "_tn"))
|
||||
# This code MUST match the arguments length check in addStubMember
|
||||
if memberNeedsCallee(member):
|
||||
f.write(", JSObject *callee")
|
||||
traceInfo["params"].append("CALLEE")
|
||||
for i, param in enumerate(member.params):
|
||||
f.write(", %s_arg%d" % (getTraceParamType(param.realtype), i))
|
||||
traceInfo["params"].append(getTraceInfoParamType(param.realtype))
|
||||
f.write(")\n{\n");
|
||||
f.write(" XPC_QS_ASSERT_CONTEXT_OK(cx);\n")
|
||||
|
||||
# Create ccx if needed.
|
||||
if haveCcx:
|
||||
f.write(" XPCCallContext ccx(JS_CALLER, cx, obj, callee);\n")
|
||||
if isInterfaceType(member.realtype):
|
||||
f.write(" XPCLazyCallContext lccx(ccx);\n")
|
||||
|
||||
# Get the 'self' pointer.
|
||||
if customMethodCall is None or not 'thisType' in customMethodCall:
|
||||
f.write(" %s *self;\n" % member.iface.name)
|
||||
else:
|
||||
f.write(" %s *self;\n" % customMethodCall['thisType'])
|
||||
f.write(" xpc_qsSelfRef selfref;\n")
|
||||
f.write(" JS::Anchor<jsval> selfanchor;\n")
|
||||
if haveCcx:
|
||||
f.write(" if (!xpc_qsUnwrapThisFromCcx(ccx, &self, &selfref.ptr, "
|
||||
"&selfanchor.get())) {\n")
|
||||
elif (member.kind == 'method') and isInterfaceType(member.realtype):
|
||||
f.write(" XPCLazyCallContext lccx(JS_CALLER, cx, obj);\n")
|
||||
f.write(" if (!xpc_qsUnwrapThis(cx, obj, callee, &self, &selfref.ptr, "
|
||||
"&selfanchor.get(), &lccx)) {\n")
|
||||
else:
|
||||
f.write(" if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, "
|
||||
"&selfanchor.get(), nsnull)) {\n")
|
||||
writeFailure(f, getTraceInfoDefaultReturn(member.realtype), 2)
|
||||
|
||||
argNames = []
|
||||
|
||||
# Convert in-parameters.
|
||||
rvdeclared = False
|
||||
for i, param in enumerate(member.params):
|
||||
argName = "arg%d" % i
|
||||
argTypeKey = argName + 'Type'
|
||||
if customMethodCall is None or not argTypeKey in customMethodCall:
|
||||
validateParam(member, param)
|
||||
realtype = unaliasType(param.realtype)
|
||||
else:
|
||||
realtype = xpidl.Forward(name=customMethodCall[argTypeKey],
|
||||
location='', doccomments='')
|
||||
rvdeclared = writeTraceableArgumentConversion(f, member, i, argName,
|
||||
realtype, haveCcx,
|
||||
rvdeclared)
|
||||
argNames.append(argName)
|
||||
|
||||
canFail = customMethodCall is None or customMethodCall.get('canFail', True)
|
||||
if canFail and not rvdeclared:
|
||||
f.write(" nsresult rv;\n")
|
||||
rvdeclared = True
|
||||
|
||||
if customMethodCall is not None and 'code' in customMethodCall:
|
||||
f.write("%s\n" % customMethodCall['code'])
|
||||
else:
|
||||
prefix = ''
|
||||
|
||||
resultname = prefix + 'result'
|
||||
selfname = prefix + 'self'
|
||||
nsresultname = prefix + 'rv'
|
||||
|
||||
# Prepare out-parameter.
|
||||
writeResultDecl(f, member.realtype, resultname)
|
||||
|
||||
# Call the method.
|
||||
comName = header.methodNativeName(member)
|
||||
if not isVoidType(member.realtype):
|
||||
argNames.append(outParamForm(resultname, member.realtype))
|
||||
args = ', '.join(argNames)
|
||||
|
||||
f.write(" ")
|
||||
if canFail:
|
||||
f.write("%s = " % nsresultname)
|
||||
f.write("%s->%s(%s);\n" % (selfname, comName, args))
|
||||
|
||||
if canFail:
|
||||
# Check for errors.
|
||||
f.write(" if (NS_FAILED(rv)) {\n")
|
||||
if haveCcx:
|
||||
f.write(" xpc_qsThrowMethodFailedWithCcx(ccx, rv);\n")
|
||||
else:
|
||||
# XXX Replace with a real error message!
|
||||
f.write(" xpc_qsThrowMethodFailedWithDetails(cx, rv, "
|
||||
"\"%s\", \"%s\");\n" % (member.iface.name, member.name))
|
||||
writeFailure(f, getTraceInfoDefaultReturn(member.realtype), 2)
|
||||
|
||||
# Convert the return value.
|
||||
writeTraceableResultConv(f, member.realtype)
|
||||
|
||||
# Epilog.
|
||||
f.write("}\n\n")
|
||||
|
||||
# Write the JS_DEFINE_TRCINFO block
|
||||
f.write("JS_DEFINE_TRCINFO_1(%s,\n" % stubName)
|
||||
f.write(" (%d, (static, %s, %s, %s, 0, nanojit::ACCSET_STORE_ANY)))\n\n"
|
||||
% (len(traceInfo["params"]), traceInfo["type"], stubName + "_tn",
|
||||
", ".join(traceInfo["params"])))
|
||||
|
||||
def writeAttrStubs(f, customMethodCalls, attr):
|
||||
cmc = customMethodCalls.get(attr.iface.name + "_" + header.methodNativeName(attr), None)
|
||||
custom = cmc and cmc.get('skipgen', False)
|
||||
|
@ -1518,18 +1096,13 @@ def writeStubsForInterface(f, customMethodCalls, iface):
|
|||
f.write("// === interface %s\n\n" % iface.name)
|
||||
propspecs = []
|
||||
funcspecs = []
|
||||
tracespecs = []
|
||||
for member in iface.stubMembers:
|
||||
if member.kind == 'attribute':
|
||||
ps = writeAttrStubs(f, customMethodCalls, member)
|
||||
propspecs.append(ps)
|
||||
elif member.kind == 'method':
|
||||
fs = writeMethodStub(f, customMethodCalls, member)
|
||||
if member.traceable:
|
||||
ts = writeTraceableStub(f, customMethodCalls, member)
|
||||
tracespecs.append(ts)
|
||||
else:
|
||||
funcspecs.append(fs)
|
||||
funcspecs.append(fs)
|
||||
else:
|
||||
raise TypeError('expected attribute or method, not %r'
|
||||
% member.__class__.__name__)
|
||||
|
@ -1545,11 +1118,6 @@ def writeStubsForInterface(f, customMethodCalls, iface):
|
|||
for fs in funcspecs:
|
||||
f.write(" %s,\n" % fs)
|
||||
f.write(" {nsnull}};\n")
|
||||
if tracespecs:
|
||||
f.write("static const xpc_qsTraceableSpec %s_traceables[] = {\n" % iface.name)
|
||||
for ts in tracespecs:
|
||||
f.write(" %s,\n" % ts)
|
||||
f.write(" {nsnull}};\n")
|
||||
f.write('\n\n')
|
||||
|
||||
def hashIID(iid):
|
||||
|
@ -1610,7 +1178,7 @@ def writeDefiner(f, conf, interfaces):
|
|||
arraySize += 1
|
||||
|
||||
entries = [" {{0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}, "
|
||||
"nsnull, nsnull, nsnull, XPC_QS_NULL_INDEX, XPC_QS_NULL_INDEX}"
|
||||
"nsnull, nsnull, XPC_QS_NULL_INDEX, XPC_QS_NULL_INDEX}"
|
||||
for i in range(arraySize)]
|
||||
for i, bucket in enumerate(buckets):
|
||||
for j, iface in enumerate(bucket):
|
||||
|
@ -1628,24 +1196,16 @@ def writeDefiner(f, conf, interfaces):
|
|||
properties = "nsnull"
|
||||
for member in iface.stubMembers:
|
||||
if member.kind == 'attribute':
|
||||
assert not member.traceable
|
||||
properties = iface.name + "_properties"
|
||||
break
|
||||
|
||||
# member field
|
||||
functions = "nsnull"
|
||||
for member in iface.stubMembers:
|
||||
if member.kind == 'method' and not member.traceable:
|
||||
if member.kind == 'method':
|
||||
functions = iface.name + "_functions"
|
||||
break
|
||||
|
||||
# traceables field
|
||||
traceables = "nsnull"
|
||||
for member in iface.stubMembers:
|
||||
if member.traceable:
|
||||
traceables = iface.name + "_traceables"
|
||||
break
|
||||
|
||||
# parentInterface field
|
||||
baseName = iface.base
|
||||
while baseName is not None:
|
||||
|
@ -1666,8 +1226,8 @@ def writeDefiner(f, conf, interfaces):
|
|||
chain = str(k)
|
||||
|
||||
# add entry
|
||||
entry = " {%s, %s, %s, %s, %s, %s}" % (
|
||||
iid, properties, functions, traceables, parentInterface, chain)
|
||||
entry = " {%s, %s, %s, %s, %s}" % (
|
||||
iid, properties, functions, parentInterface, chain)
|
||||
entries[entryIndexes[iface.attributes.uuid]] = entry
|
||||
|
||||
f.write("static const xpc_qsHashEntry tableData[] = {\n")
|
||||
|
@ -1688,11 +1248,6 @@ stubTopTemplate = '''\
|
|||
/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
/* Include nanojit.h early to avoid conflicting with nscore's |#define free|.
|
||||
* NB: needs to be kept in sync with jsbuiltins.h */
|
||||
#ifdef JS_TRACER
|
||||
# include "nanojit/nanojit.h"
|
||||
#endif
|
||||
#include "qsWinUndefs.h"
|
||||
#include "prtypes.h"
|
||||
#include "nsID.h"
|
||||
|
@ -1703,7 +1258,6 @@ stubTopTemplate = '''\
|
|||
#include "xpcprivate.h" // for XPCCallContext
|
||||
#include "XPCQuickStubs.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "jsbuiltins.h"
|
||||
'''
|
||||
|
||||
def writeStubFile(filename, headerFilename, conf, interfaces):
|
||||
|
@ -1796,8 +1350,6 @@ def main():
|
|||
help="Directory in which to cache lex/parse tables.")
|
||||
o.add_option("--verbose-errors", action='store_true', default=False,
|
||||
help="When an error happens, display the Python traceback.")
|
||||
o.add_option("--enable-traceables", action='store_true', default=False,
|
||||
help="Whether or not traceable methods are generated.")
|
||||
(options, filenames) = o.parse_args()
|
||||
|
||||
if len(filenames) != 1:
|
||||
|
@ -1822,8 +1374,7 @@ def main():
|
|||
includePath = options.idlpath.split(':')
|
||||
conf, interfaces = readConfigFile(filename,
|
||||
includePath=includePath,
|
||||
cachedir=options.cachedir,
|
||||
traceable=options.enable_traceables)
|
||||
cachedir=options.cachedir)
|
||||
writeHeaderFile(options.header_output, conf.name)
|
||||
writeStubFile(options.stub_output, options.header_output,
|
||||
conf, interfaces)
|
||||
|
|
|
@ -223,12 +223,6 @@ struct CompartmentStats
|
|||
PRInt64 mjitCodeRegexp;
|
||||
PRInt64 mjitCodeUnused;
|
||||
PRInt64 mjitData;
|
||||
#endif
|
||||
#ifdef JS_TRACER
|
||||
PRInt64 tjitCode;
|
||||
PRInt64 tjitDataAllocatorsMain;
|
||||
PRInt64 tjitDataAllocatorsReserve;
|
||||
PRInt64 tjitDataNonAllocators;
|
||||
#endif
|
||||
TypeInferenceMemoryStats typeInferenceMemory;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче