X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/4e4e5a6f2694187498445a6ac6f1634ce8141119..14957cd040308e3eeec43d26bae5d76da13fcd85:/runtime/JSValue.cpp?ds=inline diff --git a/runtime/JSValue.cpp b/runtime/JSValue.cpp index 502312c..d3ee89e 100644 --- a/runtime/JSValue.cpp +++ b/runtime/JSValue.cpp @@ -25,6 +25,7 @@ #include "BooleanConstructor.h" #include "BooleanPrototype.h" +#include "Error.h" #include "ExceptionHelpers.h" #include "JSGlobalObject.h" #include "JSFunction.h" @@ -53,18 +54,18 @@ double JSValue::toIntegerPreserveNaN(ExecState* exec) const return trunc(toNumber(exec)); } -JSObject* JSValue::toObjectSlowCase(ExecState* exec) const +JSObject* JSValue::toObjectSlowCase(ExecState* exec, JSGlobalObject* globalObject) const { ASSERT(!isCell()); if (isInt32() || isDouble()) - return constructNumber(exec, asValue()); + return constructNumber(exec, globalObject, asValue()); if (isTrue() || isFalse()) - return constructBooleanFromImmediateBoolean(exec, asValue()); + return constructBooleanFromImmediateBoolean(exec, globalObject, asValue()); + ASSERT(isUndefinedOrNull()); - JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, isNull()); - exec->setException(exception); - return new (exec) JSNotAnObject(exec, exception); + throwError(exec, createNotAnObjectError(exec, *this)); + return new (exec) JSNotAnObject(exec); } JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const @@ -72,9 +73,9 @@ JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const ASSERT(!isCell()); if (isInt32() || isDouble()) - return constructNumber(exec, asValue()); + return constructNumber(exec, exec->lexicalGlobalObject(), asValue()); if (isTrue() || isFalse()) - return constructBooleanFromImmediateBoolean(exec, asValue()); + return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue()); ASSERT(isUndefinedOrNull()); return exec->globalThisValue(); } @@ -83,13 +84,13 @@ JSObject* JSValue::synthesizeObject(ExecState* exec) const { ASSERT(!isCell()); if (isNumber()) - return constructNumber(exec, asValue()); + return constructNumber(exec, exec->lexicalGlobalObject(), asValue()); if (isBoolean()) - return constructBooleanFromImmediateBoolean(exec, asValue()); - - JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, isNull()); - exec->setException(exception); - return new (exec) JSNotAnObject(exec, exception); + return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue()); + + ASSERT(isUndefinedOrNull()); + throwError(exec, createNotAnObjectError(exec, *this)); + return new (exec) JSNotAnObject(exec); } JSObject* JSValue::synthesizePrototype(ExecState* exec) const @@ -100,9 +101,9 @@ JSObject* JSValue::synthesizePrototype(ExecState* exec) const if (isBoolean()) return exec->lexicalGlobalObject()->booleanPrototype(); - JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, isNull()); - exec->setException(exception); - return new (exec) JSNotAnObject(exec, exception); + ASSERT(isUndefinedOrNull()); + throwError(exec, createNotAnObjectError(exec, *this)); + return new (exec) JSNotAnObject(exec); } #ifndef NDEBUG @@ -125,51 +126,58 @@ char* JSValue::description() snprintf(description, size, "False"); else if (isNull()) snprintf(description, size, "Null"); - else { - ASSERT(isUndefined()); + else if (isUndefined()) snprintf(description, size, "Undefined"); - } + else + snprintf(description, size, "INVALID"); return description; } #endif -int32_t toInt32SlowCase(double d, bool& ok) +// This in the ToInt32 operation is defined in section 9.5 of the ECMA-262 spec. +// Note that this operation is identical to ToUInt32 other than to interpretation +// of the resulting bit-pattern (as such this metod is also called to implement +// ToUInt32). +// +// The operation can be descibed as round towards zero, then select the 32 least +// bits of the resulting value in 2s-complement representation. +int32_t toInt32(double number) { - ok = true; - - if (d >= -D32 / 2 && d < D32 / 2) - return static_cast(d); - - if (isnan(d) || isinf(d)) { - ok = false; + int64_t bits = WTF::bitwise_cast(number); + int32_t exp = (static_cast(bits >> 52) & 0x7ff) - 0x3ff; + + // If exponent < 0 there will be no bits to the left of the decimal point + // after rounding; if the exponent is > 83 then no bits of precision can be + // left in the low 32-bit range of the result (IEEE-754 doubles have 52 bits + // of fractional precision). + // Note this case handles 0, -0, and all infinte, NaN, & denormal value. + if (exp < 0 || exp > 83) return 0; - } - double d32 = fmod(trunc(d), D32); - if (d32 >= D32 / 2) - d32 -= D32; - else if (d32 < -D32 / 2) - d32 += D32; - return static_cast(d32); -} - -uint32_t toUInt32SlowCase(double d, bool& ok) -{ - ok = true; - - if (d >= 0.0 && d < D32) - return static_cast(d); - - if (isnan(d) || isinf(d)) { - ok = false; - return 0; + // Select the appropriate 32-bits from the floating point mantissa. If the + // exponent is 52 then the bits we need to select are already aligned to the + // lowest bits of the 64-bit integer representation of tghe number, no need + // to shift. If the exponent is greater than 52 we need to shift the value + // left by (exp - 52), if the value is less than 52 we need to shift right + // accordingly. + int32_t result = (exp > 52) + ? static_cast(bits << (exp - 52)) + : static_cast(bits >> (52 - exp)); + + // IEEE-754 double precision values are stored omitting an implicit 1 before + // the decimal point; we need to reinsert this now. We may also the shifted + // invalid bits into the result that are not a part of the mantissa (the sign + // and exponent bits from the floatingpoint representation); mask these out. + if (exp < 32) { + int32_t missingOne = 1 << exp; + result &= missingOne - 1; + result += missingOne; } - double d32 = fmod(trunc(d), D32); - if (d32 < 0) - d32 += D32; - return static_cast(d32); + // If the input value was negative (we could test either 'number' or 'bits', + // but testing 'bits' is likely faster) invert the result appropriately. + return bits < 0 ? -result : result; } NEVER_INLINE double nonInlineNaN() @@ -181,4 +189,9 @@ NEVER_INLINE double nonInlineNaN() #endif } +bool JSValue::isValidCallee() +{ + return asObject(asObject(asCell())->getAnonymousValue(0))->isGlobalObject(); +} + } // namespace JSC