Skip to content

Finish rewriting TLS #7751

New issue

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

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

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions src/libextra/rl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,24 +66,28 @@ pub unsafe fn read(prompt: &str) -> Option<~str> {
}
}

pub type CompletionCb<'self> = @fn(~str, &'self fn(~str));
pub type CompletionCb = @fn(~str, @fn(~str));

fn complete_key(_v: @CompletionCb) {}
#[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) {
local_data::set(complete_key, @(cb));
local_data::set(complete_key, @cb);

extern fn callback(line: *c_char, completions: *()) {
unsafe {
let cb = *local_data::get(complete_key, |k| k.map(|&k| *k))
.get();

do cb(str::raw::from_c_str(line)) |suggestion| {
do str::as_c_str(suggestion) |buf| {
rustrt::linenoiseAddCompletion(completions, buf);
do local_data::get(complete_key) |cb| {
let cb = **cb.unwrap();

unsafe {
do cb(str::raw::from_c_str(line)) |suggestion| {
do str::as_c_str(suggestion) |buf| {
rustrt::linenoiseAddCompletion(completions, buf);
}
}
}
}
}
}

Expand Down
35 changes: 0 additions & 35 deletions src/libextra/sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1195,39 +1195,4 @@ mod big_tests {
isSorted(arr);
}
}

struct LVal<'self> {
val: uint,
key: &'self fn:Copy(@uint),
}

#[unsafe_destructor]
impl<'self> Drop for LVal<'self> {
fn drop(&self) {
let x = unsafe { local_data::get(self.key, |k| k.map(|&k| *k)) };
match x {
Some(@y) => {
unsafe {
local_data::set(self.key, @(y+1));
}
}
_ => fail!("Expected key to work"),
}
}
}

impl<'self> Ord for LVal<'self> {
fn lt<'a>(&self, other: &'a LVal<'self>) -> bool {
(*self).val < other.val
}
fn le<'a>(&self, other: &'a LVal<'self>) -> bool {
(*self).val <= other.val
}
fn gt<'a>(&self, other: &'a LVal<'self>) -> bool {
(*self).val > other.val
}
fn ge<'a>(&self, other: &'a LVal<'self>) -> bool {
(*self).val >= other.val
}
}
}
8 changes: 5 additions & 3 deletions src/librustc/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ pub mod jit {
use metadata::cstore;

use std::cast;
#[cfg(not(stage0))]
use std::local_data;
use std::unstable::intrinsics;

Expand Down Expand Up @@ -202,18 +203,19 @@ pub mod jit {

// The stage1 compiler won't work, but that doesn't really matter. TLS
// changed only very recently to allow storage of owned values.
fn engine_key(_: ~Engine) {}
#[cfg(not(stage0))]
static engine_key: local_data::Key<~Engine> = &local_data::Key;

#[cfg(not(stage0))]
fn set_engine(engine: ~Engine) {
unsafe { local_data::set(engine_key, engine) }
local_data::set(engine_key, engine)
}
#[cfg(stage0)]
fn set_engine(_: ~Engine) {}

#[cfg(not(stage0))]
pub fn consume_engine() -> Option<~Engine> {
unsafe { local_data::pop(engine_key) }
local_data::pop(engine_key)
}
#[cfg(stage0)]
pub fn consume_engine() -> Option<~Engine> { None }
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
LintSpec {
lint: non_uppercase_statics,
desc: "static constants should have uppercase identifiers",
default: warn
default: allow
}),

("managed_heap_memory",
Expand Down
43 changes: 19 additions & 24 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,49 +87,44 @@ use syntax::abi::{X86, X86_64, Arm, Mips};

pub use middle::trans::context::task_llcx;

fn task_local_insn_key(_v: @~[&'static str]) {}
#[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])) {
unsafe {
let opt = local_data::get(task_local_insn_key, |k| k.map(|&k| *k));
if opt.is_some() {
blk(*opt.unwrap());
}
let opt = local_data::get(task_local_insn_key, |k| k.map(|&k| *k));
if opt.is_some() {
blk(*opt.unwrap());
}
}

pub fn init_insn_ctxt() {
unsafe {
local_data::set(task_local_insn_key, @~[]);
}
local_data::set(task_local_insn_key, @~[]);
}

pub struct _InsnCtxt { _x: () }

#[unsafe_destructor]
impl Drop for _InsnCtxt {
fn drop(&self) {
unsafe {
do local_data::modify(task_local_insn_key) |c| {
do c.map_consume |ctx| {
let mut ctx = copy *ctx;
ctx.pop();
@ctx
}
do local_data::modify(task_local_insn_key) |c| {
do c.map_consume |ctx| {
let mut ctx = copy *ctx;
ctx.pop();
@ctx
}
}
}
}

pub fn push_ctxt(s: &'static str) -> _InsnCtxt {
debug!("new InsnCtxt: %s", s);
unsafe {
do local_data::modify(task_local_insn_key) |c| {
do c.map_consume |ctx| {
let mut ctx = copy *ctx;
ctx.push(s);
@ctx
}
do local_data::modify(task_local_insn_key) |c| {
do c.map_consume |ctx| {
let mut ctx = copy *ctx;
ctx.push(s);
@ctx
}
}
_InsnCtxt { _x: () }
Expand Down Expand Up @@ -1428,7 +1423,7 @@ pub fn with_scope(bcx: block,

pub fn with_scope_result(bcx: block,
opt_node_info: Option<NodeInfo>,
name: &str,
_name: &str,
f: &fn(block) -> Result) -> Result {
let _icx = push_ctxt("with_scope_result");

Expand Down
18 changes: 8 additions & 10 deletions src/librustc/middle/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ fn get_impl_resolutions(bcx: block,
impl_id: ast::def_id)
-> typeck::vtable_res {
if impl_id.crate == ast::local_crate {
*bcx.ccx().maps.vtable_map.get(&impl_id.node)
bcx.ccx().maps.vtable_map.get_copy(&impl_id.node)
} else {
// XXX: This is a temporary hack to work around not properly
// exporting information about resolutions for impls.
Expand Down Expand Up @@ -670,15 +670,13 @@ pub fn trans_call_inner(in_cx: block,
None => { assert!(ty::type_is_immediate(bcx.tcx(), ret_ty)) }
Some(expr::Ignore) => {
// drop the value if it is not being saved.
unsafe {
if ty::type_needs_drop(bcx.tcx(), ret_ty) {
if ty::type_is_immediate(bcx.tcx(), ret_ty) {
let llscratchptr = alloc_ty(bcx, ret_ty, "__ret");
Store(bcx, llresult, llscratchptr);
bcx = glue::drop_ty(bcx, llscratchptr, ret_ty);
} else {
bcx = glue::drop_ty(bcx, llretslot, ret_ty);
}
if ty::type_needs_drop(bcx.tcx(), ret_ty) {
if ty::type_is_immediate(bcx.tcx(), ret_ty) {
let llscratchptr = alloc_ty(bcx, ret_ty, "__ret");
Store(bcx, llresult, llscratchptr);
bcx = glue::drop_ty(bcx, llscratchptr, ret_ty);
} else {
bcx = glue::drop_ty(bcx, llretslot, ret_ty);
}
}
}
Expand Down
14 changes: 8 additions & 6 deletions src/librustc/middle/trans/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,22 +232,24 @@ impl CrateContext {
#[unsafe_destructor]
impl Drop for CrateContext {
fn drop(&self) {
unsafe {
unset_task_llcx();
}
unset_task_llcx();
}
}

#[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 {
let opt = unsafe { local_data::get(task_local_llcx_key, |k| k.map(|&k| *k)) };
let opt = local_data::get(task_local_llcx_key, |k| k.map(|&k| *k));
*opt.expect("task-local LLVMContextRef wasn't ever set!")
}

unsafe fn set_task_llcx(c: ContextRef) {
fn set_task_llcx(c: ContextRef) {
local_data::set(task_local_llcx_key, @c);
}

unsafe fn unset_task_llcx() {
fn unset_task_llcx() {
local_data::pop(task_local_llcx_key);
}
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/controlflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ pub fn trans_break_cont(bcx: block,
// Locate closest loop block, outputting cleanup as we go.
let mut unwind = bcx;
let mut cur_scope = unwind.scope;
let mut target = unwind;
let mut target;
loop {
cur_scope = match cur_scope {
Some(@scope_info {
Expand Down
36 changes: 20 additions & 16 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3621,25 +3621,29 @@ pub fn trait_method_def_ids(cx: ctxt, id: ast::def_id) -> @~[def_id] {
}

pub fn impl_trait_ref(cx: ctxt, id: ast::def_id) -> Option<@TraitRef> {
*do cx.impl_trait_cache.find_or_insert_with(id) |_| {
if id.crate == ast::local_crate {
debug!("(impl_trait_ref) searching for trait impl %?", id);
match cx.items.find(&id.node) {
Some(&ast_map::node_item(@ast::item {
node: ast::item_impl(_, ref opt_trait, _, _),
_},
_)) => {
match opt_trait {
&Some(ref t) => Some(ty::node_id_to_trait_ref(cx, t.ref_id)),
&None => None
}
match cx.impl_trait_cache.find(&id) {
Some(&ret) => { return ret; }
None => {}
}
let ret = if id.crate == ast::local_crate {
debug!("(impl_trait_ref) searching for trait impl %?", id);
match cx.items.find(&id.node) {
Some(&ast_map::node_item(@ast::item {
node: ast::item_impl(_, ref opt_trait, _, _),
_},
_)) => {
match opt_trait {
&Some(ref t) => Some(ty::node_id_to_trait_ref(cx, t.ref_id)),
&None => None
}
_ => None
}
} else {
csearch::get_impl_trait(cx, id)
_ => None
}
}
} else {
csearch::get_impl_trait(cx, id)
};
cx.impl_trait_cache.insert(id, ret);
return ret;
}

pub fn ty_to_def_id(ty: t) -> Option<ast::def_id> {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/typeck/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
let tcx = ccx.tcx;
let main_t = ty::node_id_to_type(tcx, main_id);
match ty::get(main_t).sty {
ty::ty_bare_fn(ref fn_ty) => {
ty::ty_bare_fn(*) => {
match tcx.items.find(&main_id) {
Some(&ast_map::node_item(it,_)) => {
match it.node {
Expand Down
2 changes: 0 additions & 2 deletions src/librustc/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
#[crate_type = "lib"];

#[allow(non_implicitly_copyable_typarams)];
#[allow(non_camel_case_types)];
#[allow(non_uppercase_statics)];
#[deny(deprecated_pattern)];

extern mod extra;
Expand Down
22 changes: 6 additions & 16 deletions src/librusti/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
use std::cast;
use std::hashmap::HashMap;
use std::local_data;
use std::sys;

use syntax::ast;
use syntax::parse::token;
Expand Down Expand Up @@ -58,7 +57,7 @@ struct LocalVariable {
}

type LocalCache = @mut HashMap<~str, @~[u8]>;
fn tls_key(_k: LocalCache) {}
static tls_key: local_data::Key<LocalCache> = &local_data::Key;

impl Program {
pub fn new() -> Program {
Expand Down Expand Up @@ -131,21 +130,16 @@ impl Program {
fn main() {
");

let key: sys::Closure = unsafe {
let tls_key: &'static fn(LocalCache) = tls_key;
cast::transmute(tls_key)
};
let key: uint= unsafe { cast::transmute(tls_key) };
// First, get a handle to the tls map which stores all the local
// variables. This works by totally legitimately using the 'code'
// pointer of the 'tls_key' function as a uint, and then casting it back
// up to a function
code.push_str(fmt!("
let __tls_map: @mut ::std::hashmap::HashMap<~str, @~[u8]> = unsafe {
let key = ::std::sys::Closure{ code: %? as *(),
env: ::std::ptr::null() };
let key = ::std::cast::transmute(key);
let key = ::std::cast::transmute(%u);
::std::local_data::get(key, |k| k.map(|&x| *x)).unwrap()
};\n", key.code as uint));
};\n", key as uint));

// Using this __tls_map handle, deserialize each variable binding that
// we know about
Expand Down Expand Up @@ -226,18 +220,14 @@ impl Program {
for self.local_vars.iter().advance |(name, value)| {
map.insert(copy *name, @copy value.data);
}
unsafe {
local_data::set(tls_key, map);
}
local_data::set(tls_key, map);
}

/// Once the program has finished running, this function will consume the
/// task-local cache of local variables. After the program finishes running,
/// it updates this cache with the new values of each local variable.
pub fn consume_cache(&mut self) {
let map = unsafe {
local_data::pop(tls_key).expect("tls is empty")
};
let map = local_data::pop(tls_key).expect("tls is empty");
do map.consume |name, value| {
match self.local_vars.find_mut(&name) {
Some(v) => { v.data = copy *value; }
Expand Down
Loading