aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile13
-rw-r--r--src/boot/be/abi.ml5
-rw-r--r--src/boot/be/il.ml7
-rw-r--r--src/boot/be/x86.ml61
-rw-r--r--src/boot/me/dwarf.ml4
-rw-r--r--src/boot/me/layout.ml8
-rw-r--r--src/boot/me/semant.ml69
-rw-r--r--src/boot/me/trans.ml177
-rw-r--r--src/lib/deque.rs4
-rw-r--r--src/rt/circular_buffer.cpp4
-rw-r--r--src/rt/globals.h2
-rw-r--r--src/rt/rust.cpp8
-rw-r--r--src/rt/rust_chan.cpp27
-rw-r--r--src/rt/rust_chan.h2
-rw-r--r--src/rt/rust_dom.cpp81
-rw-r--r--src/rt/rust_dom.h4
-rw-r--r--src/rt/rust_internal.h4
-rw-r--r--src/rt/rust_log.cpp1
-rw-r--r--src/rt/rust_message.cpp3
-rw-r--r--src/rt/rust_port.cpp40
-rw-r--r--src/rt/rust_port.h2
-rw-r--r--src/rt/rust_task.cpp13
-rw-r--r--src/rt/rust_upcall.cpp96
-rw-r--r--src/rt/rust_util.h26
-rw-r--r--src/rt/sync/condition_variable.cpp28
-rw-r--r--src/rt/sync/condition_variable.h1
-rw-r--r--src/rt/sync/sync.cpp12
-rw-r--r--src/rt/sync/sync.h9
-rw-r--r--src/rt/util/array_list.h10
-rw-r--r--src/run.py81
-rw-r--r--src/test/run-pass/arith-0.rs5
-rw-r--r--src/test/run-pass/arith-1.rs22
-rw-r--r--src/test/run-pass/arith-2.rs5
-rw-r--r--src/test/run-pass/basic-1.rs25
-rw-r--r--src/test/run-pass/basic-2.rs26
-rw-r--r--src/test/run-pass/task-comm-0.rs2
-rw-r--r--src/test/run-pass/task-comm-2.rs8
-rw-r--r--src/test/run-pass/task-comm-3.rs19
-rw-r--r--src/test/run-pass/task-comm-6.rs6
-rw-r--r--src/test/run-pass/task-comm.rs18
40 files changed, 694 insertions, 244 deletions
diff --git a/src/Makefile b/src/Makefile
index 2aa06d4f..496457bb 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -245,7 +245,8 @@ BOOT_CMXS := $(BOOT_MLS:.ml=.cmx)
BOOT_OBJS := $(BOOT_MLS:.ml=.o)
BOOT_CMIS := $(BOOT_MLS:.ml=.cmi)
-RUNTIME_CS := rt/sync/spin_lock.cpp \
+RUNTIME_CS := rt/sync/sync.cpp \
+ rt/sync/spin_lock.cpp \
rt/sync/lock_free_queue.cpp \
rt/sync/condition_variable.cpp \
rt/rust.cpp \
@@ -279,7 +280,8 @@ RUNTIME_HDR := rt/globals.h \
rt/rust_message.h \
rt/circular_buffer.h \
rt/util/array_list.h \
- rt/util/hash_map.h
+ rt/util/hash_map.h \
+ rt/sync/sync.h
RUNTIME_INCS := -Irt/isaac -Irt/uthash
RUNTIME_OBJS := $(RUNTIME_CS:.cpp=$(CFG_OBJ_SUFFIX))
@@ -383,7 +385,10 @@ TASK_XFAILS := test/run-pass/acyclic-unwind.rs \
test/run-pass/threads.rs \
test/run-pass/yield.rs
+TEST_XFAILS := test/run-pass/arith-0.rs
+
TEST_XFAILS_X86 := $(TASK_XFAILS) \
+ $(TEST_XFAILS) \
test/run-pass/arithmetic-interference.rs \
test/run-pass/bind-obj-ctor.rs \
test/run-pass/child-outlives-parent.rs \
@@ -414,7 +419,9 @@ TEST_XFAILS_X86 := $(TASK_XFAILS) \
test/compile-fail/writing-through-read-alias.rs
TEST_XFAILS_LLVM := $(TASK_XFAILS) \
+ $(TEST_XFAILS) \
$(addprefix test/run-pass/, \
+ arith-1.rs \
acyclic-unwind.rs \
alt-pattern-simple.rs \
alt-tag.rs \
@@ -423,6 +430,8 @@ TEST_XFAILS_LLVM := $(TASK_XFAILS) \
autoderef-full-lval.rs \
autoderef-objfn.rs \
basic.rs \
+ basic-1.rs \
+ basic-2.rs \
bind-obj-ctor.rs \
bind-thunk.rs \
bind-trivial.rs \
diff --git a/src/boot/be/abi.ml b/src/boot/be/abi.ml
index 347d49fc..5bdf21fa 100644
--- a/src/boot/be/abi.ml
+++ b/src/boot/be/abi.ml
@@ -41,7 +41,7 @@ let box_gc_header_size = 4;;
let box_gc_malloc_return_adjustment = 3;;
-let stk_field_valgrind_id = 0 + 1;;
+let stk_field_valgrind_id = 0;;
let stk_field_limit = stk_field_valgrind_id + 1;;
let stk_field_data = stk_field_limit + 1;;
@@ -121,7 +121,8 @@ type abi =
-> Common.size (* callsz *)
-> Common.nabi
-> Common.fixup (* grow_task *)
- -> unit);
+ -> bool (* is_obj_fn *)
+ -> unit);
abi_emit_fn_epilogue: (Il.emitter -> unit);
diff --git a/src/boot/be/il.ml b/src/boot/be/il.ml
index 172d8661..2a5b643a 100644
--- a/src/boot/be/il.ml
+++ b/src/boot/be/il.ml
@@ -901,6 +901,13 @@ let get_element_ptr
(string_of_cell fmt mem_cell)
;;
+let ptr_cast (cell:cell) (rty:referent_ty) : cell =
+ match cell with
+ Mem (mem, _) -> Mem (mem, rty)
+ | Reg (reg, AddrTy _) -> Reg (reg, AddrTy rty)
+ | _ -> bug () "expected address cell in Il.ptr_cast"
+;;
+
(*
* Local Variables:
* fill-column: 78;
diff --git a/src/boot/be/x86.ml b/src/boot/be/x86.ml
index 55b101bb..826127a0 100644
--- a/src/boot/be/x86.ml
+++ b/src/boot/be/x86.ml
@@ -593,6 +593,7 @@ let restore_frame_base (e:Il.emitter) (base:Il.reg) (retpc:Il.reg) : unit =
*
* *ebp+20+(4*N) = [argN ]
* ...
+ * *ebp+28 = [arg2 ] = obj/closure ptr
* *ebp+24 = [arg1 ] = task ptr
* *ebp+20 = [arg0 ] = out ptr
* *ebp+16 = [retpc ]
@@ -1033,7 +1034,7 @@ let unwind_glue
(* Puts result in eax; clobbers ecx, edx in the process. *)
-let rec calculate_sz (e:Il.emitter) (size:size) : unit =
+let rec calculate_sz (e:Il.emitter) (size:size) (in_obj:bool) : unit =
let emit = Il.emit e in
let mov dst src = emit (Il.umov dst src) in
let push x = emit (Il.Push x) in
@@ -1045,11 +1046,48 @@ let rec calculate_sz (e:Il.emitter) (size:size) : unit =
let mul x y = emit (Il.binary Il.UMUL (rc x) (ro x) (ro y)) in
let subi x y = emit (Il.binary Il.SUB (rc x) (ro x) (immi y)) in
let eax_gets_a_and_ecx_gets_b a b =
- calculate_sz e b;
+ calculate_sz e b in_obj;
push (ro eax);
- calculate_sz e a;
+ calculate_sz e a in_obj;
pop (rc ecx);
in
+
+ let ty_param_n_in_obj_fn i =
+ (*
+ * Here we are trying to immitate the obj-fn branch of
+ * Trans.get_ty_params_of_current_frame while using
+ * eax as our only register.
+ *)
+
+ (* Bind all the referent types we'll need... *)
+
+ let obj_body_rty = Semant.obj_closure_rty word_bits in
+ let tydesc_rty = Semant.tydesc_rty word_bits in
+ (* Note that we cheat here and pretend only to have i+1 tydescs (because
+ we GEP to the i'th while still in this function, so no one outside
+ finds out about the lie. *)
+ let tydesc_tys = Array.init (i + 1) (fun _ -> Ast.TY_type) in
+ let ty_params_ty = Ast.TY_tup tydesc_tys in
+ let ty_params_rty = Semant.referent_type word_bits ty_params_ty in
+
+ (* ... and fetch! *)
+
+ mov (rc eax) (Il.Cell closure_ptr);
+ let obj_body = word_n (h eax) Abi.box_rc_field_body in
+ let obj_body = Il.ptr_cast obj_body obj_body_rty in
+ let tydesc_ptr = get_element_ptr obj_body Abi.obj_body_elt_tydesc in
+
+ mov (rc eax) (Il.Cell tydesc_ptr);
+ let tydesc = Il.ptr_cast (word_at (h eax)) tydesc_rty in
+ let ty_params_ptr =
+ get_element_ptr tydesc Abi.tydesc_field_first_param
+ in
+
+ mov (rc eax) (Il.Cell ty_params_ptr);
+ let ty_params = Il.ptr_cast (word_at (h eax)) ty_params_rty in
+ get_element_ptr ty_params i
+ in
+
match size with
SIZE_fixed i ->
mov (rc eax) (immi i)
@@ -1061,15 +1099,23 @@ let rec calculate_sz (e:Il.emitter) (size:size) : unit =
mov (rc eax) (imm (Asm.M_POS f))
| SIZE_param_size i ->
- mov (rc eax) (Il.Cell (ty_param_n i));
+ if in_obj
+ then
+ mov (rc eax) (Il.Cell (ty_param_n_in_obj_fn i))
+ else
+ mov (rc eax) (Il.Cell (ty_param_n i));
mov (rc eax) (Il.Cell (word_n (h eax) Abi.tydesc_field_size))
| SIZE_param_align i ->
- mov (rc eax) (Il.Cell (ty_param_n i));
+ if in_obj
+ then
+ mov (rc eax) (Il.Cell (ty_param_n_in_obj_fn i))
+ else
+ mov (rc eax) (Il.Cell (ty_param_n i));
mov (rc eax) (Il.Cell (word_n (h eax) Abi.tydesc_field_align))
| SIZE_rt_neg a ->
- calculate_sz e a;
+ calculate_sz e a in_obj;
neg eax
| SIZE_rt_add (a, b) ->
@@ -1185,6 +1231,7 @@ let fn_prologue
(callsz:size)
(nabi:nabi)
(grow_task_fixup:fixup)
+ (is_obj_fn:bool)
: unit =
let esi_n = word_n (h esi) in
@@ -1314,7 +1361,7 @@ let fn_prologue
emit (Il.jmp Il.JA Il.CodeNone);
(* Calculate dynamic frame size. *)
- calculate_sz e call_and_frame_sz;
+ calculate_sz e call_and_frame_sz is_obj_fn;
((ro eax), Some primordial_underflow_jmp_pc)
end
| Some e -> ((imm e), None)
diff --git a/src/boot/me/dwarf.ml b/src/boot/me/dwarf.ml
index d3fb81de..0ec7af78 100644
--- a/src/boot/me/dwarf.ml
+++ b/src/boot/me/dwarf.ml
@@ -1677,7 +1677,7 @@ let dwarf_visitor
in
let record trec =
- let rty = referent_type abi (Ast.TY_rec trec) in
+ let rty = referent_type word_bits (Ast.TY_rec trec) in
let rty_sz = Il.referent_ty_size abi.Abi.abi_word_bits in
let fix = new_fixup "record type DIE" in
let die = DEF (fix, SEQ [|
@@ -1926,7 +1926,7 @@ let dwarf_visitor
* I'm a bit surprised by that!
*)
- let rty = referent_type abi (Ast.TY_tag ttag) in
+ let rty = referent_type word_bits (Ast.TY_tag ttag) in
let rty_sz = Il.referent_ty_size abi.Abi.abi_word_bits in
let rtys =
match rty with
diff --git a/src/boot/me/layout.ml b/src/boot/me/layout.ml
index 1df37f0f..cfd087ff 100644
--- a/src/boot/me/layout.ml
+++ b/src/boot/me/layout.ml
@@ -113,7 +113,7 @@ let layout_visitor
| Il.CodeTy -> true
| Il.NilTy -> false
in
- rt_in_mem (slot_referent_type cx.ctxt_abi slot)
+ rt_in_mem (slot_referent_type cx.ctxt_abi.Abi.abi_word_bits slot)
in
let rty_sz rty = Il.referent_ty_size cx.ctxt_abi.Abi.abi_word_bits rty in
@@ -142,7 +142,7 @@ let layout_visitor
: unit =
let accum (off,align) id : (size * size) =
let slot = get_slot cx id in
- let rt = slot_referent_type cx.ctxt_abi slot in
+ let rt = slot_referent_type cx.ctxt_abi.Abi.abi_word_bits slot in
let (elt_size, elt_align) = rty_layout rt in
if vregs_ok
&& (is_subword_size elt_size)
@@ -170,7 +170,9 @@ let layout_visitor
then elt_off
else neg_sz (add_sz elt_off elt_size)
in
- Stack.push (slot_referent_type cx.ctxt_abi slot) slot_accum;
+ Stack.push
+ (slot_referent_type cx.ctxt_abi.Abi.abi_word_bits slot)
+ slot_accum;
iflog
begin
fun _ ->
diff --git a/src/boot/me/semant.ml b/src/boot/me/semant.ml
index bcaec2b4..a3a8abdf 100644
--- a/src/boot/me/semant.ml
+++ b/src/boot/me/semant.ml
@@ -1822,24 +1822,24 @@ let run_passes
(* Rust type -> IL type conversion. *)
-let word_sty (abi:Abi.abi) : Il.scalar_ty =
- Il.ValTy abi.Abi.abi_word_bits
+let word_sty (word_bits:Il.bits) : Il.scalar_ty =
+ Il.ValTy word_bits
;;
-let word_rty (abi:Abi.abi) : Il.referent_ty =
- Il.ScalarTy (word_sty abi)
+let word_rty (word_bits:Il.bits) : Il.referent_ty =
+ Il.ScalarTy (word_sty word_bits)
;;
-let tydesc_rty (abi:Abi.abi) : Il.referent_ty =
+let tydesc_rty (word_bits:Il.bits) : Il.referent_ty =
(*
* NB: must match corresponding tydesc structure
* in trans and offsets in ABI exactly.
*)
Il.StructTy
[|
- word_rty abi; (* Abi.tydesc_field_first_param *)
- word_rty abi; (* Abi.tydesc_field_size *)
- word_rty abi; (* Abi.tydesc_field_align *)
+ word_rty word_bits; (* Abi.tydesc_field_first_param *)
+ word_rty word_bits; (* Abi.tydesc_field_size *)
+ word_rty word_bits; (* Abi.tydesc_field_align *)
Il.ScalarTy (Il.AddrTy Il.CodeTy); (* Abi.tydesc_field_copy_glue *)
Il.ScalarTy (Il.AddrTy Il.CodeTy); (* Abi.tydesc_field_drop_glue *)
Il.ScalarTy (Il.AddrTy Il.CodeTy); (* Abi.tydesc_field_free_glue *)
@@ -1849,29 +1849,29 @@ let tydesc_rty (abi:Abi.abi) : Il.referent_ty =
|]
;;
-let obj_closure_rty (abi:Abi.abi) : Il.referent_ty =
+let obj_closure_rty (word_bits:Il.bits) : Il.referent_ty =
Il.StructTy [|
- word_rty abi;
+ word_rty word_bits;
Il.StructTy [|
- Il.ScalarTy (Il.AddrTy (tydesc_rty abi));
- word_rty abi (* A lie: it's opaque, but this permits
- * GEP'ing to it. *)
+ Il.ScalarTy (Il.AddrTy (tydesc_rty word_bits));
+ word_rty word_bits (* A lie: it's opaque, but this permits
+ * GEP'ing to it. *)
|]
|]
;;
-let rec referent_type (abi:Abi.abi) (t:Ast.ty) : Il.referent_ty =
+let rec referent_type (word_bits:Il.bits) (t:Ast.ty) : Il.referent_ty =
let s t = Il.ScalarTy t in
let v b = Il.ValTy b in
let p t = Il.AddrTy t in
let sv b = s (v b) in
let sp t = s (p t) in
- let word = word_rty abi in
+ let word = word_rty word_bits in
let ptr = sp Il.OpaqueTy in
let rc_ptr = sp (Il.StructTy [| word; Il.OpaqueTy |]) in
let codeptr = sp Il.CodeTy in
- let tup ttup = Il.StructTy (Array.map (referent_type abi) ttup) in
+ let tup ttup = Il.StructTy (Array.map (referent_type word_bits) ttup) in
let tag ttag =
let union =
Il.UnionTy
@@ -1916,7 +1916,7 @@ let rec referent_type (abi:Abi.abi) (t:Ast.ty) : Il.referent_ty =
Il.StructTy [| codeptr; fn_closure_ptr |]
| Ast.TY_obj _ ->
- let obj_closure_ptr = sp (obj_closure_rty abi) in
+ let obj_closure_ptr = sp (obj_closure_rty word_bits) in
Il.StructTy [| ptr; obj_closure_ptr |]
| Ast.TY_tag ttag -> tag ttag
@@ -1928,26 +1928,26 @@ let rec referent_type (abi:Abi.abi) (t:Ast.ty) : Il.referent_ty =
| Ast.TY_port _
| Ast.TY_task -> rc_ptr
- | Ast.TY_type -> sp (tydesc_rty abi)
+ | Ast.TY_type -> sp (tydesc_rty word_bits)
| Ast.TY_native _ -> ptr
| Ast.TY_box t ->
- sp (Il.StructTy [| word; referent_type abi t |])
+ sp (Il.StructTy [| word; referent_type word_bits t |])
- | Ast.TY_mutable t -> referent_type abi t
+ | Ast.TY_mutable t -> referent_type word_bits t
| Ast.TY_param (i, _) -> Il.ParamTy i
| Ast.TY_named _ -> bug () "named type in referent_type"
- | Ast.TY_constrained (t, _) -> referent_type abi t
+ | Ast.TY_constrained (t, _) -> referent_type word_bits t
-and slot_referent_type (abi:Abi.abi) (sl:Ast.slot) : Il.referent_ty =
+and slot_referent_type (word_bits:Il.bits) (sl:Ast.slot) : Il.referent_ty =
let s t = Il.ScalarTy t in
let p t = Il.AddrTy t in
let sp t = s (p t) in
- let rty = referent_type abi (slot_ty sl) in
+ let rty = referent_type word_bits (slot_ty sl) in
match sl.Ast.slot_mode with
| Ast.MODE_local -> rty
| Ast.MODE_alias -> sp rty
@@ -1958,7 +1958,7 @@ let task_rty (abi:Abi.abi) : Il.referent_ty =
begin
Array.init
Abi.n_visible_task_fields
- (fun _ -> word_rty abi)
+ (fun _ -> word_rty abi.Abi.abi_word_bits)
end
;;
@@ -1970,14 +1970,17 @@ let call_args_referent_type_full
(iterator_arg_rtys:Il.referent_ty array)
(indirect_arg_rtys:Il.referent_ty array)
: Il.referent_ty =
- let out_slot_rty = slot_referent_type abi out_slot in
+ let out_slot_rty = slot_referent_type abi.Abi.abi_word_bits out_slot in
let out_ptr_rty = Il.ScalarTy (Il.AddrTy out_slot_rty) in
let task_ptr_rty = Il.ScalarTy (Il.AddrTy (task_rty abi)) in
let ty_param_rtys =
- let td = Il.ScalarTy (Il.AddrTy (tydesc_rty abi)) in
+ let td = Il.ScalarTy (Il.AddrTy (tydesc_rty abi.Abi.abi_word_bits)) in
Il.StructTy (Array.init n_ty_params (fun _ -> td))
in
- let arg_rtys = Il.StructTy (Array.map (slot_referent_type abi) in_slots) in
+ let arg_rtys =
+ Il.StructTy
+ (Array.map (slot_referent_type abi.Abi.abi_word_bits) in_slots)
+ in
(*
* NB: must match corresponding calltup structure in trans and
* member indices in ABI exactly.
@@ -2003,7 +2006,7 @@ let call_args_referent_type
(* Abi.indirect_args_elt_closure *)
match closure with
None ->
- [| word_rty cx.ctxt_abi |]
+ [| word_rty cx.ctxt_abi.Abi.abi_word_bits |]
| Some c ->
[| Il.ScalarTy (Il.AddrTy c) |]
in
@@ -2057,16 +2060,18 @@ let direct_call_args_referent_type
;;
let ty_sz (abi:Abi.abi) (t:Ast.ty) : int64 =
- force_sz (Il.referent_ty_size abi.Abi.abi_word_bits (referent_type abi t))
+ let wb = abi.Abi.abi_word_bits in
+ force_sz (Il.referent_ty_size wb (referent_type wb t))
;;
let ty_align (abi:Abi.abi) (t:Ast.ty) : int64 =
- force_sz (Il.referent_ty_align abi.Abi.abi_word_bits (referent_type abi t))
+ let wb = abi.Abi.abi_word_bits in
+ force_sz (Il.referent_ty_align wb (referent_type wb t))
;;
let slot_sz (abi:Abi.abi) (s:Ast.slot) : int64 =
- force_sz (Il.referent_ty_size abi.Abi.abi_word_bits
- (slot_referent_type abi s))
+ let wb = abi.Abi.abi_word_bits in
+ force_sz (Il.referent_ty_size wb (slot_referent_type wb s))
;;
let word_slot (abi:Abi.abi) : Ast.slot =
diff --git a/src/boot/me/trans.ml b/src/boot/me/trans.ml
index 01a89c56..620b27e7 100644
--- a/src/boot/me/trans.ml
+++ b/src/boot/me/trans.ml
@@ -292,7 +292,7 @@ let trans_visitor
in
let ptr_at (mem:Il.mem) (pointee_ty:Ast.ty) : Il.cell =
- rty_ptr_at mem (referent_type abi pointee_ty)
+ rty_ptr_at mem (referent_type word_bits pointee_ty)
in
let need_scalar_ty (rty:Il.referent_ty) : Il.scalar_ty =
@@ -330,11 +330,7 @@ let trans_visitor
(cell_str mem_cell)
in
- let rec ptr_cast (cell:Il.cell) (rty:Il.referent_ty) : Il.cell =
- match cell with
- Il.Mem (mem, _) -> Il.Mem (mem, rty)
- | Il.Reg (reg, Il.AddrTy _) -> Il.Reg (reg, Il.AddrTy rty)
- | _ -> bug () "expected address cell in Trans.ptr_cast"
+ let rec ptr_cast = Il.ptr_cast
and curr_crate_ptr _ : Il.cell =
word_at (fp_imm frame_crate_ptr)
@@ -453,13 +449,22 @@ let trans_visitor
in
let slot_id_referent_type (slot_id:node_id) : Il.referent_ty =
- slot_referent_type abi (get_slot cx slot_id)
+ slot_referent_type word_bits (get_slot cx slot_id)
in
let caller_args_cell (args_rty:Il.referent_ty) : Il.cell =
Il.Mem (fp_imm out_mem_disp, args_rty)
in
+ let get_obj_box_from_calltup (args_cell:Il.cell) =
+ let indirect_args =
+ get_element_ptr args_cell Abi.calltup_elt_indirect_args
+ in
+ deref (ptr_cast
+ (get_element_ptr indirect_args Abi.indirect_args_elt_closure)
+ (Il.ScalarTy (Il.AddrTy (obj_closure_rty word_bits))))
+ in
+
let fp_to_args (fp:Il.cell) (args_rty:Il.referent_ty): Il.cell =
let (reg, _) = force_to_reg (Il.Cell fp) in
Il.Mem(based_imm reg out_mem_disp, args_rty)
@@ -469,11 +474,43 @@ let trans_visitor
get_element_ptr ty_params param_idx
in
- let get_ty_params_of_frame (fp:Il.reg) (n_params:int) : Il.cell =
- let fn_ty = mk_simple_ty_fn [| |] in
- let fn_rty = call_args_referent_type cx n_params fn_ty None in
- let args_cell = Il.Mem (based_imm fp out_mem_disp, fn_rty) in
- get_element_ptr args_cell Abi.calltup_elt_ty_params
+ let get_ty_params_of_frame
+ (fnid:node_id)
+ (fp:Il.reg)
+ (n_ty_params:int)
+ : Il.cell =
+
+ let fn_ty = mk_simple_ty_fn [| |] in
+ let fn_rty =
+ call_args_referent_type cx n_ty_params fn_ty (Some Il.OpaqueTy)
+ in
+ let args_cell = Il.Mem (based_imm fp out_mem_disp, fn_rty) in
+
+ if defn_id_is_obj_fn_or_drop cx fnid
+ then
+ (*
+ * To get the typarams in an obj fn, we must go to the
+ * implicit obj's captured type descriptor.
+ *)
+ let obj_box =
+ get_obj_box_from_calltup args_cell
+ in
+ let obj = get_element_ptr obj_box Abi.box_rc_field_body in
+ let tydesc = get_element_ptr obj Abi.obj_body_elt_tydesc in
+ let ty_params_ty = Ast.TY_tup (make_tydesc_tys n_ty_params) in
+ let ty_params_rty = referent_type word_bits ty_params_ty in
+ let ty_params =
+ get_element_ptr (deref tydesc) Abi.tydesc_field_first_param
+ in
+ let ty_params =
+ ptr_cast ty_params (Il.ScalarTy (Il.AddrTy ty_params_rty))
+ in
+ deref ty_params
+ else
+ (*
+ * Regular function --- typarams are right in the frame calltup.
+ *)
+ get_element_ptr args_cell Abi.calltup_elt_ty_params
in
let get_args_for_current_frame _ =
@@ -520,34 +557,10 @@ let trans_visitor
Abi.iterator_args_elt_outer_frame_ptr
in
- let get_obj_for_current_frame _ =
- deref (ptr_cast
- (get_closure_for_current_frame ())
- (Il.ScalarTy (Il.AddrTy (obj_closure_rty abi))))
- in
-
let get_ty_params_of_current_frame _ : Il.cell =
- let id = current_fn() in
- let n_ty_params = n_item_ty_params cx id in
- if defn_id_is_obj_fn_or_drop cx id
- then
- begin
- let obj_box = get_obj_for_current_frame() in
- let obj = get_element_ptr obj_box Abi.box_rc_field_body in
- let tydesc = get_element_ptr obj Abi.obj_body_elt_tydesc in
- let ty_params_ty = Ast.TY_tup (make_tydesc_tys n_ty_params) in
- let ty_params_rty = referent_type abi ty_params_ty in
- let ty_params =
- get_element_ptr (deref tydesc) Abi.tydesc_field_first_param
- in
- let ty_params =
- ptr_cast ty_params (Il.ScalarTy (Il.AddrTy ty_params_rty))
- in
- deref ty_params
- end
-
- else
- get_ty_params_of_frame abi.Abi.abi_fp_reg n_ty_params
+ let fnid = current_fn() in
+ let n_ty_params = n_item_ty_params cx fnid in
+ get_ty_params_of_frame fnid abi.Abi.abi_fp_reg n_ty_params
in
let get_ty_param_in_current_frame (param_idx:int) : Il.cell =
@@ -721,7 +734,7 @@ let trans_visitor
in
let ty_sz_in_current_frame (ty:Ast.ty) : Il.operand =
- let rty = referent_type abi ty in
+ let rty = referent_type word_bits ty in
let sz = Il.referent_ty_size word_bits rty in
calculate_sz_in_current_frame sz
in
@@ -730,7 +743,7 @@ let trans_visitor
(ty_params:Il.cell)
(ty:Ast.ty)
: Il.operand =
- let rty = referent_type abi ty in
+ let rty = referent_type word_bits ty in
let sz = Il.referent_ty_size word_bits rty in
calculate_sz ty_params sz
in
@@ -931,7 +944,7 @@ let trans_visitor
mov idx atop;
emit (Il.binary Il.UMUL idx (Il.Cell idx) unit_sz);
let elt_mem = trans_bounds_check (deref cell) (Il.Cell idx) in
- (Il.Mem (elt_mem, referent_type abi ty), ty)
+ (Il.Mem (elt_mem, referent_type word_bits ty), ty)
in
(*
* All lval components aside from explicit-deref just auto-deref
@@ -1120,7 +1133,7 @@ let trans_visitor
and trans_static_string (s:string) : Il.operand =
Il.Cell (crate_rel_to_ptr
(trans_crate_rel_static_string_operand s)
- (referent_type abi Ast.TY_str))
+ (referent_type word_bits Ast.TY_str))
and get_static_tydesc
(idopt:node_id option)
@@ -1226,7 +1239,7 @@ let trans_visitor
let fty = Hashtbl.find (snd caller) ident in
let self_args_rty =
call_args_referent_type cx 0
- (Ast.TY_fn fty) (Some (obj_closure_rty abi))
+ (Ast.TY_fn fty) (Some (obj_closure_rty word_bits))
in
let callsz = Il.referent_ty_size word_bits self_args_rty in
let spill = new_fixup "forwarding fn spill" in
@@ -1394,7 +1407,7 @@ let trans_visitor
push_new_emitter_with_vregs None;
iflog (fun _ -> annotate "prologue");
abi.Abi.abi_emit_fn_prologue (emitter())
- framesz callsz nabi_rust (upcall_fixup "upcall_grow_task");
+ framesz callsz nabi_rust (upcall_fixup "upcall_grow_task") false;
write_frame_info_ptrs None;
(* FIXME: not clear why, but checking interrupt in glue context
* causes many.rs to crash when run on a sufficiently large number
@@ -1473,8 +1486,8 @@ let trans_visitor
(* FIXME (issue #5): mutability flag *)
: Il.referent_ty =
let rc = Il.ScalarTy word_sty in
- let targ = referent_type abi (mk_simple_ty_fn [||]) in
- let bindings = Array.map (slot_referent_type abi) bs in
+ let targ = referent_type word_bits (mk_simple_ty_fn [||]) in
+ let bindings = Array.map (slot_referent_type word_bits) bs in
Il.StructTy [| rc; targ; Il.StructTy bindings |]
(* FIXME (issue #2): this should eventually use tail calling logic *)
@@ -2333,7 +2346,7 @@ let trans_visitor
(get_element_ptr_dyn_in_current_frame
vec Abi.vec_elt_data))
in
- let unit_rty = referent_type abi unit_ty in
+ let unit_rty = referent_type word_bits unit_ty in
let body_rty = Il.StructTy (Array.map (fun _ -> unit_rty) atoms) in
let body = Il.Mem (body_mem, body_rty) in
Array.iteri
@@ -2379,12 +2392,12 @@ let trans_visitor
let root_desc =
Il.Cell (crate_rel_to_ptr
(get_static_tydesc idopt t 0L 0L force_stateful)
- (tydesc_rty abi))
+ (tydesc_rty word_bits))
in
let (t, param_descs) = linearize_ty_params t in
let descs = Array.append [| root_desc |] param_descs in
let n = Array.length descs in
- let rty = referent_type abi t in
+ let rty = referent_type word_bits t in
let (size_sz, align_sz) = Il.referent_ty_layout word_bits rty in
let size = calculate_sz_in_current_frame size_sz in
let align = calculate_sz_in_current_frame align_sz in
@@ -2420,7 +2433,7 @@ let trans_visitor
(ty_sz abi ty)
(ty_align abi ty)
mut)
- (tydesc_rty abi))
+ (tydesc_rty word_bits))
and box_rc_cell (cell:Il.cell) : Il.cell =
get_element_ptr (deref cell) Abi.box_rc_field_refcnt
@@ -2437,7 +2450,7 @@ let trans_visitor
in
let ty = simplified_ty ty in
let refty_sz =
- Il.referent_ty_size abi.Abi.abi_word_bits (referent_type abi ty)
+ Il.referent_ty_size abi.Abi.abi_word_bits (referent_type word_bits ty)
in
match refty_sz with
SIZE_fixed _ -> imm (Int64.add (ty_sz abi ty) header_sz)
@@ -2534,7 +2547,7 @@ let trans_visitor
trans_compare_simple Il.JAE (Il.Cell ptr) (Il.Cell lim)
in
let unit_cell =
- deref (ptr_cast ptr (referent_type abi unit_ty))
+ deref (ptr_cast ptr (referent_type word_bits unit_ty))
in
f unit_cell unit_cell unit_ty curr_iso;
add_to ptr unit_sz;
@@ -2934,6 +2947,7 @@ let trans_visitor
(slot:Ast.slot)
(curr_iso:Ast.ty_iso option)
: unit =
+ check_and_flush_chan cell slot;
drop_slot (get_ty_params_of_current_frame()) cell slot curr_iso
and drop_ty_in_current_frame
@@ -4190,6 +4204,25 @@ let trans_visitor
let last_jumps = Array.map trans_arm at.Ast.alt_tag_arms in
Array.iter patch last_jumps
+ (* If we're about to drop a channel, synthesize an upcall_flush_chan.
+ * TODO: This should rather appear in a chan dtor when chans become
+ * objects. *)
+ and check_and_flush_chan
+ (cell:Il.cell)
+ (slot:Ast.slot)
+ : unit =
+ let ty = strip_mutable_or_constrained_ty (slot_ty slot) in
+ match simplified_ty ty with
+ Ast.TY_chan _ ->
+ annotate "check_and_flush_chan, flush_chan";
+ let rc = box_rc_cell cell in
+ emit (Il.cmp (Il.Cell rc) one);
+ let jump = mark () in
+ emit (Il.jmp Il.JNE Il.CodeNone);
+ trans_void_upcall "upcall_flush_chan" [| Il.Cell cell |];
+ patch jump;
+ | _ -> ()
+
and drop_slots_at_curr_stmt _ : unit =
let stmt = Stack.top curr_stmt in
match htab_search cx.ctxt_post_stmt_slot_drops stmt with
@@ -4292,7 +4325,7 @@ let trans_visitor
push_new_emitter_with_vregs (Some id);
iflog (fun _ -> annotate "prologue");
abi.Abi.abi_emit_fn_prologue (emitter())
- framesz callsz nabi_rust (upcall_fixup "upcall_grow_task");
+ framesz callsz nabi_rust (upcall_fixup "upcall_grow_task") false;
write_frame_info_ptrs None;
iflog (fun _ -> annotate "finished prologue");
trans_block fe.Ast.for_each_body;
@@ -4376,7 +4409,7 @@ let trans_visitor
let dst_fill = get_element_ptr dst_vec Abi.vec_elt_fill in
(* Copy loop: *)
- let eltp_rty = Il.AddrTy (referent_type abi elt_ty) in
+ let eltp_rty = Il.AddrTy (referent_type word_bits elt_ty) in
let dptr = next_vreg_cell eltp_rty in
let sptr = next_vreg_cell eltp_rty in
let dlim = next_vreg_cell eltp_rty in
@@ -4696,6 +4729,8 @@ let trans_visitor
let get_frame_glue glue inner =
get_mem_glue glue
begin
+ (* `mem` here is a pointer to the frame we are marking, dropping,
+ or relocing, etc. *)
fun mem ->
iter_frame_and_arg_slots cx fnid
begin
@@ -4703,10 +4738,19 @@ let trans_visitor
match htab_search cx.ctxt_slot_offsets slot_id with
Some off when not (slot_is_obj_state cx slot_id) ->
let referent_type = slot_id_referent_type slot_id in
+ (*
+ * This might look as though we're always taking the
+ * pointer-to-frame and giving it the type of the
+ * frame/arg of interest, but this is because our
+ * deref_off a few lines later takes the referent
+ * type of the given poiinter (`st`) as the referent
+ * type of the mem-offset-from-the-given-pointer
+ * that it returns.
+ *)
let fp_cell = rty_ptr_at mem referent_type in
let (fp, st) = force_to_reg (Il.Cell fp_cell) in
let ty_params =
- get_ty_params_of_frame fp n_ty_params
+ get_ty_params_of_frame fnid fp n_ty_params
in
let slot_cell =
deref_off_sz ty_params (Il.Reg (fp,st)) off
@@ -4754,7 +4798,7 @@ let trans_visitor
end
in
- let trans_frame_entry (fnid:node_id) : unit =
+ let trans_frame_entry (fnid:node_id) (obj_fn:bool) : unit =
let framesz = get_framesz cx fnid in
let callsz = get_callsz cx fnid in
Stack.push (Stack.create()) epilogue_jumps;
@@ -4768,7 +4812,7 @@ let trans_visitor
(string_of_size callsz)));
abi.Abi.abi_emit_fn_prologue
(emitter()) framesz callsz nabi_rust
- (upcall_fixup "upcall_grow_task");
+ (upcall_fixup "upcall_grow_task") obj_fn;
write_frame_info_ptrs (Some fnid);
check_interrupt_flag ();
@@ -4792,8 +4836,9 @@ let trans_visitor
let trans_fn
(fnid:node_id)
(body:Ast.block)
+ (obj_fn:bool)
: unit =
- trans_frame_entry fnid;
+ trans_frame_entry fnid obj_fn;
trans_block body;
trans_frame_exit fnid true;
in
@@ -4802,7 +4847,7 @@ let trans_visitor
(obj_id:node_id)
(header:Ast.header_slots)
: unit =
- trans_frame_entry obj_id;
+ trans_frame_entry obj_id true;
let all_args_rty = current_fn_args_rty None in
let all_args_cell = caller_args_cell all_args_rty in
@@ -4821,7 +4866,7 @@ let trans_visitor
let obj_args_ty = Ast.TY_tup obj_args_tup in
let state_ty = Ast.TY_tup [| Ast.TY_type; obj_args_ty |] in
let state_ptr_ty = Ast.TY_box state_ty in
- let state_ptr_rty = referent_type abi state_ptr_ty in
+ let state_ptr_rty = referent_type word_bits state_ptr_ty in
let state_malloc_sz = box_allocation_size state_ptr_ty in
let ctor_ty = Hashtbl.find cx.ctxt_all_item_types obj_id in
@@ -4923,7 +4968,7 @@ let trans_visitor
in
let trans_required_fn (fnid:node_id) (blockid:node_id) : unit =
- trans_frame_entry fnid;
+ trans_frame_entry fnid false;
emit (Il.Enter (Hashtbl.find cx.ctxt_block_fixups blockid));
let (ilib, conv) = Hashtbl.find cx.ctxt_required_items fnid in
let lib_num =
@@ -5061,7 +5106,7 @@ let trans_visitor
(tagid:node_id)
(tag:(Ast.header_tup * Ast.ty_tag * node_id))
: unit =
- trans_frame_entry tagid;
+ trans_frame_entry tagid false;
trace_str cx.ctxt_sess.Session.sess_trace_tag
("in tag constructor " ^ n);
let (header_tup, _, _) = tag in
@@ -5124,7 +5169,7 @@ let trans_visitor
iflog (fun _ -> log cx "translating defined item #%d = %s"
(int_of_node i.id) (path_name()));
match i.node.Ast.decl_item with
- Ast.MOD_ITEM_fn f -> trans_fn i.id f.Ast.fn_body
+ Ast.MOD_ITEM_fn f -> trans_fn i.id f.Ast.fn_body false
| Ast.MOD_ITEM_tag t -> trans_tag n i.id t
| Ast.MOD_ITEM_obj ob ->
trans_obj_ctor i.id
@@ -5158,7 +5203,7 @@ let trans_visitor
push_new_emitter_with_vregs (Some b.id);
iflog (fun _ -> annotate "prologue");
abi.Abi.abi_emit_fn_prologue (emitter())
- framesz callsz nabi_rust (upcall_fixup "upcall_grow_task");
+ framesz callsz nabi_rust (upcall_fixup "upcall_grow_task") true;
write_frame_info_ptrs None;
iflog (fun _ -> annotate "finished prologue");
trans_block b;
@@ -5168,7 +5213,7 @@ let trans_visitor
in
let visit_defined_obj_fn_pre _ _ fn =
- trans_fn fn.id fn.node.Ast.fn_body
+ trans_fn fn.id fn.node.Ast.fn_body true
in
let visit_required_obj_fn_pre _ _ _ =
diff --git a/src/lib/deque.rs b/src/lib/deque.rs
index bf7acb53..3f2a81a4 100644
--- a/src/lib/deque.rs
+++ b/src/lib/deque.rs
@@ -47,7 +47,7 @@ fn create[T]() -> t[T] {
ret _vec.init_fn[cell[T]](copy_op, nalloc);
}
- fn get[T](&vec[cell[T]] elts, uint i) -> T {
+ fn get[T](vec[cell[T]] elts, uint i) -> T {
alt (elts.(i)) {
case (util.some[T](t)) { ret t; }
case (_) { fail; }
@@ -100,6 +100,7 @@ fn create[T]() -> t[T] {
let T t = get[T](elts, lo);
elts.(lo) = util.none[T]();
lo = (lo + 1u) % _vec.len[cell[T]](elts);
+ nelts -= 1u;
ret t;
}
@@ -112,6 +113,7 @@ fn create[T]() -> t[T] {
let T t = get[T](elts, hi);
elts.(hi) = util.none[T]();
+ nelts -= 1u;
ret t;
}
diff --git a/src/rt/circular_buffer.cpp b/src/rt/circular_buffer.cpp
index a93f2572..dbf5059b 100644
--- a/src/rt/circular_buffer.cpp
+++ b/src/rt/circular_buffer.cpp
@@ -31,9 +31,7 @@ circular_buffer::circular_buffer(rust_dom *dom, size_t unit_sz) :
}
circular_buffer::~circular_buffer() {
- dom->log(rust_log::MEM | rust_log::COMM,
- "~circular_buffer 0x%" PRIxPTR,
- this);
+ dom->log(rust_log::MEM, "~circular_buffer 0x%" PRIxPTR, this);
I(dom, _buffer);
W(dom, _unread == 0, "~circular_buffer with unread messages.");
dom->free(_buffer);
diff --git a/src/rt/globals.h b/src/rt/globals.h
index f8025a40..85aa5860 100644
--- a/src/rt/globals.h
+++ b/src/rt/globals.h
@@ -20,12 +20,14 @@ extern "C" {
}
#elif defined(__GNUC__)
#include <unistd.h>
+#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <pthread.h>
#include <errno.h>
+#include <time.h>
#else
#error "Platform not supported."
#endif
diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp
index 82a19cbc..d0215edc 100644
--- a/src/rt/rust.cpp
+++ b/src/rt/rust.cpp
@@ -53,7 +53,9 @@ rust_srv::realloc(void *p, size_t bytes)
}
void * val = ::realloc(p, bytes);
#ifdef TRACK_ALLOCATIONS
- if (allocation_list.replace(p, val) == NULL) {
+ if (allocation_list.replace(p, val) == false) {
+ printf("realloc: ptr 0x%" PRIxPTR " is not in allocation_list\n",
+ (uintptr_t) p);
fatal("not in allocation_list", __FILE__, __LINE__);
}
#endif
@@ -64,8 +66,8 @@ void
rust_srv::free(void *p)
{
#ifdef TRACK_ALLOCATIONS
- if (allocation_list.replace(p, NULL) == NULL) {
- printf("ptr 0x%" PRIxPTR " is not in allocation_list\n",
+ if (allocation_list.replace(p, NULL) == false) {
+ printf("free: ptr 0x%" PRIxPTR " is not in allocation_list\n",
(uintptr_t) p);
fatal("not in allocation_list", __FILE__, __LINE__);
}
diff --git a/src/rt/rust_chan.cpp b/src/rt/rust_chan.cpp
index f107d287..2a0a61db 100644
--- a/src/rt/rust_chan.cpp
+++ b/src/rt/rust_chan.cpp
@@ -18,9 +18,11 @@ rust_chan::rust_chan(rust_task *task, maybe_proxy<rust_port> *port) :
}
rust_chan::~rust_chan() {
- if (port && !port->is_proxy()) {
- port->delegate()->chans.swap_delete(this);
- }
+ task->log(rust_log::MEM | rust_log::COMM,
+ "del rust_chan(task=0x%" PRIxPTR ")", (uintptr_t) this);
+
+ A(task->dom, is_associated() == false,
+ "Channel must be disassociated before being freed.");
}
/**
@@ -28,7 +30,10 @@ rust_chan::~rust_chan() {
*/
void rust_chan::associate(maybe_proxy<rust_port> *port) {
this->port = port;
- if (!port->is_proxy()) {
+ if (port->is_proxy() == false) {
+ task->log(rust_log::TASK,
+ "associating chan: 0x%" PRIxPTR " with port: 0x%" PRIxPTR,
+ this, port);
this->port->delegate()->chans.push(this);
}
}
@@ -43,14 +48,23 @@ bool rust_chan::is_associated() {
void rust_chan::disassociate() {
A(task->dom, is_associated(), "Channel must be associated with a port.");
+ if (port->is_proxy() == false) {
+ task->log(rust_log::TASK,
+ "disassociating chan: 0x%" PRIxPTR " from port: 0x%" PRIxPTR,
+ this, port->delegate());
+ port->delegate()->chans.swap_delete(this);
+ }
+
// Delete reference to the port.
port = NULL;
}
/**
- * Attempt to transmit channel data to the associated port.
+ * Attempt to send data to the associated port.
*/
-void rust_chan::transmit() {
+void rust_chan::send(void *sptr) {
+ buffer.enqueue(sptr);
+
rust_dom *dom = task->dom;
if (!is_associated()) {
W(dom, is_associated(),
@@ -81,7 +95,6 @@ void rust_chan::transmit() {
return;
}
-
//
// Local Variables:
// mode: C++
diff --git a/src/rt/rust_chan.h b/src/rt/rust_chan.h
index 055e359a..6aa98247 100644
--- a/src/rt/rust_chan.h
+++ b/src/rt/rust_chan.h
@@ -17,7 +17,7 @@ public:
void disassociate();
bool is_associated();
- void transmit();
+ void send(void *sptr);
};
//
diff --git a/src/rt/rust_dom.cpp b/src/rt/rust_dom.cpp
index 004a1027..f7b8e97b 100644
--- a/src/rt/rust_dom.cpp
+++ b/src/rt/rust_dom.cpp
@@ -4,6 +4,8 @@
template class ptr_vec<rust_task>;
+// Keeps track of all live domains, for debugging purposes.
+array_list<rust_dom*> _live_domains;
rust_dom::rust_dom(rust_srv *srv, rust_crate const *root_crate,
const char *name) :
@@ -28,13 +30,18 @@ rust_dom::rust_dom(rust_srv *srv, rust_crate const *root_crate,
pthread_attr_setdetachstate(&attr, true);
#endif
root_task = new (this) rust_task(this, NULL, name);
+
+ if (_live_domains.replace(NULL, this) == false) {
+ _live_domains.append(this);
+ }
}
static void
del_all_tasks(rust_dom *dom, ptr_vec<rust_task> *v) {
I(dom, v);
while (v->length()) {
- dom->log(rust_log::TASK, "deleting task %" PRIdPTR, v->length() - 1);
+ dom->log(rust_log::TASK, "deleting task 0x%" PRIdPTR,
+ v->length() - 1);
delete v->pop();
}
}
@@ -45,7 +52,7 @@ rust_dom::delete_proxies() {
rust_proxy<rust_task> *task_proxy;
while (_task_proxies.pop(&task, &task_proxy)) {
log(rust_log::TASK,
- "deleting proxy %" PRIxPTR " in dom %s @0x%" PRIxPTR,
+ "deleting proxy 0x%" PRIxPTR " in dom %s 0x%" PRIxPTR,
task_proxy, task_proxy->dom->name, task_proxy->dom);
delete task_proxy;
}
@@ -54,7 +61,7 @@ rust_dom::delete_proxies() {
rust_proxy<rust_port> *port_proxy;
while (_port_proxies.pop(&port, &port_proxy)) {
log(rust_log::TASK,
- "deleting proxy %" PRIxPTR " in dom %s @0x%" PRIxPTR,
+ "deleting proxy 0x%" PRIxPTR " in dom %s 0x%" PRIxPTR,
port_proxy, port_proxy->dom->name, port_proxy->dom);
delete port_proxy;
}
@@ -77,6 +84,8 @@ rust_dom::~rust_dom() {
#endif
while (caches.length())
delete caches.pop();
+
+ _live_domains.replace(this, NULL);
}
void
@@ -232,7 +241,6 @@ rust_dom::reap_dead_tasks() {
rust_task *task = dead_tasks[i];
if (task->ref_count == 0) {
I(this, task->tasks_waiting_to_join.is_empty());
-
dead_tasks.swap_delete(task);
log(rust_log::TASK,
"deleting unreferenced dead task %s @0x%" PRIxPTR,
@@ -250,14 +258,14 @@ rust_dom::reap_dead_tasks() {
*/
void rust_dom::send_message(rust_message *message) {
log(rust_log::COMM, "==> enqueueing \"%s\" 0x%" PRIxPTR
- " in queue 0x%" PRIxPTR,
+ " in queue 0x%" PRIxPTR
+ " in domain 0x%" PRIxPTR,
message->label,
message,
- &_incoming_message_queue);
+ &_incoming_message_queue,
+ this);
A(this, message->dom == this, "Message owned by non-local domain.");
_incoming_message_queue.enqueue(message);
- _incoming_message_pending.signal();
- _progress.signal();
}
/**
@@ -329,6 +337,13 @@ rust_dom::schedule_task()
}
void
+rust_dom::log_all_state() {
+ for (uint32_t i = 0; i < _live_domains.size(); i++) {
+ _live_domains[i]->log_state();
+ }
+}
+
+void
rust_dom::log_state() {
if (!running_tasks.is_empty()) {
log(rust_log::TASK, "running tasks:");
@@ -352,8 +367,9 @@ rust_dom::log_state() {
if (!dead_tasks.is_empty()) {
log(rust_log::TASK, "dead tasks:");
for (size_t i = 0; i < dead_tasks.length(); i++) {
- log(rust_log::TASK, "\t task: %s @0x%" PRIxPTR,
- dead_tasks[i]->name, dead_tasks[i]);
+ log(rust_log::TASK, "\t task: %s 0x%" PRIxPTR ", ref_count: %d",
+ dead_tasks[i], dead_tasks[i]->name,
+ dead_tasks[i]->ref_count);
}
}
}
@@ -384,22 +400,29 @@ rust_dom::start_main_loop()
// if progress is made in other domains.
if (scheduled_task == NULL) {
- log(rust_log::TASK,
- "all tasks are blocked, waiting for progress ...");
- if (_log.is_tracing(rust_log::TASK))
+ if (_log.is_tracing(rust_log::TASK)) {
log_state();
- _progress.wait();
+ }
log(rust_log::TASK,
- "progress made, resuming ...");
+ "all tasks are blocked, scheduler yielding ...");
+ sync::yield();
+ log(rust_log::TASK,
+ "scheduler resuming ...");
continue;
}
I(this, scheduled_task->running());
log(rust_log::TASK,
- "activating task %s @0x%" PRIxPTR ", sp=0x%" PRIxPTR,
- scheduled_task->name, (uintptr_t)scheduled_task,
- scheduled_task->rust_sp);
+ "activating task %s 0x%" PRIxPTR
+ ", sp=0x%" PRIxPTR
+ ", ref_count=%d"
+ ", state: %s",
+ scheduled_task->name,
+ (uintptr_t)scheduled_task,
+ scheduled_task->rust_sp,
+ scheduled_task->ref_count,
+ scheduled_task->state_str());
interrupt_flag = 0;
@@ -423,21 +446,15 @@ rust_dom::start_main_loop()
log(rust_log::DOM, "terminated scheduler loop, reaping dead tasks ...");
while (dead_tasks.length() > 0) {
- log(rust_log::DOM,
- "waiting for %d dead tasks to become dereferenced ...",
- dead_tasks.length());
-
- if (_log.is_tracing(rust_log::DOM)) {
- for (size_t i = 0; i < dead_tasks.length(); i++) {
- log(rust_log::DOM,
- "task: %s @0x%" PRIxPTR ", index: %d, ref_count: %d",
- dead_tasks[i]->name, dead_tasks[i], i,
- dead_tasks[i]->ref_count);
- }
- }
-
if (_incoming_message_queue.is_empty()) {
- _incoming_message_pending.wait();
+ log(rust_log::DOM,
+ "waiting for %d dead tasks to become dereferenced, "
+ "scheduler yielding ...",
+ dead_tasks.length());
+ if (_log.is_tracing(rust_log::TASK)) {
+ log_state();
+ }
+ sync::yield();
} else {
drain_incoming_message_queue();
}
diff --git a/src/rt/rust_dom.h b/src/rt/rust_dom.h
index abf10cef..3aaf635a 100644
--- a/src/rt/rust_dom.h
+++ b/src/rt/rust_dom.h
@@ -35,13 +35,10 @@ struct rust_dom
rust_task *curr_task;
int rval;
- condition_variable _progress;
-
hash_map<rust_task *, rust_proxy<rust_task> *> _task_proxies;
hash_map<rust_port *, rust_proxy<rust_port> *> _port_proxies;
// Incoming messages from other domains.
- condition_variable _incoming_message_pending;
lock_free_queue _incoming_message_queue;
#ifndef __WIN32__
@@ -87,6 +84,7 @@ struct rust_dom
int start_main_loop();
void log_state();
+ static void log_all_state();
};
//
diff --git a/src/rt/rust_internal.h b/src/rt/rust_internal.h
index a89144d7..46ea843f 100644
--- a/src/rt/rust_internal.h
+++ b/src/rt/rust_internal.h
@@ -38,6 +38,7 @@ extern "C" {
#error "Platform not supported."
#endif
+#include "sync/sync.h"
#include "sync/condition_variable.h"
#ifndef __i386__
@@ -75,7 +76,7 @@ template <typename T>
struct
rc_base
{
- size_t ref_count;
+ int32_t ref_count;
void ref() {
++ref_count;
@@ -151,6 +152,7 @@ public:
T *& operator[](size_t offset);
void push(T *p);
T *pop();
+ T *peek();
void trim(size_t fill);
void swap_delete(T* p);
};
diff --git a/src/rt/rust_log.cpp b/src/rt/rust_log.cpp
index 48fcd0f1..8e089791 100644
--- a/src/rt/rust_log.cpp
+++ b/src/rt/rust_log.cpp
@@ -27,6 +27,7 @@ read_type_bit_mask() {
bits |= strstr(env_str, "timer") ? rust_log::TIMER : 0;
bits |= strstr(env_str, "gc") ? rust_log::GC : 0;
bits |= strstr(env_str, "all") ? rust_log::ALL : 0;
+ bits = strstr(env_str, "none") ? 0 : bits;
}
return bits;
}
diff --git a/src/rt/rust_message.cpp b/src/rt/rust_message.cpp
index 8b396b4d..1de804c9 100644
--- a/src/rt/rust_message.cpp
+++ b/src/rt/rust_message.cpp
@@ -90,8 +90,7 @@ send(uint8_t *buffer, size_t buffer_sz, const char* label, rust_task *source,
}
void data_message::process() {
- _port->remote_channel->buffer.enqueue(_buffer);
- _port->remote_channel->transmit();
+ _port->remote_channel->send(_buffer);
_target->log(rust_log::COMM, "<=== received data via message ===");
}
diff --git a/src/rt/rust_port.cpp b/src/rt/rust_port.cpp
index 0a5b7ee7..c97b5d41 100644
--- a/src/rt/rust_port.cpp
+++ b/src/rt/rust_port.cpp
@@ -17,16 +17,50 @@ rust_port::~rust_port() {
task->log(rust_log::COMM | rust_log::MEM,
"~rust_port 0x%" PRIxPTR, (uintptr_t) this);
+ log_state();
+
// Disassociate channels from this port.
while (chans.is_empty() == false) {
- chans.pop()->disassociate();
+ rust_chan *chan = chans.peek();
+ chan->disassociate();
}
- // We're the only ones holding a reference to the remote channel, so
- // clean it up.
delete remote_channel;
}
+bool rust_port::receive(void *dptr) {
+ for (uint32_t i = 0; i < chans.length(); i++) {
+ rust_chan *chan = chans[i];
+ if (chan->buffer.is_empty() == false) {
+ chan->buffer.dequeue(dptr);
+ if (chan->buffer.is_empty() && chan->task->blocked()) {
+ task->log(rust_log::COMM,
+ "chan: 0x%" PRIxPTR
+ " is flushing, wakeup task: 0x%" PRIxPTR,
+ chan, chan->task);
+ chan->task->wakeup(this);
+ }
+ task->log(rust_log::COMM, "<=== read data ===");
+ return true;
+ }
+ }
+ return false;
+}
+
+void rust_port::log_state() {
+ task->log(rust_log::COMM,
+ "rust_port: 0x%" PRIxPTR ", associated channel(s): %d",
+ this, chans.length());
+ for (uint32_t i = 0; i < chans.length(); i++) {
+ rust_chan *chan = chans[i];
+ task->log(rust_log::COMM,
+ "\tchan: 0x%" PRIxPTR ", data pending: %s, remote: %s",
+ chan,
+ !chan->buffer.is_empty() ? "yes" : "no",
+ chan == remote_channel ? "yes" : "no");
+ }
+}
+
//
// Local Variables:
// mode: C++
diff --git a/src/rt/rust_port.h b/src/rt/rust_port.h
index 49a89437..7a58f839 100644
--- a/src/rt/rust_port.h
+++ b/src/rt/rust_port.h
@@ -15,6 +15,8 @@ public:
rust_port(rust_task *task, size_t unit_sz);
~rust_port();
+ void log_state();
+ bool receive(void *dptr);
};
//
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp
index 279850cb..aca8bca7 100644
--- a/src/rt/rust_task.cpp
+++ b/src/rt/rust_task.cpp
@@ -324,6 +324,11 @@ get_callee_save_fp(uintptr_t *top_of_callee_saves)
void
rust_task::kill() {
+ if (dead()) {
+ // Task is already dead, can't kill what's already dead.
+ return;
+ }
+
// Note the distinction here: kill() is when you're in an upcall
// from task A and want to force-fail task B, you do B->kill().
// If you want to fail yourself you do self->fail(upcall_nargs).
@@ -334,6 +339,7 @@ rust_task::kill() {
if (this == dom->root_task)
dom->fail();
+ log(rust_log::TASK, "preparing to unwind task: 0x%" PRIxPTR, this);
run_on_resume(dom->root_crate->get_unwind_glue());
}
@@ -519,6 +525,10 @@ rust_task::free(void *p, bool is_gc)
}
}
+const char *
+rust_task::state_str() {
+ return dom->state_vec_name(state);
+}
void
rust_task::transition(ptr_vec<rust_task> *src, ptr_vec<rust_task> *dst)
@@ -556,9 +566,6 @@ rust_task::wakeup(rust_cond *from)
A(dom, cond == from, "Cannot wake up blocked task on wrong condition.");
transition(&dom->blocked_tasks, &dom->running_tasks);
- // TODO: Signaling every time the task is awaken is kind of silly,
- // do this a nicer way.
- dom->_progress.signal();
I(dom, cond == from);
cond = NULL;
}
diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp
index b0757e29..90d6f6d9 100644
--- a/src/rt/rust_upcall.cpp
+++ b/src/rt/rust_upcall.cpp
@@ -6,11 +6,13 @@
#define LOG_UPCALL_ENTRY(task) \
(task)->dom->get_log().reset_indent(0); \
(task)->log(rust_log::UPCALL, \
- "> UPCALL %s - task: %s @0x%" PRIxPTR \
- " retpc: x%" PRIxPTR, \
+ "> UPCALL %s - task: %s 0x%" PRIxPTR \
+ " retpc: x%" PRIxPTR \
+ " ref_count: %d", \
__FUNCTION__, \
(task)->name, (task), \
- __builtin_return_address(0)); \
+ __builtin_return_address(0), \
+ (task->ref_count)); \
(task)->dom->get_log().indent();
#else
#define LOG_UPCALL_ENTRY(task) \
@@ -21,6 +23,20 @@
(task)->dom->get_log().indent();
#endif
+void
+log_task_state(rust_task *task, maybe_proxy<rust_task> *target) {
+ rust_task *delegate = target->delegate();
+ if (target->is_proxy()) {
+ task->log(rust_log::TASK,
+ "remote task: 0x%" PRIxPTR ", ref_count: %d state: %s",
+ delegate, delegate->ref_count, delegate->state_str());
+ } else {
+ task->log(rust_log::TASK,
+ "local task: 0x%" PRIxPTR ", ref_count: %d state: %s",
+ delegate, delegate->ref_count, delegate->state_str());
+ }
+}
+
extern "C" CDECL char const *str_buf(rust_task *task, rust_str *s);
extern "C" void upcall_grow_task(rust_task *task, size_t n_frame_bytes) {
@@ -31,14 +47,13 @@ extern "C" void upcall_grow_task(rust_task *task, size_t n_frame_bytes) {
extern "C" CDECL void upcall_log_int(rust_task *task, int32_t i) {
LOG_UPCALL_ENTRY(task);
task->log(rust_log::UPCALL | rust_log::ULOG,
- "upcall log_int(0x%" PRIx32 " = %" PRId32 " = '%c')", i, i,
- (char) i);
+ "rust: %" PRId32 " (0x%" PRIx32 ")", i, i);
}
extern "C" CDECL void upcall_log_str(rust_task *task, rust_str *str) {
LOG_UPCALL_ENTRY(task);
const char *c = str_buf(task, str);
- task->log(rust_log::UPCALL | rust_log::ULOG, "upcall log_str(\"%s\")", c);
+ task->log(rust_log::UPCALL | rust_log::ULOG, "rust: %s", c);
}
extern "C" CDECL void upcall_trace_word(rust_task *task, uintptr_t i) {
@@ -86,26 +101,50 @@ upcall_new_chan(rust_task *task, rust_port *port) {
}
/**
+ * Called whenever this channel needs to be flushed. This can happen due to a
+ * flush statement, or automatically whenever a channel's ref count is
+ * about to drop to zero.
+ */
+extern "C" CDECL void
+upcall_flush_chan(rust_task *task, rust_chan *chan) {
+ LOG_UPCALL_ENTRY(task);
+ rust_dom *dom = task->dom;
+ task->log(rust_log::UPCALL | rust_log::COMM,
+ "flush chan: 0x%" PRIxPTR, chan);
+
+ if (chan->buffer.is_empty()) {
+ return;
+ }
+
+ A(dom, chan->port->is_proxy() == false,
+ "Channels to remote ports should be flushed automatically.");
+
+ // Block on the port until this channel has been completely drained
+ // by the port.
+ task->block(chan->port);
+ task->yield(2);
+}
+
+/**
* Called whenever the channel's ref count drops to zero.
+ *
+ * Cannot Yield: If the task were to unwind, the dropped ref would still
+ * appear to be live, causing modify-after-free errors.
*/
extern "C" CDECL void upcall_del_chan(rust_task *task, rust_chan *chan) {
LOG_UPCALL_ENTRY(task);
- rust_dom *dom = task->dom;
+
task->log(rust_log::UPCALL | rust_log::MEM | rust_log::COMM,
"upcall del_chan(0x%" PRIxPTR ")", (uintptr_t) chan);
- I(dom, !chan->ref_count);
-
- if (!chan->buffer.is_empty() && chan->is_associated()) {
- A(dom, !chan->port->is_proxy(),
- "Channels to remote ports should be flushed automatically.");
- // A target port may still be reading from this channel.
- // Block on this channel until it has been completely drained
- // by the port.
- task->block(chan);
- task->yield(2);
- return;
- }
+ A(task->dom, chan->ref_count == 0,
+ "Channel's ref count should be zero.");
+
+ if (chan->is_associated()) {
+ A(task->dom, chan->buffer.is_empty(),
+ "Channel's buffer should be empty.");
+ chan->disassociate();
+ }
delete chan;
}
@@ -171,8 +210,7 @@ upcall_send(rust_task *task, rust_chan *chan, void *sptr) {
"chan: 0x%" PRIxPTR ", sptr: 0x%" PRIxPTR ", size: %d",
(uintptr_t) chan, (uintptr_t) sptr,
chan->port->delegate()->unit_sz);
- chan->buffer.enqueue(sptr);
- chan->transmit();
+ chan->send(sptr);
task->log(rust_log::COMM, "=== sent data ===>");
}
@@ -185,17 +223,8 @@ upcall_recv(rust_task *task, uintptr_t *dptr, rust_port *port) {
(uintptr_t) port, (uintptr_t) dptr, port->unit_sz,
port->chans.length());
- for (uint32_t i = 0; i < port->chans.length(); i++) {
- rust_chan *chan = port->chans[i];
- if (chan->buffer.is_empty() == false) {
- chan->buffer.dequeue(dptr);
- if (chan->buffer.is_empty() && chan->task->blocked()) {
- chan->task->wakeup(chan);
- delete chan;
- }
- task->log(rust_log::COMM, "<=== read data ===");
- return;
- }
+ if (port->receive(dptr)) {
+ return;
}
// No data was buffered on any incoming channel, so block this task
@@ -222,6 +251,7 @@ extern "C" CDECL void upcall_fail(rust_task *task, char const *expr,
extern "C" CDECL void
upcall_kill(rust_task *task, maybe_proxy<rust_task> *target) {
LOG_UPCALL_ENTRY(task);
+ log_task_state(task, target);
rust_task *target_task = target->delegate();
task->log(rust_log::UPCALL | rust_log::TASK,
@@ -247,6 +277,8 @@ upcall_exit(rust_task *task) {
LOG_UPCALL_ENTRY(task);
task->log(rust_log::UPCALL | rust_log::TASK,
"task ref_count: %d", task->ref_count);
+ A(task->dom, task->ref_count >= 0,
+ "Task ref_count should not be negative on exit!");
task->die();
task->notify_tasks_waiting_to_join();
task->yield(1);
diff --git a/src/rt/rust_util.h b/src/rt/rust_util.h
index 42082119..03b7766d 100644
--- a/src/rt/rust_util.h
+++ b/src/rt/rust_util.h
@@ -70,6 +70,13 @@ ptr_vec<T>::pop()
}
template <typename T>
+T *
+ptr_vec<T>::peek()
+{
+ return data[fill - 1];
+}
+
+template <typename T>
void
ptr_vec<T>::trim(size_t sz)
{
@@ -140,11 +147,20 @@ isaac_init(rust_dom *dom, randctx *rctx)
CryptReleaseContext(hProv, 0));
}
#else
- int fd = open("/dev/urandom", O_RDONLY);
- I(dom, fd > 0);
- I(dom, read(fd, (void*) &rctx->randrsl, sizeof(rctx->randrsl))
- == sizeof(rctx->randrsl));
- I(dom, close(fd) == 0);
+ char *rust_seed = getenv("RUST_SEED");
+ if (rust_seed != NULL) {
+ ub4 seed = (ub4) atoi(rust_seed);
+ for (size_t i = 0; i < RANDSIZ; i ++) {
+ memcpy(&rctx->randrsl[i], &seed, sizeof(ub4));
+ seed = (seed + 0x7ed55d16) + (seed << 12);
+ }
+ } else {
+ int fd = open("/dev/urandom", O_RDONLY);
+ I(dom, fd > 0);
+ I(dom, read(fd, (void*) &rctx->randrsl, sizeof(rctx->randrsl))
+ == sizeof(rctx->randrsl));
+ I(dom, close(fd) == 0);
+ }
#endif
randinit(rctx, 1);
}
diff --git a/src/rt/sync/condition_variable.cpp b/src/rt/sync/condition_variable.cpp
index d4032572..c34ab7f4 100644
--- a/src/rt/sync/condition_variable.cpp
+++ b/src/rt/sync/condition_variable.cpp
@@ -9,14 +9,16 @@
// #define TRACE
-condition_variable::condition_variable() {
#if defined(__WIN32__)
+condition_variable::condition_variable() {
_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+}
#else
+condition_variable::condition_variable() {
pthread_cond_init(&_cond, NULL);
pthread_mutex_init(&_mutex, NULL);
-#endif
}
+#endif
condition_variable::~condition_variable() {
#if defined(__WIN32__)
@@ -31,15 +33,31 @@ condition_variable::~condition_variable() {
* Wait indefinitely until condition is signaled.
*/
void condition_variable::wait() {
+ timed_wait(0);
+}
+
+void condition_variable::timed_wait(size_t timeout_in_ns) {
#ifdef TRACE
- printf("waiting on condition_variable: 0x%" PRIxPTR "\n",
- (uintptr_t)this);
+ printf("waiting on condition_variable: 0x%" PRIxPTR " for %d ns. \n",
+ (uintptr_t) this, (int) timeout_in_ns);
#endif
#if defined(__WIN32__)
WaitForSingleObject(_event, INFINITE);
#else
pthread_mutex_lock(&_mutex);
- pthread_cond_wait(&_cond, &_mutex);
+ // wait() automatically releases the mutex while it waits, and acquires
+ // it right before exiting. This allows signal() to acquire the mutex
+ // when signaling.)
+ if (timeout_in_ns == 0) {
+ pthread_cond_wait(&_cond, &_mutex);
+ } else {
+ timeval time_val;
+ gettimeofday(&time_val, NULL);
+ timespec time_spec;
+ time_spec.tv_sec = time_val.tv_sec + 0;
+ time_spec.tv_nsec = time_val.tv_usec * 1000 + timeout_in_ns;
+ pthread_cond_timedwait(&_cond, &_mutex, &time_spec);
+ }
pthread_mutex_unlock(&_mutex);
#endif
#ifdef TRACE
diff --git a/src/rt/sync/condition_variable.h b/src/rt/sync/condition_variable.h
index f847ef99..f336a7f2 100644
--- a/src/rt/sync/condition_variable.h
+++ b/src/rt/sync/condition_variable.h
@@ -13,6 +13,7 @@ public:
virtual ~condition_variable();
void wait();
+ void timed_wait(size_t timeout_in_ns);
void signal();
};
diff --git a/src/rt/sync/sync.cpp b/src/rt/sync/sync.cpp
new file mode 100644
index 00000000..eba51a49
--- /dev/null
+++ b/src/rt/sync/sync.cpp
@@ -0,0 +1,12 @@
+#include "../globals.h"
+#include "sync.h"
+
+void sync::yield() {
+#ifdef __APPLE__
+ pthread_yield_np();
+#elif __WIN32__
+
+#else
+ pthread_yield();
+#endif
+}
diff --git a/src/rt/sync/sync.h b/src/rt/sync/sync.h
new file mode 100644
index 00000000..902b5661
--- /dev/null
+++ b/src/rt/sync/sync.h
@@ -0,0 +1,9 @@
+#ifndef SYNC_H
+#define SYNC_H
+
+class sync {
+public:
+ static void yield();
+};
+
+#endif /* SYNC_H */
diff --git a/src/rt/util/array_list.h b/src/rt/util/array_list.h
index e6ce55ab..929117f3 100644
--- a/src/rt/util/array_list.h
+++ b/src/rt/util/array_list.h
@@ -16,7 +16,7 @@ public:
int32_t append(T value);
int32_t push(T value);
T pop();
- T replace(T old_value, T new_value);
+ bool replace(T old_value, T new_value);
int32_t index_of(T value);
bool is_empty();
T & operator[](size_t index);
@@ -62,16 +62,16 @@ array_list<T>::pop() {
/**
* Replaces the old_value in the list with the new_value.
- * Returns the old_value if the replacement succeeded, or NULL otherwise.
+ * Returns the true if the replacement succeeded, or false otherwise.
*/
-template<typename T> T
+template<typename T> bool
array_list<T>::replace(T old_value, T new_value) {
int index = index_of(old_value);
if (index < 0) {
- return NULL;
+ return false;
}
_data[index] = new_value;
- return old_value;
+ return true;
}
template<typename T> int32_t
diff --git a/src/run.py b/src/run.py
new file mode 100644
index 00000000..4cce4102
--- /dev/null
+++ b/src/run.py
@@ -0,0 +1,81 @@
+import os
+import sys
+import time
+import glob
+import fnmatch
+from optparse import OptionParser
+
+rustDir = os.path.abspath('.')
+rustTestDir = rustDir + "/test";
+rustTestRunPassDir = rustTestDir + "/run-pass";
+rustTestRunFailDir = rustTestDir + "/run-fail";
+rustTestCompileFailDir = rustTestDir + "/run-compile-fail";
+rustTestRunBenchDir = rustTestDir + "/run-bench";
+
+parser = OptionParser()
+parser.set_usage("run.py [options] pattern : run.py -n 100 \"bas*\" -q");
+parser.add_option("-n", dest="repetitions",
+ help="number of repetitions", metavar="NUMBER")
+parser.add_option("-q", action="store_true", dest="quiet", default=False,
+ help="suppresses rust log output")
+parser.add_option("-p", action="store_true", dest="printSource",
+ default=False, help="prints the test case's source")
+parser.add_option("-s", dest="seed", metavar="NUMBER", default=-1,
+ help="seeds the rust scheduler, use -1 to generate seeds, "
+ + " or >= 0 to specify a seed")
+
+(options, args) = parser.parse_args()
+
+def getRustTests(filter):
+ tests = []
+ for root, dirnames, filenames in os.walk(rustTestDir):
+ for filename in fnmatch.filter(filenames, filter + '.rs'):
+ tests.append(os.path.join(root, filename).
+ replace(rustDir + "/", ""));
+ return tests
+
+
+if len(args) != 1:
+ parser.print_usage();
+ sys.exit(0);
+
+tests = getRustTests(args[0]);
+
+# Make
+for rustProgram in tests:
+ print "Making: " + rustProgram;
+ result = os.system("make " + rustProgram.replace(".rs", ".x86")) >> 8;
+ if (result != 0):
+ print "Make failed!";
+ sys.exit(1);
+
+if (options.quiet):
+ os.putenv("RUST_LOG", "none")
+
+# Rut
+totalPassed = 0;
+for rustProgram in tests:
+ repetitions = 1;
+ if (options.repetitions):
+ repetitions = int(options.repetitions);
+ passed = 0;
+ if (options.printSource):
+ os.system("cat " + rustProgram);
+ for i in range(0, repetitions):
+ print "Running: " + rustProgram + " " + str(i) + \
+ " of " + str(repetitions);
+ if (options.seed):
+ if (int(options.seed) >= 0):
+ os.putenv("RUST_SEED", options.seed);
+ else:
+ os.putenv("RUST_SEED", str(i));
+ result = os.system(rustProgram.replace(".rs", ".x86"));
+ exitStatus = result >> 8;
+ signalNumber = result & 0xF;
+ if (result == 0):
+ passed += 1;
+ print "Result for: " + rustProgram + " " + str(passed) + \
+ " of " + str(repetitions) + " passed.";
+ totalPassed += passed;
+print "Total: " + str(totalPassed) + " of " + \
+ str(len(tests) * repetitions) + " passed." \ No newline at end of file
diff --git a/src/test/run-pass/arith-0.rs b/src/test/run-pass/arith-0.rs
new file mode 100644
index 00000000..7587b005
--- /dev/null
+++ b/src/test/run-pass/arith-0.rs
@@ -0,0 +1,5 @@
+fn main() -> () {
+ let int a = 10;
+ log a;
+ check (a * (a - 1) == 90);
+} \ No newline at end of file
diff --git a/src/test/run-pass/arith-1.rs b/src/test/run-pass/arith-1.rs
new file mode 100644
index 00000000..bac6a055
--- /dev/null
+++ b/src/test/run-pass/arith-1.rs
@@ -0,0 +1,22 @@
+fn main() -> () {
+ let int i32_a = 10;
+ check(i32_a == 10);
+ check(i32_a - 10 == 0);
+ check(i32_a / 10 == 1);
+ check(i32_a - 20 == -10);
+ check(i32_a << 10 == 10240);
+ check(i32_a << 16 == 655360);
+ check(i32_a * 16 == 160);
+ check(i32_a * i32_a * i32_a == 1000);
+ check(i32_a * i32_a * i32_a * i32_a == 10000);
+ check(((i32_a * i32_a) / i32_a) * i32_a == 100);
+ check(i32_a * (i32_a - 1) << 2 + i32_a == 368640);
+
+ let int i32_b = 0x10101010;
+ check(i32_b + 1 - 1 == i32_b);
+ check(i32_b << 1 == i32_b << 1);
+ check(i32_b >> 1 == i32_b >> 1);
+ check((i32_b & (i32_b << 1)) == 0);
+ log ((i32_b | (i32_b << 1)));
+ check((i32_b | (i32_b << 1)) == 0x30303030);
+} \ No newline at end of file
diff --git a/src/test/run-pass/arith-2.rs b/src/test/run-pass/arith-2.rs
new file mode 100644
index 00000000..33a740c8
--- /dev/null
+++ b/src/test/run-pass/arith-2.rs
@@ -0,0 +1,5 @@
+fn main() -> () {
+ let int i32_c = 0x10101010;
+ check (i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3) ==
+ i32_c + (((i32_c * 2) / 3) * 2) + (i32_c - (7 % 3)));
+} \ No newline at end of file
diff --git a/src/test/run-pass/basic-1.rs b/src/test/run-pass/basic-1.rs
new file mode 100644
index 00000000..bdd7ee25
--- /dev/null
+++ b/src/test/run-pass/basic-1.rs
@@ -0,0 +1,25 @@
+// -*- rust -*-
+
+io fn a(chan[int] c) {
+ c <| 10;
+}
+
+io fn main() {
+ let port[int] p = port();
+ spawn a(chan(p));
+ spawn b(chan(p));
+ let int n = 0;
+ n <- p;
+ n <- p;
+// log "Finished.";
+}
+
+io fn b(chan[int] c) {
+// log "task b0";
+// log "task b1";
+// log "task b2";
+// log "task b3";
+// log "task b4";
+// log "task b5";
+ c <| 10;
+} \ No newline at end of file
diff --git a/src/test/run-pass/basic-2.rs b/src/test/run-pass/basic-2.rs
new file mode 100644
index 00000000..975a0d4b
--- /dev/null
+++ b/src/test/run-pass/basic-2.rs
@@ -0,0 +1,26 @@
+// -*- rust -*-
+
+io fn a(chan[int] c) {
+ log "task a0";
+ log "task a1";
+ c <| 10;
+}
+
+io fn main() {
+ let port[int] p = port();
+ spawn a(chan(p));
+ spawn b(chan(p));
+ let int n = 0;
+ n <- p;
+ n <- p;
+ log "Finished.";
+}
+
+io fn b(chan[int] c) {
+ log "task b0";
+ log "task b1";
+ log "task b2";
+ log "task b2";
+ log "task b3";
+ c <| 10;
+}
diff --git a/src/test/run-pass/task-comm-0.rs b/src/test/run-pass/task-comm-0.rs
index 5992ba5c..28294422 100644
--- a/src/test/run-pass/task-comm-0.rs
+++ b/src/test/run-pass/task-comm-0.rs
@@ -15,5 +15,5 @@ io fn test05() {
let int value <- po;
value <- po;
value <- po;
- log value;
+ check(value == 30);
}
diff --git a/src/test/run-pass/task-comm-2.rs b/src/test/run-pass/task-comm-2.rs
index 9c85da34..864d49de 100644
--- a/src/test/run-pass/task-comm-2.rs
+++ b/src/test/run-pass/task-comm-2.rs
@@ -1,8 +1,8 @@
fn main() -> () {
- log "===== THREADS =====";
+ log "===== SPAWNING and JOINING TASKS =====";
+ test00(false);
+ log "===== SPAWNING and JOINING THREAD TASKS =====";
test00(true);
- log "====== TASKS ======";
- // test00(false);
}
fn start(int task_number) {
@@ -15,7 +15,7 @@ fn start(int task_number) {
}
fn test00(bool create_threads) {
- let int number_of_tasks = 0;
+ let int number_of_tasks = 8;
let int i = 0;
let vec[task] tasks = vec();
diff --git a/src/test/run-pass/task-comm-3.rs b/src/test/run-pass/task-comm-3.rs
index 6dd620cc..9a3f9e16 100644
--- a/src/test/run-pass/task-comm-3.rs
+++ b/src/test/run-pass/task-comm-3.rs
@@ -1,6 +1,8 @@
io fn main() -> () {
- log "===== THREADS =====";
+ log "===== WITHOUT THREADS =====";
test00(false);
+ log "====== WITH THREADS ======";
+ test00(true);
}
io fn test00_start(chan[int] ch, int message, int count) {
@@ -15,8 +17,9 @@ io fn test00_start(chan[int] ch, int message, int count) {
}
io fn test00(bool is_multithreaded) {
- let int number_of_tasks = 1;
- let int number_of_messages = 0;
+ let int number_of_tasks = 16;
+ let int number_of_messages = 4;
+
log "Creating tasks";
let port[int] po = port();
@@ -27,13 +30,13 @@ io fn test00(bool is_multithreaded) {
// Create and spawn tasks...
let vec[task] tasks = vec();
while (i < number_of_tasks) {
- i = i + 1;
if (is_multithreaded) {
tasks += vec(
spawn thread test00_start(ch, i, number_of_messages));
} else {
tasks += vec(spawn test00_start(ch, i, number_of_messages));
}
+ i = i + 1;
}
// Read from spawned tasks...
@@ -53,7 +56,7 @@ io fn test00(bool is_multithreaded) {
}
log "Completed: Final number is: ";
- check (sum + 1 == number_of_messages *
- (number_of_tasks * number_of_tasks + number_of_tasks) / 2);
- log sum;
-} \ No newline at end of file
+ // check (sum == (((number_of_tasks * (number_of_tasks - 1)) / 2) *
+ // number_of_messages));
+ check (sum == 480);
+}
diff --git a/src/test/run-pass/task-comm-6.rs b/src/test/run-pass/task-comm-6.rs
index c579a98c..2774c0ba 100644
--- a/src/test/run-pass/task-comm-6.rs
+++ b/src/test/run-pass/task-comm-6.rs
@@ -31,6 +31,8 @@ io fn test00() {
r <- p; sum += r;
i += 1;
}
-
- check (sum == 4 * ((number_of_messages * (number_of_messages - 1)) / 2));
+
+ check (sum == 1998000);
+ // check (sum == 4 * ((number_of_messages *
+ // (number_of_messages - 1)) / 2));
} \ No newline at end of file
diff --git a/src/test/run-pass/task-comm.rs b/src/test/run-pass/task-comm.rs
index ef71c6e1..3c5d3216 100644
--- a/src/test/run-pass/task-comm.rs
+++ b/src/test/run-pass/task-comm.rs
@@ -1,11 +1,11 @@
-fn main() -> () {
- // test00(true);
+io fn main() -> () {
+ test00(true);
// test01();
- // test02();
- // test03();
- // test04();
- // test05();
+ test02();
+ test03();
+ test04();
+ test05();
test06();
}
@@ -22,7 +22,7 @@ io fn test00_start(chan[int] ch, int message, int count) {
io fn test00(bool is_multithreaded) {
let int number_of_tasks = 1;
- let int number_of_messages = 64;
+ let int number_of_messages = 4;
log "Creating tasks";
let port[int] po = port();
@@ -103,7 +103,7 @@ fn test04_start() {
fn test04() {
log "Spawning lots of tasks.";
- let int i = 64;
+ let int i = 4;
while (i > 0) {
i = i - 1;
spawn thread test04_start();
@@ -139,7 +139,7 @@ fn test06_start(int task_number) {
}
fn test06() {
- let int number_of_tasks = 32;
+ let int number_of_tasks = 4;
log "Creating tasks";
let int i = 0;