Bug 1867190 - Add prefs for PHC probablities r=glandium
[gecko.git] / js / src / vm / Watchtower.h
blobec944ce24202794da4ed6bd39b4db8c2ca04c8bb
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef vm_Watchtower_h
8 #define vm_Watchtower_h
10 #include "js/TypeDecls.h"
11 #include "vm/NativeObject.h"
13 namespace js {
15 // [SMDOC] Watchtower
17 // Watchtower is a framework to hook into changes to certain objects. This gives
18 // us the ability to, for instance, invalidate caches or purge Warp code on
19 // object layout changes.
21 // Watchtower is only used for objects with certain ObjectFlags set on the
22 // Shape. This minimizes performance overhead for most objects.
24 // We currently use Watchtower for:
26 // - Invalidating the shape teleporting optimization. See the "Shape Teleporting
27 // Optimization" SMDOC comment in CacheIR.cpp.
29 // - Invalidating the MegamorphicCache, a property lookup cache for megamorphic
30 // property accesses. See the SMDOC comment in vm/Caches.h.
32 // There's also a testing mechanism that lets us write tests for Watchtower
33 // hooks. See setWatchtowerCallback and addWatchtowerTarget defined in
34 // TestingFunctions.cpp.
35 class Watchtower {
36 static bool watchPropertyAddSlow(JSContext* cx, Handle<NativeObject*> obj,
37 HandleId id);
38 static bool watchPropertyRemoveSlow(JSContext* cx, Handle<NativeObject*> obj,
39 HandleId id);
40 static bool watchPropertyChangeSlow(JSContext* cx, Handle<NativeObject*> obj,
41 HandleId id, PropertyFlags flags);
42 template <AllowGC allowGC>
43 static bool watchPropertyModificationSlow(
44 JSContext* cx,
45 typename MaybeRooted<NativeObject*, allowGC>::HandleType obj,
46 typename MaybeRooted<PropertyKey, allowGC>::HandleType id);
47 static bool watchFreezeOrSealSlow(JSContext* cx, Handle<NativeObject*> obj);
48 static bool watchProtoChangeSlow(JSContext* cx, HandleObject obj);
49 static bool watchObjectSwapSlow(JSContext* cx, HandleObject a,
50 HandleObject b);
52 public:
53 static bool watchesPropertyAdd(NativeObject* obj) {
54 return obj->hasAnyFlag(
55 {ObjectFlag::IsUsedAsPrototype, ObjectFlag::UseWatchtowerTestingLog});
57 static bool watchesPropertyRemove(NativeObject* obj) {
58 return obj->hasAnyFlag(
59 {ObjectFlag::IsUsedAsPrototype, ObjectFlag::GenerationCountedGlobal,
60 ObjectFlag::UseWatchtowerTestingLog, ObjectFlag::HasFuseProperty});
62 static bool watchesPropertyChange(NativeObject* obj) {
63 return obj->hasAnyFlag(
64 {ObjectFlag::IsUsedAsPrototype, ObjectFlag::GenerationCountedGlobal,
65 ObjectFlag::HasFuseProperty, ObjectFlag::UseWatchtowerTestingLog});
67 static bool watchesPropertyModification(NativeObject* obj) {
68 return obj->hasAnyFlag(
69 {ObjectFlag::HasFuseProperty, ObjectFlag::UseWatchtowerTestingLog});
71 static bool watchesFreezeOrSeal(NativeObject* obj) {
72 return obj->hasAnyFlag({ObjectFlag::UseWatchtowerTestingLog});
74 static bool watchesProtoChange(JSObject* obj) {
75 return obj->hasAnyFlag(
76 {ObjectFlag::IsUsedAsPrototype, ObjectFlag::UseWatchtowerTestingLog});
78 static bool watchesObjectSwap(JSObject* a, JSObject* b) {
79 auto watches = [](JSObject* obj) {
80 return obj->hasAnyFlag(
81 {ObjectFlag::IsUsedAsPrototype, ObjectFlag::UseWatchtowerTestingLog});
83 return watches(a) || watches(b);
86 static bool watchPropertyAdd(JSContext* cx, Handle<NativeObject*> obj,
87 HandleId id) {
88 if (MOZ_LIKELY(!watchesPropertyAdd(obj))) {
89 return true;
91 return watchPropertyAddSlow(cx, obj, id);
93 static bool watchPropertyRemove(JSContext* cx, Handle<NativeObject*> obj,
94 HandleId id) {
95 if (MOZ_LIKELY(!watchesPropertyRemove(obj))) {
96 return true;
98 return watchPropertyRemoveSlow(cx, obj, id);
100 static bool watchPropertyChange(JSContext* cx, Handle<NativeObject*> obj,
101 HandleId id, PropertyFlags flags) {
102 if (MOZ_LIKELY(!watchesPropertyChange(obj))) {
103 return true;
105 return watchPropertyChangeSlow(cx, obj, id, flags);
108 // Note: We can only watch property modification for regular object slots
109 // with an id, not reserved slots.
110 template <AllowGC allowGC>
111 static bool watchPropertyModification(
112 JSContext* cx,
113 typename MaybeRooted<NativeObject*, allowGC>::HandleType obj,
114 typename MaybeRooted<PropertyKey, allowGC>::HandleType id) {
115 if (MOZ_LIKELY(!watchesPropertyModification(obj))) {
116 return true;
118 return watchPropertyModificationSlow<allowGC>(cx, obj, id);
120 static bool watchFreezeOrSeal(JSContext* cx, Handle<NativeObject*> obj) {
121 if (MOZ_LIKELY(!watchesFreezeOrSeal(obj))) {
122 return true;
124 return watchFreezeOrSealSlow(cx, obj);
126 static bool watchProtoChange(JSContext* cx, HandleObject obj) {
127 if (MOZ_LIKELY(!watchesProtoChange(obj))) {
128 return true;
130 return watchProtoChangeSlow(cx, obj);
133 static bool watchObjectSwap(JSContext* cx, HandleObject a, HandleObject b) {
134 if (MOZ_LIKELY(!watchesObjectSwap(a, b))) {
135 return true;
137 return watchObjectSwapSlow(cx, a, b);
141 } // namespace js
143 #endif /* vm_Watchtower_h */