Skip to content

libcore: Use LLVM intrinsics for floor; add a new Perlin noise benchmark #4511

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 2 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
10 changes: 9 additions & 1 deletion src/libcore/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ delegate!(fn exp2(n: c_float) -> c_float = cmath::c_float_utils::exp2)
delegate!(fn abs(n: c_float) -> c_float = cmath::c_float_utils::abs)
delegate!(fn abs_sub(a: c_float, b: c_float) -> c_float =
cmath::c_float_utils::abs_sub)
delegate!(fn floor(n: c_float) -> c_float = cmath::c_float_utils::floor)
delegate!(fn mul_add(a: c_float, b: c_float, c: c_float) -> c_float =
cmath::c_float_utils::mul_add)
delegate!(fn fmax(a: c_float, b: c_float) -> c_float =
Expand Down Expand Up @@ -141,6 +140,10 @@ pub pure fn ge(x: f32, y: f32) -> bool { return x >= y; }
#[inline(always)]
pub pure fn gt(x: f32, y: f32) -> bool { return x > y; }

/// Returns `x` rounded down
#[inline(always)]
pub pure fn floor(x: f32) -> f32 { unsafe { floorf32(x) } }

// FIXME (#1999): replace the predicates below with llvm intrinsics or
// calls to the libmath macros in the rust runtime for performance.

Expand Down Expand Up @@ -298,6 +301,11 @@ impl f32: num::One {
static pure fn one() -> f32 { 1.0 }
}

#[abi="rust-intrinsic"]
pub extern {
fn floorf32(val: f32) -> f32;
}

//
// Local Variables:
// mode: rust
Expand Down
12 changes: 10 additions & 2 deletions src/libcore/f64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ delegate!(fn exp2(n: c_double) -> c_double = cmath::c_double_utils::exp2)
delegate!(fn abs(n: c_double) -> c_double = cmath::c_double_utils::abs)
delegate!(fn abs_sub(a: c_double, b: c_double) -> c_double =
cmath::c_double_utils::abs_sub)
delegate!(fn floor(n: c_double) -> c_double = cmath::c_double_utils::floor)
delegate!(fn mul_add(a: c_double, b: c_double, c: c_double) -> c_double =
cmath::c_double_utils::mul_add)
delegate!(fn fmax(a: c_double, b: c_double) -> c_double =
Expand Down Expand Up @@ -210,12 +209,16 @@ pub pure fn is_infinite(x: f64) -> bool {
return x == infinity || x == neg_infinity;
}

/// Returns true if `x`is a finite number
/// Returns true if `x` is a finite number
#[inline(always)]
pub pure fn is_finite(x: f64) -> bool {
return !(is_NaN(x) || is_infinite(x));
}

/// Returns `x` rounded down
#[inline(always)]
pub pure fn floor(x: f64) -> f64 { unsafe { floorf64(x) } }

// FIXME (#1999): add is_normal, is_subnormal, and fpclassify

/* Module: consts */
Expand Down Expand Up @@ -322,6 +325,11 @@ impl f64: num::One {
static pure fn one() -> f64 { 1.0 }
}

#[abi="rust-intrinsic"]
pub extern {
fn floorf64(val: f64) -> f64;
}

//
// Local Variables:
// mode: rust
Expand Down
31 changes: 31 additions & 0 deletions src/libcore/managed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];

use cast::transmute;
use cmp::{Eq, Ord};
use managed::raw::BoxRepr;
use prelude::*;
use ptr;
use rt::rt_fail_borrowed;

pub mod raw {
use intrinsic::TyDesc;
Expand All @@ -35,12 +38,40 @@ pub mod raw {

}

#[cfg(target_word_size = "32")]
const FROZEN_BIT: uint = 0x80000000;
#[cfg(target_word_size = "64")]
const FROZEN_BIT: uint = 0x8000000000000000;

#[inline(always)]
pub pure fn ptr_eq<T>(a: @T, b: @T) -> bool {
//! Determine if two shared boxes point to the same object
unsafe { ptr::addr_of(&(*a)) == ptr::addr_of(&(*b)) }
}

#[lang="borrow_as_imm"]
#[inline(always)]
pub unsafe fn borrow_as_imm(a: *u8) {
let a: *mut BoxRepr = transmute(a);
(*a).header.ref_count |= FROZEN_BIT;
}

#[lang="return_to_mut"]
#[inline(always)]
pub unsafe fn return_to_mut(a: *u8) {
let a: *mut BoxRepr = transmute(a);
(*a).header.ref_count &= !FROZEN_BIT;
}

#[lang="check_not_borrowed"]
#[inline(always)]
pub unsafe fn check_not_borrowed(a: *u8) {
let a: *mut BoxRepr = transmute(a);
if ((*a).header.ref_count & FROZEN_BIT) != 0 {
rt_fail_borrowed();
}
}

#[cfg(notest)]
impl<T:Eq> @const T : Eq {
#[inline(always)]
Expand Down
9 changes: 9 additions & 0 deletions src/libcore/rt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ pub unsafe fn rt_fail_bounds_check(file: *c_char, line: size_t,
}
}

pub unsafe fn rt_fail_borrowed() {
let msg = "borrowed";
do str::as_buf(msg) |msg_p, _| {
do str::as_buf("???") |file_p, _| {
rt_fail_(msg_p as *c_char, file_p as *c_char, 0);
}
}
}

#[rt(exchange_malloc)]
#[lang="exchange_malloc"]
pub unsafe fn rt_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
Expand Down
5 changes: 3 additions & 2 deletions src/librustc/driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ fn compile_upto(sess: Session, cfg: ast::crate_cfg,
time(time_passes, ~"liveness checking", ||
middle::liveness::check_crate(ty_cx, method_map, crate));

let (root_map, mutbl_map) =
let (root_map, mutbl_map, write_guard_map) =
time(time_passes, ~"borrow checking", ||
middle::borrowck::check_crate(ty_cx, method_map,
last_use_map, crate));
Expand All @@ -309,7 +309,8 @@ fn compile_upto(sess: Session, cfg: ast::crate_cfg,
root_map: root_map,
last_use_map: last_use_map,
method_map: method_map,
vtable_map: vtable_map};
vtable_map: vtable_map,
write_guard_map: write_guard_map};

time(time_passes, ~"translation", ||
trans::base::trans_crate(sess, crate, ty_cx,
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type maps = {
last_use_map: middle::liveness::last_use_map,
method_map: middle::typeck::method_map,
vtable_map: middle::typeck::vtable_map,
write_guard_map: middle::borrowck::write_guard_map,
};

type decode_ctxt = @{
Expand Down
56 changes: 27 additions & 29 deletions src/librustc/middle/borrowck/check_loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use core::prelude::*;

use middle::borrowck::{Loan, bckerr, borrowck_ctxt, cmt, inherent_mutability};
use middle::borrowck::{req_maps, save_and_restore};
use middle::mem_categorization::{cat_arg, cat_binding, cat_deref, cat_local};
use middle::mem_categorization::{cat_rvalue, cat_special};
use middle::mem_categorization::{cat_arg, cat_binding, cat_comp, cat_deref};
use middle::mem_categorization::{cat_local, cat_rvalue, cat_special, gc_ptr};
use middle::mem_categorization::{loan_path, lp_arg, lp_comp, lp_deref};
use middle::mem_categorization::{lp_local};
use middle::ty::{CopyValue, MoveValue, ReadValue};
Expand Down Expand Up @@ -54,6 +54,7 @@ enum check_loan_ctxt = @{
};

// if we are enforcing purity, why are we doing so?
#[deriving_eq]
enum purity_cause {
// enforcing purity because fn was declared pure:
pc_pure_fn,
Expand All @@ -64,26 +65,6 @@ enum purity_cause {
pc_cmt(bckerr)
}

impl purity_cause : cmp::Eq {
pure fn eq(&self, other: &purity_cause) -> bool {
match (*self) {
pc_pure_fn => {
match (*other) {
pc_pure_fn => true,
_ => false
}
}
pc_cmt(ref e0a) => {
match (*other) {
pc_cmt(ref e0b) => (*e0a) == (*e0b),
_ => false
}
}
}
}
pure fn ne(&self, other: &purity_cause) -> bool { !(*self).eq(other) }
}

fn check_loans(bccx: borrowck_ctxt,
req_maps: req_maps,
crate: @ast::crate) {
Expand All @@ -100,18 +81,12 @@ fn check_loans(bccx: borrowck_ctxt,
visit::visit_crate(*crate, clcx, vt);
}

#[deriving_eq]
enum assignment_type {
at_straight_up,
at_swap
}

impl assignment_type : cmp::Eq {
pure fn eq(&self, other: &assignment_type) -> bool {
((*self) as uint) == ((*other) as uint)
}
pure fn ne(&self, other: &assignment_type) -> bool { !(*self).eq(other) }
}

impl assignment_type {
fn checked_by_liveness() -> bool {
// the liveness pass guarantees that immutable local variables
Expand Down Expand Up @@ -410,6 +385,29 @@ impl check_loan_ctxt {
}

self.bccx.add_to_mutbl_map(cmt);

// Check for and insert write guards as necessary.
self.add_write_guards_if_necessary(cmt);
}

fn add_write_guards_if_necessary(cmt: cmt) {
match cmt.cat {
cat_deref(base, deref_count, ptr_kind) => {
self.add_write_guards_if_necessary(base);

match ptr_kind {
gc_ptr(ast::m_mutbl) => {
let key = { id: base.id, derefs: deref_count };
self.bccx.write_guard_map.insert(key, ());
}
_ => {}
}
}
cat_comp(base, _) => {
self.add_write_guards_if_necessary(base);
}
_ => {}
}
}

fn check_for_loan_conflicting_with_assignment(
Expand Down
14 changes: 10 additions & 4 deletions src/librustc/middle/borrowck/gather_loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,10 +454,16 @@ impl gather_loan_ctxt {
let e = {cmt: cmt,
code: err_mutbl(req_mutbl)};
if req_mutbl == m_imm {
// you can treat mutable things as imm if you are pure
debug!("imm required, must be pure");

Ok(pc_if_pure(e))
// if this is an @mut box, then it's generally OK to borrow as
// &imm; this will result in a write guard
if cmt.cat.is_mutable_box() {
Ok(pc_ok)
} else {
// you can treat mutable things as imm if you are pure
debug!("imm required, must be pure");

Ok(pc_if_pure(e))
}
} else {
Err(e)
}
Expand Down
5 changes: 3 additions & 2 deletions src/librustc/middle/borrowck/loan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ use middle::borrowck::{err_out_of_scope};
use middle::mem_categorization::{cat_arg, cat_binding, cat_discr, cat_comp};
use middle::mem_categorization::{cat_deref, cat_discr, cat_local};
use middle::mem_categorization::{cat_special, cat_stack_upvar, comp_field};
use middle::mem_categorization::{comp_index, comp_variant, region_ptr};
use middle::mem_categorization::{comp_index, comp_variant, gc_ptr};
use middle::mem_categorization::{region_ptr};
use middle::ty;
use util::common::indenter;

Expand Down Expand Up @@ -162,7 +163,7 @@ impl LoanContext {
self.loan_unstable_deref(cmt, cmt_base, req_mutbl)
}
cat_deref(_, _, unsafe_ptr) |
cat_deref(_, _, gc_ptr) |
cat_deref(_, _, gc_ptr(_)) |
cat_deref(_, _, region_ptr(_)) => {
// Aliased data is simply not lendable.
self.bccx.tcx.sess.span_bug(
Expand Down
28 changes: 17 additions & 11 deletions src/librustc/middle/borrowck/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,13 +263,15 @@ pub mod preserve;
fn check_crate(tcx: ty::ctxt,
method_map: typeck::method_map,
last_use_map: liveness::last_use_map,
crate: @ast::crate) -> (root_map, mutbl_map) {
crate: @ast::crate)
-> (root_map, mutbl_map, write_guard_map) {

let bccx = borrowck_ctxt_(@{tcx: tcx,
method_map: method_map,
last_use_map: last_use_map,
root_map: root_map(),
mutbl_map: HashMap(),
write_guard_map: HashMap(),
mut loaned_paths_same: 0,
mut loaned_paths_imm: 0,
mut stable_paths: 0,
Expand All @@ -293,7 +295,7 @@ fn check_crate(tcx: ty::ctxt,
make_stat(bccx, bccx.req_pure_paths)));
}

return (bccx.root_map, bccx.mutbl_map);
return (bccx.root_map, bccx.mutbl_map, bccx.write_guard_map);

fn make_stat(bccx: borrowck_ctxt, stat: uint) -> ~str {
let stat_f = stat as float;
Expand All @@ -310,6 +312,7 @@ type borrowck_ctxt_ = {tcx: ty::ctxt,
last_use_map: liveness::last_use_map,
root_map: root_map,
mutbl_map: mutbl_map,
write_guard_map: write_guard_map,

// Statistics:
mut loaned_paths_same: uint,
Expand All @@ -322,10 +325,17 @@ enum borrowck_ctxt {
borrowck_ctxt_(@borrowck_ctxt_)
}

struct RootInfo {
scope: ast::node_id,
// This will be true if we need to freeze this box at runtime. This will
// result in a call to `borrow_as_imm()` and `return_to_mut()`.
freezes: bool // True if we need to freeze this box at runtime.
}

// a map mapping id's of expressions of gc'd type (@T, @[], etc) where
// the box needs to be kept live to the id of the scope for which they
// must stay live.
type root_map = HashMap<root_map_key, ast::node_id>;
type root_map = HashMap<root_map_key, RootInfo>;

// the keys to the root map combine the `id` of the expression with
// the number of types that it is autodereferenced. So, for example,
Expand All @@ -338,6 +348,10 @@ type root_map_key = {id: ast::node_id, derefs: uint};
// this is used in trans for optimization purposes.
type mutbl_map = HashMap<ast::node_id, ()>;

// A set containing IDs of expressions of gc'd type that need to have a write
// guard.
type write_guard_map = HashMap<root_map_key, ()>;

// Errors that can occur"]
enum bckerr_code {
err_mut_uniq,
Expand Down Expand Up @@ -447,14 +461,6 @@ impl root_map_key : to_bytes::IterBytes {

fn root_map() -> root_map {
return HashMap();

pure fn root_map_key_eq(k1: &root_map_key, k2: &root_map_key) -> bool {
k1.id == k2.id && k1.derefs == k2.derefs
}

pure fn root_map_key_hash(k: &root_map_key) -> uint {
(k.id << 4) as uint | k.derefs
}
}

// ___________________________________________________________________________
Expand Down
Loading