Added:
branches/sandbox/tinypy/sandbox.c
Modified:
branches/sandbox/tinypy/builtins.c
branches/sandbox/tinypy/dict.c
branches/sandbox/tinypy/gc.c
branches/sandbox/tinypy/list.c
branches/sandbox/tinypy/misc.c
branches/sandbox/tinypy/string.c
branches/sandbox/tinypy/tests.py
branches/sandbox/tinypy/tp.c
branches/sandbox/tinypy/tp.h
branches/sandbox/tinypy/vm.c
Log:
Added the memory limit.
Modified: branches/sandbox/tinypy/builtins.c
==============================================================================
--- branches/sandbox/tinypy/builtins.c (original)
+++ branches/sandbox/tinypy/builtins.c Mon Jul 21 10:02:41 2008
@@ -302,8 +302,9 @@
}
tp_obj tp_sandbox_(TP) {
- tp_num e = TP_NUM();
- tp_sandbox(tp, e, TP_NO_LIMIT);
+ tp_num time = TP_NUM();
+ tp_num mem = TP_NUM();
+ tp_sandbox(tp, time, mem);
tp_del(tp, tp->builtins, tp_string("sandbox"));
return tp_None;
}
Modified: branches/sandbox/tinypy/dict.c
==============================================================================
--- branches/sandbox/tinypy/dict.c (original)
+++ branches/sandbox/tinypy/dict.c Mon Jul 21 10:02:41 2008
@@ -9,9 +9,9 @@
}
return h;
}
-void _tp_dict_free(_tp_dict *self) {
- tp_free(self->items);
- tp_free(self);
+void _tp_dict_free(TP, _tp_dict *self) {
+ tp_free(tp, self->items);
+ tp_free(tp, self);
}
/* void _tp_dict_reset(_tp_dict *self) {
@@ -60,7 +60,7 @@
int i,alloc = self->alloc;
len = _tp_max(8,len);
- self->items = (tp_item*)tp_malloc(len*sizeof(tp_item));
+ self->items = (tp_item*)tp_malloc(tp, len*sizeof(tp_item));
self->alloc = len; self->mask = len-1;
self->len = 0; self->used = 0;
@@ -68,7 +68,7 @@
if (items[i].used != 1) { continue; }
_tp_dict_hash_set(tp,self,items[i].hash,items[i].key,items[i].val);
}
- tp_free(items);
+ tp_free(tp, items);
}
int _tp_dict_hash_find(TP,_tp_dict *self, int hash, tp_obj k) {
@@ -121,16 +121,16 @@
self->len -= 1;
}
-_tp_dict *_tp_dict_new(void) {
- _tp_dict *self = (_tp_dict*)tp_malloc(sizeof(_tp_dict));
+_tp_dict *_tp_dict_new(TP) {
+ _tp_dict *self = (_tp_dict*)tp_malloc(tp, sizeof(_tp_dict));
return self;
}
tp_obj _tp_dict_copy(TP,tp_obj rr) {
tp_obj obj = {TP_DICT};
_tp_dict *o = rr.dict.val;
- _tp_dict *r = _tp_dict_new();
+ _tp_dict *r = _tp_dict_new(tp);
*r = *o; r->gci = 0;
- r->items = (tp_item*)tp_malloc(sizeof(tp_item)*o->alloc);
+ r->items = (tp_item*)tp_malloc(tp, sizeof(tp_item)*o->alloc);
memcpy(r->items,o->items,sizeof(tp_item)*o->alloc);
obj.dict.val = r;
obj.dict.dtype = 1;
@@ -170,7 +170,7 @@
*/
tp_obj tp_dict(TP) {
tp_obj r = {TP_DICT};
- r.dict.val = _tp_dict_new();
+ r.dict.val = _tp_dict_new(tp);
r.dict.dtype = 1;
return tp ? tp_track(tp,r) : r;
}
Modified: branches/sandbox/tinypy/gc.c
==============================================================================
--- branches/sandbox/tinypy/gc.c (original)
+++ branches/sandbox/tinypy/gc.c Mon Jul 21 10:02:41 2008
@@ -50,39 +50,39 @@
}
void tp_gc_init(TP) {
- tp->white = _tp_list_new();
- tp->strings = _tp_dict_new();
- tp->grey = _tp_list_new();
- tp->black = _tp_list_new();
+ tp->white = _tp_list_new(tp);
+ tp->strings = _tp_dict_new(tp);
+ tp->grey = _tp_list_new(tp);
+ tp->black = _tp_list_new(tp);
tp->steps = 0;
}
void tp_gc_deinit(TP) {
- _tp_list_free(tp->white);
- _tp_dict_free(tp->strings);
- _tp_list_free(tp->grey);
- _tp_list_free(tp->black);
+ _tp_list_free(tp, tp->white);
+ _tp_dict_free(tp, tp->strings);
+ _tp_list_free(tp, tp->grey);
+ _tp_list_free(tp, tp->black);
}
void tp_delete(TP,tp_obj v) {
int type = v.type;
if (type == TP_LIST) {
- _tp_list_free(v.list.val);
+ _tp_list_free(tp, v.list.val);
return;
} else if (type == TP_DICT) {
- _tp_dict_free(v.dict.val);
+ _tp_dict_free(tp, v.dict.val);
return;
} else if (type == TP_STRING) {
- tp_free(v.string.info);
+ tp_free(tp, v.string.info);
return;
} else if (type == TP_DATA) {
if (v.data.info->free) {
v.data.info->free(tp,v);
}
- tp_free(v.data.info);
+ tp_free(tp, v.data.info);
return;
} else if (type == TP_FNC) {
- tp_free(v.fnc.info);
+ tp_free(tp, v.fnc.info);
return;
}
tp_raise(,"tp_delete(%s)",TP_CSTR(v));
Modified: branches/sandbox/tinypy/list.c
==============================================================================
--- branches/sandbox/tinypy/list.c (original)
+++ branches/sandbox/tinypy/list.c Mon Jul 21 10:02:41 2008
@@ -1,6 +1,6 @@
-void _tp_list_realloc(_tp_list *self,int len) {
+void _tp_list_realloc(TP, _tp_list *self,int len) {
if (!len) { len=1; }
- self->items = (tp_obj*)tp_realloc(self->items,len*sizeof(tp_obj));
+ self->items = (tp_obj*)tp_realloc(tp, self->items,len*sizeof(tp_obj));
self->alloc = len;
}
@@ -9,9 +9,9 @@
self->items[k] = v;
tp_grey(tp,v);
}
-void _tp_list_free(_tp_list *self) {
- tp_free(self->items);
- tp_free(self);
+void _tp_list_free(TP, _tp_list *self) {
+ tp_free(tp, self->items);
+ tp_free(tp, self);
}
tp_obj _tp_list_get(TP,_tp_list *self,int k,const char *error) {
@@ -20,7 +20,7 @@
}
void _tp_list_insertx(TP,_tp_list *self, int n, tp_obj v) {
if (self->len >= self->alloc) {
- _tp_list_realloc(self,self->alloc*2);
+ _tp_list_realloc(tp, self,self->alloc*2);
}
if (n < self->len) {
memmove(&self->items[n+1],&self->items[n],sizeof(tp_obj)*(self->len-n)); }
self->items[n] = v;
@@ -61,16 +61,16 @@
return tp_number(i);
}
-_tp_list *_tp_list_new(void) {
- return (_tp_list*)tp_malloc(sizeof(_tp_list));
+_tp_list *_tp_list_new(TP) {
+ return (_tp_list*)tp_malloc(tp, sizeof(_tp_list));
}
tp_obj _tp_list_copy(TP, tp_obj rr) {
tp_obj val = {TP_LIST};
_tp_list *o = rr.list.val;
- _tp_list *r = _tp_list_new();
+ _tp_list *r = _tp_list_new(tp);
*r = *o; r->gci = 0;
- r->items = (tp_obj*)tp_malloc(sizeof(tp_obj)*o->len);
+ r->items = (tp_obj*)tp_malloc(tp, sizeof(tp_obj)*o->len);
memcpy(r->items,o->items,sizeof(tp_obj)*o->len);
val.list.val = r;
return tp_track(tp,val);
@@ -106,15 +106,21 @@
return tp_None;
}
+tp_obj tp_list_nt(TP) {
+ tp_obj r = {TP_LIST};
+ r.list.val = _tp_list_new(tp);
+ return r;
+}
+
tp_obj tp_list(TP) {
tp_obj r = {TP_LIST};
- r.list.val = _tp_list_new();
- return tp ? tp_track(tp,r) : r;
+ r.list.val = _tp_list_new(tp);
+ return tp_track(tp,r);
}
tp_obj tp_list_n(TP,int n,tp_obj *argv) {
int i;
- tp_obj r = tp_list(tp); _tp_list_realloc(r.list.val,n);
+ tp_obj r = tp_list(tp); _tp_list_realloc(tp, r.list.val,n);
for (i=0; i<n; i++) {
_tp_list_append(tp,r.list.val,argv[i]);
}
Modified: branches/sandbox/tinypy/misc.c
==============================================================================
--- branches/sandbox/tinypy/misc.c (original)
+++ branches/sandbox/tinypy/misc.c Mon Jul 21 10:02:41 2008
@@ -14,7 +14,7 @@
tp_obj tp_fnc_new(TP,int t, void *v, tp_obj s, tp_obj g) {
tp_obj r = {TP_FNC};
- _tp_fnc *info = (_tp_fnc*)tp_malloc(sizeof(_tp_fnc));
+ _tp_fnc *info = (_tp_fnc*)tp_malloc(tp, sizeof(_tp_fnc));
info->self = s;
info->globals = g;
r.fnc.ftype = t;
@@ -73,7 +73,7 @@
*/
tp_obj tp_data(TP,int magic,void *v) {
tp_obj r = {TP_DATA};
- r.data.info = (_tp_data*)tp_malloc(sizeof(_tp_data));
+ r.data.info = (_tp_data*)tp_malloc(tp, sizeof(_tp_data));
r.data.val = v;
r.data.magic = magic;
return tp_track(tp,r);
Added: branches/sandbox/tinypy/sandbox.c
==============================================================================
--- (empty file)
+++ branches/sandbox/tinypy/sandbox.c Mon Jul 21 10:02:41 2008
@@ -0,0 +1,69 @@
+void tp_sandbox(TP, double time_limit, size_t mem_limit) {
+ tp->time_limit = time_limit;
+ tp->mem_limit = mem_limit;
+}
+
+void tp_mem_update(TP) {
+ if((!tp->mem_exceeded) &&
+ (tp->mem_used > tp->mem_limit) &&
+ (tp->mem_limit != TP_NO_LIMIT)) {
+ tp->mem_exceeded = 1;
+ tp_raise(,"memory_limit_exceeded: %lu (limit: %lu)",
+ (unsigned long) tp->mem_used,
+ (unsigned long) tp->mem_limit);
+ }
+}
+
+void tp_time_update(TP) {
+ clock_t tmp = tp->clocks;
+ if(tp->time_limit != TP_NO_LIMIT)
+ {
+ tp->clocks = clock();
+ tp->time_elapsed += ((double) (tp->clocks - tmp) /
CLOCKS_PER_SEC) * 1000.0;
+ if(tp->time_elapsed >= tp->time_limit)
+ tp_raise(,"time_limit_exceeded: %.4lf (limit: %.4lf)",
tp->time_elapsed, tp->time_limit);
+ }
+}
+
+void *tp_malloc(TP, size_t bytes) {
+ size_t *ptr = calloc(bytes + sizeof(size_t), 1);
+ if(ptr) {
+ *ptr = bytes;
+ tp->mem_used += bytes + sizeof(size_t);
+ }
+ tp_mem_update(tp);
+ return ptr+1;
+}
+
+void tp_free(TP, void *ptr) {
+ size_t *temp = ptr;
+ if(temp) {
+ --temp;
+ tp->mem_used -= (*temp + sizeof(size_t));
+ free(temp);
+ }
+ tp_mem_update(tp);
+}
+
+void *tp_realloc(TP, void *ptr, size_t bytes) {
+ size_t *temp = ptr;
+ int diff;
+ if(temp && bytes) {
+ --temp;
+ diff = bytes - *temp;
+ *temp = bytes;
+ tp->mem_used += diff;
+ temp = realloc(temp, bytes+sizeof(size_t));
+ return temp+1;
+ }
+ else if(temp && !bytes) {
+ tp_free(tp, temp);
+ return NULL;
+ }
+ else if(!temp && bytes) {
+ return tp_malloc(tp, bytes);
+ }
+ else {
+ return NULL;
+ }
+}
Modified: branches/sandbox/tinypy/string.c
==============================================================================
--- branches/sandbox/tinypy/string.c (original)
+++ branches/sandbox/tinypy/string.c Mon Jul 21 10:02:41 2008
@@ -3,7 +3,7 @@
*/
tp_obj tp_string_t(TP, int n) {
tp_obj r = tp_string_n(0,n);
- r.string.info = (_tp_string*)tp_malloc(sizeof(_tp_string)+n);
+ r.string.info = (_tp_string*)tp_malloc(tp, sizeof(_tp_string)+n);
r.string.val = r.string.info->s;
return r;
}
Modified: branches/sandbox/tinypy/tests.py
==============================================================================
--- branches/sandbox/tinypy/tests.py (original)
+++ branches/sandbox/tinypy/tests.py Mon Jul 21 10:02:41 2008
@@ -908,21 +908,28 @@
print(foo)
""", "")
-#test that sandbox() raises an exception when the time limit is passed
+ #test that sandbox() raises an exception when the time limit is passed
t_render("""
-sandbox(1)
+sandbox(1, False)
while True:
pass
-""", "Exception", False)
+""", "time_limit_exceeded", False)
-#test that calling sandbox() removes the sandbox builtin
+ #test that calling sandbox() removes the sandbox builtin
t_render("""
-sandbox(500)
+sandbox(500, False)
try:
sandbox(200)
except:
print("OK")
""", "OK")
+
+ #test that sandbox() raises an exception when the memory limit is passed
+ t_render("""
+sandbox(False, 1)
+a = 42
+""", "memory_limit_exceeded", False)
+
################################################################################
Modified: branches/sandbox/tinypy/tp.c
==============================================================================
--- branches/sandbox/tinypy/tp.c (original)
+++ branches/sandbox/tinypy/tp.c Mon Jul 21 10:02:41 2008
@@ -10,6 +10,7 @@
#include "builtins.c"
#include "gc.c"
#include "ops.c"
+#include "sandbox.c"
void tp_compiler(TP);
#include "vm.c"
Modified: branches/sandbox/tinypy/tp.h
==============================================================================
--- branches/sandbox/tinypy/tp.h (original)
+++ branches/sandbox/tinypy/tp.h Mon Jul 21 10:02:41 2008
@@ -33,9 +33,9 @@
#error "Unsuported compiler"
#endif
-#define tp_malloc(x) calloc((x),1)
-#define tp_realloc(x,y) realloc(x,y)
-#define tp_free(x) free(x)
+//#define tp_malloc(x) calloc((x),1)
+//#define tp_realloc(x,y) realloc(x,y)
+//#define tp_free(x) free(x)
/* #include <gc/gc.h>
#define tp_malloc(x) GC_MALLOC(x)
@@ -206,15 +206,19 @@
tp_obj ex;
char chars[256][2];
int cur;
- /* gc*/
+ /* gc */
_tp_list *white;
_tp_list *grey;
_tp_list *black;
_tp_dict *strings;
int steps;
+ /* sandbox */
clock_t clocks;
double time_elapsed;
double time_limit;
+ size_t mem_limit;
+ size_t mem_used;
+ int mem_exceeded;
} tp_vm;
#define TP tp_vm *tp
@@ -229,6 +233,14 @@
extern tp_obj tp_None;
+void *tp_malloc(TP, size_t);
+void *tp_realloc(TP, void *, size_t);
+void tp_free(TP, void *);
+void tp_sandbox(TP, double, size_t);
+void tp_time_update(TP);
+void tp_mem_update(TP);
+
+void tp_run(TP,int cur);
void tp_set(TP,tp_obj,tp_obj,tp_obj);
tp_obj tp_get(TP,tp_obj,tp_obj);
tp_obj tp_has(TP,tp_obj self, tp_obj k);
@@ -238,7 +250,6 @@
int tp_cmp(TP,tp_obj,tp_obj);
void _tp_raise(TP,tp_obj);
tp_obj tp_printf(TP,char const *fmt,...);
-void tp_sandbox(TP, double, double);
tp_obj tp_track(TP,tp_obj);
void tp_grey(TP,tp_obj);
tp_obj tp_call(TP, tp_obj fnc, tp_obj params);
@@ -261,7 +272,7 @@
return v;
}
-#define TP_NO_LIMIT -1
+#define TP_NO_LIMIT 0
#define TP_TYPE(t) tp_type(tp,t,TP_OBJ())
#define TP_NUM() (TP_TYPE(TP_NUMBER).number.val)
#define TP_STR() (TP_CSTR(TP_TYPE(TP_STRING)))
Modified: branches/sandbox/tinypy/vm.c
==============================================================================
--- branches/sandbox/tinypy/vm.c (original)
+++ branches/sandbox/tinypy/vm.c Mon Jul 21 10:02:41 2008
@@ -1,16 +1,20 @@
/* File: VM
* Functionality pertaining to the virtual machine.
*/
-void tp_run(TP,int cur);
-void tp_time_update(TP);
tp_vm *_tp_init(void) {
int i;
- tp_vm *tp = (tp_vm*)tp_malloc(sizeof(tp_vm));
+ tp_vm *tp = (tp_vm*)malloc(sizeof(tp_vm));
+ tp->time_limit = TP_NO_LIMIT;
+ tp->clocks = clock();
+ tp->time_elapsed = 0.0;
+ tp->mem_limit = TP_NO_LIMIT;
+ tp->mem_exceeded = 0;
+ tp->mem_used = sizeof(tp_vm);
tp->cur = 0;
tp->jmp = 0;
tp->ex = tp_None;
- tp->root = tp_list(0);
+ tp->root = tp_list_nt(tp);
for (i=0; i<256; i++) { tp->chars[i][0]=i; }
tp_gc_init(tp);
tp->_regs = tp_list(tp);
@@ -27,9 +31,6 @@
tp_set(tp,tp->modules,tp_string("BUILTINS"),tp->builtins);
tp_set(tp,tp->builtins,tp_string("BUILTINS"),tp->builtins);
tp->regs = tp->_regs.list.val->items;
- tp->time_limit = TP_NO_LIMIT;
- tp->clocks = clock();
- tp->time_elapsed = 0.0;
tp_full(tp);
return tp;
}
@@ -49,7 +50,8 @@
tp_full(tp); tp_full(tp);
tp_delete(tp,tp->root);
tp_gc_deinit(tp);
- tp_free(tp);
+ tp->mem_used -= sizeof(tp_vm);
+ free(tp);
}
@@ -97,8 +99,6 @@
printf("\nException:\n%s\n",TP_CSTR(tp->ex));
}
-
-
void tp_handle(TP) {
int i;
for (i=tp->cur; i>=0; i--) {
@@ -293,6 +293,7 @@
default: tp_raise(0,"tp_step: invalid instruction %d",e.i); break;
}
tp_time_update(tp);
+ tp_mem_update(tp);
cur += 1;
}
SR(0);
@@ -459,20 +460,5 @@
tp_compiler(tp);
return tp;
}
-
-void tp_sandbox(TP, double time_limit, double mem_limit) {
- tp->time_limit = time_limit;
-}
-
-void tp_time_update(TP) {
- clock_t tmp = tp->clocks;
- if(tp->time_limit != TP_NO_LIMIT)
- {
- tp->clocks = clock();
- tp->time_elapsed += ((double) (tp->clocks - tmp) /
CLOCKS_PER_SEC) * 1000.0;
- if(tp->time_elapsed >= tp->time_limit)
- tp_raise(,"time_limit_exceeded: %.4lf (limit: %.4lf)",
tp->time_elapsed, tp->time_limit);
- }
-}
/**/