| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #pragma once
- namespace Js
- {
- #if FLOATVAR
- inline JavascriptNumber::JavascriptNumber(double value, StaticType*
- #if DBG
- , bool oopJIT /*= false*/
- #endif
- )
- {
- AssertMsg(!IsNan(value) || ToSpecial(value) == k_Nan || ToSpecial(value) == 0x7FF8000000000000ull, "We should only produce a NaN with this value");
- SetSpecial(ToSpecial(value) ^ FloatTag_Value);
- }
- #else
- inline JavascriptNumber::JavascriptNumber(double value, StaticType * type
- #if DBG
- , bool oopJIT /*= false*/
- #endif
- ) : RecyclableObject(type), m_value(value)
- {
- // for oopjit type will be pointing to address of StaticType on other proc, so don't dereference it
- Assert(oopJIT || type->GetTypeId() == TypeIds_Number);
- }
- #endif
- __forceinline Var JavascriptNumber::ToVar(int32 nValue, ScriptContext* scriptContext)
- {
- if (!TaggedInt::IsOverflow(nValue))
- {
- return TaggedInt::ToVarUnchecked(nValue);
- }
- else
- {
- return JavascriptNumber::NewInlined((double) nValue, scriptContext);
- }
- }
- #if defined(__clang__) && defined(_M_IX86)
- __forceinline Var JavascriptNumber::ToVar(intptr_t nValue, ScriptContext* scriptContext)
- {
- if (!TaggedInt::IsOverflow(nValue))
- {
- return TaggedInt::ToVarUnchecked(nValue);
- }
- else
- {
- return JavascriptNumber::NewInlined((double) nValue, scriptContext);
- }
- }
- #endif
- inline Var JavascriptNumber::ToVar(uint32 nValue, ScriptContext* scriptContext)
- {
- return !TaggedInt::IsOverflow(nValue) ? TaggedInt::ToVarUnchecked(nValue) :
- JavascriptNumber::New((double) nValue,scriptContext);
- }
- inline Var JavascriptNumber::ToVar(int64 nValue, ScriptContext* scriptContext)
- {
- return !TaggedInt::IsOverflow(nValue) ?
- TaggedInt::ToVarUnchecked((int) nValue) :
- JavascriptNumber::New((double) nValue,scriptContext);
- }
- inline Var JavascriptNumber::ToVar(uint64 nValue, ScriptContext* scriptContext)
- {
- return !TaggedInt::IsOverflow(nValue) ?
- TaggedInt::ToVarUnchecked((int) nValue) :
- JavascriptNumber::New((double) nValue,scriptContext);
- }
- inline bool JavascriptNumber::TryToVarFast(int32 nValue, Var* result)
- {
- if (!TaggedInt::IsOverflow(nValue))
- {
- *result = TaggedInt::ToVarUnchecked(nValue);
- return true;
- }
- #if FLOATVAR
- *result = JavascriptNumber::ToVar((double)nValue);
- return true;
- #else
- return false;
- #endif
- }
- inline bool JavascriptNumber::TryToVarFastWithCheck(double value, Var* result)
- {
- #if FLOATVAR
- if (IsNan(value))
- {
- value = JavascriptNumber::NaN;
- }
- *result = JavascriptNumber::ToVar(value);
- return true;
- #else
- return false;
- #endif
- }
- #if FLOATVAR
- inline bool JavascriptNumber::Is(Var aValue)
- {
- return Is_NoTaggedIntCheck(aValue);
- }
- inline JavascriptNumber* JavascriptNumber::InPlaceNew(double value, ScriptContext* scriptContext, Js::JavascriptNumber *result)
- {
- AssertMsg( result != NULL, "Cannot use InPlaceNew without a value result location" );
- result = (JavascriptNumber*)ToVar(value);
- return result;
- }
- inline Var JavascriptNumber::New(double value, ScriptContext* scriptContext)
- {
- return ToVar(value);
- }
- inline Var JavascriptNumber::NewWithCheck(double value, ScriptContext* scriptContext)
- {
- if (IsNan(value))
- {
- value = JavascriptNumber::NaN;
- }
- return ToVar(value);
- }
- inline Var JavascriptNumber::NewInlined(double value, ScriptContext* scriptContext)
- {
- return ToVar(value);
- }
- #if ENABLE_NATIVE_CODEGEN
- inline Var JavascriptNumber::NewCodeGenInstance(double value, ScriptContext* scriptContext)
- {
- return ToVar(value);
- }
- #endif
- inline Var JavascriptNumber::ToVar(double value)
- {
- uint64 val = *(uint64*)&value;
- AssertMsg(!IsNan(value) || ToSpecial(value) == k_Nan || ToSpecial(value) == 0x7FF8000000000000ull, "We should only produce a NaN with this value");
- return reinterpret_cast<Var>(val ^ FloatTag_Value);
- }
- #else
- inline bool JavascriptNumber::Is(Var aValue)
- {
- return !TaggedInt::Is(aValue) && Is_NoTaggedIntCheck(aValue);
- }
- #if !defined(USED_IN_STATIC_LIB)
- inline bool JavascriptNumber::Is_NoTaggedIntCheck(Var aValue)
- {
- RecyclableObject* object = RecyclableObject::FromVar(aValue);
- AssertMsg((object->GetTypeId() == TypeIds_Number) == VirtualTableInfo<JavascriptNumber>::HasVirtualTable(object), "JavascriptNumber has no unique VTABLE?");
- return VirtualTableInfo<JavascriptNumber>::HasVirtualTable(object);
- }
- #endif
- inline JavascriptNumber* JavascriptNumber::FromVar(Var aValue)
- {
- AssertMsg(Is(aValue), "Ensure var is actually a 'JavascriptNumber'");
- return reinterpret_cast<JavascriptNumber *>(aValue);
- }
- inline double JavascriptNumber::GetValue(Var aValue)
- {
- AssertMsg(Is(aValue), "Ensure var is actually a 'JavascriptNumber'");
- return JavascriptNumber::FromVar(aValue)->GetValue();
- }
- inline JavascriptNumber* JavascriptNumber::InPlaceNew(double value, ScriptContext* scriptContext, Js::JavascriptNumber *result)
- {
- AssertMsg( result != NULL, "Cannot use InPlaceNew without a value result location" );
- Assume(result != NULL); // Encourage the compiler to omit a NULL check on the return from placement new
- return ::new(result) JavascriptNumber(value, scriptContext->GetLibrary()->GetNumberTypeStatic());
- }
- inline Var JavascriptNumber::New(double value, ScriptContext* scriptContext)
- {
- return scriptContext->GetLibrary()->CreateNumber(value, scriptContext->GetNumberAllocator());
- }
- inline Var JavascriptNumber::NewWithCheck(double value, ScriptContext* scriptContext)
- {
- return scriptContext->GetLibrary()->CreateNumber(value, scriptContext->GetNumberAllocator());
- }
- inline Var JavascriptNumber::NewInlined(double value, ScriptContext* scriptContext)
- {
- return scriptContext->GetLibrary()->CreateNumber(value, scriptContext->GetNumberAllocator());
- }
- #if ENABLE_NATIVE_CODEGEN
- inline Var JavascriptNumber::NewCodeGenInstance(CodeGenNumberAllocator *alloc, double value, ScriptContext* scriptContext)
- {
- return scriptContext->GetLibrary()->CreateCodeGenNumber(alloc, value);
- }
- #endif
- #endif
- inline JavascriptString * JavascriptNumber::ToStringNan(ScriptContext* scriptContext)
- {
- return ToStringNan(*scriptContext->GetLibrary());
- }
- inline JavascriptString* JavascriptNumber::ToStringNanOrInfinite(double value, ScriptContext* scriptContext)
- {
- return ToStringNanOrInfinite(value, *scriptContext->GetLibrary());
- }
- inline Var JavascriptNumber::FormatDoubleToString( double value, Js::NumberUtilities::FormatType formatType, int formatDigits, ScriptContext* scriptContext )
- {
- static const int bufSize = 256;
- char16 szBuffer[bufSize] = _u("");
- char16 * psz = szBuffer;
- char16 * pszToBeFreed = NULL;
- int nOut;
- if ((nOut = Js::NumberUtilities::FDblToStr(value, formatType, formatDigits, szBuffer, bufSize)) > bufSize )
- {
- int nOut1;
- pszToBeFreed = psz = (char16 *)malloc(nOut * sizeof(char16));
- if(0 == psz)
- {
- Js::JavascriptError::ThrowOutOfMemoryError(scriptContext);
- }
- nOut1 = Js::NumberUtilities::FDblToStr(value, Js::NumberUtilities::FormatFixed, formatDigits, psz, nOut);
- Assert(nOut1 == nOut);
- }
- // nOut includes room for terminating NUL
- JavascriptString* result = JavascriptString::NewCopyBuffer(psz, nOut - 1, scriptContext);
- if(pszToBeFreed)
- {
- free(pszToBeFreed);
- }
- return result;
- }
- }
|