Skip to content

Commit

Permalink
BigInt => Rc<BigInt>
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat committed Jun 17, 2020
1 parent 06f058c commit e10cc88
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 46 deletions.
11 changes: 7 additions & 4 deletions boa/src/builtins/bigint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
builtins::{
function::{make_builtin_fn, make_constructor_fn},
object::ObjectData,
value::{ResultValue, Value},
value::{RcBigInt, ResultValue, Value},
},
exec::Interpreter,
BoaProfiler,
Expand Down Expand Up @@ -61,7 +61,7 @@ impl BigInt {
///
/// [spec]: https://tc39.es/ecma262/#sec-thisbigintvalue
#[inline]
fn this_bigint_value(value: &Value, ctx: &mut Interpreter) -> Result<Self, Value> {
fn this_bigint_value(value: &Value, ctx: &mut Interpreter) -> Result<RcBigInt, Value> {
match value {
// 1. If Type(value) is BigInt, return value.
Value::BigInt(ref bigint) => return Ok(bigint.clone()),
Expand Down Expand Up @@ -94,7 +94,7 @@ impl BigInt {
pub(crate) fn make_bigint(_: &mut Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
let data = match args.get(0) {
Some(ref value) => ctx.to_bigint(value)?,
None => Self::from(0),
None => RcBigInt::from(Self::from(0)),
};
Ok(Value::from(data))
}
Expand Down Expand Up @@ -206,7 +206,10 @@ impl BigInt {
let bigint = ctx.to_bigint(bigint_arg)?;

Ok((
bigint.mod_floor(&BigInt::from(2).pow(&BigInt::from(bits as i64))),
bigint
.as_inner()
.clone()
.mod_floor(&BigInt::from(2).pow(&BigInt::from(bits as i64))),
bits,
))
}
Expand Down
6 changes: 3 additions & 3 deletions boa/src/builtins/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{
builtins::{
function::Function,
property::Property,
value::{RcString, RcSymbol, ResultValue, Value},
value::{RcBigInt, RcString, RcSymbol, ResultValue, Value},
BigInt,
},
exec::Interpreter,
Expand Down Expand Up @@ -64,7 +64,7 @@ pub struct Object {
#[derive(Debug, Trace, Finalize, Clone)]
pub enum ObjectData {
Array,
BigInt(BigInt),
BigInt(RcBigInt),
Boolean(bool),
Function(Function),
String(RcString),
Expand Down Expand Up @@ -186,7 +186,7 @@ impl Object {
}

/// Return a new `BigInt` object whose `[[BigIntData]]` internal slot is set to argument.
pub fn bigint(value: BigInt) -> Self {
pub fn bigint(value: RcBigInt) -> Self {
Self {
data: ObjectData::BigInt(value),
internal_slots: FxHashMap::default(),
Expand Down
6 changes: 6 additions & 0 deletions boa/src/builtins/value/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ impl From<BigInt> for Value {
}
}

impl From<RcBigInt> for Value {
fn from(value: RcBigInt) -> Self {
Value::BigInt(value)
}
}

impl From<usize> for Value {
fn from(value: usize) -> Value {
Value::integer(value as i32)
Expand Down
12 changes: 6 additions & 6 deletions boa/src/builtins/value/equality.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@ impl Value {
// b. If n is NaN, return false.
// c. Return the result of the comparison x == n.
(Self::BigInt(ref a), Self::String(ref b)) => match string_to_bigint(b) {
Some(ref b) => a == b,
Some(ref b) => a.as_inner() == b,
None => false,
},

// 7. If Type(x) is String and Type(y) is BigInt, return the result of the comparison y == x.
(Self::String(ref a), Self::BigInt(ref b)) => match string_to_bigint(a) {
Some(ref a) => a == b,
Some(ref a) => a == b.as_inner(),
None => false,
},

Expand All @@ -104,10 +104,10 @@ impl Value {
// 12. If Type(x) is BigInt and Type(y) is Number, or if Type(x) is Number and Type(y) is BigInt, then
// a. If x or y are any of NaN, +∞, or -∞, return false.
// b. If the mathematical value of x is equal to the mathematical value of y, return true; otherwise return false.
(Self::BigInt(ref a), Self::Rational(ref b)) => a == b,
(Self::Rational(ref a), Self::BigInt(ref b)) => a == b,
(Self::BigInt(ref a), Self::Integer(ref b)) => a == b,
(Self::Integer(ref a), Self::BigInt(ref b)) => a == b,
(Self::BigInt(ref a), Self::Rational(ref b)) => a.as_inner() == b,
(Self::Rational(ref a), Self::BigInt(ref b)) => a == b.as_inner(),
(Self::BigInt(ref a), Self::Integer(ref b)) => a.as_inner() == b,
(Self::Integer(ref a), Self::BigInt(ref b)) => a == b.as_inner(),

// 13. Return false.
_ => false,
Expand Down
17 changes: 11 additions & 6 deletions boa/src/builtins/value/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub mod display;
pub mod equality;
pub mod hash;
pub mod operations;
pub mod rcbigint;
pub mod rcstring;
pub mod rcsymbol;

Expand All @@ -42,6 +43,7 @@ pub(crate) use display::display_obj;
pub use equality::*;
pub use hash::*;
pub use operations::*;
pub use rcbigint::RcBigInt;
pub use rcstring::RcString;
pub use rcsymbol::RcSymbol;

Expand All @@ -65,7 +67,7 @@ pub enum Value {
/// `Number` - A 32-bit integer, such as `42`.
Integer(i32),
/// `BigInt` - holds any arbitrary large signed integer.
BigInt(BigInt),
BigInt(RcBigInt),
/// `Object` - An object, such as `Math`, represented by a binary tree of string keys to Javascript values.
Object(Gc<GcCell<Object>>),
/// `Symbol` - A Symbol Primitive type.
Expand Down Expand Up @@ -129,8 +131,11 @@ impl Value {

/// Creates a new bigint value.
#[inline]
pub fn bigint(value: BigInt) -> Self {
Self::BigInt(value)
pub fn bigint<B>(value: B) -> Self
where
B: Into<RcBigInt>,
{
Self::BigInt(value.into())
}

/// Creates a new boolean value.
Expand All @@ -154,7 +159,7 @@ impl Value {
/// Helper function to convert the `Value` to a number and compute its power.
pub fn as_num_to_power(&self, other: Self) -> Self {
match (self, other) {
(Self::BigInt(ref a), Self::BigInt(ref b)) => Self::bigint(a.clone().pow(b)),
(Self::BigInt(ref a), Self::BigInt(ref b)) => Self::bigint(a.as_inner().clone().pow(b)),
(a, b) => Self::rational(a.to_number().powf(b.to_number())),
}
}
Expand Down Expand Up @@ -413,7 +418,7 @@ impl Value {
Self::Rational(n) if n != 0.0 && !n.is_nan() => true,
Self::Integer(n) if n != 0 => true,
Self::Boolean(v) => v,
Self::BigInt(ref n) if *n != 0 => true,
Self::BigInt(ref n) if *n.as_inner() != 0 => true,
_ => false,
}
}
Expand Down Expand Up @@ -471,7 +476,7 @@ impl Value {
Self::String(ref s) if !s.is_empty() => true,
Self::Rational(n) if n != 0.0 && !n.is_nan() => true,
Self::Integer(n) if n != 0 => true,
Self::BigInt(ref n) if *n != 0 => true,
Self::BigInt(ref n) if *n.as_inner() != 0 => true,
Self::Boolean(v) => v,
_ => false,
}
Expand Down
42 changes: 31 additions & 11 deletions boa/src/builtins/value/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ impl Add for Value {
(Self::String(ref s), ref o) => {
Self::string(format!("{}{}", s.clone(), &o.to_string()))
}
(Self::BigInt(ref n1), Self::BigInt(ref n2)) => Self::bigint(n1.clone() + n2.clone()),
(Self::BigInt(ref n1), Self::BigInt(ref n2)) => {
Self::bigint(n1.as_inner().clone() + n2.as_inner().clone())
}
(ref s, Self::String(ref o)) => Self::string(format!("{}{}", s.to_string(), o)),
(ref s, ref o) => Self::rational(s.to_number() + o.to_number()),
}
Expand All @@ -17,7 +19,9 @@ impl Sub for Value {
type Output = Self;
fn sub(self, other: Self) -> Self {
match (self, other) {
(Self::BigInt(ref a), Self::BigInt(ref b)) => Self::bigint(a.clone() - b.clone()),
(Self::BigInt(ref a), Self::BigInt(ref b)) => {
Self::bigint(a.as_inner().clone() - b.as_inner().clone())
}
(a, b) => Self::rational(a.to_number() - b.to_number()),
}
}
Expand All @@ -26,7 +30,9 @@ impl Mul for Value {
type Output = Self;
fn mul(self, other: Self) -> Self {
match (self, other) {
(Self::BigInt(ref a), Self::BigInt(ref b)) => Self::bigint(a.clone() * b.clone()),
(Self::BigInt(ref a), Self::BigInt(ref b)) => {
Self::bigint(a.as_inner().clone() * b.as_inner().clone())
}
(a, b) => Self::rational(a.to_number() * b.to_number()),
}
}
Expand All @@ -35,7 +41,9 @@ impl Div for Value {
type Output = Self;
fn div(self, other: Self) -> Self {
match (self, other) {
(Self::BigInt(ref a), Self::BigInt(ref b)) => Self::bigint(a.clone() / b.clone()),
(Self::BigInt(ref a), Self::BigInt(ref b)) => {
Self::bigint(a.as_inner().clone() / b.as_inner().clone())
}
(a, b) => Self::rational(a.to_number() / b.to_number()),
}
}
Expand All @@ -44,7 +52,9 @@ impl Rem for Value {
type Output = Self;
fn rem(self, other: Self) -> Self {
match (self, other) {
(Self::BigInt(ref a), Self::BigInt(ref b)) => Self::bigint(a.clone() % b.clone()),
(Self::BigInt(ref a), Self::BigInt(ref b)) => {
Self::bigint(a.as_inner().clone() % b.as_inner().clone())
}
(a, b) => Self::rational(a.to_number() % b.to_number()),
}
}
Expand All @@ -53,7 +63,9 @@ impl BitAnd for Value {
type Output = Self;
fn bitand(self, other: Self) -> Self {
match (self, other) {
(Self::BigInt(ref a), Self::BigInt(ref b)) => Self::bigint(a.clone() & b.clone()),
(Self::BigInt(ref a), Self::BigInt(ref b)) => {
Self::bigint(a.as_inner().clone() & b.as_inner().clone())
}
(a, b) => Self::integer(a.to_integer() & b.to_integer()),
}
}
Expand All @@ -62,7 +74,9 @@ impl BitOr for Value {
type Output = Self;
fn bitor(self, other: Self) -> Self {
match (self, other) {
(Self::BigInt(ref a), Self::BigInt(ref b)) => Self::bigint(a.clone() | b.clone()),
(Self::BigInt(ref a), Self::BigInt(ref b)) => {
Self::bigint(a.as_inner().clone() | b.as_inner().clone())
}
(a, b) => Self::integer(a.to_integer() | b.to_integer()),
}
}
Expand All @@ -71,7 +85,9 @@ impl BitXor for Value {
type Output = Self;
fn bitxor(self, other: Self) -> Self {
match (self, other) {
(Self::BigInt(ref a), Self::BigInt(ref b)) => Self::bigint(a.clone() ^ b.clone()),
(Self::BigInt(ref a), Self::BigInt(ref b)) => {
Self::bigint(a.as_inner().clone() ^ b.as_inner().clone())
}
(a, b) => Self::integer(a.to_integer() ^ b.to_integer()),
}
}
Expand All @@ -81,7 +97,9 @@ impl Shl for Value {
type Output = Self;
fn shl(self, other: Self) -> Self {
match (self, other) {
(Self::BigInt(ref a), Self::BigInt(ref b)) => Self::bigint(a.clone() << b.clone()),
(Self::BigInt(ref a), Self::BigInt(ref b)) => {
Self::bigint(a.as_inner().clone() << b.as_inner().clone())
}
(a, b) => Self::integer(a.to_integer() << b.to_integer()),
}
}
Expand All @@ -90,7 +108,9 @@ impl Shr for Value {
type Output = Self;
fn shr(self, other: Self) -> Self {
match (self, other) {
(Self::BigInt(ref a), Self::BigInt(ref b)) => Self::bigint(a.clone() >> b.clone()),
(Self::BigInt(ref a), Self::BigInt(ref b)) => {
Self::bigint(a.as_inner().clone() >> b.as_inner().clone())
}
(a, b) => Self::integer(a.to_integer() >> b.to_integer()),
}
}
Expand All @@ -116,7 +136,7 @@ impl Neg for Value {
Self::Integer(num) => Self::rational(-f64::from(num)),
Self::Boolean(true) => Self::integer(1),
Self::Boolean(false) | Self::Null => Self::integer(0),
Self::BigInt(ref num) => Self::bigint(-num.clone()),
Self::BigInt(ref num) => Self::bigint(-num.as_inner().clone()),
}
}
}
42 changes: 42 additions & 0 deletions boa/src/builtins/value/rcbigint.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use crate::builtins::BigInt;

use std::fmt::{self, Display};
use std::ops::Deref;
use std::rc::Rc;

use gc::{unsafe_empty_trace, Finalize, Trace};

#[derive(Debug, Finalize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RcBigInt(Rc<BigInt>);

unsafe impl Trace for RcBigInt {
unsafe_empty_trace!();
}

impl RcBigInt {
pub(crate) fn as_inner(&self) -> &BigInt {
&self.0
}
}

impl Display for RcBigInt {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.0, f)
}
}

impl Deref for RcBigInt {
type Target = BigInt;

#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}

impl From<BigInt> for RcBigInt {
#[inline]
fn from(bigint: BigInt) -> Self {
Self(Rc::from(bigint))
}
}
4 changes: 1 addition & 3 deletions boa/src/exec/identifier/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ impl Executable for Identifier {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
let reference = resolve_binding(interpreter, self.as_ref());
match reference {
Value::Undefined => Err(interpreter
.throw_reference_error(self.as_ref())
.expect_err("throw_reference_error() must return an error")),
Value::Undefined => Err(interpreter.construct_reference_error(self.as_ref())),
_ => Ok(reference),
}
}
Expand Down
14 changes: 7 additions & 7 deletions boa/src/exec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::{
function::{Function as FunctionObject, FunctionBody, ThisMode},
object::{Object, ObjectData, INSTANCE_PROTOTYPE, PROTOTYPE},
property::Property,
value::{RcString, ResultValue, Type, Value},
value::{RcBigInt, RcString, ResultValue, Type, Value},
BigInt, Number,
},
realm::Realm,
Expand Down Expand Up @@ -192,19 +192,19 @@ impl Interpreter {

/// Helper function.
#[allow(clippy::wrong_self_convention)]
pub fn to_bigint(&mut self, value: &Value) -> Result<BigInt, Value> {
pub fn to_bigint(&mut self, value: &Value) -> Result<RcBigInt, Value> {
match value {
Value::Null => Err(self.construct_type_error("cannot convert null to a BigInt")),
Value::Undefined => {
Err(self.construct_type_error("cannot convert undefined to a BigInt"))
}
Value::String(ref string) => Ok(BigInt::from_string(string, self)?),
Value::Boolean(true) => Ok(BigInt::from(1)),
Value::Boolean(false) => Ok(BigInt::from(0)),
Value::Integer(num) => Ok(BigInt::from(*num)),
Value::String(ref string) => Ok(RcBigInt::from(BigInt::from_string(string, self)?)),
Value::Boolean(true) => Ok(RcBigInt::from(BigInt::from(1))),
Value::Boolean(false) => Ok(RcBigInt::from(BigInt::from(0))),
Value::Integer(num) => Ok(RcBigInt::from(BigInt::from(*num))),
Value::Rational(num) => {
if let Ok(bigint) = BigInt::try_from(*num) {
return Ok(bigint);
return Ok(RcBigInt::from(bigint));
}
Err(self.construct_type_error(format!(
"The number {} cannot be converted to a BigInt because it is not an integer",
Expand Down
Loading

0 comments on commit e10cc88

Please sign in to comment.