Added implementation if Uint32::Value.

Review URL: http://codereview.chromium.org/661275

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4008 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
lrn@chromium.org 2010-03-03 13:44:20 +00:00
parent fca7b2cefa
commit d51f2c96cb
5 changed files with 149 additions and 5 deletions

View File

@ -550,13 +550,13 @@ class V8EXPORT Script {
* Compiles the specified script (context-independent).
*
* \param source Script source code.
* \param origin Script origin, owned by caller, no references are kept
* \param origin Script origin, owned by caller, no references are kept
* when New() returns
* \param pre_data Pre-parsing data, as obtained by ScriptData::PreCompile()
* using pre_data speeds compilation if it's done multiple times.
* Owned by caller, no references are kept when New() returns.
* \param script_data Arbitrary data associated with script. Using
* this has same effect as calling SetData(), but allows data to be
* this has same effect as calling SetData(), but allows data to be
* available to compile event handlers.
* \return Compiled script object (context independent; when run it
* will use the currently entered context).
@ -571,7 +571,7 @@ class V8EXPORT Script {
* object (typically a string) as the script's origin.
*
* \param source Script source code.
* \patam file_name file name object (typically a string) to be used
* \param file_name file name object (typically a string) to be used
* as the script's origin.
* \return Compiled script object (context independent; when run it
* will use the currently entered context).
@ -583,7 +583,7 @@ class V8EXPORT Script {
* Compiles the specified script (bound to current context).
*
* \param source Script source code.
* \param origin Script origin, owned by caller, no references are kept
* \param origin Script origin, owned by caller, no references are kept
* when Compile() returns
* \param pre_data Pre-parsing data, as obtained by ScriptData::PreCompile()
* using pre_data speeds compilation if it's done multiple times.
@ -766,6 +766,11 @@ class V8EXPORT Value : public Data {
*/
bool IsInt32() const;
/**
* Returns true if this value is a 32-bit signed integer.
*/
bool IsUint32() const;
/**
* Returns true if this value is a Date.
*/

View File

@ -1569,6 +1569,18 @@ bool Value::IsInt32() const {
}
bool Value::IsUint32() const {
if (IsDeadCheck("v8::Value::IsUint32()")) return false;
i::Handle<i::Object> obj = Utils::OpenHandle(this);
if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
if (obj->IsNumber()) {
double value = obj->Number();
return i::FastUI2D(i::FastD2UI(value)) == value;
}
return false;
}
bool Value::IsDate() const {
if (IsDeadCheck("v8::Value::IsDate()")) return false;
i::Handle<i::Object> obj = Utils::OpenHandle(this);
@ -2756,6 +2768,17 @@ int32_t Int32::Value() const {
}
uint32_t Uint32::Value() const {
if (IsDeadCheck("v8::Uint32::Value()")) return 0;
i::Handle<i::Object> obj = Utils::OpenHandle(this);
if (obj->IsSmi()) {
return i::Smi::cast(*obj)->value();
} else {
return static_cast<uint32_t>(obj->Number());
}
}
int v8::Object::InternalFieldCount() {
if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
i::Handle<i::JSObject> obj = Utils::OpenHandle(this);

View File

@ -59,6 +59,32 @@ static inline int FastD2I(double x) {
}
// The fast double-to-unsigned-int conversion routine does not guarantee
// rounding towards zero.
static inline unsigned int FastD2UI(double x) {
// There is no unsigned version of lrint, so there is no fast path
// in this function as there is in FastD2I. Using lrint doesn't work
// for values of 2^31 and above.
// Convert "small enough" doubles to uint32_t by fixing the 32
// least significant non-fractional bits in the low 32 bits of the
// double, and reading them from there.
const double k2Pow52 = 4503599627370496.0;
bool negative = x < 0;
if (negative) {
x = -x;
}
if (x < k2Pow52) {
x += k2Pow52;
uint32_t result;
memcpy(&result, &x, sizeof(result)); // Copy low 32 bits.
return negative ? ~result + 1 : result;
}
// Large number (outside uint32 range), Infinity or NaN.
return 0x80000000u; // Return integer indefinite.
}
static inline double DoubleToInteger(double x) {
if (isnan(x)) return 0;
if (!isfinite(x) || x == 0) return x;

View File

@ -32,11 +32,12 @@ namespace v8 {
namespace internal {
// The fast double-to-int conversion routine does not guarantee
// The fast double-to-(unsigned-)int conversion routine does not guarantee
// rounding towards zero.
// The result is unspecified if x is infinite or NaN, or if the rounded
// integer value is outside the range of type int.
static inline int FastD2I(double x);
static inline unsigned int FastD2UI(double x);
static inline double FastI2D(int x) {

View File

@ -1960,6 +1960,95 @@ static void CheckUncle(v8::TryCatch* try_catch) {
}
THREADED_TEST(ConversionNumber) {
v8::HandleScope scope;
LocalContext env;
// Very large number.
CompileRun("var obj = Math.pow(2,32) * 1237;");
Local<Value> obj = env->Global()->Get(v8_str("obj"));
CHECK_EQ(5312874545152.0, obj->ToNumber()->Value());
CHECK_EQ(0, obj->ToInt32()->Value());
CHECK(0u == obj->ToUint32()->Value()); // NOLINT - no CHECK_EQ for unsigned.
// Large number.
CompileRun("var obj = -1234567890123;");
obj = env->Global()->Get(v8_str("obj"));
CHECK_EQ(-1234567890123.0, obj->ToNumber()->Value());
CHECK_EQ(-1912276171, obj->ToInt32()->Value());
CHECK(2382691125u == obj->ToUint32()->Value()); // NOLINT
// Small positive integer.
CompileRun("var obj = 42;");
obj = env->Global()->Get(v8_str("obj"));
CHECK_EQ(42.0, obj->ToNumber()->Value());
CHECK_EQ(42, obj->ToInt32()->Value());
CHECK(42u == obj->ToUint32()->Value()); // NOLINT
// Negative integer.
CompileRun("var obj = -37;");
obj = env->Global()->Get(v8_str("obj"));
CHECK_EQ(-37.0, obj->ToNumber()->Value());
CHECK_EQ(-37, obj->ToInt32()->Value());
CHECK(4294967259u == obj->ToUint32()->Value()); // NOLINT
// Positive non-int32 integer.
CompileRun("var obj = 0x81234567;");
obj = env->Global()->Get(v8_str("obj"));
CHECK_EQ(2166572391.0, obj->ToNumber()->Value());
CHECK_EQ(-2128394905, obj->ToInt32()->Value());
CHECK(2166572391u == obj->ToUint32()->Value()); // NOLINT
// Fraction.
CompileRun("var obj = 42.3;");
obj = env->Global()->Get(v8_str("obj"));
CHECK_EQ(42.3, obj->ToNumber()->Value());
CHECK_EQ(42, obj->ToInt32()->Value());
CHECK(42u == obj->ToUint32()->Value()); // NOLINT
// Large negative fraction.
CompileRun("var obj = -5726623061.75;");
obj = env->Global()->Get(v8_str("obj"));
CHECK_EQ(-5726623061.75, obj->ToNumber()->Value());
CHECK_EQ(-1431655765, obj->ToInt32()->Value());
CHECK(2863311531u == obj->ToUint32()->Value()); // NOLINT
}
THREADED_TEST(isNumberType) {
v8::HandleScope scope;
LocalContext env;
// Very large number.
CompileRun("var obj = Math.pow(2,32) * 1237;");
Local<Value> obj = env->Global()->Get(v8_str("obj"));
CHECK(!obj->IsInt32());
CHECK(!obj->IsUint32());
// Large negative number.
CompileRun("var obj = -1234567890123;");
obj = env->Global()->Get(v8_str("obj"));
CHECK(!obj->IsInt32());
CHECK(!obj->IsUint32());
// Small positive integer.
CompileRun("var obj = 42;");
obj = env->Global()->Get(v8_str("obj"));
CHECK(obj->IsInt32());
CHECK(obj->IsUint32());
// Negative integer.
CompileRun("var obj = -37;");
obj = env->Global()->Get(v8_str("obj"));
CHECK(obj->IsInt32());
CHECK(!obj->IsUint32());
// Positive non-int32 integer.
CompileRun("var obj = 0x81234567;");
obj = env->Global()->Get(v8_str("obj"));
CHECK(!obj->IsInt32());
CHECK(obj->IsUint32());
// Fraction.
CompileRun("var obj = 42.3;");
obj = env->Global()->Get(v8_str("obj"));
CHECK(!obj->IsInt32());
CHECK(!obj->IsUint32());
// Large negative fraction.
CompileRun("var obj = -5726623061.75;");
obj = env->Global()->Get(v8_str("obj"));
CHECK(!obj->IsInt32());
CHECK(!obj->IsUint32());
}
THREADED_TEST(ConversionException) {
v8::HandleScope scope;
LocalContext env;