diff --git a/lib/Backend/GlobOpt.cpp b/lib/Backend/GlobOpt.cpp index 6aedc3d28a3..d25a490144f 100644 --- a/lib/Backend/GlobOpt.cpp +++ b/lib/Backend/GlobOpt.cpp @@ -21446,7 +21446,7 @@ GlobOpt::EmitMemop(Loop * loop, LoopCount *loopCount, const MemOpEmitData* emitD case TyInt16: case TyInt32: case TyInt64: - _snwprintf_s(constBuf, constBufSize, sizeof(IntConstType) == 8 ? _u("lld%") : _u("%d"), candidate->constant.u.intConst.value); + _snwprintf_s(constBuf, constBufSize, sizeof(IntConstType) == 8 ? _u("%lld") : _u("%d"), candidate->constant.u.intConst.value); break; case TyFloat32: case TyFloat64: diff --git a/lib/Runtime/Library/JavascriptArray.cpp b/lib/Runtime/Library/JavascriptArray.cpp index ec6068aff2f..4948006930d 100644 --- a/lib/Runtime/Library/JavascriptArray.cpp +++ b/lib/Runtime/Library/JavascriptArray.cpp @@ -3956,6 +3956,62 @@ namespace Js return -1; } + template + bool AreAllBytesEqual(T value) + { + byte* bValue = (byte*)&value; + byte firstByte = *bValue++; + for (int i = 1; i < sizeof(T); ++i) + { + if (*bValue++ != firstByte) + { + return false; + } + } + return true; + } + + template<> + void JavascriptArray::CopyValueToSegmentBuferNoCheck(double* buffer, uint32 length, double value) + { + if (JavascriptNumber::IsZero(value) && !JavascriptNumber::IsNegZero(value)) + { + memset(buffer, 0, sizeof(double) * length); + } + else + { + for (uint32 i = 0; i < length; i++) + { + buffer[i] = value; + } + } + } + + template<> + void JavascriptArray::CopyValueToSegmentBuferNoCheck(int32* buffer, uint32 length, int32 value) + { + if (value == 0 || AreAllBytesEqual(value)) + { + memset(buffer, *(byte*)&value, sizeof(int32)* length); + } + else + { + for (uint32 i = 0; i < length; i++) + { + buffer[i] = value; + } + } + } + + template<> + void JavascriptArray::CopyValueToSegmentBuferNoCheck(Js::Var* buffer, uint32 length, Js::Var value) + { + for (uint32 i = 0; i < length; i++) + { + buffer[i] = value; + } + } + int32 JavascriptNativeIntArray::HeadSegmentIndexOfHelper(Var search, uint32 &fromIndex, uint32 toIndex, bool includesAlgorithm, ScriptContext * scriptContext) { // We proceed largely in the same manner as in JavascriptArray's version of this method (see comments there for more information), diff --git a/lib/Runtime/Library/JavascriptArray.h b/lib/Runtime/Library/JavascriptArray.h index cff4a5eb861..cce2deecee7 100644 --- a/lib/Runtime/Library/JavascriptArray.h +++ b/lib/Runtime/Library/JavascriptArray.h @@ -169,6 +169,7 @@ namespace Js #if ENABLE_PROFILE_INFO template inline void DirectProfiledSetItemInHeadSegmentAt(const uint32 offset, const T newValue, StElemInfo *const stElemInfo); #endif + template static void CopyValueToSegmentBuferNoCheck(T* buffer, uint32 length, T value); template void DirectSetItem_Full(uint32 itemIndex, T newValue); template SparseArraySegment* PrepareSegmentForMemOp(uint32 startIndex, uint32 length); template bool DirectSetItemAtRange(uint32 startIndex, uint32 length, T newValue); diff --git a/lib/Runtime/Library/JavascriptArray.inl b/lib/Runtime/Library/JavascriptArray.inl index 4e63a6fafd1..9668db1b838 100644 --- a/lib/Runtime/Library/JavascriptArray.inl +++ b/lib/Runtime/Library/JavascriptArray.inl @@ -1014,6 +1014,7 @@ SECOND_PASS: #endif return true; } + template bool JavascriptArray::DirectSetItemAtRange(uint32 startIndex, uint32 length, T newValue) { @@ -1033,18 +1034,7 @@ SECOND_PASS: if (startIndex == 0 && head != EmptySegment && length < head->size) { - if (newValue == (T)0 || newValue == (T)(-1)) - { - memset(((Js::SparseArraySegment*)head)->elements, ((int)(intptr_t)newValue), sizeof(T)* length); - } - else - { - Js::SparseArraySegment* headSegment = ((Js::SparseArraySegment*)head); - for (uint32 i = 0; i < length; i++) - { - headSegment->elements[i] = newValue; - } - } + CopyValueToSegmentBuferNoCheck(((Js::SparseArraySegment*)head)->elements, length, newValue); if (length > this->length) { @@ -1082,17 +1072,7 @@ SECOND_PASS: SetHasNoMissingValues(true); - if (newValue == (T)0 || newValue == (T)(-1)) - { - memset(((Js::SparseArraySegment*)current)->elements, ((int)(intptr_t)newValue), sizeof(T)* length); - } - else - { - for (uint32 i = 0; i < length; i++) - { - ((Js::SparseArraySegment*)current)->elements[i] = newValue; - } - } + CopyValueToSegmentBuferNoCheck(((Js::SparseArraySegment*)current)->elements, length, newValue); this->SetLastUsedSegment(current); } else @@ -1116,17 +1096,9 @@ SECOND_PASS: { return false; } - if (newValue == (T)0 || newValue == (T)(-1)) - { - memset((((Js::SparseArraySegment*)current)->elements + (startIndex - current->left)), ((int)(intptr_t)newValue), sizeof(T)* length); - } - else - { - for (uint32 i = 0; i < length; i++) - { - ((Js::SparseArraySegment*)current)->elements[startIndex - current->left + i] = newValue; - } - } + Assert(current->left + current->length >= startIndex + length); + T* segmentCopyStart = current->elements + (startIndex - current->left); + CopyValueToSegmentBuferNoCheck(segmentCopyStart, length, newValue); this->SetLastUsedSegment(current); #if DBG if (Js::Configuration::Global.flags.MemOpMissingValueValidate)