forked from rubinius/rubinius
/
data.cpp
111 lines (80 loc) · 2.82 KB
/
data.cpp
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
#include "builtin/data.hpp"
#include "builtin/class.hpp"
#include "objectmemory.hpp"
#include "object_utils.hpp"
#include "gc/gc.hpp"
#include "capi/capi.hpp"
namespace rubinius {
void Data::init(STATE) {
GO(data).set(state->new_class("Data", G(object)));
G(data)->set_object_type(state, DataType);
}
Data* Data::create(STATE, void* data_ptr, Data::MarkFunctor mark, Data::FreeFunctor free) {
Data* data;
data = state->new_object<Data>(G(data));
// Data is just a heap alias for the handle, so go ahead and create
// the handle and populate it as an RData now.
InflatedHeader* ih = state->om->inflate_header(state, data);
capi::Handle* handle = ih->handle();
assert(!handle && "can't already have a handle, it's brand new!");
handle = new capi::Handle(state, data);
ih->set_handle(handle);
// Don't call ->ref() on handle! We don't want the handle to keep the object
// alive by default. The handle needs to have the lifetime of the object.
state->shared.add_global_handle(state, handle);
RDataShadow* rdata = reinterpret_cast<RDataShadow*>(handle->as_rdata(0));
rdata->data = data_ptr;
rdata->dmark = mark;
rdata->dfree = free;
data->internal_ = rdata;
// If this Data requires a free function, register this object
// as needing finalization.
if(free) {
state->om->needs_finalization(data, (FinalizerFunction)&Data::finalize);
}
return data;
}
RDataShadow* Data::slow_rdata(STATE) {
InflatedHeader* ih = state->om->inflate_header(state, this);
capi::Handle* handle = ih->handle();
assert(handle && handle->is_rdata() && "invalid initialized Data object");
return reinterpret_cast<RDataShadow*>(handle->as_rdata(0));
}
void* Data::data(STATE) {
return rdata(state)->data;
}
Data::FreeFunctor Data::free(STATE) {
return rdata(state)->dfree;
}
Data::MarkFunctor Data::mark(STATE) {
return rdata(state)->dmark;
}
void Data::finalize(STATE, Data* data) {
// MRI only calls free if the data_ptr is not NULL.
void* data_ptr = data->data(state);
if(data_ptr) {
Data::FreeFunctor f = data->free(state);
if(f) {
// If the user specifies -1, then we call free. We check here rather
// than when Data_Make_Struct is called because the user is allowed to
// change dfree.
if(reinterpret_cast<intptr_t>(f) == -1) {
::free(data_ptr);
} else {
f(data_ptr);
}
}
}
}
void Data::Info::mark(Object* t, ObjectMark& mark) {
// auto_mark(t, mark);
Data* data = force_as<Data>(t);
RDataShadow* rdata = data->rdata();
if(rdata->dmark) {
ObjectMark* cur = capi::current_mark();
capi::set_current_mark(&mark);
(*rdata->dmark)(rdata->data);
capi::set_current_mark(cur);
}
}
}