Skip to content

Commit e02f19b

Browse files
author
Jimmy Huang
authored
Merge pull request zephyrproject-rtos#34 from grgustaf/create-buffer
Improvements to Buffer support
2 parents 5221f48 + cc66d10 commit e02f19b

File tree

3 files changed

+118
-26
lines changed

3 files changed

+118
-26
lines changed

samples/tests/BufferMemory.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright (c) 2016, Intel Corporation.
2+
3+
// Stress test for buffer code
4+
print("Buffer stress test...");
5+
6+
// This was useful for catching memory leaks in the original Buffer code
7+
for (var i = 1; i <= 1000; i++) {
8+
print("Allocating buffer", i);
9+
10+
var mybuf = new Buffer(8);
11+
for (var j = 0; j < 8; j++)
12+
mybuf.writeUInt8(j * 4, j);
13+
}

src/zjs_buffer.c

Lines changed: 102 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414

1515
static struct zjs_buffer_t *zjs_buffers = NULL;
1616

17-
struct zjs_buffer_t *zjs_find_buffer(const jerry_object_t *obj)
17+
// TODO: this could probably be replaced more efficiently now that there is a
18+
// get_native_handle API
19+
struct zjs_buffer_t *zjs_buffer_find(const jerry_object_t *obj)
1820
{
1921
// requires: obj should be the JS object associated with a buffer, created
2022
// in zjs_buffer
@@ -26,13 +28,51 @@ struct zjs_buffer_t *zjs_find_buffer(const jerry_object_t *obj)
2628
return NULL;
2729
}
2830

31+
static bool zjs_buffer_read_uint8(const jerry_object_t *function_obj_p,
32+
const jerry_value_t this_val,
33+
const jerry_value_t args_p[],
34+
const jerry_length_t args_cnt,
35+
jerry_value_t *ret_val_p)
36+
{
37+
// requires: this_val is a JS buffer object created with zjs_buffer_create,
38+
// expects argument of an offset into the buffer, but will
39+
// treat offset as 0 if not given, as node.js seems to
40+
// effects: reads single byte value from the buffer associated with the
41+
// this_p JS object, if found, at the given offset, if within
42+
// the bounds of the buffer; otherwise returns an error
43+
if (args_cnt >= 1 && !jerry_value_is_number(args_p[0])) {
44+
PRINT("Unsupported argument to readUInt8\n");
45+
return false;
46+
}
47+
48+
uint32_t offset = 0;
49+
if (args_cnt > 1)
50+
offset = (uint32_t)jerry_get_number_value(args_p[0]);
51+
52+
jerry_object_t *obj = jerry_get_object_value(this_val);
53+
struct zjs_buffer_t *buf = zjs_buffer_find(obj);
54+
if (buf) {
55+
if (offset >= buf->bufsize) {
56+
PRINT("Tried to read beyond end of buffer\n");
57+
return false;
58+
}
59+
uint8_t value = buf->buffer[offset];
60+
61+
*ret_val_p = jerry_create_number_value(value);
62+
return true;
63+
}
64+
65+
PRINT("Read called on a buffer not in list"); // Fatal
66+
return false;
67+
}
68+
2969
static bool zjs_buffer_write_uint8(const jerry_object_t *function_obj_p,
3070
const jerry_value_t this_val,
3171
const jerry_value_t args_p[],
3272
const jerry_length_t args_cnt,
3373
jerry_value_t *ret_val_p)
3474
{
35-
// requires: this_val is a JS buffer object created with zjs_buffer,
75+
// requires: this_val is a JS buffer object created with zjs_buffer_create,
3676
// expects arguments of the value to write and an offset
3777
// into the buffer, but will treat offset as 0 if not given,
3878
// as node.js seems to
@@ -52,17 +92,19 @@ static bool zjs_buffer_write_uint8(const jerry_object_t *function_obj_p,
5292
offset = (uint32_t)jerry_get_number_value(args_p[1]);
5393

5494
jerry_object_t *obj = jerry_get_object_value(this_val);
55-
struct zjs_buffer_t *buf = zjs_find_buffer(obj);
95+
struct zjs_buffer_t *buf = zjs_buffer_find(obj);
5696
if (buf) {
5797
if (offset >= buf->bufsize) {
5898
PRINT("Tried to write beyond end of buffer\n");
5999
return false;
60100
}
61-
((char *)buf->buffer)[offset] = value;
101+
buf->buffer[offset] = value;
62102

63103
*ret_val_p = jerry_create_number_value(offset + 1);
64104
return true;
65105
}
106+
107+
PRINT("Write called on a buffer not in list"); // Fatal
66108
return false;
67109
}
68110

@@ -91,7 +133,7 @@ static bool zjs_buffer_to_string(const jerry_object_t *function_obj_p,
91133
}
92134

93135
jerry_object_t *obj = jerry_get_object_value(this_val);
94-
struct zjs_buffer_t *buf = zjs_find_buffer(obj);
136+
struct zjs_buffer_t *buf = zjs_buffer_find(obj);
95137
if (buf && args_cnt == 0) {
96138
*ret_val_p = jerry_create_string_value(jerry_create_string(
97139
(jerry_char_t *)"[Buffer Object]"));
@@ -127,25 +169,28 @@ static bool zjs_buffer_to_string(const jerry_object_t *function_obj_p,
127169
return false;
128170
}
129171

130-
// Buffer constructor
131-
static bool zjs_buffer(const jerry_object_t *function_obj_p,
132-
const jerry_value_t this_val,
133-
const jerry_value_t args_p[],
134-
const jerry_length_t args_cnt,
135-
jerry_value_t *ret_val_p)
172+
static void zjs_buffer_callback_free(uintptr_t handle)
136173
{
137-
// requires: single argument is a numeric size in bytes; soon will also
138-
// support an array argument to initialize the buffer
139-
// effects: constructs a new JS Buffer object, and an associated buffer
140-
// tied to it through a zjs_buffer_t struct stored in a global
141-
// list
142-
if (args_cnt != 1 || !jerry_value_is_number(args_p[0])) {
143-
PRINT("Unsupported arguments to Buffer constructor\n");
144-
return false;
174+
// requires: handle is the native pointer we registered with
175+
// jerry_set_object_native_handle
176+
// effects: frees the callback list item for the given pin object
177+
struct zjs_buffer_t **pItem = &zjs_buffers;
178+
while (*pItem) {
179+
if ((uintptr_t)*pItem == handle) {
180+
task_free((*pItem)->buffer);
181+
*pItem = (*pItem)->next;
182+
task_free((void *)handle);
183+
}
184+
pItem = &(*pItem)->next;
145185
}
186+
}
146187

147-
uint32_t size = (uint32_t)jerry_get_number_value(args_p[0]);
148-
188+
jerry_object_t *zjs_buffer_create(uint32_t size)
189+
{
190+
// requires: size is size of desired buffer, in bytes
191+
// effects: allocates a JS Buffer object, an underlying C buffer, and a
192+
// list item to track it; if any of these fail, free them all
193+
// and return NULL, otherwise return the JS object
149194
jerry_object_t *buf_obj = jerry_create_object();
150195
void *buf = task_malloc(size);
151196
struct zjs_buffer_t *buf_item =
@@ -156,7 +201,7 @@ static bool zjs_buffer(const jerry_object_t *function_obj_p,
156201
jerry_release_object(buf_obj);
157202
task_free(buf);
158203
task_free(buf_item);
159-
return false;
204+
return NULL;
160205
}
161206

162207
buf_item->obj = buf_obj;
@@ -165,13 +210,46 @@ static bool zjs_buffer(const jerry_object_t *function_obj_p,
165210
buf_item->next = zjs_buffers;
166211
zjs_buffers = buf_item;
167212

213+
zjs_obj_add_uint32(buf_obj, size, "length");
214+
zjs_obj_add_function(buf_obj, zjs_buffer_read_uint8, "readUInt8");
168215
zjs_obj_add_function(buf_obj, zjs_buffer_write_uint8, "writeUInt8");
169216
zjs_obj_add_function(buf_obj, zjs_buffer_to_string, "toString");
170217

171-
zjs_init_value_object(ret_val_p, buf_obj);
172-
173218
// TODO: sign up to get callback when the object is freed, then free the
174219
// buffer and remove it from the list
220+
221+
// watch for the object getting garbage collected, and clean up
222+
jerry_set_object_native_handle(buf_obj, (uintptr_t)buf_item,
223+
zjs_buffer_callback_free);
224+
225+
return buf_obj;
226+
}
227+
228+
// Buffer constructor
229+
static bool zjs_buffer(const jerry_object_t *function_obj_p,
230+
const jerry_value_t this_val,
231+
const jerry_value_t args_p[],
232+
const jerry_length_t args_cnt,
233+
jerry_value_t *ret_val_p)
234+
{
235+
// requires: single argument is a numeric size in bytes; soon will also
236+
// support an array argument to initialize the buffer
237+
// effects: constructs a new JS Buffer object, and an associated buffer
238+
// tied to it through a zjs_buffer_t struct stored in a global
239+
// list
240+
if (args_cnt != 1 || !jerry_value_is_number(args_p[0])) {
241+
PRINT("Unsupported arguments to Buffer constructor\n");
242+
return false;
243+
}
244+
245+
uint32_t size = (uint32_t)jerry_get_number_value(args_p[0]);
246+
247+
jerry_object_t *buf_obj = zjs_buffer_create(size);
248+
if (!buf_obj)
249+
return false;
250+
251+
*ret_val_p = jerry_create_object_value(buf_obj);
252+
175253
return true;
176254
}
177255

src/zjs_buffer.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ void zjs_buffer_init();
44

55
struct zjs_buffer_t {
66
jerry_object_t *obj;
7-
char *buffer;
7+
uint8_t *buffer;
88
uint32_t bufsize;
99
struct zjs_buffer_t *next;
1010
};
1111

12-
struct zjs_buffer_t *zjs_find_buffer(const jerry_object_t *obj);
12+
struct zjs_buffer_t *zjs_buffer_find(const jerry_object_t *obj);
13+
jerry_object_t *zjs_buffer_create(uint32_t size);

0 commit comments

Comments
 (0)