diff options
| author | Graydon Hoare <graydon@mozilla.com> | 2012-05-03 12:56:55 -0700 |
|---|---|---|
| committer | Graydon Hoare <graydon@mozilla.com> | 2012-05-03 13:09:02 -0700 |
| commit | 11a5d10bf2958c642ae6a7c4afff8e181aa2167d (patch) | |
| tree | 94e14a4863f8ff951f82556485146960d5584b8a | |
| parent | e1fc7d5f0126e4c213cac589bf301814e0327b9e (diff) | |
| download | rust-11a5d10bf2958c642ae6a7c4afff8e181aa2167d.tar.gz rust-11a5d10bf2958c642ae6a7c4afff8e181aa2167d.zip | |
Implement better shape code for evec, estr.
| -rw-r--r-- | src/rt/rust_box_annihilator.cpp | 12 | ||||
| -rw-r--r-- | src/rt/rust_cc.cpp | 61 | ||||
| -rw-r--r-- | src/rt/rust_shape.cpp | 23 | ||||
| -rw-r--r-- | src/rt/rust_shape.h | 163 | ||||
| -rw-r--r-- | src/rustc/middle/trans/shape.rs | 53 | ||||
| -rw-r--r-- | src/test/run-pass/estr-internal.rs | 22 | ||||
| -rw-r--r-- | src/test/run-pass/estr-slice.rs | 48 |
7 files changed, 336 insertions, 46 deletions
diff --git a/src/rt/rust_box_annihilator.cpp b/src/rt/rust_box_annihilator.cpp index 6322c528791..bc5e0dfdda5 100644 --- a/src/rt/rust_box_annihilator.cpp +++ b/src/rt/rust_box_annihilator.cpp @@ -49,8 +49,16 @@ class annihilator : public shape::data<annihilator,shape::ptr> { task->kernel->free(vec); } + void walk_fixedvec2(uint16_t sz, bool is_pod) { + walk_vec2(is_pod, get_fixedvec_data_range(sz, dp)); + } + void walk_vec2(bool is_pod, const std::pair<shape::ptr,shape::ptr> &data_range) { + + if (is_pod) + return; + annihilator sub(*this, data_range.first); shape::ptr data_end = sub.end_dp = data_range.second; while (sub.dp < data_end) { @@ -64,6 +72,10 @@ class annihilator : public shape::data<annihilator,shape::ptr> { ::walk_variant1(tinfo, tag_variant); } + void walk_rptr2() { } + + void walk_slice2(bool, bool) { } + void walk_uniq2() { void *x = *((void **)dp); // free contents first: diff --git a/src/rt/rust_cc.cpp b/src/rt/rust_cc.cpp index 0b75d856f81..4e3facd0413 100644 --- a/src/rt/rust_cc.cpp +++ b/src/rt/rust_cc.cpp @@ -73,19 +73,37 @@ class irc : public shape::data<irc,shape::ptr> { in_tables, in_data), ircs(in_ircs) {} - void walk_vec2(bool is_pod) { - if (is_pod || shape::get_dp<void *>(dp) == NULL) - return; // There can't be any outbound pointers from this. - std::pair<uint8_t *,uint8_t *> data_range(get_vec_data_range(dp)); + void walk_vec2(bool is_pod, std::pair<uint8_t *,uint8_t *> data_range) { + + // There can't be any outbound pointers from pod. + if (is_pod) + return; + irc sub(*this, data_range.first); shape::ptr data_end = sub.end_dp = data_range.second; while (sub.dp < data_end) { sub.walk_reset(); + // FIXME: shouldn't this be 'sub.align = true;'? align = true; } } + void walk_vec2(bool is_pod) { + if (shape::get_dp<void *>(dp) == NULL) + return; + + walk_vec2(is_pod, get_vec_data_range(dp)); + } + + void walk_slice2(bool is_pod, bool is_str) { + walk_vec2(is_pod, get_slice_data_range(is_str, dp)); + } + + void walk_fixedvec2(uint16_t sz, bool is_pod) { + walk_vec2(is_pod, get_fixedvec_data_range(sz, dp)); + } + void walk_tag2(shape::tag_info &tinfo, uint32_t tag_variant) { shape::data<irc,shape::ptr>::walk_variant1(tinfo, tag_variant); } @@ -102,6 +120,10 @@ class irc : public shape::data<irc,shape::ptr> { shape::data<irc,shape::ptr>::walk_uniq_contents1(); } + void walk_rptr2() { + shape::data<irc,shape::ptr>::walk_rptr_contents1(); + } + void walk_fn2(char code) { switch (code) { case shape::SHAPE_BOX_FN: { @@ -137,6 +159,8 @@ class irc : public shape::data<irc,shape::ptr> { void walk_uniq_contents2(irc &sub) { sub.walk(); } + void walk_rptr_contents2(irc &sub) { sub.walk(); } + void walk_box_contents2(irc &sub) { maybe_record_irc(); @@ -305,11 +329,12 @@ class mark : public shape::data<mark,shape::ptr> { in_tables, in_data), marked(in_marked) {} - void walk_vec2(bool is_pod) { - if (is_pod || shape::get_dp<void *>(dp) == NULL) - return; // There can't be any outbound pointers from this. + void walk_vec2(bool is_pod, std::pair<uint8_t *,uint8_t *> data_range) { + + // There can't be any outbound pointers from pod. + if (is_pod) + return; - std::pair<uint8_t *,uint8_t *> data_range(get_vec_data_range(dp)); if (data_range.second - data_range.first > 100000) abort(); // FIXME: Temporary sanity check. @@ -321,6 +346,20 @@ class mark : public shape::data<mark,shape::ptr> { } } + void walk_vec2(bool is_pod) { + if (shape::get_dp<void *>(dp) == NULL) + return; + walk_vec2(is_pod, get_vec_data_range(dp)); + } + + void walk_slice2(bool is_pod, bool is_str) { + walk_vec2(is_pod, get_slice_data_range(is_str, dp)); + } + + void walk_fixedvec2(uint16_t sz, bool is_pod) { + walk_vec2(is_pod, get_fixedvec_data_range(sz, dp)); + } + void walk_tag2(shape::tag_info &tinfo, uint32_t tag_variant) { shape::data<mark,shape::ptr>::walk_variant1(tinfo, tag_variant); } @@ -337,6 +376,10 @@ class mark : public shape::data<mark,shape::ptr> { shape::data<mark,shape::ptr>::walk_uniq_contents1(); } + void walk_rptr2() { + shape::data<mark,shape::ptr>::walk_rptr_contents1(); + } + void walk_fn2(char code) { switch (code) { case shape::SHAPE_BOX_FN: { @@ -372,6 +415,8 @@ class mark : public shape::data<mark,shape::ptr> { void walk_uniq_contents2(mark &sub) { sub.walk(); } + void walk_rptr_contents2(mark &sub) { sub.walk(); } + void walk_box_contents2(mark &sub) { rust_opaque_box *box_ptr = *(rust_opaque_box **) dp; diff --git a/src/rt/rust_shape.cpp b/src/rt/rust_shape.cpp index 0413b7f9493..9f3fbbed89e 100644 --- a/src/rt/rust_shape.cpp +++ b/src/rt/rust_shape.cpp @@ -254,6 +254,9 @@ class cmp : public data<cmp,ptr_pair> { friend class data<cmp,ptr_pair>; private: + void walk_slice2(bool is_pod, + const std::pair<ptr_pair,ptr_pair> &data_range); + void walk_vec2(bool is_pod, const std::pair<ptr_pair,ptr_pair> &data_range); @@ -274,6 +277,12 @@ private: result = sub.result; } + inline void walk_rptr_contents2(cmp &sub) { + sub.align = true; + sub.walk(); + result = sub.result; + } + inline void cmp_two_pointers() { ALIGN_TO(rust_alignof<void *>()); data_pair<uint8_t *> fst = bump_dp<uint8_t *>(dp); @@ -341,6 +350,16 @@ public: walk_vec2(is_pod, get_vec_data_range(dp)); } + void walk_slice2(bool is_pod, bool is_str) { + // Slices compare just like vecs. + walk_vec2(is_pod, get_slice_data_range(is_str, dp)); + } + + void walk_fixedvec2(uint16_t sz, bool is_pod) { + // Fixedvecs compare just like vecs. + walk_vec2(is_pod, get_fixedvec_data_range(sz, dp)); + } + void walk_box2() { data<cmp,ptr_pair>::walk_box_contents1(); } @@ -349,6 +368,10 @@ public: data<cmp,ptr_pair>::walk_uniq_contents1(); } + void walk_rptr2() { + data<cmp,ptr_pair>::walk_rptr_contents1(); + } + void walk_iface2() { data<cmp,ptr_pair>::walk_box_contents1(); } diff --git a/src/rt/rust_shape.h b/src/rt/rust_shape.h index ee9b6400cd4..112a61ee239 100644 --- a/src/rt/rust_shape.h +++ b/src/rt/rust_shape.h @@ -59,6 +59,8 @@ const uint8_t SHAPE_BARE_FN = 27u; const uint8_t SHAPE_TYDESC = 28u; const uint8_t SHAPE_SEND_TYDESC = 29u; const uint8_t SHAPE_RPTR = 31u; +const uint8_t SHAPE_FIXEDVEC = 32u; +const uint8_t SHAPE_SLICE = 33u; #ifdef _LP64 const uint8_t SHAPE_PTR = SHAPE_U64; @@ -279,6 +281,9 @@ private: void walk_struct0(); void walk_res0(); void walk_var0(); + void walk_rptr0(); + void walk_fixedvec0(); + void walk_slice0(); }; @@ -377,8 +382,11 @@ ctxt<T>::walk() { case SHAPE_UNIQ_FN: case SHAPE_STACK_FN: case SHAPE_BARE_FN: static_cast<T*>(this)->walk_fn1(s); break; - case SHAPE_SEND_TYDESC: - case SHAPE_TYDESC: static_cast<T*>(this)->walk_tydesc1(s); break; + case SHAPE_TYDESC: + case SHAPE_SEND_TYDESC: static_cast<T*>(this)->walk_tydesc1(s); break; + case SHAPE_RPTR: walk_rptr0(); break; + case SHAPE_FIXEDVEC: walk_fixedvec0(); break; + case SHAPE_SLICE: walk_slice0(); break; default: abort(); } } @@ -504,6 +512,44 @@ ctxt<T>::walk_uniq0() { template<typename T> void +ctxt<T>::walk_rptr0() { + uint16_t sp_size = get_u16_bump(sp); + const uint8_t *end_sp = sp + sp_size; + + static_cast<T *>(this)->walk_rptr1(); + + sp = end_sp; +} + +template<typename T> +void +ctxt<T>::walk_fixedvec0() { + uint16_t vec_size = get_u16_bump(sp); + bool is_pod = *sp++; + uint16_t sp_size = get_u16_bump(sp); + const uint8_t *end_sp = sp + sp_size; + + static_cast<T *>(this)->walk_fixedvec1(vec_size, is_pod); + + sp = end_sp; +} + +template<typename T> +void +ctxt<T>::walk_slice0() { + bool is_pod = *sp++; + bool is_str = *sp++; + uint16_t sp_size = get_u16_bump(sp); + const uint8_t *end_sp = sp + sp_size; + + static_cast<T *>(this)->walk_slice1(is_pod, is_str); + + sp = end_sp; +} + + +template<typename T> +void ctxt<T>::walk_struct0() { uint16_t sp_size = get_u16_bump(sp); const uint8_t *end_sp = sp + sp_size; @@ -580,6 +626,15 @@ public: void walk_box1() { DPRINT("@<"); walk(); DPRINT(">"); } + void walk_rptr1() { + DPRINT("&<"); walk(); DPRINT(">"); + } + void walk_fixedvec1(uint16_t sz, bool is_pod) { + DPRINT("fixedvec<%u, ", sz); walk(); DPRINT(">"); + } + void walk_slice1(bool is_pod, bool is_str) { + DPRINT("slice<"); walk(); DPRINT(">"); + } void walk_fn1(char kind) { switch(kind) { @@ -641,6 +696,9 @@ public: void walk_struct1(const uint8_t *end_sp); void walk_uniq1() { sa.set(sizeof(void *), sizeof(void *)); } + void walk_rptr1() { sa.set(sizeof(void *), sizeof(void *)); } + void walk_slice1(bool,bool) + { sa.set(sizeof(void *)*2, sizeof(void *)); } void walk_box1() { sa.set(sizeof(void *), sizeof(void *)); } void walk_fn1(char) { sa.set(sizeof(void *)*2, sizeof(void *)); } void walk_iface1() { sa.set(sizeof(void *), sizeof(void *)); } @@ -663,6 +721,12 @@ public: abort(); // TODO } + void walk_fixedvec1(uint16_t sz, bool is_pod) { + size_of sub(*this); + sub.walk(); + sa.set(sub.sa.size * sz, sub.sa.alignment); + } + template<typename T> void walk_number1() { sa.set(sizeof(T), rust_alignof<T>()); } @@ -881,6 +945,7 @@ protected: void walk_box_contents1(); void walk_uniq_contents1(); + void walk_rptr_contents1(); void walk_fn_contents1(); void walk_iface_contents1(); void walk_variant1(tag_info &tinfo, tag_variant_t variant); @@ -888,6 +953,16 @@ protected: static std::pair<uint8_t *,uint8_t *> get_vec_data_range(ptr dp); static std::pair<ptr_pair,ptr_pair> get_vec_data_range(ptr_pair &dp); + static std::pair<uint8_t *,uint8_t *> get_slice_data_range(bool is_str, + ptr dp); + static std::pair<ptr_pair,ptr_pair> get_slice_data_range(bool is_str, + ptr_pair &dp); + + static std::pair<uint8_t *,uint8_t *> + get_fixedvec_data_range(uint16_t sz, ptr dp); + static std::pair<ptr_pair,ptr_pair> + get_fixedvec_data_range(uint16_t sz, ptr_pair &dp); + public: data(rust_task *in_task, bool in_align, @@ -902,6 +977,7 @@ public: void walk_tag1(tag_info &tinfo); void walk_struct1(const uint8_t *end_sp) { + // FIXME: shouldn't we be aligning to the first element here? static_cast<T *>(this)->walk_struct2(end_sp); } @@ -909,10 +985,22 @@ public: DATA_SIMPLE(void *, walk_vec2(is_pod)); } + void walk_slice1(bool is_pod, bool is_str) { + DATA_SIMPLE(void *, walk_slice2(is_pod, is_str)); + } + + void walk_fixedvec1(uint16_t sz, bool is_pod) { + size_align sa = size_of::get(*this); + ALIGN_TO(sa.alignment); + static_cast<T *>(this)->walk_fixedvec2(sz, is_pod); + } + void walk_box1() { DATA_SIMPLE(void *, walk_box2()); } void walk_uniq1() { DATA_SIMPLE(void *, walk_uniq2()); } + void walk_rptr1() { DATA_SIMPLE(void *, walk_rptr2()); } + void walk_fn1(char code) { ALIGN_TO(rust_alignof<void *>()); U next_dp = dp + sizeof(void *) * 2; @@ -987,6 +1075,15 @@ data<T,U>::walk_uniq_contents1() { template<typename T,typename U> void +data<T,U>::walk_rptr_contents1() { + typename U::template data<uint8_t *>::t box_ptr = bump_dp<uint8_t *>(dp); + U data_ptr(box_ptr); + T sub(*static_cast<T *>(this), data_ptr); + static_cast<T *>(this)->walk_rptr_contents2(sub); +} + +template<typename T,typename U> +void data<T,U>::walk_variant1(tag_info &tinfo, tag_variant_t variant_id) { std::pair<const uint8_t *,const uint8_t *> variant_ptr_and_end = this->get_variant_sp(tinfo, variant_id); @@ -1013,6 +1110,45 @@ data<T,U>::get_vec_data_range(ptr_pair &dp) { } template<typename T,typename U> +std::pair<uint8_t *,uint8_t *> +data<T,U>::get_slice_data_range(bool is_str, ptr dp) { + uint8_t* ptr = bump_dp<uint8_t*>(dp); + size_t len = bump_dp<size_t>(dp); + if (is_str) len--; + return std::make_pair(ptr, ptr + len); +} + +template<typename T,typename U> +std::pair<ptr_pair,ptr_pair> +data<T,U>::get_slice_data_range(bool is_str, ptr_pair &dp) { + std::pair<uint8_t *,uint8_t *> fst = + get_slice_data_range(is_str, dp.fst); + std::pair<uint8_t *,uint8_t *> snd = + get_slice_data_range(is_str, dp.snd); + ptr_pair start(fst.first, snd.first); + ptr_pair end(fst.second, snd.second); + return std::make_pair(start, end); +} + +template<typename T,typename U> +std::pair<uint8_t *,uint8_t *> +data<T,U>::get_fixedvec_data_range(uint16_t sz, ptr dp) { + uint8_t* ptr = (uint8_t*)(dp); + return std::make_pair(ptr, ptr + sz); +} + +template<typename T,typename U> +std::pair<ptr_pair,ptr_pair> +data<T,U>::get_fixedvec_data_range(uint16_t sz, ptr_pair &dp) { + std::pair<uint8_t *,uint8_t *> fst = get_fixedvec_data_range(sz, dp.fst); + std::pair<uint8_t *,uint8_t *> snd = get_fixedvec_data_range(sz, dp.snd); + ptr_pair start(fst.first, snd.first); + ptr_pair end(fst.second, snd.second); + return std::make_pair(start, end); +} + + +template<typename T,typename U> void data<T,U>::walk_tag1(tag_info &tinfo) { size_of::compute_tag_size(*this, tinfo); @@ -1111,6 +1247,16 @@ private: walk_vec2(is_pod, get_vec_data_range(dp)); } + void walk_slice2(bool is_pod, bool is_str) { + walk_vec2(is_pod, get_slice_data_range(dp, is_str)); + out << "/&"; + } + + void walk_fixedvec2(uint16_t sz, bool is_pod) { + walk_vec2(is_pod, get_fixedvec_data_range(sz, dp)); + out << "/" << sz; + } + void walk_tag2(tag_info &tinfo, tag_variant_t tag_variant) { // out << prefix << "tag" << tag_variant; out << prefix << get_variant_name(tinfo, tag_variant); @@ -1129,6 +1275,12 @@ private: data<log,ptr>::walk_uniq_contents1(); } + void walk_rptr2() { + out << prefix << "&"; + prefix = ""; + data<log,ptr>::walk_rptr_contents1(); + } + void walk_fn2(char kind) { out << prefix << "fn"; prefix = ""; @@ -1165,8 +1317,15 @@ private: sub.walk(); } + void walk_rptr_contents2(log &sub) { + out << prefix; + sub.align = true; + sub.walk(); + } + void walk_struct2(const uint8_t *end_sp); void walk_vec2(bool is_pod, const std::pair<ptr,ptr> &data); + void walk_slice2(bool is_pod, const std::pair<ptr,ptr> &data); void walk_variant2(tag_info &tinfo, tag_variant_t variant_id, const std::pair<const uint8_t *,const uint8_t *> diff --git a/src/rustc/middle/trans/shape.rs b/src/rustc/middle/trans/shape.rs index 68166cbf728..ce6afcd844d 100644 --- a/src/rustc/middle/trans/shape.rs +++ b/src/rustc/middle/trans/shape.rs @@ -361,50 +361,39 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] { s } - // FIXME: grotesque hacks for encoding fixed-size evecs and estrs. - ty::ty_estr(ty::vstore_fixed(n)) { - let mut s = [shape_struct], sub = []; - let mut i = 0u; + let mut s = [shape_fixedvec]; let u8_t = ty::mk_mach_uint(ccx.tcx, ast::ty_u8); - while i < n { - sub += shape_of(ccx, u8_t, ty_param_map); - i += 1u; - } - add_substr(s, sub); + assert (n + 1u) <= 0xffffu; + add_u16(s, (n + 1u) as u16); + add_bool(s, true); + add_substr(s, shape_of(ccx, u8_t, ty_param_map)); s } ty::ty_evec(mt, ty::vstore_fixed(n)) { - let mut s = [shape_struct], sub = []; - let mut i = 0u; - while i < n { - sub += shape_of(ccx, mt.ty, ty_param_map); - i += 1u; - } - add_substr(s, sub); + let mut s = [shape_fixedvec]; + assert n <= 0xffffu; + add_u16(s, n as u16); + add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty)); + add_substr(s, shape_of(ccx, mt.ty, ty_param_map)); s } - - // FIXME: slightly-less-grotesque hack for encoding slic,e evecs and - // estrs. - ty::ty_estr(ty::vstore_slice(r)) { - let mut s = [shape_struct], sub = []; - let u8_mt = {ty: ty::mk_mach_uint(ccx.tcx, ast::ty_u8), - mutbl: ast::m_imm }; - sub += shape_of(ccx, ty::mk_rptr(ccx.tcx, r, u8_mt), ty_param_map); - sub += shape_of(ccx, ty::mk_uint(ccx.tcx), ty_param_map); - add_substr(s, sub); + let mut s = [shape_slice]; + let u8_t = ty::mk_mach_uint(ccx.tcx, ast::ty_u8); + add_bool(s, true); // is_pod + add_bool(s, true); // is_str + add_substr(s, shape_of(ccx, u8_t, ty_param_map)); s } ty::ty_evec(mt, ty::vstore_slice(r)) { - let mut s = [shape_struct], sub = []; - sub += shape_of(ccx, ty::mk_rptr(ccx.tcx, r, mt), ty_param_map); - sub += shape_of(ccx, ty::mk_uint(ccx.tcx), ty_param_map); - add_substr(s, sub); + let mut s = [shape_slice]; + add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty)); + add_bool(s, false); // is_str + add_substr(s, shape_of(ccx, mt.ty, ty_param_map)); s } @@ -434,9 +423,9 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] { add_substr(s, sub); s } - ty::ty_rptr(_, tm) { + ty::ty_rptr(_, mt) { let mut s = [shape_rptr]; - add_substr(s, shape_of(ccx, tm.ty, ty_param_map)); + add_substr(s, shape_of(ccx, mt.ty, ty_param_map)); s } ty::ty_res(did, raw_subt, substs) { diff --git a/src/test/run-pass/estr-internal.rs b/src/test/run-pass/estr-internal.rs index d7f7fd6b41a..b5290f3c0ab 100644 --- a/src/test/run-pass/estr-internal.rs +++ b/src/test/run-pass/estr-internal.rs @@ -5,4 +5,26 @@ fn main() { z = x; assert z[0] == ('h' as u8); assert z[4] == ('o' as u8); + + let a = "aaaa"/_; + let b = "bbbb"/_; + let c = "cccc"/_; + + log(debug, a); + + assert a < b; + assert a <= b; + assert a != b; + assert b >= a; + assert b > a; + + log(debug, b); + + assert a < c; + assert a <= c; + assert a != c; + assert c >= a; + assert c > a; + + log(debug, c); } diff --git a/src/test/run-pass/estr-slice.rs b/src/test/run-pass/estr-slice.rs index f91474cba8b..af31e546c6a 100644 --- a/src/test/run-pass/estr-slice.rs +++ b/src/test/run-pass/estr-slice.rs @@ -1,7 +1,47 @@ + fn main() { let x = "hello"/&; - let mut y = "there"/&; - y = x; - assert y[0] == 'h' as u8; - assert y[4] == 'o' as u8; + let v = "hello"/&; + let mut y : str/& = "there"/&; + + log(debug, x); + log(debug, y); + + assert x[0] == 'h' as u8; + assert x[4] == 'o' as u8; + + let z : str/& = "thing"/&; + assert v == x; + assert x != z; + + let a = "aaaa"/&; + let b = "bbbb"/&; + let c = "cccc"/&; + let cc = "ccccc"/&; + + log(debug, a); + + assert a < b; + assert a <= b; + assert a != b; + assert b >= a; + assert b > a; + + log(debug, b); + + assert a < c; + assert a <= c; + assert a != c; + assert c >= a; + assert c > a; + + log(debug, c); + + assert c < cc; + assert c <= cc; + assert c != cc; + assert cc >= c; + assert cc > c; + + log(debug, cc); } \ No newline at end of file |
