diff --git a/js.rc b/js.rc index a7cf33bf4..4fc9c3f19 100644 --- a/js.rc +++ b/js.rc @@ -13,7 +13,7 @@ extern crate green; extern crate libc; -#[phase(syntax, link)] +#[phase(plugin, link)] extern crate log; #[cfg(test)] extern crate rustuv; diff --git a/jsval.rs b/jsval.rs index ffe88d80b..427cc284e 100644 --- a/jsval.rs +++ b/jsval.rs @@ -7,6 +7,7 @@ use jsapi::{JSObject, JSString, JSGCTraceKind, JSTRACE_OBJECT, JSTRACE_STRING}; use libc::c_void; use std::mem; +#[cfg(target_word_size = "64")] static JSVAL_TAG_SHIFT: int = 47; #[repr(u8)] @@ -25,8 +26,13 @@ enum ValueType { JSVAL_TYPE_MISSING = 0x21 } +#[cfg(target_word_size = "64")] static JSVAL_TAG_MAX_DOUBLE: u32 = 0x1FFF0u32; +#[cfg(target_word_size = "32")] +static JSVAL_TAG_CLEAR: u32 = 0xFFFFFF80; + +#[cfg(target_word_size = "64")] #[repr(u32)] enum ValueTag { JSVAL_TAG_DOUBLE = JSVAL_TAG_MAX_DOUBLE | (JSVAL_TYPE_DOUBLE as u32), @@ -39,6 +45,20 @@ enum ValueTag { JSVAL_TAG_OBJECT = JSVAL_TAG_MAX_DOUBLE | (JSVAL_TYPE_OBJECT as u32), } +#[cfg(target_word_size = "32")] +#[repr(u32)] +enum ValueTag { + JSVAL_TAG_PRIVATE = 0, + JSVAL_TAG_INT32 = JSVAL_TAG_CLEAR as u32 | (JSVAL_TYPE_INT32 as u32), + JSVAL_TAG_UNDEFINED = JSVAL_TAG_CLEAR as u32 | (JSVAL_TYPE_UNDEFINED as u32), + JSVAL_TAG_STRING = JSVAL_TAG_CLEAR as u32 | (JSVAL_TYPE_STRING as u32), + JSVAL_TAG_BOOLEAN = JSVAL_TAG_CLEAR as u32 | (JSVAL_TYPE_BOOLEAN as u32), + JSVAL_TAG_MAGIC = JSVAL_TAG_CLEAR as u32 | (JSVAL_TYPE_MAGIC as u32), + JSVAL_TAG_NULL = JSVAL_TAG_CLEAR as u32 | (JSVAL_TYPE_NULL as u32), + JSVAL_TAG_OBJECT = JSVAL_TAG_CLEAR as u32 | (JSVAL_TYPE_OBJECT as u32), +} + +#[cfg(target_word_size = "64")] #[repr(u64)] enum ValueShiftedTag { JSVAL_SHIFTED_TAG_MAX_DOUBLE = (((JSVAL_TAG_MAX_DOUBLE as u64) << JSVAL_TAG_SHIFT) | 0xFFFFFFFFu64), @@ -52,6 +72,7 @@ enum ValueShiftedTag { } +#[cfg(target_word_size = "64")] static JSVAL_PAYLOAD_MASK: u64 = 0x00007FFFFFFFFFFF; // JSVal was originally type of u64. @@ -61,6 +82,7 @@ pub struct JSVal { pub v: u64 } +#[cfg(target_word_size = "64")] #[inline(always)] fn BuildJSVal(tag: ValueTag, payload: u64) -> JSVal { JSVal { @@ -68,6 +90,13 @@ fn BuildJSVal(tag: ValueTag, payload: u64) -> JSVal { } } +#[cfg(target_word_size = "32")] +#[inline(always)] +fn BuildJSVal(tag: ValueTag, payload: u64) -> JSVal { + JSVal { + v: ((tag as u32 as u64) << 32) | payload + } +} #[inline(always)] pub fn NullValue() -> JSVal { @@ -84,6 +113,7 @@ pub fn Int32Value(i: i32) -> JSVal { BuildJSVal(JSVAL_TAG_INT32, i as u32 as u64) } +#[cfg(target_word_size = "64")] #[inline(always)] pub fn DoubleValue(f: f64) -> JSVal { let bits: u64 = unsafe { mem::transmute(f) }; @@ -93,6 +123,17 @@ pub fn DoubleValue(f: f64) -> JSVal { } } +#[cfg(target_word_size = "32")] +#[inline(always)] +pub fn DoubleValue(f: f64) -> JSVal { + let bits: u64 = unsafe { mem::transmute(f) }; + let val = JSVal { + v: bits + }; + assert!(val.is_double()); + val +} + #[inline(always)] pub fn UInt32Value(ui: u32) -> JSVal { if ui > 0x7fffffff { @@ -102,6 +143,7 @@ pub fn UInt32Value(ui: u32) -> JSVal { } } +#[cfg(target_word_size = "64")] #[inline(always)] pub fn StringValue(s: &JSString) -> JSVal { let bits = s as *JSString as uint as u64; @@ -109,11 +151,19 @@ pub fn StringValue(s: &JSString) -> JSVal { BuildJSVal(JSVAL_TAG_STRING, bits) } +#[cfg(target_word_size = "32")] +#[inline(always)] +pub fn StringValue(s: &JSString) -> JSVal { + let bits = s as *JSString as uint as u64; + BuildJSVal(JSVAL_TAG_STRING, bits) +} + #[inline(always)] pub fn BooleanValue(b: bool) -> JSVal { BuildJSVal(JSVAL_TAG_BOOLEAN, b as u64) } +#[cfg(target_word_size = "64")] #[inline(always)] pub fn ObjectValue(o: &JSObject) -> JSVal { let bits = o as *JSObject as uint as u64; @@ -121,6 +171,13 @@ pub fn ObjectValue(o: &JSObject) -> JSVal { BuildJSVal(JSVAL_TAG_OBJECT, bits) } +#[cfg(target_word_size = "32")] +#[inline(always)] +pub fn ObjectValue(o: &JSObject) -> JSVal { + let bits = o as *JSObject as uint as u64; + BuildJSVal(JSVAL_TAG_OBJECT, bits) +} + #[inline(always)] pub fn ObjectOrNullValue(o: *mut JSObject) -> JSVal { if o.is_null() { @@ -130,6 +187,7 @@ pub fn ObjectOrNullValue(o: *mut JSObject) -> JSVal { } } +#[cfg(target_word_size = "64")] #[inline(always)] pub fn PrivateValue(o: *c_void) -> JSVal { let ptrBits = o as uint as u64; @@ -139,48 +197,102 @@ pub fn PrivateValue(o: *c_void) -> JSVal { } } +#[cfg(target_word_size = "32")] +#[inline(always)] +pub fn PrivateValue(o: *c_void) -> JSVal { + let ptrBits = o as uint as u64; + assert!((ptrBits & 1) == 0); + BuildJSVal(JSVAL_TAG_PRIVATE, ptrBits) +} + impl JSVal { + #[cfg(target_word_size = "64")] pub fn is_undefined(&self) -> bool { self.v == JSVAL_SHIFTED_TAG_UNDEFINED as u64 } + #[cfg(target_word_size = "32")] + pub fn is_undefined(&self) -> bool { + (self.v >> 32) == JSVAL_TAG_UNDEFINED as u64 + } + + #[cfg(target_word_size = "64")] pub fn is_null(&self) -> bool { self.v == JSVAL_SHIFTED_TAG_NULL as u64 } + #[cfg(target_word_size = "32")] + pub fn is_null(&self) -> bool { + (self.v >> 32) == JSVAL_TAG_NULL as u64 + } + pub fn is_null_or_undefined(&self) -> bool { self.is_null() || self.is_undefined() } + #[cfg(target_word_size = "64")] pub fn is_double(&self) -> bool { self.v <= JSVAL_SHIFTED_TAG_MAX_DOUBLE as u64 } + #[cfg(target_word_size = "32")] + pub fn is_double(&self) -> bool { + (self.v >> 32) <= JSVAL_TAG_CLEAR as u64 + } + + #[cfg(target_word_size = "64")] pub fn is_primitive(&self) -> bool { static JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET: u64 = JSVAL_SHIFTED_TAG_OBJECT as u64; self.v < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET } + #[cfg(target_word_size = "32")] + pub fn is_primitive(&self) -> bool { + static JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET: u64 = JSVAL_TAG_OBJECT as u64; + (self.v >> 32) < JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET + } + + #[cfg(target_word_size = "64")] pub fn is_string(&self) -> bool { (self.v >> JSVAL_TAG_SHIFT) == JSVAL_TAG_STRING as u64 } + #[cfg(target_word_size = "32")] + pub fn is_string(&self) -> bool { + (self.v >> 32) == JSVAL_TAG_STRING as u64 + } + + #[cfg(target_word_size = "64")] pub fn is_object(&self) -> bool { assert!((self.v >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT as u64); self.v >= JSVAL_SHIFTED_TAG_OBJECT as u64 } + #[cfg(target_word_size = "32")] + pub fn is_object(&self) -> bool { + (self.v >> 32) == JSVAL_TAG_OBJECT as u64 + } + pub fn to_object(&self) -> *mut JSObject { assert!(self.is_object()); self.to_object_or_null() } + #[cfg(target_word_size = "64")] pub fn is_object_or_null(&self) -> bool { static JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET: u64 = JSVAL_SHIFTED_TAG_NULL as u64; assert!((self.v >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT as u64); self.v >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET } + #[cfg(target_word_size = "32")] + pub fn is_object_or_null(&self) -> bool { + static JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET: u64 = JSVAL_TAG_NULL as u64; + assert!((self.v >> 32) <= JSVAL_TAG_OBJECT as u64); + (self.v >> 32) >= JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET + } + + #[cfg(target_word_size = "64")] pub fn to_object_or_null(&self) -> *mut JSObject { assert!(self.is_object_or_null()); let ptrBits = self.v & JSVAL_PAYLOAD_MASK; @@ -188,17 +300,39 @@ impl JSVal { ptrBits as uint as *mut JSObject } + #[cfg(target_word_size = "32")] + pub fn to_object_or_null(&self) -> *mut JSObject { + assert!(self.is_object_or_null()); + let ptrBits: u32 = (self.v & 0x00000000FFFFFFFF) as u32; + ptrBits as *mut JSObject + } + + #[cfg(target_word_size = "64")] pub fn to_private(&self) -> *c_void { assert!(self.is_double()); assert!((self.v & 0x8000000000000000u64) == 0); (self.v << 1) as uint as *c_void } + #[cfg(target_word_size = "32")] + pub fn to_private(&self) -> *c_void { + let ptrBits: u32 = (self.v & 0x00000000FFFFFFFF) as u32; + ptrBits as *c_void + } + + #[cfg(target_word_size = "64")] pub fn is_gcthing(&self) -> bool { static JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET: u64 = JSVAL_SHIFTED_TAG_STRING as u64; self.v >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET } + #[cfg(target_word_size = "32")] + pub fn is_gcthing(&self) -> bool { + static JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET: u64 = JSVAL_TAG_STRING as u64; + (self.v >> 32) >= JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET + } + + #[cfg(target_word_size = "64")] pub fn to_gcthing(&self) -> *mut c_void { assert!(self.is_gcthing()); let ptrBits = self.v & JSVAL_PAYLOAD_MASK; @@ -206,6 +340,13 @@ impl JSVal { ptrBits as *mut c_void } + #[cfg(target_word_size = "32")] + pub fn to_gcthing(&self) -> *mut c_void { + assert!(self.is_gcthing()); + let ptrBits: u32 = (self.v & 0x00000000FFFFFFFF) as u32; + ptrBits as *mut c_void + } + pub fn is_markable(&self) -> bool { self.is_gcthing() && !self.is_null() }