summaryrefslogtreecommitdiff
path: root/js/src/vm/ReceiverGuard.h
blob: a43ba206a4efd5e1d1ad038b04f4cbcdd1387091 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef vm_ReceiverGuard_h
#define vm_ReceiverGuard_h

#include "vm/Shape.h"

namespace js {

// A ReceiverGuard encapsulates the information about an object that needs to
// be tested to determine if it has the same 'structure' as another object.
// The guard includes the shape and/or group of the object, and which of these
// is tested, as well as the meaning here of 'structure', depends on the kind
// of object being tested:
//
// NativeObject: The structure of a native object is determined by its shape.
//   Two objects with the same shape have the same class, prototype, flags,
//   and all properties except those stored in dense elements.
//
// ProxyObject: The structure of a proxy object is determined by its shape.
//   Proxies with the same shape have the same class and prototype, but no
//   other commonality is guaranteed.
//
// TypedObject: The structure of a typed object is determined by its group.
//   All typed objects with the same group have the same class, prototype, and
//   own properties.
//
// UnboxedPlainObject: The structure of an unboxed plain object is determined
//   by its group and its expando object's shape, if there is one. All unboxed
//   plain objects with the same group and expando shape have the same
//   properties except those stored in the expando's dense elements.

class HeapReceiverGuard;
class RootedReceiverGuard;

class ReceiverGuard
{
  public:
    ObjectGroup* group;
    Shape* shape;

    ReceiverGuard()
      : group(nullptr), shape(nullptr)
    {}

    inline MOZ_IMPLICIT ReceiverGuard(const HeapReceiverGuard& guard);
    inline MOZ_IMPLICIT ReceiverGuard(const RootedReceiverGuard& guard);

    explicit ReceiverGuard(JSObject* obj);
    ReceiverGuard(ObjectGroup* group, Shape* shape);

    bool operator ==(const ReceiverGuard& other) const {
        return group == other.group && shape == other.shape;
    }

    bool operator !=(const ReceiverGuard& other) const {
        return !(*this == other);
    }

    uintptr_t hash() const {
        return (uintptr_t(group) >> 3) ^ (uintptr_t(shape) >> 3);
    }
};

class HeapReceiverGuard
{
    GCPtrObjectGroup group_;
    GCPtrShape shape_;

  public:
    explicit HeapReceiverGuard(const ReceiverGuard& guard)
      : group_(guard.group), shape_(guard.shape)
    {}

    bool matches(const ReceiverGuard& guard) {
        return group_ == guard.group && shape_ == guard.shape;
    }

    void update(const ReceiverGuard& other) {
        group_ = other.group;
        shape_ = other.shape;
    }

    void init(const ReceiverGuard& other) {
        group_.init(other.group);
        shape_.init(other.shape);
    }

    void trace(JSTracer* trc);

    Shape* shape() const {
        return shape_;
    }
    ObjectGroup* group() const {
        return group_;
    }

    static size_t offsetOfShape() {
        return offsetof(HeapReceiverGuard, shape_);
    }
    static size_t offsetOfGroup() {
        return offsetof(HeapReceiverGuard, group_);
    }

    // Bits to munge into Baseline IC compiler keys when that IC has a
    // HeapReceiverGuard. This uses at most two bits for data.
    static int32_t keyBits(JSObject* obj);
};

class RootedReceiverGuard
{
  public:
    RootedObjectGroup group;
    RootedShape shape;

    RootedReceiverGuard(JSContext* cx, const ReceiverGuard& guard)
      : group(cx, guard.group), shape(cx, guard.shape)
    {}
};

inline
ReceiverGuard::ReceiverGuard(const HeapReceiverGuard& guard)
  : group(guard.group()), shape(guard.shape())
{}

inline
ReceiverGuard::ReceiverGuard(const RootedReceiverGuard& guard)
  : group(guard.group), shape(guard.shape)
{}

} // namespace js

#endif /* vm_ReceiverGuard_h */