~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/xpcom/reflect/xptcall/src/md/test/stub_test.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#include <stdio.h>
 
3
 
 
4
typedef unsigned nsresult;
 
5
typedef unsigned PRUint32;
 
6
typedef unsigned nsXPCVariant;
 
7
 
 
8
 
 
9
#if defined(WIN32)
 
10
#define NS_IMETHOD virtual nsresult __stdcall
 
11
#define NS_IMETHODIMP nsresult __stdcall
 
12
#else
 
13
#define NS_IMETHOD virtual nsresult
 
14
#define NS_IMETHODIMP nsresult
 
15
#endif
 
16
 
 
17
 
 
18
class base{
 
19
public:
 
20
  NS_IMETHOD ignored() = 0;
 
21
};
 
22
 
 
23
class foo : public base {
 
24
public:
 
25
  NS_IMETHOD callme1(int i, int j) = 0;
 
26
  NS_IMETHOD callme2(int i, int j) = 0;
 
27
  NS_IMETHOD callme3(int i, int j) = 0;
 
28
};
 
29
 
 
30
class bar : public foo{
 
31
public:
 
32
  NS_IMETHOD ignored();
 
33
  NS_IMETHOD callme1(int i, int j);
 
34
  NS_IMETHOD callme2(int i, int j);
 
35
  NS_IMETHOD callme3(int i, int j);
 
36
};
 
37
 
 
38
class baz : public base {
 
39
public:
 
40
  NS_IMETHOD ignored();
 
41
  NS_IMETHOD callme1();
 
42
  NS_IMETHOD callme2();
 
43
  NS_IMETHOD callme3();
 
44
  void setfoo(foo* f) {other = f;}
 
45
 
 
46
  foo* other;
 
47
};
 
48
NS_IMETHODIMP baz::ignored(){return 0;}
 
49
 
 
50
NS_IMETHODIMP bar::ignored(){return 0;}
 
51
 
 
52
NS_IMETHODIMP bar::callme1(int i, int j)
 
53
{
 
54
  printf("called bar::callme1 with: %d %d\n", i, j);
 
55
  return 15;
 
56
}
 
57
 
 
58
NS_IMETHODIMP bar::callme2(int i, int j)
 
59
{
 
60
  printf("called bar::callme2 with: %d %d\n", i, j);
 
61
  return 25;
 
62
}
 
63
 
 
64
NS_IMETHODIMP bar::callme3(int i, int j)
 
65
{
 
66
  printf("called bar::callme3 with: %d %d\n", i, j);
 
67
  return 35;
 
68
}
 
69
 
 
70
void docall(foo* f, int i, int j){
 
71
  f->callme1(i, j); 
 
72
}
 
73
 
 
74
/***************************************************************************/
 
75
#if defined(WIN32)
 
76
 
 
77
static int __stdcall
 
78
PrepareAndDispatch(baz* self, PRUint32 methodIndex,
 
79
                   PRUint32* args, PRUint32* stackBytesToPop)
 
80
{
 
81
    fprintf(stdout, "PrepareAndDispatch (%p, %d, %p)\n",
 
82
        (void*)self, methodIndex, (void*)args);
 
83
    foo* a = self->other;
 
84
    int p1 = (int) *args;
 
85
    int p2 = (int) *(args+1);
 
86
    int out = 0;
 
87
    switch(methodIndex)
 
88
    {
 
89
    case 1: out = a->callme1(p1, p2); break;
 
90
    case 2: out = a->callme2(p1, p2); break;
 
91
    case 3: out = a->callme3(p1, p2); break;
 
92
    }
 
93
    *stackBytesToPop = 2*4;
 
94
    return out;
 
95
}
 
96
 
 
97
#ifndef __GNUC__
 
98
static __declspec(naked) void SharedStub(void)
 
99
{
 
100
    __asm {
 
101
        push ebp            // set up simple stack frame
 
102
        mov  ebp, esp       // stack has: ebp/vtbl_index/retaddr/this/args
 
103
        push ecx            // make room for a ptr
 
104
        lea  eax, [ebp-4]   // pointer to stackBytesToPop
 
105
        push eax
 
106
        lea  ecx, [ebp+16]  // pointer to args
 
107
        push ecx
 
108
        mov  edx, [ebp+4]   // vtbl_index
 
109
        push edx
 
110
        mov  eax, [ebp+12]  // this
 
111
        push eax
 
112
        call PrepareAndDispatch
 
113
        mov  edx, [ebp+8]   // return address
 
114
        mov  ecx, [ebp-4]   // stackBytesToPop
 
115
        add  ecx, 12        // for this, the index, and ret address
 
116
        mov  esp, ebp
 
117
        pop  ebp
 
118
        add  esp, ecx       // fix up stack pointer
 
119
        jmp  edx            // simulate __stdcall return
 
120
    }
 
121
}
 
122
 
 
123
// these macros get expanded (many times) in the file #included below
 
124
#define STUB_ENTRY(n) \
 
125
__declspec(naked) nsresult __stdcall baz::callme##n() \
 
126
{ __asm push n __asm jmp SharedStub }
 
127
 
 
128
#else /* __GNUC__ */
 
129
 
 
130
#define STUB_ENTRY(n) \
 
131
nsresult __stdcall baz::callme##n() \
 
132
{ \
 
133
  PRUint32 *args, stackBytesToPop; \
 
134
  int result = 0; \
 
135
  baz *obj; \
 
136
  __asm__ __volatile__ ( \
 
137
    "leal   0x0c(%%ebp), %0\n\t"    /* args */ \
 
138
    "movl   0x08(%%ebp), %1\n\t"    /* this */ \
 
139
    : "=r" (args), \
 
140
      "=r" (obj)); \
 
141
  result = PrepareAndDispatch(obj, n, args,&stackBytesToPop); \
 
142
    fprintf(stdout, "stub returning: %d\n", result); \
 
143
    fprintf(stdout, "bytes to pop:  %d\n", stackBytesToPop); \
 
144
    return result; \
 
145
}
 
146
 
 
147
#endif /* ! __GNUC__ */
 
148
 
 
149
#else
 
150
/***************************************************************************/
 
151
// just Linux_x86 now. Add other later...
 
152
 
 
153
static int
 
154
PrepareAndDispatch(baz* self, PRUint32 methodIndex, PRUint32* args)
 
155
{
 
156
    foo* a = self->other;
 
157
    int p1 = (int) *args;
 
158
    int p2 = (int) *(args+1);
 
159
    switch(methodIndex)
 
160
    {
 
161
    case 1: a->callme1(p1, p2); break;
 
162
    case 2: a->callme2(p1, p2); break;
 
163
    case 3: a->callme3(p1, p2); break;
 
164
    }
 
165
    return 1;
 
166
}
 
167
 
 
168
#define STUB_ENTRY(n) \
 
169
nsresult baz::callme##n() \
 
170
{ \
 
171
  register void* method = PrepareAndDispatch; \
 
172
  register nsresult result; \
 
173
  __asm__ __volatile__( \
 
174
    "leal   0x0c(%%ebp), %%ecx\n\t"    /* args */ \
 
175
    "pushl  %%ecx\n\t" \
 
176
    "pushl  $"#n"\n\t"                 /* method index */ \
 
177
    "movl   0x08(%%ebp), %%ecx\n\t"    /* this */ \
 
178
    "pushl  %%ecx\n\t" \
 
179
    "call   *%%edx"                    /* PrepareAndDispatch */ \
 
180
    : "=a" (result)     /* %0 */ \
 
181
    : "d" (method)      /* %1 */ \
 
182
    : "memory" ); \
 
183
    return result; \
 
184
}
 
185
 
 
186
#endif
 
187
/***************************************************************************/
 
188
 
 
189
STUB_ENTRY(1)
 
190
STUB_ENTRY(2)
 
191
STUB_ENTRY(3)
 
192
 
 
193
int main()
 
194
{
 
195
  foo* a = new bar();
 
196
  baz* b = new baz();
 
197
 
 
198
  /* here we make the global 'check for alloc failure' checker happy */
 
199
  if(!a || !b)
 
200
    return 1;
 
201
  
 
202
  foo* c = (foo*)b;
 
203
 
 
204
  b->setfoo(a);
 
205
  c->callme1(1,2);
 
206
  c->callme2(2,4);
 
207
  c->callme3(3,6);
 
208
 
 
209
  return 0;
 
210
}