Bug 872669. Slightly speed up our named proxy gets by making use of the inline chars/length getters we can have when our id is an atom. r=waldo,peterv
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -6664,31 +6664,56 @@ class CGProxyNamedOperation(CGProxySpeci
"""
Class to generate a call to a named operation.
'value' is the jsval to use for the name; None indicates that it should be
gotten from the property id.
"""
def __init__(self, descriptor, name, value=None):
CGProxySpecialOperation.__init__(self, descriptor, name)
- if value is None:
- value = "js::IdToValue(id)"
self.value = value
def define(self):
# Our first argument is the id we're getting.
argName = self.arguments[0].identifier.name
- return (("JS::Rooted<JS::Value> nameVal(cx, %s);\n"
- "FakeDependentString %s;\n"
- "if (!ConvertJSValueToString(cx, nameVal, &nameVal,\n"
- " eStringify, eStringify, %s)) {\n"
- " return false;\n"
- "}\n"
+ if argName == "id":
+ # deal with the name collision
+ idDecl = "JS::Rooted<jsid> id_(cx, id);\n"
+ idName = "id_"
+ else:
+ idDecl = ""
+ idName = "id"
+ unwrapString = (
+ "if (!ConvertJSValueToString(cx, nameVal, &nameVal,\n"
+ " eStringify, eStringify, %s)) {\n"
+ " return false;\n"
+ "}" % argName)
+ if self.value is None:
+ # We're just using 'id', and if it's an atom we can take a
+ # fast path here.
+ unwrapString = CGIfElseWrapper(
+ ("MOZ_LIKELY(JSID_IS_ATOM(%s))" % idName),
+ CGGeneric(
+ "%s.SetData(js::GetAtomChars(JSID_TO_ATOM(%s)), js::GetAtomLength(JSID_TO_ATOM(%s)));" % (argName, idName, idName)),
+ CGGeneric(("nameVal = js::IdToValue(%s);\n" % idName) +
+ unwrapString)).define()
+ else:
+ unwrapString = ("nameVal = %s;\n" % self.value) + unwrapString
+
+ # Sadly, we have to set up nameVal even if we have an atom id,
+ # because we don't know for sure, and we can end up needing it
+ # so it needs to be higher up the stack. Using a Maybe here
+ # seems like probable overkill.
+ return ("JS::Rooted<JS::Value> nameVal(cx);\n" +
+ idDecl +
+ ("FakeDependentString %s;\n" % argName) +
+ unwrapString +
+ ("\n"
"\n"
"%s* self = UnwrapProxy(proxy);\n" %
- (self.value, argName, argName, self.descriptor.nativeType)) +
+ self.descriptor.nativeType) +
CGProxySpecialOperation.define(self))
class CGProxyNamedGetter(CGProxyNamedOperation):
"""
Class to generate a call to an named getter. If templateValues is not None
the returned value will be wrapped with wrapForType using templateValues.
'value' is the jsval to use for the name; None indicates that it should be
gotten from the property id.
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -364,17 +364,18 @@ struct Function {
uint16_t flags;
/* Used only for natives */
Native native;
const JSJitInfo *jitinfo;
void *_1;
};
struct Atom {
- size_t _;
+ static const size_t LENGTH_SHIFT = 4;
+ size_t lengthAndFlags;
const jschar *chars;
};
} /* namespace shadow */
extern JS_FRIEND_DATA(js::Class) CallClass;
extern JS_FRIEND_DATA(js::Class) DeclEnvClass;
extern JS_FRIEND_DATA(js::Class) FunctionClass;
@@ -538,16 +539,23 @@ GetObjectSlot(JSObject *obj, size_t slot
}
inline const jschar *
GetAtomChars(JSAtom *atom)
{
return reinterpret_cast<shadow::Atom *>(atom)->chars;
}
+inline size_t
+GetAtomLength(JSAtom *atom)
+{
+ using shadow::Atom;
+ return reinterpret_cast<Atom*>(atom)->lengthAndFlags >> Atom::LENGTH_SHIFT;
+}
+
inline JSLinearString *
AtomToLinearString(JSAtom *atom)
{
return reinterpret_cast<JSLinearString *>(atom);
}
static inline js::PropertyOp
CastAsJSPropertyOp(JSObject *object)