GithubHelp home page GithubHelp logo

taylordotfish / tagged-pointer Goto Github PK

View Code? Open in Web Editor NEW
15.0 2.0 3.0 86 KB

Platform-independent space-efficient tagged pointers in Rust

License: Apache License 2.0

Rust 100.00%
rust tagged-pointers platform-independent tag pointer memory-efficient

tagged-pointer's Introduction

tagged-pointer

This crate provides an implementation of tagged pointers: pointers that also contain an integer tag in a space-efficient manner.

Unless the fallback implementation is used (see the Assumptions section below), both TaggedPtr and Option<TaggedPtr> will be the size of a pointer.

This crate depends only on core, so it can be used in no_std environments.

Example

use core::mem::size_of;
use core::ptr::NonNull;
use tagged_pointer::TaggedPtr;

#[repr(align(4))]
struct Item(u32, u32);

// `TaggedPtr` and `Option<TaggedPtr>` are both the size of a pointer:
assert_eq!(size_of::<TaggedPtr<Item, 2>>(), size_of::<*mut ()>());
assert_eq!(size_of::<Option<TaggedPtr<Item, 2>>>(), size_of::<*mut ()>());

let item1 = Item(1, 2);
let item2 = Item(3, 4);

// We can store two bits of the tag, since `Item` has an alignment of 4.
let tp1 = TaggedPtr::<_, 2>::new(NonNull::from(&item1), 1);
let tp2 = TaggedPtr::<_, 2>::new(NonNull::from(&item2), 3);

let (ptr1, tag1) = tp1.get();
let (ptr2, tag2) = tp2.get();

assert_eq!((ptr1, tag1), (NonNull::from(&item1), 1));
assert_eq!((ptr2, tag2), (NonNull::from(&item2), 3));

Assumptions

This crate relies on pointer::align_offset not failing under certain circumstances. Specifically, align_offset, when called in a non-const context on a pointer to u8, must succeed when the desired alignment is less than or equal to the alignment of the allocation pointed to by the provided pointer. In practice, this is true, even in Miri with the -Zmiri-symbolic-alignment-check flag, but the specifications of align_offset technically allow an implementation not to follow this behavior. If you experience issues due to this, please file an issue in the Git repository. As a workaround, you can enable the fallback feature, which avoids relying on align_offset at the cost of making TaggedPtr twice as large.

Note that this crate is always sound: an implementation of align_offset that doesn’t follow the required behavior may cause panics, but not undefined behavior.

Unfortunately, there’s currently no way to implement space-efficient tagged pointers in Rust without making some assumptions. However, this approach has some advantages over the usual method of casting the pointer to a usize and reusing the lower bits: the usual approach makes platform-specific assumptions about the representation of pointers (which currently apply to all platforms supported by rustc but could be invalidated if support for new architectures is added, and there are real architectures which do not allow reusing the lower bits of aligned pointers), whereas this crate’s assumptions are platform-independent (aside from the requirements already imposed by Rust, like having 8-bit bytes) and are satisfied by all known implementations of Rust, including Miri with -Zmiri-symbolic-alignment-check.

Documentation

Documentation is available on docs.rs.

License

tagged-pointer is licensed under version 2 of the Apache License. See LICENSE.

Contributing

By contributing to tagged-pointer, you agree that your contribution may be used according to the terms of tagged-pointer’s license.

tagged-pointer's People

Contributors

jonasalaif avatar taylordotfish avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

tagged-pointer's Issues

Too strict requirments for TaggedPtr::new and ::get/::ptr?

The documentation requires a dereferenceable pointer provided to ::new.
This seems like a too strict precondition, even the cited core::ptr only restricts read and write operations to dereferenceable pointers.

So, from my understanding, either the documentation is too strict, or the implementation of ::new/::get/::ptr needs to reserve the option to read or write to the pointer passed in order to tag it.

This basically prevents an allocator to have a tagged end-pointer (pointing just beyond the allocated memory) - such an end pointer is not dereferenceable, and thus not useable in a TaggedPtr.

Did I miss something?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.