[gjs: 1/2] object: Avoid looking up predefined methods in GI
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs: 1/2] object: Avoid looking up predefined methods in GI
- Date: Thu, 8 Nov 2018 03:49:05 +0000 (UTC)
commit b95e9a1f374b921f6ff867e0f971bc4f704cb50d
Author: Colin Walters <walters verbum org>
Date: Tue Oct 19 06:13:24 2010 -0700
object: Avoid looking up predefined methods in GI
SpiderMonkey will call the property resolve operation every time we
try to call one of the predefined override functions like "emit".
This is particularly problematic because the code to loop over
interfaces for a given class is hit badly by introspections' lack
of indexing in the typelib directory.
Concretely, every time we were calling foo.emit("blah", param), we'd scan
typelibs multiple times (e.g. for an object implementing an interface in
both Atk and Gtk).
Sadly, because of methods like Gio.Cancellable.connect(), we can't do the
same thing for "connect()" which is probably the worst case.
(Patch originally by Colin Walters, rewritten by Philip Chimento)
Closes #54.
gi/object.cpp | 18 ++++++++++++++++++
gjs/atoms.h | 2 ++
2 files changed, 20 insertions(+)
---
diff --git a/gi/object.cpp b/gi/object.cpp
index fcc58be4..d98419c5 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -838,10 +838,28 @@ bool ObjectBase::resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
return priv->to_prototype()->resolve_impl(cx, obj, id, resolved);
}
+/* The JSResolveOp for an instance is called for every property not
+ * defined, even if it's one of the functions or properties we're
+ * adding to the proto manually.
+ */
+static bool name_is_overridden(jsid name, const GjsAtoms& atoms) {
+ // Keep this list in sync with gjs_object_instance_proto_props and
+ // gjs_object_instance_proto_funcs. However, explicitly do not include
+ // connect() in it, because there are a few cases where the lazy property
+ // should override the predefined one, such as Gio.Cancellable.connect().
+ return name == atoms.init() || name == atoms.connect_after() ||
+ name == atoms.emit() || name == atoms.to_string();
+}
+
bool ObjectPrototype::resolve_impl(JSContext* context, JS::HandleObject obj,
JS::HandleId id, bool* resolved) {
debug_jsprop("Resolve hook", id, obj);
+ if (name_is_overridden(id, GjsContextPrivate::atoms(context))) {
+ *resolved = false;
+ return true;
+ }
+
JS::UniqueChars name;
if (!gjs_get_string_id(context, id, &name))
return false;
diff --git a/gjs/atoms.h b/gjs/atoms.h
index 674a2289..ed8e4fe7 100644
--- a/gjs/atoms.h
+++ b/gjs/atoms.h
@@ -32,8 +32,10 @@
#define FOR_EACH_ATOM(macro) \
macro(code, "code") \
macro(column_number, "columnNumber") \
+ macro(connect_after, "connect_after") \
macro(constructor, "constructor") \
macro(debuggee, "debuggee") \
+ macro(emit, "emit") \
macro(file, "__file__") \
macro(file_name, "fileName") \
macro(gi, "gi") \
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]