Support a special const-value refcount, use it for const strings.
This commit is contained in:
parent
3e9be14757
commit
89946609f2
10 changed files with 97 additions and 30 deletions
|
@ -12,6 +12,9 @@
|
||||||
|
|
||||||
let rc_base_field_refcnt = 0;;
|
let rc_base_field_refcnt = 0;;
|
||||||
|
|
||||||
|
(* FIXME: this needs updating if you ever want to work on 64 bit. *)
|
||||||
|
let const_refcount = 0x7badfaceL;;
|
||||||
|
|
||||||
let task_field_refcnt = rc_base_field_refcnt;;
|
let task_field_refcnt = rc_base_field_refcnt;;
|
||||||
let task_field_stk = task_field_refcnt + 2;;
|
let task_field_stk = task_field_refcnt + 2;;
|
||||||
let task_field_runtime_sp = task_field_stk + 1;;
|
let task_field_runtime_sp = task_field_stk + 1;;
|
||||||
|
|
|
@ -1531,13 +1531,32 @@ let trans_visitor
|
||||||
if not init
|
if not init
|
||||||
then drop_ty_in_current_frame cell ty
|
then drop_ty_in_current_frame cell ty
|
||||||
|
|
||||||
and trans_new_str (initializing:bool) (dst:Ast.lval) (s:string) : unit =
|
and trans_new_str
|
||||||
|
(initializing:bool)
|
||||||
|
(dst:Ast.lval)
|
||||||
|
(s:string)
|
||||||
|
(id:node_id)
|
||||||
|
: unit =
|
||||||
(* Include null byte. *)
|
(* Include null byte. *)
|
||||||
let init_sz = Int64.of_int ((String.length s) + 1) in
|
let init_sz = Int64.of_int ((String.length s) + 1) in
|
||||||
let static = trans_static_string s in
|
|
||||||
let (dst_cell, dst_ty) = trans_lval_maybe_init initializing dst in
|
let (dst_cell, dst_ty) = trans_lval_maybe_init initializing dst in
|
||||||
drop_existing_if_not_init initializing dst_cell dst_ty;
|
drop_existing_if_not_init initializing dst_cell dst_ty;
|
||||||
trans_upcall "upcall_new_str" dst_cell [| static; imm init_sz |]
|
let ptr =
|
||||||
|
crate_rel_to_ptr
|
||||||
|
(trans_crate_rel_data_operand
|
||||||
|
(DATA_const id)
|
||||||
|
(fun _ ->
|
||||||
|
Asm.SEQ
|
||||||
|
[|
|
||||||
|
Asm.WORD (word_ty_signed_mach,
|
||||||
|
Asm.IMM Abi.const_refcount);
|
||||||
|
Asm.WORD (word_ty_mach, Asm.IMM init_sz);
|
||||||
|
Asm.WORD (word_ty_mach, Asm.IMM init_sz);
|
||||||
|
Asm.ZSTRING s
|
||||||
|
|]))
|
||||||
|
(referent_type cx Ast.TY_str)
|
||||||
|
in
|
||||||
|
mov dst_cell (Il.Cell ptr);
|
||||||
|
|
||||||
and trans_lit (lit:Ast.lit) : Il.operand =
|
and trans_lit (lit:Ast.lit) : Il.operand =
|
||||||
match lit with
|
match lit with
|
||||||
|
@ -3185,7 +3204,7 @@ let trans_visitor
|
||||||
in
|
in
|
||||||
let _ = check_box_rty box_ptr in
|
let _ = check_box_rty box_ptr in
|
||||||
let null_jmp = null_check box_ptr in
|
let null_jmp = null_check box_ptr in
|
||||||
let rc_jmp = drop_refcount_and_cmp box_ptr in
|
let rc_jmps = drop_refcount_and_cmp box_ptr in
|
||||||
let box = deref box_ptr in
|
let box = deref box_ptr in
|
||||||
let body = get_element_ptr box Abi.box_rc_field_body in
|
let body = get_element_ptr box Abi.box_rc_field_body in
|
||||||
let tydesc = get_element_ptr body Abi.obj_body_elt_tydesc in
|
let tydesc = get_element_ptr body Abi.obj_body_elt_tydesc in
|
||||||
|
@ -3230,7 +3249,7 @@ let trans_visitor
|
||||||
note_drop_step ty "drop_ty: freeing obj/fn body";
|
note_drop_step ty "drop_ty: freeing obj/fn body";
|
||||||
trans_free box_ptr (type_has_state cx ty);
|
trans_free box_ptr (type_has_state cx ty);
|
||||||
mov box_ptr zero;
|
mov box_ptr zero;
|
||||||
patch rc_jmp;
|
List.iter patch rc_jmps;
|
||||||
patch null_jmp;
|
patch null_jmp;
|
||||||
note_drop_step ty "drop_ty: done obj path";
|
note_drop_step ty "drop_ty: done obj path";
|
||||||
|
|
||||||
|
@ -3262,7 +3281,7 @@ let trans_visitor
|
||||||
|
|
||||||
let _ = check_box_rty cell in
|
let _ = check_box_rty cell in
|
||||||
let null_jmp = null_check cell in
|
let null_jmp = null_check cell in
|
||||||
let j = drop_refcount_and_cmp cell in
|
let js = drop_refcount_and_cmp cell in
|
||||||
|
|
||||||
(* FIXME (issue #25): check to see that the box has
|
(* FIXME (issue #25): check to see that the box has
|
||||||
* further box members; if it doesn't we can elide the
|
* further box members; if it doesn't we can elide the
|
||||||
|
@ -3277,7 +3296,7 @@ let trans_visitor
|
||||||
(* Null the slot out to prevent double-free if the frame
|
(* Null the slot out to prevent double-free if the frame
|
||||||
* unwinds. *)
|
* unwinds. *)
|
||||||
mov cell zero;
|
mov cell zero;
|
||||||
patch j;
|
List.iter patch js;
|
||||||
patch null_jmp;
|
patch null_jmp;
|
||||||
note_drop_step ty "drop_ty: done box-drop path";
|
note_drop_step ty "drop_ty: done box-drop path";
|
||||||
|
|
||||||
|
@ -3525,7 +3544,7 @@ let trans_visitor
|
||||||
(* Returns a mark for a jmp that must be patched to the continuation of
|
(* Returns a mark for a jmp that must be patched to the continuation of
|
||||||
* the non-zero refcount case (i.e. fall-through means zero refcount).
|
* the non-zero refcount case (i.e. fall-through means zero refcount).
|
||||||
*)
|
*)
|
||||||
and drop_refcount_and_cmp (boxed:Il.cell) : quad_idx =
|
and drop_refcount_and_cmp (boxed:Il.cell) : quad_idx list =
|
||||||
in_quad_category "refcount"
|
in_quad_category "refcount"
|
||||||
begin
|
begin
|
||||||
fun _ ->
|
fun _ ->
|
||||||
|
@ -3539,11 +3558,14 @@ let trans_visitor
|
||||||
trace_word true boxed;
|
trace_word true boxed;
|
||||||
trace_word true rc
|
trace_word true rc
|
||||||
end;
|
end;
|
||||||
emit (Il.binary Il.SUB rc (Il.Cell rc) one);
|
emit (Il.cmp (Il.Cell rc) (simm Abi.const_refcount));
|
||||||
emit (Il.cmp (Il.Cell rc) zero);
|
let j0 = mark() in
|
||||||
let j = mark () in
|
emit (Il.jmp Il.JE Il.CodeNone);
|
||||||
emit (Il.jmp Il.JNE Il.CodeNone);
|
emit (Il.binary Il.SUB rc (Il.Cell rc) one);
|
||||||
j
|
emit (Il.cmp (Il.Cell rc) zero);
|
||||||
|
let j1 = mark () in
|
||||||
|
emit (Il.jmp Il.JNE Il.CodeNone);
|
||||||
|
[j0; j1]
|
||||||
end
|
end
|
||||||
|
|
||||||
and incr_refcount (boxed:Il.cell) : unit =
|
and incr_refcount (boxed:Il.cell) : unit =
|
||||||
|
@ -3559,7 +3581,11 @@ let trans_visitor
|
||||||
trace_word true boxed;
|
trace_word true boxed;
|
||||||
trace_word true rc
|
trace_word true rc
|
||||||
end;
|
end;
|
||||||
add_to rc one
|
emit (Il.cmp (Il.Cell rc) (simm Abi.const_refcount));
|
||||||
|
let j = mark() in
|
||||||
|
emit (Il.jmp Il.JE Il.CodeNone);
|
||||||
|
add_to rc one;
|
||||||
|
patch j;
|
||||||
end
|
end
|
||||||
|
|
||||||
and drop_slot
|
and drop_slot
|
||||||
|
@ -5316,7 +5342,7 @@ let trans_visitor
|
||||||
|
|
||||||
| Ast.STMT_new_str (dst, s) ->
|
| Ast.STMT_new_str (dst, s) ->
|
||||||
let init = maybe_init stmt.id "new str" dst in
|
let init = maybe_init stmt.id "new str" dst in
|
||||||
trans_new_str init dst s
|
trans_new_str init dst s stmt.id
|
||||||
|
|
||||||
| Ast.STMT_new_vec (dst, _, atoms) ->
|
| Ast.STMT_new_vec (dst, _, atoms) ->
|
||||||
let init = maybe_init stmt.id "new vec" dst in
|
let init = maybe_init stmt.id "new vec" dst in
|
||||||
|
|
|
@ -97,8 +97,13 @@ fn from_bytes(vec[u8] v) : is_utf8(v) -> str {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn refcount(str s) -> uint {
|
fn refcount(str s) -> uint {
|
||||||
// -1 because calling this function incremented the refcount.
|
auto r = rustrt.refcount[u8](s);
|
||||||
ret rustrt.refcount[u8](s) - 1u;
|
if (r == dbg.const_refcount) {
|
||||||
|
ret r;
|
||||||
|
} else {
|
||||||
|
// -1 because calling this function incremented the refcount.
|
||||||
|
ret r - 1u;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,13 @@ fn alloc[T](uint n_elts) -> vec[T] {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn refcount[T](vec[T] v) -> uint {
|
fn refcount[T](vec[T] v) -> uint {
|
||||||
// -1 because calling this function incremented the refcount.
|
auto r = rustrt.refcount[T](v);
|
||||||
ret rustrt.refcount[T](v) - 1u;
|
if (r == dbg.const_refcount) {
|
||||||
|
ret r;
|
||||||
|
} else {
|
||||||
|
// -1 because calling this function incremented the refcount.
|
||||||
|
ret r - 1u;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type init_op[T] = fn(uint i) -> T;
|
type init_op[T] = fn(uint i) -> T;
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
|
|
||||||
import std._vec;
|
import std._vec;
|
||||||
|
|
||||||
|
// FIXME: handle 64-bit case.
|
||||||
|
const uint const_refcount = 0x7bad_face_u;
|
||||||
|
|
||||||
native "rust" mod rustrt {
|
native "rust" mod rustrt {
|
||||||
fn debug_tydesc[T]();
|
fn debug_tydesc[T]();
|
||||||
fn debug_opaque[T](&T x);
|
fn debug_opaque[T](&T x);
|
||||||
|
|
|
@ -61,8 +61,12 @@ align_of(rust_task *task, type_desc *t) {
|
||||||
return t->align;
|
return t->align;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" CDECL size_t
|
extern "C" CDECL intptr_t
|
||||||
refcount(rust_task *task, type_desc *t, size_t *v) {
|
refcount(rust_task *task, type_desc *t, intptr_t *v) {
|
||||||
|
|
||||||
|
if (*v == CONST_REFCOUNT)
|
||||||
|
return CONST_REFCOUNT;
|
||||||
|
|
||||||
// Passed-in value has refcount 1 too high
|
// Passed-in value has refcount 1 too high
|
||||||
// because it was ref'ed while making the call.
|
// because it was ref'ed while making the call.
|
||||||
return (*v) - 1;
|
return (*v) - 1;
|
||||||
|
@ -277,7 +281,9 @@ debug_box(rust_task *task, type_desc *t, rust_box *box)
|
||||||
task->log(rust_log::STDLIB, "debug_box(0x%" PRIxPTR ")", box);
|
task->log(rust_log::STDLIB, "debug_box(0x%" PRIxPTR ")", box);
|
||||||
debug_tydesc_helper(task, t);
|
debug_tydesc_helper(task, t);
|
||||||
task->log(rust_log::STDLIB, " refcount %" PRIdPTR,
|
task->log(rust_log::STDLIB, " refcount %" PRIdPTR,
|
||||||
box->ref_count - 1); // -1 because we ref'ed for this call
|
box->ref_count == CONST_REFCOUNT
|
||||||
|
? CONST_REFCOUNT
|
||||||
|
: box->ref_count - 1); // -1 because we ref'ed for this call
|
||||||
for (uintptr_t i = 0; i < t->size; ++i) {
|
for (uintptr_t i = 0; i < t->size; ++i) {
|
||||||
task->log(rust_log::STDLIB,
|
task->log(rust_log::STDLIB,
|
||||||
" byte %" PRIdPTR ": 0x%" PRIx8, i, box->data[i]);
|
" byte %" PRIdPTR ": 0x%" PRIx8, i, box->data[i]);
|
||||||
|
|
|
@ -81,6 +81,13 @@ struct frame_glue_fns;
|
||||||
|
|
||||||
static size_t const TIME_SLICE_IN_MS = 10;
|
static size_t const TIME_SLICE_IN_MS = 10;
|
||||||
|
|
||||||
|
// Since every refcounted object is > 4 bytes, any refcount with any of the
|
||||||
|
// top two bits set is invalid. We reserve a particular bit pattern in this
|
||||||
|
// set for indicating objects that are "constant" as far as the memory model
|
||||||
|
// knows.
|
||||||
|
|
||||||
|
static intptr_t const CONST_REFCOUNT = 0x7badface;
|
||||||
|
|
||||||
// Every reference counted object should derive from this base class.
|
// Every reference counted object should derive from this base class.
|
||||||
|
|
||||||
template <typename T> struct rc_base {
|
template <typename T> struct rc_base {
|
||||||
|
|
|
@ -424,7 +424,10 @@ upcall_vec_grow(rust_task *task,
|
||||||
task->fail(4);
|
task->fail(4);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
v->deref();
|
|
||||||
|
if (v->ref_count != CONST_REFCOUNT)
|
||||||
|
v->deref();
|
||||||
|
|
||||||
v = new (mem) rust_vec(dom, alloc, 0, NULL);
|
v = new (mem) rust_vec(dom, alloc, 0, NULL);
|
||||||
*need_copy = 1;
|
*need_copy = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
use std;
|
use std;
|
||||||
import std._str;
|
import std._str;
|
||||||
|
|
||||||
|
// FIXME: import std.dbg.const_refcount. Currently
|
||||||
|
// cross-crate const references don't work.
|
||||||
|
const uint const_refcount = 0x7bad_face_u;
|
||||||
|
|
||||||
tag t {
|
tag t {
|
||||||
make_t(str);
|
make_t(str);
|
||||||
clam;
|
clam;
|
||||||
|
@ -17,12 +21,12 @@ fn foo(str s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
log _str.refcount(s);
|
log _str.refcount(s);
|
||||||
check (_str.refcount(s) == 3u);
|
check (_str.refcount(s) == const_refcount);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let str s = "hi"; // ref up
|
let str s = "hi"; // ref up
|
||||||
foo(s); // ref up then down
|
foo(s); // ref up then down
|
||||||
log _str.refcount(s);
|
log _str.refcount(s);
|
||||||
check (_str.refcount(s) == 1u);
|
check (_str.refcount(s) == const_refcount);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,11 @@ use std;
|
||||||
import std._str;
|
import std._str;
|
||||||
import std._vec;
|
import std._vec;
|
||||||
|
|
||||||
|
|
||||||
|
// FIXME: import std.dbg.const_refcount. Currently
|
||||||
|
// cross-crate const references don't work.
|
||||||
|
const uint const_refcount = 0x7bad_face_u;
|
||||||
|
|
||||||
fn fast_growth() {
|
fn fast_growth() {
|
||||||
let vec[int] v = vec(1,2,3,4,5);
|
let vec[int] v = vec(1,2,3,4,5);
|
||||||
v += vec(6,7,8,9,0);
|
v += vec(6,7,8,9,0);
|
||||||
|
@ -55,8 +60,8 @@ fn slow_growth2_helper(str s) { // ref up: s
|
||||||
log _str.refcount(mumble);
|
log _str.refcount(mumble);
|
||||||
|
|
||||||
check (_vec.refcount[str](v) == 1u);
|
check (_vec.refcount[str](v) == 1u);
|
||||||
check (_str.refcount(s) == 4u);
|
check (_str.refcount(s) == const_refcount);
|
||||||
check (_str.refcount(mumble) == 3u);
|
check (_str.refcount(mumble) == const_refcount);
|
||||||
|
|
||||||
log v.(0);
|
log v.(0);
|
||||||
log _vec.len[str](v);
|
log _vec.len[str](v);
|
||||||
|
@ -67,8 +72,8 @@ fn slow_growth2_helper(str s) { // ref up: s
|
||||||
log _str.refcount(s);
|
log _str.refcount(s);
|
||||||
log _str.refcount(mumble);
|
log _str.refcount(mumble);
|
||||||
|
|
||||||
check (_str.refcount(s) == 3u);
|
check (_str.refcount(s) == const_refcount);
|
||||||
check (_str.refcount(mumble) == 1u);
|
check (_str.refcount(mumble) == const_refcount);
|
||||||
|
|
||||||
log mumble;
|
log mumble;
|
||||||
log ss;
|
log ss;
|
||||||
|
@ -78,7 +83,7 @@ fn slow_growth2() {
|
||||||
let str s = "hi"; // ref up: s
|
let str s = "hi"; // ref up: s
|
||||||
slow_growth2_helper(s);
|
slow_growth2_helper(s);
|
||||||
log _str.refcount(s);
|
log _str.refcount(s);
|
||||||
check (_str.refcount(s) == 1u);
|
check (_str.refcount(s) == const_refcount);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
Loading…
Reference in a new issue