*
* Unlike mutex_arcs, rw_arcs are safe, because they cannot be nested.
*/
-#[mutable] // XXX remove after snap
#[no_freeze]
struct RWARC<T> {
priv x: UnsafeAtomicRcBox<RWARCInner<T>>,
use std::uint;
use std::vec;
use std::unstable::intrinsics;
-use std::unstable::intrinsics::{TyDesc};
-
-#[cfg(not(stage0))]
-use std::unstable::intrinsics::{get_tydesc};
-
-#[cfg(stage0)]
-unsafe fn get_tydesc<T>() -> *TyDesc {
- intrinsics::get_tydesc::<T>() as *TyDesc
-}
+use std::unstable::intrinsics::{TyDesc, get_tydesc};
// The way arena uses arrays is really deeply awful. The arrays are
// allocated, and have capacities reserved, but the fill for the array
is_pod: bool,
}
-#[mutable] // XXX remove after snap
#[no_freeze]
pub struct Arena {
// The head is separated out from the list as a unbenchmarked
(base + (align - 1)) & !(align - 1)
}
-#[inline]
-#[cfg(not(stage0))]
-unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
- // This function should be inlined when stage0 is gone
- ((*tydesc).drop_glue)(data);
-}
-
-#[inline]
-#[cfg(stage0)]
-unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
- ((*tydesc).drop_glue)(0 as **TyDesc, data);
-}
-
// Walk down a chunk, running the destructors for any objects stored
// in it.
unsafe fn destroy_chunk(chunk: &Chunk) {
//debug!("freeing object: idx = %u, size = %u, align = %u, done = %b",
// start, size, align, is_done);
if is_done {
- call_drop_glue(tydesc, ptr::offset(buf, start) as *i8);
+ ((*tydesc).drop_glue)(ptr::offset(buf, start) as *i8);
}
// Find where the next tydesc lives
#[allow(missing_doc)];
use std::cast::transmute;
-#[cfg(stage0)]
-use intrinsic::{get_tydesc};
-#[cfg(not(stage0))]
use std::unstable::intrinsics::{get_tydesc};
pub mod rustrt {
- #[cfg(stage0)]
- use intrinsic::{TyDesc};
- #[cfg(not(stage0))]
use std::unstable::intrinsics::{TyDesc};
#[abi = "cdecl"]
}
/// Mutable reference counted pointer type
-#[non_owned]
#[no_send]
-#[mutable] // XXX remove after snap
#[no_freeze]
#[unsafe_no_drop_flag]
pub struct RcMut<T> {
pub type CompletionCb = @fn(~str, @fn(~str));
-#[cfg(not(stage0))]
static complete_key: local_data::Key<@CompletionCb> = &local_data::Key;
-#[cfg(stage0)]
-fn complete_key(_: @CompletionCb) {}
/// Bind to the main completion callback
pub unsafe fn complete(cb: CompletionCb) {
use metadata::cstore;
use std::cast;
- #[cfg(not(stage0))]
use std::local_data;
use std::unstable::intrinsics;
// The stage1 compiler won't work, but that doesn't really matter. TLS
// changed only very recently to allow storage of owned values.
- #[cfg(not(stage0))]
static engine_key: local_data::Key<~Engine> = &local_data::Key;
- #[cfg(not(stage0))]
fn set_engine(engine: ~Engine) {
local_data::set(engine_key, engine)
}
- #[cfg(stage0)]
- fn set_engine(_: ~Engine) {}
- #[cfg(not(stage0))]
pub fn consume_engine() -> Option<~Engine> {
local_data::pop(engine_key)
}
- #[cfg(stage0)]
- pub fn consume_engine() -> Option<~Engine> { None }
}
pub mod write {
pub use middle::trans::context::task_llcx;
-#[cfg(not(stage0))]
static task_local_insn_key: local_data::Key<@~[&'static str]> = &local_data::Key;
-#[cfg(stage0)]
-fn task_local_insn_key(_: @~[&'static str]) {}
pub fn with_insn_ctxt(blk: &fn(&[&'static str])) {
let opt = local_data::get(task_local_insn_key, |k| k.map(|&k| *k));
}
}
-#[cfg(stage0)]
-fn task_local_llcx_key(_v: @ContextRef) {}
-#[cfg(not(stage0))]
static task_local_llcx_key: local_data::Key<@ContextRef> = &local_data::Key;
pub fn task_llcx() -> ContextRef {
span);
}
-// The stage0 snapshot does not yet support the fixes from PR #7557, so there are two versions of
-// following function for now
-#[cfg(not(stage0))]
fn enum_metadata(cx: &mut CrateContext,
enum_type: ty::t,
enum_def_id: ast::def_id,
}
}
-#[cfg(stage0)]
-fn enum_metadata(cx: &mut CrateContext,
- enum_type: ty::t,
- enum_def_id: ast::def_id,
- substs: &ty::substs,
- span: span)
- -> DIType {
-
- let enum_name = ty_to_str(cx.tcx, enum_type);
-
- // For empty enums there is an early exit. Just describe it as an empty struct with the
- // appropriate type name
- if ty::type_is_empty(cx.tcx, enum_type) {
- return composite_type_metadata(cx, Type::nil(), enum_name, &[], &[], &[], span);
- }
-
- // Prepare some data (llvm type, size, align, ...) about the discriminant. This data will be
- // needed in all of the following cases.
- let discriminant_llvm_type = Type::enum_discrim(cx);
- let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type);
-
- assert!(Type::enum_discrim(cx) == cx.int_type);
- let discriminant_type_metadata = type_metadata(cx, ty::mk_int(), span);
-
- let variants: &[@ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id);
-
- let enumerators_metadata: ~[DIDescriptor] = variants
- .iter()
- .transform(|v| {
- let name: &str = cx.sess.str_of(v.name);
- let discriminant_value = v.disr_val as c_ulonglong;
-
- do name.as_c_str |name| {
- unsafe {
- llvm::LLVMDIBuilderCreateEnumerator(
- DIB(cx),
- name,
- discriminant_value)
- }
- }
- })
- .collect();
-
- let loc = span_start(cx, span);
- let file_metadata = file_metadata(cx, loc.file.name);
-
- let discriminant_type_metadata = do enum_name.as_c_str |enum_name| {
- unsafe {
- llvm::LLVMDIBuilderCreateEnumerationType(
- DIB(cx),
- file_metadata,
- enum_name,
- file_metadata,
- loc.line as c_uint,
- bytes_to_bits(discriminant_size),
- bytes_to_bits(discriminant_align),
- create_DIArray(DIB(cx), enumerators_metadata),
- discriminant_type_metadata)
- }
- };
-
- if ty::type_is_c_like_enum(cx.tcx, enum_type) {
- return discriminant_type_metadata;
- }
-
- let is_univariant = variants.len() == 1;
-
- let variants_metadata = do variants.map |&vi| {
-
- let raw_types: &[ty::t] = vi.args;
- let arg_types = do raw_types.map |&raw_type| { ty::subst(cx.tcx, substs, raw_type) };
-
- let mut arg_llvm_types = do arg_types.map |&ty| { type_of::type_of(cx, ty) };
- let mut arg_names = match vi.arg_names {
- Some(ref names) => do names.map |ident| { cx.sess.str_of(*ident).to_owned() },
- None => do arg_types.map |_| { ~"" }
- };
-
- let mut arg_metadata = do arg_types.map |&ty| { type_metadata(cx, ty, span) };
-
- if !is_univariant {
- arg_llvm_types.insert(0, discriminant_llvm_type);
- arg_names.insert(0, ~"");
- arg_metadata.insert(0, discriminant_type_metadata);
- }
-
- let variant_llvm_type = Type::struct_(arg_llvm_types, false);
- let (variant_type_size, variant_type_align) = size_and_align_of(cx, variant_llvm_type);
-
- let variant_type_metadata = composite_type_metadata(
- cx,
- variant_llvm_type,
- &"",
- arg_llvm_types,
- arg_names,
- arg_metadata,
- span);
-
- do "".as_c_str |name| {
- unsafe {
- llvm::LLVMDIBuilderCreateMemberType(
- DIB(cx),
- file_metadata,
- name,
- file_metadata,
- loc.line as c_uint,
- bytes_to_bits(variant_type_size),
- bytes_to_bits(variant_type_align),
- bytes_to_bits(0),
- 0,
- variant_type_metadata)
- }
- }
- };
-
- let enum_llvm_type = type_of::type_of(cx, enum_type);
- let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
-
- return do enum_name.as_c_str |enum_name| {
- unsafe {
- llvm::LLVMDIBuilderCreateUnionType(
- DIB(cx),
- file_metadata,
- enum_name,
- file_metadata,
- loc.line as c_uint,
- bytes_to_bits(enum_type_size),
- bytes_to_bits(enum_type_align),
- 0, // Flags
- create_DIArray(DIB(cx), variants_metadata),
- 0) // RuntimeLang
- }
- };
-}
-
-
/// Creates debug information for a composite type, that is, anything that results in a LLVM struct.
///
/// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
Similar to a mutable option type, but friendlier.
*/
-#[mutable] // XXX remove after snap
#[no_freeze]
#[deriving(Clone, DeepClone, Eq)]
#[allow(missing_doc)]
false
}
-#[inline]
-#[cfg(not(stage0))]
-unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
- // This function should be inlined when stage0 is gone
- ((*tydesc).drop_glue)(data);
-}
-
-#[inline]
-#[cfg(stage0)]
-unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
- ((*tydesc).drop_glue)(0 as **TyDesc, data);
-}
-
/// Destroys all managed memory (i.e. @ boxes) held by the current task.
pub unsafe fn annihilate() {
use rt::local_heap::local_free;
if !uniq {
let tydesc: *TyDesc = transmute((*box).header.type_desc);
let data = transmute(&(*box).data);
- call_drop_glue(tydesc, data);
+ ((*tydesc).drop_glue)(data);
}
}
prev: Option<@Handler<T, U>>,
}
-#[cfg(stage0)]
-pub struct Condition<'self, T, U> {
- name: &'static str,
- key: local_data::Key<'self, @Handler<T, U>>
-}
-#[cfg(not(stage0))]
pub struct Condition<T, U> {
name: &'static str,
key: local_data::Key<@Handler<T, U>>
}
-#[cfg(not(stage0))]
impl<T, U> Condition<T, U> {
pub fn trap<'a>(&'a self, h: &'a fn(T) -> U) -> Trap<'a, T, U> {
unsafe {
}
}
}
-#[cfg(stage0)]
-impl<'self, T, U> Condition<'self, T, U> {
- pub fn trap<'a>(&'a self, h: &'a fn(T) -> U) -> Trap<'a, T, U> {
- unsafe {
- let p : *RustClosure = ::cast::transmute(&h);
- let prev = local_data::get(::cast::unsafe_copy(&self.key),
- |k| k.map(|&x| *x));
- let h = @Handler { handle: *p, prev: prev };
- Trap { cond: self, handler: h }
- }
- }
-
- pub fn raise(&self, t: T) -> U {
- let msg = fmt!("Unhandled condition: %s: %?", self.name, t);
- self.raise_default(t, || fail!(msg.clone()))
- }
-
- pub fn raise_default(&self, t: T, default: &fn() -> U) -> U {
- unsafe {
- match local_data::pop(::cast::unsafe_copy(&self.key)) {
- None => {
- debug!("Condition.raise: found no handler");
- default()
- }
- Some(handler) => {
- debug!("Condition.raise: found handler");
- match handler.prev {
- None => {}
- Some(hp) => {
- local_data::set(::cast::unsafe_copy(&self.key),
- hp)
- }
- }
- let handle : &fn(T) -> U =
- ::cast::transmute(handler.handle);
- let u = handle(t);
- local_data::set(::cast::unsafe_copy(&self.key), handler);
- u
- }
- }
- }
- }
-}
-#[cfg(stage0)]
-struct Trap<'self, T, U> {
- cond: &'self Condition<'self, T, U>,
- handler: @Handler<T, U>
-}
-#[cfg(not(stage0))]
struct Trap<'self, T, U> {
cond: &'self Condition<T, U>,
handler: @Handler<T, U>
}
}
-#[cfg(stage0)]
-struct Guard<'self, T, U> {
- cond: &'self Condition<'self, T, U>
-}
-#[cfg(not(stage0))]
struct Guard<'self, T, U> {
cond: &'self Condition<T, U>
}
#[cfg(nogc)]
fn expect_sentinel() -> bool { false }
-#[inline]
-#[cfg(not(stage0))]
-unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
- // This function should be inlined when stage0 is gone
- ((*tydesc).drop_glue)(data);
-}
-
-#[inline]
-#[cfg(stage0)]
-unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
- ((*tydesc).drop_glue)(0 as **TyDesc, data);
-}
-
// Entry point for GC-based cleanup. Walks stack looking for exchange
// heap and stack allocations requiring drop, and runs all
// destructors.
// FIXME #4420: Destroy this box
// FIXME #4330: Destroy this box
} else {
- call_drop_glue(tydesc, *root as *i8);
+ ((*tydesc).drop_glue)(*root as *i8);
}
}
}
#[allow(missing_doc)];
-#[cfg(stage0)]
-#[lang="copy"]
-pub trait Copy {
- // Empty.
-}
-
-#[cfg(stage0)]
-#[lang="owned"]
-pub trait Send {
- // empty.
-}
-
-#[cfg(not(stage0))]
#[lang="send"]
pub trait Send {
// empty.
}
-#[cfg(stage0)]
-#[lang="const"]
-pub trait Freeze {
- // empty.
-}
-
-#[cfg(not(stage0))]
#[lang="freeze"]
pub trait Freeze {
// empty.
* sections to ensure that each value of the `Key` type points to a unique
* location.
*/
-#[cfg(not(stage0))]
pub type Key<T> = &'static KeyValue<T>;
-#[cfg(stage0)]
-pub type Key<'self,T> = &'self fn(v: T);
pub enum KeyValue<T> { Key }
* Remove a task-local data value from the table, returning the
* reference that was originally created to insert it.
*/
-#[cfg(stage0)]
-pub fn pop<T: 'static>(key: Key<@T>) -> Option<@T> {
- unsafe { local_pop(Handle::new(), key) }
-}
-/**
- * Remove a task-local data value from the table, returning the
- * reference that was originally created to insert it.
- */
-#[cfg(not(stage0))]
pub fn pop<T: 'static>(key: Key<T>) -> Option<T> {
unsafe { local_pop(Handle::new(), key) }
}
+
/**
* Retrieve a task-local data value. It will also be kept alive in the
* table until explicitly removed.
*/
-#[cfg(stage0)]
-pub fn get<T: 'static, U>(key: Key<@T>, f: &fn(Option<&@T>) -> U) -> U {
- unsafe { local_get(Handle::new(), key, f) }
-}
-/**
- * Retrieve a task-local data value. It will also be kept alive in the
- * table until explicitly removed.
- */
-#[cfg(not(stage0))]
pub fn get<T: 'static, U>(key: Key<T>, f: &fn(Option<&T>) -> U) -> U {
unsafe { local_get(Handle::new(), key, f) }
}
+
/**
* Retrieve a mutable borrowed pointer to a task-local data value.
*/
-#[cfg(not(stage0))]
pub fn get_mut<T: 'static, U>(key: Key<T>, f: &fn(Option<&mut T>) -> U) -> U {
unsafe { local_get_mut(Handle::new(), key, f) }
}
+
/**
* Store a value in task-local data. If this key already has a value,
* that value is overwritten (and its destructor is run).
*/
-#[cfg(stage0)]
-pub fn set<T: 'static>(key: Key<@T>, data: @T) {
- unsafe { local_set(Handle::new(), key, data) }
-}
-/**
- * Store a value in task-local data. If this key already has a value,
- * that value is overwritten (and its destructor is run).
- */
-#[cfg(not(stage0))]
pub fn set<T: 'static>(key: Key<T>, data: T) {
unsafe { local_set(Handle::new(), key, data) }
}
+
/**
* Modify a task-local data value. If the function returns 'None', the
* data is removed (and its reference dropped).
*/
-#[cfg(stage0)]
-pub fn modify<T: 'static>(key: Key<@T>, f: &fn(Option<@T>) -> Option<@T>) {
- match f(pop(key)) {
- Some(next) => { set(key, next); }
- None => {}
- }
-}
-/**
- * Modify a task-local data value. If the function returns 'None', the
- * data is removed (and its reference dropped).
- */
-#[cfg(not(stage0))]
pub fn modify<T: 'static>(key: Key<T>, f: &fn(Option<T>) -> Option<T>) {
unsafe {
match f(pop(::cast::unsafe_copy(&key))) {
val: ~[~str]
}
-#[cfg(stage0)]
-fn overridden_arg_key(_v: @OverriddenArgs) {}
-#[cfg(not(stage0))]
static overridden_arg_key: local_data::Key<@OverriddenArgs> = &local_data::Key;
/// Returns the arguments which this program was started with (normally passed
}
// used to make space in TLS for a random number generator
-#[cfg(stage0)]
-fn tls_rng_state(_v: @@mut IsaacRng) {}
-#[cfg(not(stage0))]
static tls_rng_state: local_data::Key<@@mut IsaacRng> = &local_data::Key;
/**
#[allow(missing_doc)];
-#[cfg(stage0)]
-use intrinsic::{Opaque, TyDesc, TyVisitor};
-#[cfg(not(stage0))]
use unstable::intrinsics::{Opaque, TyDesc, TyVisitor};
use libc::c_void;
use sys;
true
}
- #[cfg(stage0)]
- fn visit_str(&self) -> bool {
- self.align_to::<~str>();
- if ! self.inner.visit_str() { return false; }
- self.bump_past::<~str>();
- true
- }
-
fn visit_estr_box(&self) -> bool {
self.align_to::<@str>();
if ! self.inner.visit_estr_box() { return false; }
true
}
- #[cfg(not(stage0))]
fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
self.align_to::<~u8>();
if ! self.inner.visit_uniq_managed(mtbl, inner) { return false; }
true
}
- #[cfg(not(stage0))]
fn visit_evec_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
self.align_to::<~[@u8]>();
if ! self.inner.visit_evec_uniq_managed(mtbl, inner) { return false; }
use vec::raw::{VecRepr, SliceRepr};
use vec;
use vec::{OwnedVector, UnboxedVecRepr};
-#[cfg(stage0)]
-use intrinsic::{Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc};
-#[cfg(not(stage0))]
use unstable::intrinsics::{Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc};
#[cfg(test)] use io;
}
}
- // Type no longer exists, vestigial function.
- #[cfg(stage0)]
- fn visit_str(&self) -> bool { fail!(); }
-
fn visit_estr_box(&self) -> bool {
do self.get::<@str> |s| {
self.writer.write_char('@');
}
}
- #[cfg(not(stage0))]
fn visit_uniq_managed(&self, _mtbl: uint, inner: *TyDesc) -> bool {
self.writer.write_char('~');
do self.get::<&managed::raw::BoxRepr> |b| {
}
}
- #[cfg(stage0)]
- fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
- do self.get::<&VecRepr> |b| {
- self.writer.write_char('~');
- self.write_unboxed_vec_repr(mtbl, &b.unboxed, inner);
- }
- }
-
- #[cfg(not(stage0))]
fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
do self.get::<&UnboxedVecRepr> |b| {
self.writer.write_char('~');
}
}
- #[cfg(not(stage0))]
fn visit_evec_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
do self.get::<&VecRepr> |b| {
self.writer.write_char('~');
fn visit_self(&self) -> bool { true }
fn visit_type(&self) -> bool { true }
- #[cfg(not(stage0))]
fn visit_opaque_box(&self) -> bool {
self.writer.write_char('@');
do self.get::<&managed::raw::BoxRepr> |b| {
self.visit_ptr_inner(p, b.header.type_desc);
}
}
- #[cfg(stage0)]
- fn visit_opaque_box(&self) -> bool {
- self.writer.write_char('@');
- do self.get::<&managed::raw::BoxRepr> |b| {
- let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
- unsafe {
- self.visit_ptr_inner(p, transmute(b.header.type_desc));
- }
- }
- }
// Type no longer exists, vestigial function.
fn visit_constr(&self, _inner: *TyDesc) -> bool { fail!(); }
p
}
-// FIXME #4942: Make these signatures agree with exchange_alloc's signatures
-#[cfg(stage0, not(test))]
-#[lang="exchange_malloc"]
-#[inline]
-pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
- let td = td as *TyDesc;
- let size = size as uint;
-
- assert!(td.is_not_null());
-
- let total_size = get_box_size(size, (*td).align);
- let p = malloc_raw(total_size as uint);
-
- let box: *mut BoxRepr = p as *mut BoxRepr;
- (*box).header.ref_count = -1;
- (*box).header.type_desc = td;
-
- box as *c_char
-}
-
/// The allocator for unique pointers without contained managed pointers.
-#[cfg(not(stage0), not(test))]
+#[cfg(not(test))]
#[lang="exchange_malloc"]
#[inline]
pub unsafe fn exchange_malloc(size: uintptr_t) -> *c_char {
/// Sets the length of the string and adds the null terminator
#[inline]
- #[cfg(stage0)]
- pub unsafe fn set_len(v: &mut ~str, new_len: uint) {
- let v: **mut vec::raw::VecRepr = cast::transmute(v);
- let repr: *mut vec::raw::VecRepr = *v;
- (*repr).unboxed.fill = new_len + 1u;
- let null = ptr::mut_offset(cast::transmute(&((*repr).unboxed.data)),
- new_len);
- *null = 0u8;
- }
-
- /// Sets the length of the string and adds the null terminator
- #[inline]
- #[cfg(not(stage0))]
pub unsafe fn set_len(v: &mut ~str, new_len: uint) {
let v: **mut vec::UnboxedVecRepr = cast::transmute(v);
let repr: *mut vec::UnboxedVecRepr = *v;
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[allow(missing_doc)];
-
-use cast;
-use cmp::Eq;
-use libc;
-use local_data;
-use prelude::*;
-use sys;
-use task::rt;
-
-use super::rt::rust_task;
-use rt::task::{Task, LocalStorage};
-
-pub enum Handle {
- OldHandle(*rust_task),
- NewHandle(*mut LocalStorage)
-}
-
-impl Handle {
- pub fn new() -> Handle {
- use rt::{context, OldTaskContext};
- use rt::local::Local;
- unsafe {
- match context() {
- OldTaskContext => {
- OldHandle(rt::rust_get_task())
- }
- _ => {
- let task = Local::unsafe_borrow::<Task>();
- NewHandle(&mut (*task).storage)
- }
- }
- }
- }
-}
-
-pub trait LocalData { }
-impl<T: 'static> LocalData for @T { }
-
-impl Eq for @LocalData {
- fn eq(&self, other: &@LocalData) -> bool {
- unsafe {
- let ptr_a: &(uint, uint) = cast::transmute(self);
- let ptr_b: &(uint, uint) = cast::transmute(other);
- return ptr_a == ptr_b;
- }
- }
- fn ne(&self, other: &@LocalData) -> bool { !(*self).eq(other) }
-}
-
-// If TLS is used heavily in future, this could be made more efficient with a
-// proper map.
-type TaskLocalElement = (*libc::c_void, *libc::c_void, @LocalData);
-// Has to be a pointer at outermost layer; the foreign call returns void *.
-type TaskLocalMap = ~[Option<TaskLocalElement>];
-
-fn cleanup_task_local_map(map_ptr: *libc::c_void) {
- unsafe {
- assert!(!map_ptr.is_null());
- // Get and keep the single reference that was created at the
- // beginning.
- let _map: TaskLocalMap = cast::transmute(map_ptr);
- // All local_data will be destroyed along with the map.
- }
-}
-
-// Gets the map from the runtime. Lazily initialises if not done so already.
-unsafe fn get_local_map(handle: Handle) -> &mut TaskLocalMap {
- match handle {
- OldHandle(task) => get_task_local_map(task),
- NewHandle(local_storage) => get_newsched_local_map(local_storage)
- }
-}
-
-unsafe fn get_task_local_map(task: *rust_task) -> &mut TaskLocalMap {
-
- extern fn cleanup_task_local_map_extern_cb(map_ptr: *libc::c_void) {
- cleanup_task_local_map(map_ptr);
- }
-
- // Relies on the runtime initialising the pointer to null.
- // Note: the map is an owned pointer and is "owned" by TLS. It is moved
- // into the tls slot for this task, and then mutable loans are taken from
- // this slot to modify the map.
- let map_ptr = rt::rust_get_task_local_data(task);
- if (*map_ptr).is_null() {
- // First time TLS is used, create a new map and set up the necessary
- // TLS information for its safe destruction
- let map: TaskLocalMap = ~[];
- *map_ptr = cast::transmute(map);
- rt::rust_task_local_data_atexit(task, cleanup_task_local_map_extern_cb);
- }
- return cast::transmute(map_ptr);
-}
-
-unsafe fn get_newsched_local_map(local: *mut LocalStorage) -> &mut TaskLocalMap {
- // This is based on the same idea as the oldsched code above.
- match &mut *local {
- // If the at_exit function is already set, then we just need to take a
- // loan out on the TLS map stored inside
- &LocalStorage(ref mut map_ptr, Some(_)) => {
- assert!(map_ptr.is_not_null());
- return cast::transmute(map_ptr);
- }
- // If this is the first time we've accessed TLS, perform similar
- // actions to the oldsched way of doing things.
- &LocalStorage(ref mut map_ptr, ref mut at_exit) => {
- assert!(map_ptr.is_null());
- assert!(at_exit.is_none());
- let map: TaskLocalMap = ~[];
- *map_ptr = cast::transmute(map);
- *at_exit = Some(cleanup_task_local_map);
- return cast::transmute(map_ptr);
- }
- }
-}
-
-unsafe fn key_to_key_value<T: 'static>(key: local_data::Key<@T>) -> *libc::c_void {
- let pair: sys::Closure = cast::transmute(key);
- return pair.code as *libc::c_void;
-}
-
-// If returning Some(..), returns with @T with the map's reference. Careful!
-unsafe fn local_data_lookup<T: 'static>(
- map: &mut TaskLocalMap, key: local_data::Key<@T>)
- -> Option<(uint, *libc::c_void)> {
-
- let key_value = key_to_key_value(key);
- for map.iter().enumerate().advance |(i, entry)| {
- match *entry {
- Some((k, data, _)) if k == key_value => { return Some((i, data)); }
- _ => {}
- }
- }
- return None;
-}
-
-unsafe fn local_get_helper<T: 'static>(
- handle: Handle, key: local_data::Key<@T>,
- do_pop: bool) -> Option<@T> {
-
- let map = get_local_map(handle);
- // Interpreturn our findings from the map
- do local_data_lookup(map, key).map |result| {
- // A reference count magically appears on 'data' out of thin air. It
- // was referenced in the local_data box, though, not here, so before
- // overwriting the local_data_box we need to give an extra reference.
- // We must also give an extra reference when not removing.
- let (index, data_ptr) = *result;
- let data: @T = cast::transmute(data_ptr);
- cast::bump_box_refcount(data);
- if do_pop {
- map[index] = None;
- }
- data
- }
-}
-
-
-pub unsafe fn local_pop<T: 'static>(
- handle: Handle,
- key: local_data::Key<@T>) -> Option<@T> {
-
- local_get_helper(handle, key, true)
-}
-
-pub unsafe fn local_get<T: 'static, U>(
- handle: Handle,
- key: local_data::Key<@T>,
- f: &fn(Option<&@T>) -> U) -> U {
-
- match local_get_helper(handle, key, false) {
- Some(ref x) => f(Some(x)),
- None => f(None)
- }
-}
-
-pub unsafe fn local_set<T: 'static>(
- handle: Handle, key: local_data::Key<@T>, data: @T) {
-
- let map = get_local_map(handle);
- // Store key+data as *voids. Data is invisibly referenced once; key isn't.
- let keyval = key_to_key_value(key);
- // We keep the data in two forms: one as an unsafe pointer, so we can get
- // it back by casting; another in an existential box, so the reference we
- // own on it can be dropped when the box is destroyed. The unsafe pointer
- // does not have a reference associated with it, so it may become invalid
- // when the box is destroyed.
- let data_ptr = *cast::transmute::<&@T, &*libc::c_void>(&data);
- let data_box = @data as @LocalData;
- // Construct new entry to store in the map.
- let new_entry = Some((keyval, data_ptr, data_box));
- // Find a place to put it.
- match local_data_lookup(map, key) {
- Some((index, _old_data_ptr)) => {
- // Key already had a value set, _old_data_ptr, whose reference
- // will get dropped when the local_data box is overwritten.
- map[index] = new_entry;
- }
- None => {
- // Find an empty slot. If not, grow the vector.
- match map.iter().position(|x| x.is_none()) {
- Some(empty_index) => { map[empty_index] = new_entry; }
- None => { map.push(new_entry); }
- }
- }
- }
-}
-
-pub unsafe fn local_modify<T: 'static>(
- handle: Handle, key: local_data::Key<@T>,
- modify_fn: &fn(Option<@T>) -> Option<@T>) {
-
- // Could be more efficient by doing the lookup work, but this is easy.
- let newdata = modify_fn(local_pop(handle, key));
- if newdata.is_some() {
- local_set(handle, key, newdata.unwrap());
- }
-}
#[cfg(test)] use ptr;
#[cfg(test)] use task;
-#[cfg(stage0)]
-#[path="local_data_priv_stage0.rs"]
-mod local_data_priv;
-#[cfg(not(stage0))]
mod local_data_priv;
pub mod rt;
pub mod spawn;
// FIXME (#2912): Work around core-vs-coretest function duplication. Can't use
// a proper closure because the #[test]s won't understand. Have to fake it.
-#[cfg(not(stage0))]
fn taskgroup_key() -> local_data::Key<@@mut Taskgroup> {
unsafe { cast::transmute(-2) }
}
-#[cfg(stage0)]
-fn taskgroup_key() -> local_data::Key<@@mut Taskgroup> {
- unsafe { cast::transmute((-2, 0)) }
-}
// Transitionary.
struct RuntimeGlue;
#[cfg(test)]
pub use realstd::unstable::intrinsics::{TyDesc, Opaque, TyVisitor};
-#[cfg(not(stage0))]
pub type GlueFn = extern "Rust" fn(*i8);
-#[cfg(stage0)]
-pub type GlueFn = extern "Rust" fn(**TyDesc, *i8);
-
// NB: this has to be kept in sync with the Rust ABI.
#[lang="ty_desc"]
#[cfg(not(test))]
pub fn pref_align_of<T>() -> uint;
/// Get a static pointer to a type descriptor.
- #[cfg(not(stage0))]
pub fn get_tydesc<T>() -> *TyDesc;
- #[cfg(stage0)]
- pub fn get_tydesc<T>() -> *();
/// Create a value initialized to zero.
///
pub fn needs_drop<T>() -> bool;
/// Returns `true` if a type is managed (will be allocated on the local heap)
- #[cfg(not(stage0))]
pub fn contains_managed<T>() -> bool;
- #[cfg(not(stage0))]
pub fn visit_tydesc(td: *TyDesc, tv: @TyVisitor);
pub fn frame_address(f: &once fn(*u8));
// verify that `#[unsafe_no_drop_flag]` works as intended on a zero-size struct
- // NOTE: uncomment after snapshot, will not parse yet
- //static mut did_run: bool = false;
+ static mut did_run: bool = false;
struct Foo { five: int }
impl Drop for Foo {
fn drop(&self) {
assert_eq!(self.five, 5);
- // NOTE: uncomment after snapshot, will not parse yet
- //unsafe {
- //did_run = true;
- //}
+ unsafe {
+ did_run = true;
+ }
}
}
let _a = (NonCopyable, Foo { five: 5 }, NonCopyable);
}
- // NOTE: uncomment after snapshot, will not parse yet
- //unsafe { assert_eq!(did_run, true); }
+ unsafe { assert_eq!(did_run, true); }
}
}
use ptr::to_unsafe_ptr;
use ptr;
use ptr::RawPtr;
-#[cfg(not(stage0))]
use rt::global_heap::malloc_raw;
use rt::global_heap::realloc_raw;
use sys;
use sys::size_of;
use uint;
use unstable::intrinsics;
-#[cfg(stage0)]
-use intrinsic::{get_tydesc};
-#[cfg(not(stage0))]
use unstable::intrinsics::{get_tydesc, contains_managed};
use vec;
use util;
}
/// Creates a new vector with a capacity of `capacity`
-#[cfg(stage0)]
-pub fn with_capacity<T>(capacity: uint) -> ~[T] {
- let mut vec = ~[];
- vec.reserve(capacity);
- vec
-}
-
-/// Creates a new vector with a capacity of `capacity`
-#[cfg(not(stage0))]
pub fn with_capacity<T>(capacity: uint) -> ~[T] {
unsafe {
if contains_managed::<T>() {
*
* * n - The number of elements to reserve space for
*/
- #[cfg(stage0)]
- fn reserve(&mut self, n: uint) {
- // Only make the (slow) call into the runtime if we have to
- use managed;
- if self.capacity() < n {
- unsafe {
- let ptr: *mut *mut raw::VecRepr = cast::transmute(self);
- let td = get_tydesc::<T>();
- if ((**ptr).box_header.ref_count ==
- managed::raw::RC_MANAGED_UNIQUE) {
- // XXX transmute shouldn't be necessary
- let td = cast::transmute(td);
- ::at_vec::raw::reserve_raw(td, ptr, n);
- } else {
- let alloc = n * sys::nonzero_size_of::<T>();
- *ptr = realloc_raw(*ptr as *mut c_void, alloc + size_of::<raw::VecRepr>())
- as *mut raw::VecRepr;
- (**ptr).unboxed.alloc = alloc;
- }
- }
- }
- }
-
- /**
- * Reserves capacity for exactly `n` elements in the given vector.
- *
- * If the capacity for `self` is already equal to or greater than the requested
- * capacity, then no action is taken.
- *
- * # Arguments
- *
- * * n - The number of elements to reserve space for
- */
- #[cfg(not(stage0))]
fn reserve(&mut self, n: uint) {
// Only make the (slow) call into the runtime if we have to
if self.capacity() < n {
/// Returns the number of elements the vector can hold without reallocating.
#[inline]
- #[cfg(stage0)]
- fn capacity(&self) -> uint {
- unsafe {
- let repr: **raw::VecRepr = transmute(self);
- (**repr).unboxed.alloc / sys::nonzero_size_of::<T>()
- }
- }
-
- /// Returns the number of elements the vector can hold without reallocating.
- #[inline]
- #[cfg(not(stage0))]
fn capacity(&self) -> uint {
unsafe {
if contains_managed::<T>() {
/// Append an element to a vector
#[inline]
- #[cfg(stage0)]
- fn push(&mut self, t: T) {
- unsafe {
- let repr: **raw::VecRepr = transmute(&mut *self);
- let fill = (**repr).unboxed.fill;
- if (**repr).unboxed.alloc <= fill {
- let new_len = self.len() + 1;
- self.reserve_at_least(new_len);
- }
-
- self.push_fast(t);
- }
- }
-
- /// Append an element to a vector
- #[inline]
- #[cfg(not(stage0))]
fn push(&mut self, t: T) {
unsafe {
if contains_managed::<T>() {
// This doesn't bother to make sure we have space.
#[inline] // really pretty please
- #[cfg(stage0)]
- unsafe fn push_fast(&mut self, t: T) {
- let repr: **mut raw::VecRepr = transmute(self);
- let fill = (**repr).unboxed.fill;
- (**repr).unboxed.fill += sys::nonzero_size_of::<T>();
- let p = to_unsafe_ptr(&((**repr).unboxed.data));
- let p = ptr::offset(p, fill) as *mut T;
- intrinsics::move_val_init(&mut(*p), t);
- }
-
- // This doesn't bother to make sure we have space.
- #[inline] // really pretty please
- #[cfg(not(stage0))]
unsafe fn push_fast(&mut self, t: T) {
if contains_managed::<T>() {
let repr: **mut raw::VecRepr = transmute(self);
use sys;
use unstable::intrinsics;
use vec::{UnboxedVecRepr, with_capacity, ImmutableVector, MutableVector};
- #[cfg(not(stage0))]
use unstable::intrinsics::contains_managed;
/// The internal representation of a (boxed) vector
* the vector is actually the specified size.
*/
#[inline]
- #[cfg(stage0)]
- pub unsafe fn set_len<T>(v: &mut ~[T], new_len: uint) {
- let repr: **mut VecRepr = transmute(v);
- (**repr).unboxed.fill = new_len * sys::nonzero_size_of::<T>();
- }
-
- /**
- * Sets the length of a vector
- *
- * This will explicitly set the size of the vector, without actually
- * modifing its buffers, so it is up to the caller to ensure that
- * the vector is actually the specified size.
- */
- #[inline]
- #[cfg(not(stage0))]
pub unsafe fn set_len<T>(v: &mut ~[T], new_len: uint) {
if contains_managed::<T>() {
let repr: **mut VecRepr = transmute(v);
}
}
-#[cfg(stage0)]
-impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] {
- pub fn from_iterator(iterator: &mut T) -> ~[A] {
- let mut xs = ~[];
- for iterator.advance |x| {
- xs.push(x);
- }
- xs
- }
-}
-
-
-#[cfg(not(stage0))]
impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] {
pub fn from_iterator(iterator: &mut T) -> ~[A] {
let (lower, _) = iterator.size_hint();
// fetch the SCTable from TLS, create one if it doesn't yet exist.
pub fn get_sctable() -> @mut SCTable {
- #[cfg(not(stage0))]
static sctable_key: local_data::Key<@@mut SCTable> = &local_data::Key;
- #[cfg(stage0)]
- fn sctable_key(_: @@mut SCTable) {}
match local_data::get(sctable_key, |k| k.map(|&k| *k)) {
None => {
let new_table = @@mut new_sctable_internal();
}
fn print_maybe_styled(msg: &str, color: term::attr::Attr) {
- #[cfg(not(stage0))]
static tls_terminal: local_data::Key<@Option<term::Terminal>> = &local_data::Key;
- #[cfg(stage0)]
- fn tls_terminal(_: @Option<term::Terminal>) {}
let stderr = io::stderr();
// if an interner exists in TLS, return it. Otherwise, prepare a
// fresh one.
pub fn get_ident_interner() -> @ident_interner {
- #[cfg(not(stage0))]
static key: local_data::Key<@@::parse::token::ident_interner> =
&local_data::Key;
- #[cfg(stage0)]
- fn key(_: @@::parse::token::ident_interner) {}
match local_data::get(key, |k| k.map(|&k| *k)) {
Some(interner) => *interner,
None => {
// free the environment (which should be a unique closure).
const type_desc *td = env->td;
td->drop_glue(NULL,
-#ifdef _RUST_STAGE0
- NULL,
-#endif
box_body(env));
task->kernel->region()->free(env);
}
struct type_desc;
typedef void CDECL (glue_fn)(void *,
-#ifdef _RUST_STAGE0
- const type_desc **,
-#endif
void *);
// Corresponds to the boxed data in the @ region. The body follows the
+S 2013-07-21 e336cbf
+ macos-i386 d9666dccc1040ebe298a54acb378902a7472ad0f
+ macos-x86_64 808f68916444e3857ef2aab20f8db9db8f4b0b4a
+ winnt-i386 f9a5f891fd24e9446acb2a1b5d697461665c4388
+ freebsd-x86_64 8e79f6e970bc33ea6a3b9329bc4526d89ca63d47
+ linux-i386 054a0229b9cbdadf013868ba01a8277883f83a6d
+ linux-x86_64 2c53a72e9c9bb547df248a2d4b857d480ce0b910
+
S 2013-06-23 f827561
macos-i386 63ffbcf99b6853d7840bdfe01380068518d0e466
macos-x86_64 b34fdf3845f8ef4760817007d8ef820cd32f2e07