Skip to content

[proof of concept] completely remove nlr from py, extmod and unix port #4131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 43 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
896a610
WIP removing nlr completely
dpgeorge Aug 12, 2018
1b07950
WIP simplify VM handling of FOR_ITER/YIELD_FROM exceptions
dpgeorge Aug 12, 2018
fcb4490
WIP make stack check return success/fail
dpgeorge Aug 13, 2018
276cbdc
WIP removing nlr from extmod
dpgeorge Aug 14, 2018
1a2b030
WIP removing nlr from unix port
dpgeorge Aug 14, 2018
1946512
WIP modify re1.5 to return -1 on error
dpgeorge Sep 12, 2018
2cbad6e
WIP get modure working without nlr
dpgeorge Sep 12, 2018
0fac236
WIP more work removing nlr from py/ core
dpgeorge Sep 12, 2018
a9153d2
WIP more changes, including to vstr, lexer and emitnative
dpgeorge Sep 13, 2018
002a64c
WIP removing nlr from unix/coverage.c
dpgeorge Sep 13, 2018
7f5c169
WIP update modmath.c not to raise nlr
dpgeorge Oct 5, 2018
96c39e9
WIP update emitnative to pass viper_error test
dpgeorge Oct 5, 2018
e06c19d
WIP updates to py/emitnative.c
dpgeorge Oct 20, 2018
4456a1e
WIP updates to unix/moduselect.c
dpgeorge Oct 20, 2018
e701748
WIP improving checking for malloc errors
dpgeorge Oct 20, 2018
a89e69e
WIP updates to work after rebase
dpgeorge Jun 25, 2019
905d2ca
unix/main: Check for errors returned from mp_compile.
dpgeorge Jun 26, 2019
2c89fc1
WIP check for exc when loading mpy file
dpgeorge Jul 19, 2019
33ecfb5
WIP handle exc in modthread
dpgeorge Jul 19, 2019
4d56569
WIP make mp_setup_code_state return mp_obj_t, not int
dpgeorge Jul 19, 2019
b0ffa1f
WIP runtime: clear cur_exc on mp_init
dpgeorge Jul 19, 2019
c0c1c75
WIP unix: get package import working
dpgeorge Jul 19, 2019
eb1794c
WIP return MP_OBJ_NULL to indicate exc raised in more API functions
dpgeorge Jul 19, 2019
ac23580
WIP get native code working without NLR
dpgeorge Jul 19, 2019
9a6fb4d
WIP py: rename cur_exc to active_exception
dpgeorge Jul 19, 2019
ca8e055
WIP extmod: rename cur_exc to active_exception
dpgeorge Jul 19, 2019
b2e62d9
WIP unix: rename cur_exc to active_exception
dpgeorge Jul 19, 2019
7f42429
WIP py: handle some more exceptions
dpgeorge Jul 21, 2019
d8b751a
WIP extmod: handle some more exceptions
dpgeorge Jul 21, 2019
0dfd1c6
WIP unix: handle OS errno exceptions
dpgeorge Jul 21, 2019
4affcc0
WIP qemu-arm: get working without NLR
dpgeorge Jul 21, 2019
070880f
WIP lib/upytesthelper: remove need for NLR
dpgeorge Jul 21, 2019
83431c3
WIP py: support stackless without NLR
dpgeorge Jul 21, 2019
50e45bf
WIP py: start to check for OOM in lexer/parser/compiler
dpgeorge Jul 22, 2019
675f23f
WIP unix: start to check for exceptions in start-up code
dpgeorge Jul 22, 2019
599d965
WIP add a way to automatically test for OOM errors
dpgeorge Jul 22, 2019
82d712c
WIP py/runtime: Clear active_exception at very start of mp_init().
dpgeorge Oct 27, 2019
578f7a2
WIP py/vm: Fix access of current exception with sys.settrace enabled.
dpgeorge Oct 27, 2019
7885d49
WIP esp8266: Use minimal manifest for 512k build.
dpgeorge Oct 27, 2019
4561694
WIP extmod/modussl_axtls: Check NULL return from mp_obj_str_get_data.
dpgeorge Nov 1, 2019
b4710b4
WIP py/objstr: Handle invalid iteration when constructing bytes.
dpgeorge Nov 1, 2019
b00107a
WIP extmod/vfs_lfs: Make it work without NLR.
dpgeorge Nov 1, 2019
c5da53f
WIP updates to work after rebase
dpgeorge Dec 13, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion extmod/machine_mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
STATIC uintptr_t machine_mem_get_addr(mp_obj_t addr_o, uint align) {
uintptr_t addr = mp_obj_int_get_truncated(addr_o);
if ((addr & (align - 1)) != 0) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "address %08x is not aligned to %d bytes", addr, align));
mp_raise_o(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "address %08x is not aligned to %d bytes", addr, align));
}
return addr;
}
Expand All @@ -69,6 +69,9 @@ STATIC mp_obj_t machine_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t va
} else if (value == MP_OBJ_SENTINEL) {
// load
uintptr_t addr = MICROPY_MACHINE_MEM_GET_READ_ADDR(index, self->elem_size);
if (MP_STATE_THREAD(active_exception) != NULL) {
return MP_OBJ_NULL;
}
uint32_t val;
switch (self->elem_size) {
case 1: val = (*(uint8_t*)addr); break;
Expand All @@ -79,6 +82,9 @@ STATIC mp_obj_t machine_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t va
} else {
// store
uintptr_t addr = MICROPY_MACHINE_MEM_GET_WRITE_ADDR(index, self->elem_size);
if (MP_STATE_THREAD(active_exception) != NULL) {
return MP_OBJ_NULL;
}
uint32_t val = mp_obj_get_int_truncated(value);
switch (self->elem_size) {
case 1: (*(uint8_t*)addr) = val; break;
Expand Down
2 changes: 1 addition & 1 deletion extmod/machine_signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t
}
} else {
error:
mp_raise_TypeError(NULL);
return mp_raise_TypeError_o(NULL);
}
}

Expand Down
8 changes: 4 additions & 4 deletions extmod/modbtree.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ STATIC const mp_obj_type_t btree_type;

#define CHECK_ERROR(res) \
if (res == RET_ERROR) { \
mp_raise_OSError(errno); \
return mp_raise_OSError_o(errno); \
}

void __dbpanic(DB *db) {
Expand Down Expand Up @@ -256,7 +256,7 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
key.data = (void*)mp_obj_str_get_data(index, &key.size);
int res = __bt_delete(self->db, &key, 0);
if (res == RET_SPECIAL) {
nlr_raise(mp_obj_new_exception(&mp_type_KeyError));
return mp_raise_o(mp_obj_new_exception(&mp_type_KeyError));
}
CHECK_ERROR(res);
return mp_const_none;
Expand All @@ -266,7 +266,7 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
key.data = (void*)mp_obj_str_get_data(index, &key.size);
int res = __bt_get(self->db, &key, &val, 0);
if (res == RET_SPECIAL) {
nlr_raise(mp_obj_new_exception(&mp_type_KeyError));
return mp_raise_o(mp_obj_new_exception(&mp_type_KeyError));
}
CHECK_ERROR(res);
return mp_obj_new_bytes(val.data, val.size);
Expand Down Expand Up @@ -359,7 +359,7 @@ STATIC mp_obj_t mod_btree_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t

DB *db = __bt_open(MP_OBJ_TO_PTR(pos_args[0]), &btree_stream_fvtable, &openinfo, /*dflags*/0);
if (db == NULL) {
mp_raise_OSError(errno);
return mp_raise_OSError_o(errno);
}
return MP_OBJ_FROM_PTR(btree_new(db));
}
Expand Down
2 changes: 1 addition & 1 deletion extmod/modframebuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size
case FRAMEBUF_GS8:
break;
default:
mp_raise_ValueError("invalid format");
return mp_raise_ValueError_o("invalid format");
}

return MP_OBJ_FROM_PTR(o);
Expand Down
6 changes: 3 additions & 3 deletions extmod/modubinascii.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ mp_obj_t mod_binascii_unhexlify(mp_obj_t data) {
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);

if ((bufinfo.len & 1) != 0) {
mp_raise_ValueError("odd-length string");
return mp_raise_ValueError_o("odd-length string");
}
vstr_t vstr;
vstr_init_len(&vstr, bufinfo.len / 2);
Expand All @@ -89,7 +89,7 @@ mp_obj_t mod_binascii_unhexlify(mp_obj_t data) {
if (unichar_isxdigit(hex_ch)) {
hex_byte += unichar_xdigit_value(hex_ch);
} else {
mp_raise_ValueError("non-hex digit found");
return mp_raise_ValueError_o("non-hex digit found");
}
if (i & 1) {
hex_byte <<= 4;
Expand Down Expand Up @@ -157,7 +157,7 @@ mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) {
}

if (nbits) {
mp_raise_ValueError("incorrect padding");
return mp_raise_ValueError_o("incorrect padding");
}

return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
Expand Down
14 changes: 7 additions & 7 deletions extmod/moducryptolib.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ STATIC mp_obj_t ucryptolib_aes_make_new(const mp_obj_type_t *type, size_t n_args
break;

default:
mp_raise_ValueError("mode");
return mp_raise_ValueError_o("mode");
}

mp_obj_aes_t *o = m_new_obj_var(mp_obj_aes_t, struct ctr_params, !!is_ctr_mode(block_mode));
Expand All @@ -237,7 +237,7 @@ STATIC mp_obj_t ucryptolib_aes_make_new(const mp_obj_type_t *type, size_t n_args
mp_buffer_info_t keyinfo;
mp_get_buffer_raise(args[0], &keyinfo, MP_BUFFER_READ);
if (32 != keyinfo.len && 16 != keyinfo.len) {
mp_raise_ValueError("key");
return mp_raise_ValueError_o("key");
}

mp_buffer_info_t ivinfo;
Expand All @@ -246,10 +246,10 @@ STATIC mp_obj_t ucryptolib_aes_make_new(const mp_obj_type_t *type, size_t n_args
mp_get_buffer_raise(args[2], &ivinfo, MP_BUFFER_READ);

if (16 != ivinfo.len) {
mp_raise_ValueError("IV");
return mp_raise_ValueError_o("IV");
}
} else if (o->block_mode == UCRYPTOLIB_MODE_CBC || is_ctr_mode(o->block_mode)) {
mp_raise_ValueError("IV");
return mp_raise_ValueError_o("IV");
}

if (is_ctr_mode(block_mode)) {
Expand All @@ -274,7 +274,7 @@ STATIC mp_obj_t aes_process(size_t n_args, const mp_obj_t *args, bool encrypt) {
mp_get_buffer_raise(in_buf, &in_bufinfo, MP_BUFFER_READ);

if (!is_ctr_mode(self->block_mode) && in_bufinfo.len % 16 != 0) {
mp_raise_ValueError("blksize % 16");
return mp_raise_ValueError_o("blksize % 16");
}

vstr_t vstr;
Expand All @@ -284,7 +284,7 @@ STATIC mp_obj_t aes_process(size_t n_args, const mp_obj_t *args, bool encrypt) {
if (out_buf != MP_OBJ_NULL) {
mp_get_buffer_raise(out_buf, &out_bufinfo, MP_BUFFER_WRITE);
if (out_bufinfo.len < in_bufinfo.len) {
mp_raise_ValueError("output too small");
return mp_raise_ValueError_o("output too small");
}
out_buf_ptr = out_bufinfo.buf;
} else {
Expand All @@ -301,7 +301,7 @@ STATIC mp_obj_t aes_process(size_t n_args, const mp_obj_t *args, bool encrypt) {
if ((encrypt && self->key_type == AES_KEYTYPE_DEC) ||
(!encrypt && self->key_type == AES_KEYTYPE_ENC)) {

mp_raise_ValueError("can't encrypt & decrypt");
return mp_raise_ValueError_o("can't encrypt & decrypt");
}
}

Expand Down
24 changes: 15 additions & 9 deletions extmod/moductypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ typedef struct _mp_obj_uctypes_struct_t {
uint32_t flags;
} mp_obj_uctypes_struct_t;

STATIC NORETURN void syntax_error(void) {
mp_raise_TypeError("syntax error in uctypes descriptor");
STATIC mp_obj_t syntax_error(void) {
return mp_raise_TypeError_o("syntax error in uctypes descriptor");
}

STATIC mp_obj_t uctypes_struct_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
Expand Down Expand Up @@ -222,9 +222,11 @@ STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, int layout_type, mp_uint_
// but scalar structure field is lowered into native Python int, so all
// type info is lost. So, we cannot say if it's scalar type description,
// or such lowered scalar.
mp_raise_TypeError("Cannot unambiguously get sizeof scalar");
mp_raise_TypeError_o("Cannot unambiguously get sizeof scalar");
return (mp_uint_t)-1;
}
syntax_error();
return (mp_uint_t)-1;
}

mp_obj_dict_t *d = MP_OBJ_TO_PTR(desc_in);
Expand All @@ -250,6 +252,7 @@ STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, int layout_type, mp_uint_
} else {
if (!mp_obj_is_type(v, &mp_type_tuple)) {
syntax_error();
return (mp_uint_t)-1;
}
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(v);
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
Expand Down Expand Up @@ -280,7 +283,7 @@ STATIC mp_obj_t uctypes_struct_sizeof(size_t n_args, const mp_obj_t *args) {
// or to instantiated structure
if (mp_obj_is_type(obj_in, &uctypes_struct_type)) {
if (n_args != 1) {
mp_raise_TypeError(NULL);
return mp_raise_TypeError_o(NULL);
}
// Extract structure definition
mp_obj_uctypes_struct_t *obj = MP_OBJ_TO_PTR(obj_in);
Expand All @@ -292,6 +295,9 @@ STATIC mp_obj_t uctypes_struct_sizeof(size_t n_args, const mp_obj_t *args) {
}
}
mp_uint_t size = uctypes_struct_size(obj_in, layout_type, &max_field_size);
if (size == (mp_uint_t)-1) {
return MP_OBJ_NULL;
}
return MP_OBJ_NEW_SMALL_INT(size);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(uctypes_struct_sizeof_obj, 1, 2, uctypes_struct_sizeof);
Expand Down Expand Up @@ -411,7 +417,7 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
&& !mp_obj_is_type(self->desc, &mp_type_ordereddict)
#endif
) {
mp_raise_TypeError("struct: no fields");
return mp_raise_TypeError_o("struct: no fields");
}

mp_obj_t deref = mp_obj_dict_get(self->desc, MP_OBJ_NEW_QSTR(attr));
Expand Down Expand Up @@ -477,12 +483,12 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
}

if (!mp_obj_is_type(deref, &mp_type_tuple)) {
syntax_error();
return syntax_error();
}

if (set_val != MP_OBJ_NULL) {
// Cannot assign to aggregate
syntax_error();
return syntax_error();
}

mp_obj_tuple_t *sub = MP_OBJ_TO_PTR(deref);
Expand Down Expand Up @@ -544,7 +550,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_ob
} else {
// load / store
if (!mp_obj_is_type(self->desc, &mp_type_tuple)) {
mp_raise_TypeError("struct: cannot index");
return mp_raise_TypeError_o("struct: cannot index");
}

mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->desc);
Expand All @@ -558,7 +564,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_ob
uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS);
arr_sz &= VALUE_MASK(VAL_TYPE_BITS);
if (index >= arr_sz) {
mp_raise_msg(&mp_type_IndexError, "struct: index out of range");
return mp_raise_msg_o(&mp_type_IndexError, "struct: index out of range");
}

if (t->len == 2) {
Expand Down
14 changes: 12 additions & 2 deletions extmod/moduheapq.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@

STATIC mp_obj_list_t *uheapq_get_heap(mp_obj_t heap_in) {
if (!mp_obj_is_type(heap_in, &mp_type_list)) {
mp_raise_TypeError("heap must be a list");
mp_raise_TypeError_o("heap must be a list");
return NULL;
}
return MP_OBJ_TO_PTR(heap_in);
}
Expand Down Expand Up @@ -72,6 +73,9 @@ STATIC void uheapq_heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) {

STATIC mp_obj_t mod_uheapq_heappush(mp_obj_t heap_in, mp_obj_t item) {
mp_obj_list_t *heap = uheapq_get_heap(heap_in);
if (heap == NULL) {
return MP_OBJ_NULL;
}
mp_obj_list_append(heap_in, item);
uheapq_heap_siftdown(heap, 0, heap->len - 1);
return mp_const_none;
Expand All @@ -80,8 +84,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_uheapq_heappush_obj, mod_uheapq_heappush);

STATIC mp_obj_t mod_uheapq_heappop(mp_obj_t heap_in) {
mp_obj_list_t *heap = uheapq_get_heap(heap_in);
if (heap == NULL) {
return MP_OBJ_NULL;
}
if (heap->len == 0) {
mp_raise_msg(&mp_type_IndexError, "empty heap");
return mp_raise_msg_o(&mp_type_IndexError, "empty heap");
}
mp_obj_t item = heap->items[0];
heap->len -= 1;
Expand All @@ -96,6 +103,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_uheapq_heappop_obj, mod_uheapq_heappop);

STATIC mp_obj_t mod_uheapq_heapify(mp_obj_t heap_in) {
mp_obj_list_t *heap = uheapq_get_heap(heap_in);
if (heap == NULL) {
return MP_OBJ_NULL;
}
for (mp_uint_t i = heap->len / 2; i > 0;) {
uheapq_heap_siftup(heap, --i);
}
Expand Down
10 changes: 7 additions & 3 deletions extmod/modujson.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
#if MICROPY_PY_UJSON

STATIC mp_obj_t mod_ujson_dump(mp_obj_t obj, mp_obj_t stream) {
mp_get_stream_raise(stream, MP_STREAM_OP_WRITE);
if (mp_get_stream_raise(stream, MP_STREAM_OP_WRITE) == NULL) {
return MP_OBJ_NULL;
}
mp_print_t print = {MP_OBJ_TO_PTR(stream), mp_stream_write_adaptor};
mp_obj_print_helper(&print, obj, PRINT_JSON);
return mp_const_none;
Expand Down Expand Up @@ -79,7 +81,9 @@ typedef struct _ujson_stream_t {
STATIC byte ujson_stream_next(ujson_stream_t *s) {
mp_uint_t ret = s->read(s->stream_obj, &s->cur, 1, &s->errcode);
if (s->errcode != 0) {
mp_raise_OSError(s->errcode);
// TODO deal with raising exception
mp_raise_OSError_o(s->errcode);
return 0xff;
}
if (ret == 0) {
s->cur = S_EOF;
Expand Down Expand Up @@ -276,7 +280,7 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
return stack_top;

fail:
mp_raise_ValueError("syntax error in JSON");
return mp_raise_ValueError_o("syntax error in JSON");
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_load_obj, mod_ujson_load);

Expand Down
8 changes: 4 additions & 4 deletions extmod/modurandom.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ STATIC uint32_t yasmarang_randbelow(uint32_t n) {
STATIC mp_obj_t mod_urandom_getrandbits(mp_obj_t num_in) {
int n = mp_obj_get_int(num_in);
if (n > 32 || n == 0) {
mp_raise_ValueError(NULL);
return mp_raise_ValueError_o(NULL);
}
uint32_t mask = ~0;
// Beware of C undefined behavior when shifting by >= than bit size
Expand Down Expand Up @@ -134,7 +134,7 @@ STATIC mp_obj_t mod_urandom_randrange(size_t n_args, const mp_obj_t *args) {
}

error:
mp_raise_ValueError(NULL);
return mp_raise_ValueError_o(NULL);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_urandom_randrange_obj, 1, 3, mod_urandom_randrange);

Expand All @@ -144,7 +144,7 @@ STATIC mp_obj_t mod_urandom_randint(mp_obj_t a_in, mp_obj_t b_in) {
if (a <= b) {
return mp_obj_new_int(a + yasmarang_randbelow(b - a + 1));
} else {
mp_raise_ValueError(NULL);
return mp_raise_ValueError_o(NULL);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_urandom_randint_obj, mod_urandom_randint);
Expand All @@ -154,7 +154,7 @@ STATIC mp_obj_t mod_urandom_choice(mp_obj_t seq) {
if (len > 0) {
return mp_obj_subscr(seq, mp_obj_new_int(yasmarang_randbelow(len)), MP_OBJ_SENTINEL);
} else {
nlr_raise(mp_obj_new_exception(&mp_type_IndexError));
return mp_raise_o(mp_obj_new_exception(&mp_type_IndexError));
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_urandom_choice_obj, mod_urandom_choice);
Expand Down
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy