зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1118978 part 1. Introduce "Affects" and "DependsOn" state for IDL attributes and operations and desugar [Pure] and [Constant] into that state. r=peterv
This does not change the generated binding code in any way for our existing IDL files.
This commit is contained in:
Родитель
94ea67ad55
Коммит
cb9b43858f
|
@ -10,7 +10,7 @@ import string
|
|||
import math
|
||||
import textwrap
|
||||
|
||||
from WebIDL import BuiltinTypes, IDLBuiltinType, IDLNullValue, IDLSequenceType, IDLType, IDLAttribute, IDLUndefinedValue, IDLEmptySequenceValue, IDLDictionary
|
||||
from WebIDL import BuiltinTypes, IDLBuiltinType, IDLNullValue, IDLSequenceType, IDLType, IDLAttribute, IDLInterfaceMember, IDLUndefinedValue, IDLEmptySequenceValue, IDLDictionary
|
||||
from Configuration import NoSuchDescriptorError, getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback, getAllTypes, Descriptor
|
||||
|
||||
AUTOGENERATED_WARNING_COMMENT = \
|
||||
|
@ -2114,8 +2114,7 @@ def clearableCachedAttrs(descriptor):
|
|||
return (m for m in descriptor.interface.members if
|
||||
m.isAttr() and
|
||||
# Constants should never need clearing!
|
||||
not m.getExtendedAttribute("Constant") and
|
||||
not m.getExtendedAttribute("SameObject") and
|
||||
m.dependsOn != "Nothing" and
|
||||
m.slotIndex is not None)
|
||||
|
||||
def MakeClearCachedValueNativeName(member):
|
||||
|
@ -8080,16 +8079,9 @@ class CGMemberJITInfo(CGThing):
|
|||
getter = ("(JSJitGetterOp)get_%s" %
|
||||
IDLToCIdentifier(self.member.identifier.name))
|
||||
getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True)
|
||||
getterconst = (self.member.getExtendedAttribute("SameObject") or
|
||||
self.member.getExtendedAttribute("Constant"))
|
||||
getterpure = getterconst or self.member.getExtendedAttribute("Pure")
|
||||
if getterconst:
|
||||
aliasSet = "AliasNone"
|
||||
elif getterpure:
|
||||
aliasSet = "AliasDOMSets"
|
||||
else:
|
||||
aliasSet = "AliasEverything"
|
||||
movable = getterpure and getterinfal
|
||||
|
||||
movable = self.mayBeMovable() and getterinfal
|
||||
aliasSet = self.aliasSet()
|
||||
|
||||
getterinfal = getterinfal and infallibleForMember(self.member, self.member.type, self.descriptor)
|
||||
isAlwaysInSlot = self.member.getExtendedAttribute("StoreInSlot")
|
||||
|
@ -8134,7 +8126,6 @@ class CGMemberJITInfo(CGThing):
|
|||
name = CGMethodPromiseWrapper.makeName(name)
|
||||
# Actually a JSJitMethodOp, but JSJitGetterOp is first in the union.
|
||||
method = ("(JSJitGetterOp)%s" % name)
|
||||
methodPure = self.member.getExtendedAttribute("Pure")
|
||||
|
||||
# Methods are infallible if they are infallible, have no arguments
|
||||
# to unwrap, and have a return type that's infallible to wrap up for
|
||||
|
@ -8148,13 +8139,13 @@ class CGMemberJITInfo(CGThing):
|
|||
movable = False
|
||||
else:
|
||||
sig = sigs[0]
|
||||
# For pure methods, it's OK to set movable to our notion of
|
||||
# infallible on the C++ side, without considering argument
|
||||
# conversions, since argument conversions that can reliably
|
||||
# throw would be effectful anyway and the jit doesn't move
|
||||
# effectful things.
|
||||
# For methods that affect nothing, it's OK to set movable to our
|
||||
# notion of infallible on the C++ side, without considering
|
||||
# argument conversions, since argument conversions that can
|
||||
# reliably throw would be effectful anyway and the jit doesn't
|
||||
# move effectful things.
|
||||
hasInfallibleImpl = "infallible" in self.descriptor.getExtendedAttributes(self.member)
|
||||
movable = methodPure and hasInfallibleImpl
|
||||
movable = self.mayBeMovable() and hasInfallibleImpl
|
||||
# XXXbz can we move the smarts about fallibility due to arg
|
||||
# conversions into the JIT, using our new args stuff?
|
||||
if (len(sig[1]) != 0 or
|
||||
|
@ -8163,16 +8154,13 @@ class CGMemberJITInfo(CGThing):
|
|||
methodInfal = False
|
||||
else:
|
||||
methodInfal = hasInfallibleImpl
|
||||
# For now, only bother to output args if we're pure
|
||||
if methodPure:
|
||||
# For now, only bother to output args if we're side-effect-free.
|
||||
if self.member.affects == "Nothing":
|
||||
args = sig[1]
|
||||
else:
|
||||
args = None
|
||||
|
||||
if args is not None:
|
||||
aliasSet = "AliasDOMSets"
|
||||
else:
|
||||
aliasSet = "AliasEverything"
|
||||
aliasSet = self.aliasSet()
|
||||
result = self.defineJitInfo(methodinfo, method, "Method",
|
||||
methodInfal, movable, aliasSet,
|
||||
False, False, "0",
|
||||
|
@ -8180,6 +8168,37 @@ class CGMemberJITInfo(CGThing):
|
|||
return result
|
||||
raise TypeError("Illegal member type to CGPropertyJITInfo")
|
||||
|
||||
def mayBeMovable(self):
|
||||
"""
|
||||
Returns whether this attribute or method may be movable, just
|
||||
based on Affects/DependsOn annotations.
|
||||
"""
|
||||
affects = self.member.affects
|
||||
dependsOn = self.member.dependsOn
|
||||
assert affects in IDLInterfaceMember.AffectsValues
|
||||
assert dependsOn in IDLInterfaceMember.DependsOnValues
|
||||
return affects == "Nothing" and dependsOn != "Everything"
|
||||
|
||||
def aliasSet(self):
|
||||
"""Returns the alias set to store in the jitinfo. This may not be the
|
||||
effective alias set the JIT uses, depending on whether we have enough
|
||||
information about our args to allow the JIT to prove that effectful
|
||||
argument conversions won't happen.
|
||||
|
||||
"""
|
||||
dependsOn = self.member.dependsOn
|
||||
assert dependsOn in IDLInterfaceMember.DependsOnValues
|
||||
|
||||
if dependsOn == "Nothing":
|
||||
assert self.member.affects == "Nothing"
|
||||
return "AliasNone"
|
||||
|
||||
if dependsOn == "DOMState":
|
||||
assert self.member.affects == "Nothing"
|
||||
return "AliasDOMSets"
|
||||
|
||||
return "AliasEverything"
|
||||
|
||||
@staticmethod
|
||||
def getJSReturnTypeTag(t):
|
||||
if t.nullable():
|
||||
|
|
|
@ -3043,6 +3043,9 @@ class IDLInterfaceMember(IDLObjectWithIdentifier):
|
|||
'Stringifier'
|
||||
)
|
||||
|
||||
AffectsValues = ("Nothing", "Everything")
|
||||
DependsOnValues = ("Nothing", "DOMState", "Everything")
|
||||
|
||||
def __init__(self, location, identifier, tag):
|
||||
IDLObjectWithIdentifier.__init__(self, location, None, identifier)
|
||||
self.tag = tag
|
||||
|
@ -3097,6 +3100,22 @@ class IDLInterfaceMember(IDLObjectWithIdentifier):
|
|||
self._scope.primaryGlobalName,
|
||||
[self.location])
|
||||
|
||||
def _setDependsOn(self, dependsOn):
|
||||
if self.dependsOn != "Everything":
|
||||
raise WebIDLError("Trying to specify multiple different "
|
||||
"Pure, or Constant extended attributes for "
|
||||
"attribute", [self.location])
|
||||
assert dependsOn in IDLInterfaceMember.DependsOnValues:
|
||||
self.dependsOn = dependsOn
|
||||
|
||||
def _setAffects(self, affects):
|
||||
if self.affects != "Everything":
|
||||
raise WebIDLError("Trying to specify multiple different "
|
||||
"Pure, or Constant extended attributes for "
|
||||
"attribute", [self.location])
|
||||
assert affects in IDLInterfaceMember.AffectsValues:
|
||||
self.affects = affects
|
||||
|
||||
class IDLConst(IDLInterfaceMember):
|
||||
def __init__(self, location, identifier, type, value):
|
||||
IDLInterfaceMember.__init__(self, location, identifier,
|
||||
|
@ -3175,6 +3194,8 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
self.enforceRange = False
|
||||
self.clamp = False
|
||||
self.slotIndex = None
|
||||
self.dependsOn = "Everything"
|
||||
self.affects = "Everything"
|
||||
|
||||
if static and identifier.name == "prototype":
|
||||
raise WebIDLError("The identifier of a static attribute must not be 'prototype'",
|
||||
|
@ -3243,10 +3264,9 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
|
||||
if ((self.getExtendedAttribute("Cached") or
|
||||
self.getExtendedAttribute("StoreInSlot")) and
|
||||
not self.getExtendedAttribute("Constant") and
|
||||
not self.getExtendedAttribute("Pure")):
|
||||
not self.affects == "Nothing"):
|
||||
raise WebIDLError("Cached attributes and attributes stored in "
|
||||
"slots must be constant or pure, since the "
|
||||
"slots must be Constant or Pure, since the "
|
||||
"getter won't always be called.",
|
||||
[self.location])
|
||||
if self.getExtendedAttribute("Frozen"):
|
||||
|
@ -3372,14 +3392,23 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
[attr.location, self.location])
|
||||
elif identifier == "Exposed":
|
||||
convertExposedAttrToGlobalNameSet(attr, self._exposureGlobalNames)
|
||||
elif identifier == "Pure":
|
||||
if not attr.noArguments():
|
||||
raise WebIDLError("[Pure] must take no arguments",
|
||||
[attr.location])
|
||||
self._setDependsOn("DOMState")
|
||||
self._setAffects("Nothing")
|
||||
elif identifier == "Constant" or identifier == "SameObject":
|
||||
if not attr.noArguments():
|
||||
raise WebIDLError("[%s] must take no arguments" % identifier,
|
||||
[attr.location])
|
||||
self._setDependsOn("Nothing")
|
||||
self._setAffects("Nothing")
|
||||
elif (identifier == "Pref" or
|
||||
identifier == "SetterThrows" or
|
||||
identifier == "Pure" or
|
||||
identifier == "Throws" or
|
||||
identifier == "GetterThrows" or
|
||||
identifier == "ChromeOnly" or
|
||||
identifier == "SameObject" or
|
||||
identifier == "Constant" or
|
||||
identifier == "Func" or
|
||||
identifier == "Frozen" or
|
||||
identifier == "AvailableIn" or
|
||||
|
@ -3663,6 +3692,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
self._jsonifier = jsonifier
|
||||
self._specialType = specialType
|
||||
self._unforgeable = False
|
||||
self.dependsOn = "Everything"
|
||||
self.affects = "Everything"
|
||||
|
||||
if static and identifier.name == "prototype":
|
||||
raise WebIDLError("The identifier of a static operation must not be 'prototype'",
|
||||
|
@ -3974,13 +4005,18 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
[attr.location, self.location])
|
||||
elif identifier == "Exposed":
|
||||
convertExposedAttrToGlobalNameSet(attr, self._exposureGlobalNames)
|
||||
elif (identifier == "Pure" or
|
||||
identifier == "CrossOriginCallable" or
|
||||
elif (identifier == "CrossOriginCallable" or
|
||||
identifier == "WebGLHandlesContextLoss"):
|
||||
# Known no-argument attributes.
|
||||
if not attr.noArguments():
|
||||
raise WebIDLError("[%s] must take no arguments" % identifier,
|
||||
[attr.location])
|
||||
elif identifier == "Pure":
|
||||
if not attr.noArguments():
|
||||
raise WebIDLError("[Pure] must take no arguments",
|
||||
[attr.location])
|
||||
self._setDependsOn("DOMState")
|
||||
self._setAffects("Nothing")
|
||||
elif (identifier == "Throws" or
|
||||
identifier == "NewObject" or
|
||||
identifier == "ChromeOnly" or
|
||||
|
|
Загрузка…
Ссылка в новой задаче