Skip to content
This repository was archived by the owner on Mar 29, 2024. It is now read-only.

Commit fc9869a

Browse files
committed
Use std containers for weak structures
1 parent 3dd24f2 commit fc9869a

17 files changed

+287
-323
lines changed

src/php_v8_callbacks.cc

Lines changed: 99 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -31,218 +31,153 @@
3131

3232
#include "php_v8_value.h"
3333
#include "php_v8_isolate.h"
34+
#include <string>
3435

36+
namespace phpv8 {
3537

36-
php_v8_callbacks_bucket_t *php_v8_callback_create_bucket(size_t size) {
38+
Callback::Callback(zend_fcall_info fci, zend_fcall_info_cache fci_cache) : fci_(fci), fci_cache_(fci_cache) {
39+
if (fci.size) {
40+
Z_ADDREF(fci.function_name);
3741

38-
assert (size > 0);
39-
40-
php_v8_callbacks_bucket_t *bucket;
41-
42-
bucket = (php_v8_callbacks_bucket_t *) ecalloc(1, sizeof(*bucket));
43-
44-
bucket->size = size;
45-
bucket->cb = (php_v8_callback_t **) ecalloc(size, sizeof(*bucket->cb));
46-
47-
return bucket;
48-
}
49-
50-
51-
void php_v8_callback_cleanup_bucket(php_v8_callbacks_bucket_t *bucket, size_t index) {
52-
assert(bucket->size >= index);
53-
54-
if (bucket->cb[index] == NULL) {
55-
return;
56-
}
57-
58-
if (bucket->cb[index]->fci.size) {
59-
zval_ptr_dtor(&bucket->cb[index]->fci.function_name);
60-
61-
if (!Z_ISUNDEF(bucket->cb[index]->object)) {
62-
zval_ptr_dtor(&bucket->cb[index]->object);
42+
if (fci.object) {
43+
ZVAL_OBJ(&object, fci.object);
44+
Z_ADDREF(object);
45+
} else {
46+
ZVAL_UNDEF(&object);
47+
}
6348
}
6449
}
6550

66-
efree(bucket->cb[index]);
67-
bucket->cb[index] = NULL;
68-
}
51+
Callback::~Callback() {
52+
if (fci_.size) {
53+
zval_ptr_dtor(&fci_.function_name);
6954

70-
void php_v8_callback_destroy_bucket(php_v8_callbacks_bucket_t *bucket) {
71-
for (size_t i = 0; i < bucket->size; i++) {
72-
php_v8_callback_cleanup_bucket(bucket, i);
55+
if (!Z_ISUNDEF(object)) {
56+
zval_ptr_dtor(&object);
57+
}
58+
}
7359
}
7460

75-
efree(bucket->cb);
76-
efree(bucket);
77-
}
78-
79-
php_v8_callbacks_bucket_t *php_v8_callback_get_or_create_bucket(size_t size, const char *prefix, bool is_symbol, const char *name, php_v8_callbacks_t *callbacks) {
80-
char *internal_name;
81-
82-
spprintf(&internal_name, 0, "%s%s%s", prefix, (is_symbol ? "sym_" : "str_"), name);
61+
int Callback::getGcCount() {
62+
int size = 0;
8363

84-
php_v8_callbacks_t::iterator it = callbacks->find(internal_name);
64+
if (fci_.size) {
65+
size += 1;
8566

86-
if (it != callbacks->end()) {
87-
efree(internal_name);
67+
if (!Z_ISUNDEF(object)) {
68+
size += 1;
69+
}
70+
}
8871

89-
return it->second;
72+
return size;
9073
}
9174

92-
php_v8_callbacks_bucket_t *bucket = php_v8_callback_create_bucket(size);
93-
94-
(*callbacks)[internal_name] = bucket;
75+
void Callback::collectGcZvals(zval *&zv) {
76+
if (fci_.size) {
77+
ZVAL_COPY_VALUE(zv++, &fci_.function_name);
9578

96-
return bucket;
97-
}
98-
99-
void php_v8_callbacks_copy_bucket(php_v8_callbacks_bucket_t *from, php_v8_callbacks_bucket_t *to) {
100-
for (size_t i = 0; i < from->size; i++) {
101-
if (from->cb[i]) {
102-
php_v8_callback_add(i, from->cb[i]->fci, from->cb[i]->fci_cache, to);
79+
if (!Z_ISUNDEF(object)) {
80+
ZVAL_COPY_VALUE(zv++, &object);
81+
}
10382
}
10483
}
105-
}
106-
107-
108-
php_v8_callback_t *php_v8_callback_add(size_t index, zend_fcall_info fci, zend_fcall_info_cache fci_cache, php_v8_callbacks_bucket_t *bucket) {
109-
assert(bucket->size >= index);
110-
111-
php_v8_callback_cleanup_bucket(bucket, index);
11284

113-
php_v8_callback_t *callback = (php_v8_callback_t *) ecalloc(1, sizeof(*callback));
85+
void CallbacksBucket::reset(CallbacksBucket *bucket) {
86+
callbacks.clear();
11487

115-
callback->fci = fci;
116-
callback->fci_cache = fci_cache;
117-
118-
if (fci.size) {
119-
Z_ADDREF(callback->fci.function_name);
120-
121-
if (fci.object) {
122-
ZVAL_OBJ(&callback->object, fci.object);
123-
Z_ADDREF(callback->object);
88+
for (auto const &item : bucket->callbacks) {
89+
callbacks[item.first] = item.second;
12490
}
12591
}
12692

127-
bucket->cb[index] = callback;
93+
phpv8::Callback *CallbacksBucket::get(size_t index) {
94+
auto it = callbacks.find(index);
12895

129-
return callback;
130-
}
131-
132-
void php_v8_callbacks_cleanup(php_v8_callbacks_t *callbacks) {
133-
if (callbacks == NULL) {
134-
return;
135-
}
96+
if (it != callbacks.end()) {
97+
return it->second.get();
98+
}
13699

137-
for (php_v8_callbacks_t::iterator it = callbacks->begin(); it != callbacks->end(); ++it) {
138-
php_v8_callback_destroy_bucket(it->second);
139-
efree(it->first);
100+
return NULL;
140101
}
141-
}
142102

143-
void php_v8_callbacks_gc(php_v8_callbacks_t *callbacks, zval **gc_data, int * gc_data_count, zval **table, int *n) {
144-
145-
int size = php_v8_weak_callbacks_get_count(callbacks);
146-
147-
if (*gc_data_count < size) {
148-
*gc_data = (zval *)safe_erealloc(*gc_data, size, sizeof(zval), 0);
103+
void CallbacksBucket::add(size_t index, zend_fcall_info fci, zend_fcall_info_cache fci_cache) {
104+
callbacks[index] = std::make_shared<Callback>(fci, fci_cache);
149105
}
150106

151-
*gc_data_count = size;
152-
153-
zval *local_gc_data = *gc_data;
154-
155-
php_v8_weak_callbacks_get_zvals(callbacks, local_gc_data);
107+
int CallbacksBucket::getGcCount() {
108+
int size = 0;
156109

157-
*table = *gc_data;
158-
*n = *gc_data_count;
159-
}
160-
161-
162-
int php_v8_callback_get_callback_count(php_v8_callback_t *cb) {
163-
int size = 0;
110+
for (auto const &item : callbacks) {
111+
size += item.second->getGcCount();
112+
}
164113

165-
if (!cb) {
166114
return size;
167115
}
168116

169-
if (cb->fci.size) {
170-
size += 1;
171-
172-
if (!Z_ISUNDEF(cb->object)) {
173-
size += 1;
117+
void CallbacksBucket::collectGcZvals(zval *&zv) {
118+
for (auto const &item : callbacks) {
119+
item.second->collectGcZvals(zv);
174120
}
175121
}
176122

177-
return size;
178-
}
123+
int PersistentData::getGcCount() {
124+
int size = 0;
179125

180-
int php_v8_callback_get_bucket_count(php_v8_callbacks_bucket_t *bucket) {
181-
int size = 0;
126+
for (auto const &item : buckets) {
127+
size += item.second->getGcCount();
128+
}
182129

183-
if (!bucket) {
184130
return size;
185131
}
186132

187-
for (size_t i = 0; i < bucket->size; i++) {
188-
size += php_v8_callback_get_callback_count(bucket->cb[i]);
133+
void PersistentData::collectGcZvals(zval *&zv) {
134+
for (auto const &item : buckets) {
135+
item.second->collectGcZvals(zv);
136+
}
189137
}
190138

191-
return size;
192-
}
193-
194-
int php_v8_weak_callbacks_get_count(php_v8_callbacks_t *callbacks) {
195-
int size = 0;
139+
CallbacksBucket *PersistentData::bucket(const char *prefix, bool is_symbol, const char *name) {
140+
char *internal_name;
196141

197-
if (callbacks == NULL || callbacks->empty()) {
198-
return size;
199-
}
142+
size_t size = spprintf(&internal_name, 0, "%s%s%s", prefix, (is_symbol ? "sym_" : "str_"), name);
200143

201-
for (auto it = callbacks->begin(); it != callbacks->end(); ++it) {
202-
size += php_v8_callback_get_bucket_count(it->second);
203-
}
144+
std::string str_name(internal_name, size);
145+
efree(internal_name);
204146

205-
return size;
206-
}
147+
auto it = buckets.find(str_name);
207148

208-
void php_v8_callback_get_callback_zvals(php_v8_callback_t *cb, zval *& zv) {
209-
if (!cb) {
210-
return;
211-
}
149+
if (it != buckets.end()) {
150+
return it->second.get();
151+
}
212152

213-
if (cb->fci.size) {
214-
ZVAL_COPY_VALUE(zv++, &cb->fci.function_name);
153+
auto bucket = std::make_shared<CallbacksBucket>();
154+
buckets[str_name] = bucket;
215155

216-
if (!Z_ISUNDEF(cb->object)) {
217-
ZVAL_COPY_VALUE(zv++, &cb->object);
218-
}
156+
return bucket.get();
219157
}
220158
}
221159

160+
void php_v8_callbacks_gc(phpv8::PersistentData *data, zval **gc_data, int * gc_data_count, zval **table, int *n) {
222161

223-
void php_v8_callback_get_bucket_zvals(php_v8_callbacks_bucket_t *bucket, zval *& zv) {
224-
if (!bucket) {
225-
return;
226-
}
162+
int size = data->getGcCount();
227163

228-
for (size_t i = 0; i < bucket->size; i++) {
229-
php_v8_callback_get_callback_zvals(bucket->cb[i], zv);
164+
if (*gc_data_count < size) {
165+
*gc_data = (zval *)safe_erealloc(*gc_data, size, sizeof(zval), 0);
230166
}
231-
}
232167

233-
void php_v8_weak_callbacks_get_zvals(php_v8_callbacks_t *callbacks, zval *& zv) {
234-
if (callbacks == NULL) {
235-
return;
236-
}
168+
*gc_data_count = size;
237169

238-
for (php_v8_callbacks_t::iterator it = callbacks->begin(); it != callbacks->end(); ++it) {
239-
php_v8_callback_get_bucket_zvals(it->second, zv);
240-
}
170+
zval *local_gc_data = *gc_data;
171+
172+
data->collectGcZvals(local_gc_data);
173+
174+
*table = *gc_data;
175+
*n = *gc_data_count;
241176
}
242177

243-
void php_v8_bucket_gc(php_v8_callbacks_bucket_t *bucket, zval **gc_data, int * gc_data_count, zval **table, int *n) {
178+
void php_v8_bucket_gc(phpv8::CallbacksBucket *bucket, zval **gc_data, int * gc_data_count, zval **table, int *n) {
244179

245-
int size = php_v8_callback_get_bucket_count(bucket);
180+
int size = bucket->getGcCount();
246181

247182
if (*gc_data_count < size) {
248183
*gc_data = (zval *)safe_erealloc(*gc_data, size, sizeof(zval), 0);
@@ -252,7 +187,7 @@ void php_v8_bucket_gc(php_v8_callbacks_bucket_t *bucket, zval **gc_data, int * g
252187

253188
zval *local_gc_data = *gc_data;
254189

255-
php_v8_callback_get_bucket_zvals(bucket, local_gc_data);
190+
bucket->collectGcZvals(local_gc_data);
256191

257192
*table = *gc_data;
258193
*n = *gc_data_count;
@@ -285,20 +220,25 @@ static inline void php_v8_callback_set_retval_from_callback_info(v8::ReturnValue
285220

286221

287222
void php_v8_callback_call_from_bucket_with_zargs(size_t index, v8::Local<v8::Value> data, zval *args, zval *retval) {
288-
php_v8_callbacks_bucket_t *bucket;
223+
phpv8::CallbacksBucket *bucket;
289224

290225
if (data.IsEmpty() || !data->IsExternal()) {
291226
PHP_V8_THROW_EXCEPTION("Callback has no stored callback function");
292227
return;
293228
}
294229

295-
bucket = static_cast<php_v8_callbacks_bucket_t *>(v8::Local<v8::External>::Cast(data)->Value());
296-
assert(bucket->size > index);
230+
bucket = static_cast<phpv8::CallbacksBucket *>(v8::Local<v8::External>::Cast(data)->Value());
297231

298-
php_v8_callback_t *cb = bucket->cb[index];
232+
phpv8::Callback *cb = bucket->get(index);
233+
234+
// highly unlikely, but to play safe
235+
if (!cb) {
236+
PHP_V8_THROW_EXCEPTION("Callback has no stored callback function");
237+
return;
238+
}
299239

300-
zend_fcall_info fci = cb->fci;
301-
zend_fcall_info_cache fci_cache = cb->fci_cache;
240+
zend_fcall_info fci = cb->fci();
241+
zend_fcall_info_cache fci_cache = cb->fci_cache();
302242

303243
/* Convert everything to be callable */
304244
zend_fcall_info_args(&fci, args);

0 commit comments

Comments
 (0)