-
Notifications
You must be signed in to change notification settings - Fork 609
/
sendsite.hpp
142 lines (119 loc) · 4.18 KB
/
sendsite.hpp
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
#ifndef RBX_BUILTIN_SENDSITE_HPP
#define RBX_BUILTIN_SENDSITE_HPP
#include "builtin/object.hpp"
#include "type_info.hpp"
namespace rubinius {
class CompiledMethod;
class Selector;
class Message;
class SendSite;
class MethodContext;
typedef bool (*MethodResolver)(STATE, Message& msg);
class SendSite : public Object {
public:
static const object_type type = SendSiteType;
typedef Object* (*Performer)(STATE, CallFrame* call_frame, Task* task, Message& msg);
private:
Symbol* name_; // slot
CompiledMethod* sender_; // slot
Selector* selector_; // slot
Executable* method_; // slot
Module* module_; // slot
Module* recv_class_; // slot
public:
// @todo fix up data members that aren't slots
bool method_missing;
size_t hits;
size_t misses;
MethodResolver resolver;
Performer performer;
public:
/* accessors */
attr_accessor(name, Symbol);
attr_accessor(sender, CompiledMethod);
attr_accessor(selector, Selector);
attr_accessor(method, Executable);
attr_accessor(module, Module);
attr_accessor(recv_class, Module);
/* interface */
static void init(STATE);
// Ruby.primitive :sendsite_create
static SendSite* create(STATE, Object* name);
// Ruby.primitive :sendsite_set_sender
Object* set_sender(STATE, CompiledMethod* cm);
// Ruby.primitive :sendsite_hits
Object* hits_prim(STATE);
// Ruby.primitive :sendsite_misses
Object* misses_prim(STATE);
void initialize(STATE);
bool locate(STATE, Message& msg);
// Check and see if the method referenced has the given serial
// Sideffect: populates the sendsite if empty
bool check_serial(STATE, CallFrame* call_frame, Object* reciever, int serial);
class Info : public TypeInfo {
public:
BASIC_TYPEINFO(TypeInfo)
virtual void show(STATE, Object* self, int level);
};
};
namespace performer {
Object* basic_performer(STATE, CallFrame*, Task* task, Message& msg);
Object* mono_performer(STATE, CallFrame*, Task* task, Message& msg);
Object* mono_mm_performer(STATE, CallFrame*, Task* task, Message& msg);
}
/**
* Standard Ruby method lookup path.
*
* The normal, slow method lookup path. Given the Module in which
* to start looking and the method name, the lookup progresses up
* the inheritance tree until the method is located or no more
* method tables exist. If the method was found, it is verified
* that the method is visible (see MethodVisibility) for this
* call. If everything checks out, the Executable object representing
* the method and the Module in which it was found are stored in
* the Message.
*
* @returns true if method is found, false otherwise.
*/
class HierarchyResolver {
public:
static bool resolve(STATE, Message& msg);
};
/**
* Cached method lookup path.
*
* The method is first attempted to be located in the globally
* which the lookup *starts* as the key. If the method is found
* in the cache, the cached information is used. If not, the
* fallback is to look it up using HierarchyResolver. If the
* slower path locates the method, it is stored in the cache.
* Either way, the Executable object and the Module in which
* the Executable was originally located are stored in the
* Message.
*
* @note the cache is indexed using the name and Module where
* the lookup *started*. The information stored includes
* the Module in which the Executable was *found*.
*
* @returns true if the method was found, false otherwise.
*/
class GlobalCacheResolver {
public:
static bool resolve(STATE, Message& msg);
};
/**
* Monomorphic inline method lookup.
*
* First checks if the cached receiver class matchs msg.lookup_from.
* If so, set the +msg+ method and module to the cached ones. If not,
* invoke the GlobalCacheResolver::resolve method. If the method is
* found, cache it in +ss+.
*
* @returns true if the method was found, false otherwise.
*/
class MonomorphicInlineCacheResolver {
public:
static bool resolve(STATE, Message& msg);
};
};
#endif