summaryrefslogtreecommitdiffstats
path: root/xpcom/reflect/xptcall/xptcall.h
blob: a36ca53d230d3d1dcfa7107912cee04cb946006e (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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */

/* Public declarations for xptcall. */

#ifndef xptcall_h___
#define xptcall_h___

#include "nscore.h"
#include "nsISupports.h"
#include "xptinfo.h"
#include "js/Value.h"
#include "mozilla/MemoryReporting.h"

struct nsXPTCMiniVariant {
  // No ctors or dtors so that we can use arrays of these on the stack
  // with no penalty.
  union Union {
    int8_t i8;
    int16_t i16;
    int32_t i32;
    int64_t i64;
    uint8_t u8;
    uint16_t u16;
    uint32_t u32;
    uint64_t u64;
    float f;
    double d;
    bool b;
    char c;
    char16_t wc;
    void* p;
  };

  Union val;
};

static_assert(offsetof(nsXPTCMiniVariant, val) == 0,
              "nsXPTCMiniVariant must be a thin wrapper");

struct nsXPTCVariant {
  union ExtendedVal {
    // ExtendedVal is an extension on nsXPTCMiniVariant. It contains types
    // unknown to the assembly implementations which must be passed by indirect
    // semantics.
    //
    // nsXPTCVariant contains enough space to store ExtendedVal inline, which
    // can be used to store these types when IsIndirect() is true.
    nsXPTCMiniVariant mini;

    nsID nsid;
    nsCString nscstr;
    nsString nsstr;
    JS::Value jsval;
    xpt::detail::UntypedTArray array;

    // This type contains non-standard-layout types, so needs an explicit
    // Ctor/Dtor - we'll just delete them.
    ExtendedVal() = delete;
    ~ExtendedVal() = delete;
  };

  union {
    // The `val` field from nsXPTCMiniVariant.
    nsXPTCMiniVariant::Union val;

    // Storage for any extended variants.
    ExtendedVal ext;
  };

  nsXPTType type;
  uint8_t flags;

  // Clear to a valid, null state.
  nsXPTCVariant() {
    memset(this, 0, sizeof(nsXPTCVariant));
    type = nsXPTType::T_VOID;
  }

  enum {
    //
    // Bitflag definitions
    //

    // Indicates that we &val.p should be passed n the stack, i.e. that
    // val should be passed by reference.
    IS_INDIRECT = 0x1,
  };

  void ClearFlags() { flags = 0; }
  void SetIndirect() { flags |= IS_INDIRECT; }

  bool IsIndirect() const { return 0 != (flags & IS_INDIRECT); }

  // Implicitly convert to nsXPTCMiniVariant.
  operator nsXPTCMiniVariant&() { return *(nsXPTCMiniVariant*)&val; }
  operator const nsXPTCMiniVariant&() const {
    return *(const nsXPTCMiniVariant*)&val;
  }

  // As this type contains an anonymous union, we need to provide an explicit
  // destructor.
  ~nsXPTCVariant() {}
};

static_assert(offsetof(nsXPTCVariant, val) == offsetof(nsXPTCVariant, ext),
              "nsXPTCVariant::{ext,val} must have matching offsets");

// static_assert that nsXPTCVariant::ExtendedVal is large enough and
// well-aligned enough for every XPT-supported type.
#define XPT_CHECK_SIZEOF(xpt, type)                                            \
  static_assert(sizeof(nsXPTCVariant::ExtendedVal) >= sizeof(type),            \
                "nsXPTCVariant::ext not big enough for " #xpt " (" #type ")"); \
  static_assert(MOZ_ALIGNOF(nsXPTCVariant::ExtendedVal) >= MOZ_ALIGNOF(type),  \
                "nsXPTCVariant::ext not aligned enough for " #xpt " (" #type   \
                ")");
XPT_FOR_EACH_TYPE(XPT_CHECK_SIZEOF)
#undef XPT_CHECK_SIZEOF

class nsIXPTCProxy : public nsISupports {
 public:
  NS_IMETHOD CallMethod(uint16_t aMethodIndex, const nsXPTMethodInfo* aInfo,
                        nsXPTCMiniVariant* aParams) = 0;
};

/**
 * This is a typedef to avoid confusion between the canonical
 * nsISupports* that provides object identity and an interface pointer
 * for inheriting interfaces that aren't known at compile-time.
 */
typedef nsISupports nsISomeInterface;

/**
 * Get a proxy object to implement the specified interface.
 *
 * @param aIID    The IID of the interface to implement.
 * @param aOuter  An object to receive method calls from the proxy object.
 *                The stub forwards QueryInterface/AddRef/Release to the
 *                outer object. The proxy object does not hold a reference to
 *                the outer object; it is the caller's responsibility to
 *                ensure that this pointer remains valid until the stub has
 *                been destroyed.
 * @param aStub   Out parameter for the new proxy object. The object is
 *                not addrefed. The object never destroys itself. It must be
 *                explicitly destroyed by calling
 *                NS_DestroyXPTCallStub when it is no longer needed.
 */
XPCOM_API(nsresult)
NS_GetXPTCallStub(REFNSIID aIID, nsIXPTCProxy* aOuter,
                  nsISomeInterface** aStub);

/**
 * Destroys an XPTCall stub previously created with NS_GetXPTCallStub.
 */
XPCOM_API(void)
NS_DestroyXPTCallStub(nsISomeInterface* aStub);

/**
 * Measures the size of an XPTCall stub previously created with
 * NS_GetXPTCallStub.
 */
XPCOM_API(size_t)
NS_SizeOfIncludingThisXPTCallStub(const nsISomeInterface* aStub,
                                  mozilla::MallocSizeOf aMallocSizeOf);

// this is extern "C" because on some platforms it is implemented in assembly
extern "C" nsresult NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
                                     uint32_t paramCount,
                                     nsXPTCVariant* params);

#endif /* xptcall_h___ */