| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- using namespace Js;
- Var JavascriptMath::Negate_Full(Var aRight, ScriptContext* scriptContext)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_Negate_Full);
- // Special case for zero. Must return -0
- if( aRight == TaggedInt::ToVarUnchecked(0) )
- {
- return scriptContext->GetLibrary()->GetNegativeZero();
- }
- if (JavascriptOperators::GetTypeId(aRight) == TypeIds_BigInt)
- {
- return JavascriptBigInt::Negate(aRight);
- }
- double value = Negate_Helper(aRight, scriptContext);
- return JavascriptNumber::ToVarIntCheck(value, scriptContext);
- JIT_HELPER_END(Op_Negate_Full);
- }
- JIT_HELPER_TEMPLATE(Op_Negate_Full, Op_Negate)
- Var JavascriptMath::Negate_InPlace(Var aRight, ScriptContext* scriptContext, JavascriptNumber* result)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_NegateInPlace);
- // Special case for zero. Must return -0
- if( aRight == TaggedInt::ToVarUnchecked(0) )
- {
- return scriptContext->GetLibrary()->GetNegativeZero();
- }
- if (JavascriptOperators::GetTypeId(aRight) == TypeIds_BigInt)
- {
- return JavascriptBigInt::Negate(aRight);
- }
- double value = Negate_Helper(aRight, scriptContext);
- return JavascriptNumber::InPlaceNew(value, scriptContext, result);
- JIT_HELPER_END(Op_NegateInPlace);
- }
- Var JavascriptMath::Not_Full(Var aRight, ScriptContext* scriptContext)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_Not_Full);
- #if _M_IX86
- AssertMsg(!TaggedInt::Is(aRight), "Should be detected");
- #endif
- if (JavascriptOperators::GetTypeId(aRight) == TypeIds_BigInt)
- {
- return JavascriptBigInt::Not(aRight);
- }
- int nValue = JavascriptConversion::ToInt32(aRight, scriptContext);
- return JavascriptNumber::ToVar(~nValue, scriptContext);
- JIT_HELPER_END(Op_Not_Full);
- }
- JIT_HELPER_TEMPLATE(Op_Not_Full, Op_Not)
- Var JavascriptMath::Not_InPlace(Var aRight, ScriptContext* scriptContext, JavascriptNumber* result)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_NotInPlace);
- AssertMsg(!TaggedInt::Is(aRight), "Should be detected");
- if (JavascriptOperators::GetTypeId(aRight) == TypeIds_BigInt)
- {
- return JavascriptBigInt::Not(aRight);
- }
- int nValue = JavascriptConversion::ToInt32(aRight, scriptContext);
- return JavascriptNumber::ToVarInPlace(~nValue, scriptContext, result);
- JIT_HELPER_END(Op_NotInPlace);
- }
- Var JavascriptMath::Increment_InPlace(Var aRight, ScriptContext* scriptContext, JavascriptNumber* result)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_IncrementInPlace);
- if (TaggedInt::Is(aRight))
- {
- return TaggedInt::Increment(aRight, scriptContext);
- }
- if (VarIs<JavascriptBigInt>(aRight))
- {
- return JavascriptBigInt::Increment(aRight);
- }
- double inc = Increment_Helper(aRight, scriptContext);
- return JavascriptNumber::InPlaceNew(inc, scriptContext, result);
- JIT_HELPER_END(Op_IncrementInPlace);
- }
- Var JavascriptMath::Increment_Full(Var aRight, ScriptContext* scriptContext)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_Increment_Full);
- if (TaggedInt::Is(aRight))
- {
- return TaggedInt::Increment(aRight, scriptContext);
- }
- if (VarIs<JavascriptBigInt>(aRight))
- {
- return JavascriptBigInt::Increment(aRight);
- }
- double inc = Increment_Helper(aRight, scriptContext);
- return JavascriptNumber::ToVarIntCheck(inc, scriptContext);
- JIT_HELPER_END(Op_Increment_Full);
- }
- JIT_HELPER_TEMPLATE(Op_Increment_Full, Op_Increment)
- Var JavascriptMath::Decrement_InPlace(Var aRight, ScriptContext* scriptContext, JavascriptNumber* result)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_DecrementInPlace);
- if (TaggedInt::Is(aRight))
- {
- return TaggedInt::Decrement(aRight, scriptContext);
- }
- if (VarIs<JavascriptBigInt>(aRight))
- {
- return JavascriptBigInt::Decrement(aRight);
- }
- double dec = Decrement_Helper(aRight,scriptContext);
- return JavascriptNumber::InPlaceNew(dec, scriptContext, result);
- JIT_HELPER_END(Op_DecrementInPlace);
- }
- Var JavascriptMath::Decrement_Full(Var aRight, ScriptContext* scriptContext)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_Decrement_Full);
- if (TaggedInt::Is(aRight))
- {
- return TaggedInt::Decrement(aRight, scriptContext);
- }
- if (VarIs<JavascriptBigInt>(aRight))
- {
- return JavascriptBigInt::Decrement(aRight);
- }
- double dec = Decrement_Helper(aRight,scriptContext);
- return JavascriptNumber::ToVarIntCheck(dec, scriptContext);
- JIT_HELPER_END(Op_Decrement_Full);
- }
- JIT_HELPER_TEMPLATE(Op_Decrement_Full, Op_Decrement)
- Var JavascriptMath::Increment_Numeric(Var aRight, ScriptContext* scriptContext)
- {
- if (VarIs<JavascriptBigInt>(aRight))
- {
- return JavascriptBigInt::Increment(aRight);
- }
- return JavascriptMath::Add(aRight, TaggedInt::ToVarUnchecked(1), scriptContext);
- }
- Var JavascriptMath::Decrement_Numeric(Var aRight, ScriptContext* scriptContext)
- {
- if (VarIs<JavascriptBigInt>(aRight))
- {
- return JavascriptBigInt::Decrement(aRight);
- }
- return JavascriptMath::Subtract(aRight, TaggedInt::ToVarUnchecked(1), scriptContext);
- }
-
- Var JavascriptMath::And_Full(Var aLeft, Var aRight, ScriptContext* scriptContext)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_And_Full);
- int32 value = And_Helper(aLeft, aRight, scriptContext);
- return JavascriptNumber::ToVar(value, scriptContext);
- JIT_HELPER_END(Op_And_Full);
- }
- JIT_HELPER_TEMPLATE(Op_And_Full, Op_And)
- Var JavascriptMath::And_InPlace(Var aLeft, Var aRight, ScriptContext* scriptContext, JavascriptNumber* result)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_AndInPlace);
- int32 value = And_Helper(aLeft, aRight, scriptContext);
- return JavascriptNumber::ToVarInPlace(value, scriptContext, result);
- JIT_HELPER_END(Op_AndInPlace);
- }
- Var JavascriptMath::Or_Full(Var aLeft, Var aRight, ScriptContext* scriptContext)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_Or_Full);
- int32 value = Or_Helper(aLeft, aRight, scriptContext);
- return JavascriptNumber::ToVar(value, scriptContext);
- JIT_HELPER_END(Op_Or_Full);
- }
- JIT_HELPER_TEMPLATE(Op_Or_Full, Op_Or)
- Var JavascriptMath::Or_InPlace(Var aLeft, Var aRight, ScriptContext* scriptContext, JavascriptNumber* result)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_OrInPlace);
- int32 value = Or_Helper(aLeft, aRight, scriptContext);
- return JavascriptNumber::ToVarInPlace(value, scriptContext, result);
- JIT_HELPER_END(Op_OrInPlace);
- }
- Var JavascriptMath::Xor_Full(Var aLeft, Var aRight, ScriptContext* scriptContext)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_Xor_Full);
- int32 nLeft = TaggedInt::Is(aLeft) ? TaggedInt::ToInt32(aLeft) : JavascriptConversion::ToInt32(aLeft, scriptContext);
- int32 nRight = TaggedInt::Is(aRight) ? TaggedInt::ToInt32(aRight) : JavascriptConversion::ToInt32(aRight, scriptContext);
- return JavascriptNumber::ToVar(nLeft ^ nRight,scriptContext);
- JIT_HELPER_END(Op_Xor_Full);
- }
- JIT_HELPER_TEMPLATE(Op_Xor_Full, Op_Xor)
- Var JavascriptMath::Xor_InPlace(Var aLeft, Var aRight, ScriptContext* scriptContext, JavascriptNumber* result)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_XorInPlace);
- int32 nLeft = TaggedInt::Is(aLeft) ? TaggedInt::ToInt32(aLeft) : JavascriptConversion::ToInt32(aLeft, scriptContext);
- int32 nRight = TaggedInt::Is(aRight) ? TaggedInt::ToInt32(aRight) : JavascriptConversion::ToInt32(aRight, scriptContext);
- return JavascriptNumber::ToVarInPlace(nLeft ^ nRight, scriptContext, result);
- JIT_HELPER_END(Op_XorInPlace);
- }
- Var JavascriptMath::ShiftLeft_Full(Var aLeft, Var aRight, ScriptContext* scriptContext)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_ShiftLeft_Full);
- int32 nValue = JavascriptConversion::ToInt32(aLeft, scriptContext);
- uint32 nShift = JavascriptConversion::ToUInt32(aRight, scriptContext);
- int32 nResult = nValue << (nShift & 0x1F);
- return JavascriptNumber::ToVar(nResult,scriptContext);
- JIT_HELPER_END(Op_ShiftLeft_Full);
- }
- JIT_HELPER_TEMPLATE(Op_ShiftLeft_Full, Op_ShiftLeft)
- Var JavascriptMath::ShiftRight_Full(Var aLeft, Var aRight, ScriptContext* scriptContext)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_ShiftRight_Full);
- int32 nValue = JavascriptConversion::ToInt32(aLeft, scriptContext);
- uint32 nShift = JavascriptConversion::ToUInt32(aRight, scriptContext);
- int32 nResult = nValue >> (nShift & 0x1F);
- return JavascriptNumber::ToVar(nResult,scriptContext);
- JIT_HELPER_END(Op_ShiftRight_Full);
- }
- Var JavascriptMath::ShiftRightU_Full(Var aLeft, Var aRight, ScriptContext* scriptContext)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_ShiftRightU_Full);
- uint32 nValue = JavascriptConversion::ToUInt32(aLeft, scriptContext);
- uint32 nShift = JavascriptConversion::ToUInt32(aRight, scriptContext);
- uint32 nResult = nValue >> (nShift & 0x1F);
- return JavascriptNumber::ToVar(nResult,scriptContext);
- JIT_HELPER_END(Op_ShiftRightU_Full);
- }
- #if FLOATVAR
- Var JavascriptMath::Add_Full(Var aLeft, Var aRight, ScriptContext* scriptContext)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_Add_Full);
- Assert(aLeft != nullptr);
- Assert(aRight != nullptr);
- Assert(scriptContext != nullptr);
- Js::TypeId typeLeft = JavascriptOperators::GetTypeId(aLeft);
- Js::TypeId typeRight = JavascriptOperators::GetTypeId(aRight);
- if (typeRight == typeLeft)
- {
- // If both sides are numbers/string, then we can do the addition directly
- if(typeLeft == TypeIds_Number)
- {
- double sum = JavascriptNumber::GetValue(aLeft) + JavascriptNumber::GetValue(aRight);
- return JavascriptNumber::ToVarNoCheck(sum, scriptContext);
- }
- else if (typeLeft == TypeIds_Integer)
- {
- __int64 sum = TaggedInt::ToInt64(aLeft) + TaggedInt::ToInt64(aRight);
- return JavascriptNumber::ToVar(sum, scriptContext);
- }
- else if (typeLeft == TypeIds_String)
- {
- return JavascriptString::Concat(UnsafeVarTo<JavascriptString>(aLeft), UnsafeVarTo<JavascriptString>(aRight));
- }
- }
- else if(typeLeft == TypeIds_Number && typeRight == TypeIds_Integer)
- {
- double sum = JavascriptNumber::GetValue(aLeft) + TaggedInt::ToDouble(aRight);
- return JavascriptNumber::ToVarNoCheck(sum, scriptContext);
- }
- else if(typeLeft == TypeIds_Integer && typeRight == TypeIds_Number)
- {
- double sum = TaggedInt::ToDouble(aLeft) + JavascriptNumber::GetValue(aRight);
- return JavascriptNumber::ToVarNoCheck(sum, scriptContext);
- }
- return Add_FullHelper_Wrapper(aLeft, aRight, scriptContext, nullptr, false);
- JIT_HELPER_END(Op_Add_Full);
- }
- #else
- Var JavascriptMath::Add_Full(Var aLeft, Var aRight, ScriptContext* scriptContext)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_Add_Full);
- Assert(aLeft != nullptr);
- Assert(aRight != nullptr);
- Assert(scriptContext != nullptr);
- Js::TypeId typeLeft = JavascriptOperators::GetTypeId(aLeft);
- Js::TypeId typeRight = JavascriptOperators::GetTypeId(aRight);
- // Handle combinations of TaggedInt and Number or String pairs directly,
- // otherwise call the helper.
- switch( typeLeft )
- {
- case TypeIds_Integer:
- {
- switch( typeRight )
- {
- case TypeIds_Integer:
- {
- // Compute the sum using integer addition, then convert to double.
- // That way there's only one int->float conversion.
- #if INT32VAR
- int64 sum = TaggedInt::ToInt64(aLeft) + TaggedInt::ToInt64(aRight);
- #else
- int32 sum = TaggedInt::ToInt32(aLeft) + TaggedInt::ToInt32(aRight);
- #endif
- return JavascriptNumber::ToVar(sum, scriptContext );
- }
- case TypeIds_Number:
- {
- double sum = TaggedInt::ToDouble(aLeft) + JavascriptNumber::GetValue(aRight);
- return JavascriptNumber::NewInlined( sum, scriptContext );
- }
- }
- break;
- }
- case TypeIds_Number:
- {
- switch( typeRight )
- {
- case TypeIds_Integer:
- {
- double sum = JavascriptNumber::GetValue(aLeft) + TaggedInt::ToDouble(aRight);
- return JavascriptNumber::NewInlined( sum, scriptContext );
- }
- case TypeIds_Number:
- {
- double sum = JavascriptNumber::GetValue(aLeft) + JavascriptNumber::GetValue(aRight);
- return JavascriptNumber::NewInlined( sum, scriptContext );
- }
- }
- break;
- }
- case TypeIds_String:
- {
- if( typeRight == TypeIds_String )
- {
- JavascriptString* leftString = UnsafeVarTo<JavascriptString>(aLeft);
- JavascriptString* rightString = UnsafeVarTo<JavascriptString>(aRight);
- return JavascriptString::Concat(leftString, rightString);
- }
- break;
- }
- }
- return Add_FullHelper_Wrapper(aLeft, aRight, scriptContext, nullptr, false);
- JIT_HELPER_END(Op_Add_Full);
- }
- #endif
- JIT_HELPER_TEMPLATE(Op_Add_Full, Op_Add)
- Var JavascriptMath::Add_InPlace(Var aLeft, Var aRight, ScriptContext* scriptContext, JavascriptNumber* result)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_AddInPlace);
- Assert(aLeft != nullptr);
- Assert(aRight != nullptr);
- Assert(scriptContext != nullptr);
- Assert(result != nullptr);
- // If both sides are numbers, then we can do the addition directly, otherwise
- // we need to call the helper.
- if( TaggedInt::Is(aLeft) )
- {
- if( TaggedInt::Is(aRight) )
- {
- // Compute the sum using integer addition, then convert to double.
- // That way there's only one int->float conversion.
- #if INT32VAR
- int64 sum = TaggedInt::ToInt64(aLeft) + TaggedInt::ToInt64(aRight);
- #else
- int32 sum = TaggedInt::ToInt32(aLeft) + TaggedInt::ToInt32(aRight);
- #endif
- return JavascriptNumber::ToVarInPlace(sum, scriptContext, result);
- }
- else if( JavascriptNumber::Is_NoTaggedIntCheck(aRight) )
- {
- double sum = TaggedInt::ToDouble(aLeft) + JavascriptNumber::GetValue(aRight);
- return JavascriptNumber::InPlaceNew( sum, scriptContext, result );
- }
- }
- else if( TaggedInt::Is(aRight) )
- {
- if( JavascriptNumber::Is_NoTaggedIntCheck(aLeft) )
- {
- double sum = JavascriptNumber::GetValue(aLeft) + TaggedInt::ToDouble(aRight);
- return JavascriptNumber::InPlaceNew( sum, scriptContext, result );
- }
- }
- else if( JavascriptNumber::Is_NoTaggedIntCheck(aLeft) && JavascriptNumber::Is_NoTaggedIntCheck(aRight) )
- {
- double sum = JavascriptNumber::GetValue(aLeft) + JavascriptNumber::GetValue(aRight);
- return JavascriptNumber::InPlaceNew( sum, scriptContext, result );
- }
- return Add_FullHelper_Wrapper(aLeft, aRight, scriptContext, result, false);
- JIT_HELPER_END(Op_AddInPlace);
- }
- Var JavascriptMath::AddLeftDead(Var aLeft, Var aRight, ScriptContext* scriptContext, JavascriptNumber *result)
- {
- // Conservatively assume src1 is not dead until proven otherwise.
- bool leftIsDead = false;
- JIT_HELPER_REENTRANT_HEADER(Op_AddLeftDead);
- if (JavascriptOperators::GetTypeId(aLeft) == TypeIds_String)
- {
- leftIsDead = true;
- JavascriptString* leftString = UnsafeVarTo<JavascriptString>(aLeft);
- JavascriptString* rightString;
- TypeId rightType = JavascriptOperators::GetTypeId(aRight);
- switch(rightType)
- {
- case TypeIds_String:
- rightString = UnsafeVarTo<JavascriptString>(aRight);
- StringCommon:
- return leftString->ConcatDestructive(rightString);
- case TypeIds_Integer:
- rightString = scriptContext->GetIntegerString(aRight);
- goto StringCommon;
- case TypeIds_Number:
- rightString = JavascriptNumber::ToStringRadix10(JavascriptNumber::GetValue(aRight), scriptContext);
- goto StringCommon;
- }
- }
- if (TaggedInt::Is(aLeft))
- {
- if (TaggedInt::Is(aRight))
- {
- return TaggedInt::Add(aLeft, aRight, scriptContext);
- }
- else if (JavascriptNumber::Is_NoTaggedIntCheck(aRight))
- {
- return JavascriptNumber::ToVarMaybeInPlace(TaggedInt::ToDouble(aLeft) + JavascriptNumber::GetValue(aRight), scriptContext, result);
- }
- }
- else if (TaggedInt::Is(aRight))
- {
- if (JavascriptNumber::Is_NoTaggedIntCheck(aLeft))
- {
- return JavascriptNumber::ToVarMaybeInPlace(JavascriptNumber::GetValue(aLeft) + TaggedInt::ToDouble(aRight), scriptContext, result);
- }
- }
- else if (JavascriptNumber::Is_NoTaggedIntCheck(aLeft) && JavascriptNumber::Is_NoTaggedIntCheck(aRight))
- {
- return JavascriptNumber::ToVarMaybeInPlace(JavascriptNumber::GetValue(aLeft) + JavascriptNumber::GetValue(aRight), scriptContext, result);
- }
- return Add_FullHelper_Wrapper(aLeft, aRight, scriptContext, result, leftIsDead);
- JIT_HELPER_END(Op_AddLeftDead);
- }
- Var JavascriptMath::Add_FullHelper_Wrapper(Var aLeft, Var aRight, ScriptContext* scriptContext, JavascriptNumber* result, bool leftIsDead)
- {
- Var aLeftToPrim = JavascriptConversion::ToPrimitive<JavascriptHint::None>(aLeft, scriptContext);
- Var aRightToPrim = JavascriptConversion::ToPrimitive<JavascriptHint::None>(aRight, scriptContext);
- return Add_FullHelper(aLeftToPrim, aRightToPrim, scriptContext, result, leftIsDead);
- }
- Var JavascriptMath::Add_FullHelper(Var primLeft, Var primRight, ScriptContext* scriptContext, JavascriptNumber *result, bool leftIsDead)
- {
- TypeId typeLeft = JavascriptOperators::GetTypeId(primLeft);
- TypeId typeRight = JavascriptOperators::GetTypeId(primRight);
- if (typeLeft == TypeIds_BigInt || typeRight == TypeIds_BigInt)
- {
- if (typeRight != typeLeft)
- {
- JavascriptError::ThrowTypeError(scriptContext, VBSERR_TypeMismatch, _u("Add BigInt"));
- }
- return JavascriptBigInt::Add(primLeft, primRight);
- }
- // If either side is a string, then the result is also a string
- if (typeLeft == TypeIds_String)
- {
- JavascriptString* stringLeft = UnsafeVarTo<JavascriptString>(primLeft);
- JavascriptString* stringRight = nullptr;
- if (typeRight == TypeIds_String)
- {
- stringRight = UnsafeVarTo<JavascriptString>(primRight);
- }
- else
- {
- stringRight = JavascriptConversion::ToString(primRight, scriptContext);
- }
- if(leftIsDead)
- {
- return stringLeft->ConcatDestructive(stringRight);
- }
- return JavascriptString::Concat(stringLeft, stringRight);
- }
- if (typeRight == TypeIds_String)
- {
- JavascriptString* stringLeft = JavascriptConversion::ToString(primLeft, scriptContext);
- JavascriptString* stringRight = UnsafeVarTo<JavascriptString>(primRight);
- if(leftIsDead)
- {
- return stringLeft->ConcatDestructive(stringRight);
- }
- return JavascriptString::Concat(stringLeft, stringRight);
- }
- double sum = Add_Helper(primLeft, primRight, scriptContext);
- return JavascriptNumber::ToVarMaybeInPlace(sum, scriptContext, result);
- }
- Var JavascriptMath::MulAddLeft(Var mulLeft, Var mulRight, Var addLeft, ScriptContext* scriptContext, JavascriptNumber* result)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_MulAddLeft);
- if(TaggedInt::Is(mulLeft))
- {
- if(TaggedInt::Is(mulRight))
- {
- // Compute the sum using integer addition, then convert to double.
- // That way there's only one int->float conversion.
- JavascriptNumber mulTemp(0, scriptContext->GetLibrary()->GetNumberTypeStatic());
- Var mulResult = TaggedInt::MultiplyInPlace(mulLeft, mulRight, scriptContext, &mulTemp);
- if (result)
- {
- return JavascriptMath::Add_InPlace(addLeft, mulResult, scriptContext, result);
- }
- else
- {
- return JavascriptMath::Add_Full(addLeft, mulResult, scriptContext);
- }
- }
- else if(JavascriptNumber::Is_NoTaggedIntCheck(mulRight))
- {
- double mulResult = TaggedInt::ToDouble(mulLeft) * JavascriptNumber::GetValue(mulRight);
- return JavascriptMath::Add_DoubleHelper(addLeft, mulResult, scriptContext, result);
- }
- }
- else if(TaggedInt::Is(mulRight))
- {
- if(JavascriptNumber::Is_NoTaggedIntCheck(mulLeft))
- {
- double mulResult = JavascriptNumber::GetValue(mulLeft) * TaggedInt::ToDouble(mulRight);
- return JavascriptMath::Add_DoubleHelper(addLeft, mulResult, scriptContext, result);
- }
- }
- else if(JavascriptNumber::Is_NoTaggedIntCheck(mulLeft) && JavascriptNumber::Is_NoTaggedIntCheck(mulRight))
- {
- double mulResult = JavascriptNumber::GetValue(mulLeft) * JavascriptNumber::GetValue(mulRight);
- return JavascriptMath::Add_DoubleHelper(addLeft, mulResult, scriptContext, result);
- }
- Var aMul;
- JavascriptNumber mulTemp(0, scriptContext->GetLibrary()->GetNumberTypeStatic());
- aMul = JavascriptMath::Multiply_InPlace(mulLeft, mulRight, scriptContext, &mulTemp);
- if (result)
- {
- return JavascriptMath::Add_InPlace(addLeft, aMul, scriptContext, result);
- }
- else
- {
- return JavascriptMath::Add_Full(addLeft, aMul, scriptContext);
- }
- JIT_HELPER_END(Op_MulAddLeft);
- }
- Var JavascriptMath::MulAddRight(Var mulLeft, Var mulRight, Var addRight, ScriptContext* scriptContext, JavascriptNumber* result)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_MulAddRight);
- if (TaggedInt::Is(mulLeft))
- {
- if(TaggedInt::Is(mulRight))
- {
- // Compute the sum using integer addition, then convert to double.
- // That way there's only one int->float conversion.
- JavascriptNumber mulTemp(0, scriptContext->GetLibrary()->GetNumberTypeStatic());
- Var mulResult = TaggedInt::MultiplyInPlace(mulLeft, mulRight, scriptContext, &mulTemp);
- if (result)
- {
- return JavascriptMath::Add_InPlace(mulResult, addRight, scriptContext, result);
- }
- else
- {
- return JavascriptMath::Add_Full(mulResult, addRight, scriptContext);
- }
- }
- else if(JavascriptNumber::Is_NoTaggedIntCheck(mulRight))
- {
- double mulResult = TaggedInt::ToDouble(mulLeft) * JavascriptNumber::GetValue(mulRight);
- return JavascriptMath::Add_DoubleHelper(mulResult, addRight, scriptContext, result);
- }
- }
- else if(TaggedInt::Is(mulRight))
- {
- if(JavascriptNumber::Is_NoTaggedIntCheck(mulLeft))
- {
- double mulResult = JavascriptNumber::GetValue(mulLeft) * TaggedInt::ToDouble(mulRight);
- return JavascriptMath::Add_DoubleHelper(mulResult, addRight, scriptContext, result);
- }
- }
- else if(JavascriptNumber::Is_NoTaggedIntCheck(mulLeft) && JavascriptNumber::Is_NoTaggedIntCheck(mulRight))
- {
- double mulResult = JavascriptNumber::GetValue(mulLeft) * JavascriptNumber::GetValue(mulRight);
- return JavascriptMath::Add_DoubleHelper(mulResult, addRight, scriptContext, result);
- }
- Var aMul;
- JavascriptNumber mulTemp(0, scriptContext->GetLibrary()->GetNumberTypeStatic());
- aMul = JavascriptMath::Multiply_InPlace(mulLeft, mulRight, scriptContext, &mulTemp);
- if (result)
- {
- return JavascriptMath::Add_InPlace(aMul, addRight, scriptContext, result);
- }
- else
- {
- return JavascriptMath::Add_Full(aMul, addRight, scriptContext);
- }
- JIT_HELPER_END(Op_MulAddRight);
- }
- Var JavascriptMath::MulSubLeft(Var mulLeft, Var mulRight, Var subLeft, ScriptContext* scriptContext, JavascriptNumber* result)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_MulSubLeft);
- if (TaggedInt::Is(mulLeft))
- {
- if(TaggedInt::Is(mulRight))
- {
- // Compute the sum using integer addition, then convert to double.
- // That way there's only one int->float conversion.
- JavascriptNumber mulTemp(0, scriptContext->GetLibrary()->GetNumberTypeStatic());
- Var mulResult = TaggedInt::MultiplyInPlace(mulLeft, mulRight, scriptContext, &mulTemp);
- if (result)
- {
- return JavascriptMath::Subtract_InPlace(subLeft, mulResult, scriptContext, result);
- }
- else
- {
- return JavascriptMath::Subtract_Full(subLeft, mulResult, scriptContext);
- }
- }
- else if(JavascriptNumber::Is_NoTaggedIntCheck(mulRight))
- {
- double mulResult = TaggedInt::ToDouble(mulLeft) * JavascriptNumber::GetValue(mulRight);
- return JavascriptMath::Subtract_DoubleHelper(subLeft, mulResult, scriptContext, result);
- }
- }
- else if(TaggedInt::Is(mulRight))
- {
- if(JavascriptNumber::Is_NoTaggedIntCheck(mulLeft))
- {
- double mulResult = JavascriptNumber::GetValue(mulLeft) * TaggedInt::ToDouble(mulRight);
- return JavascriptMath::Subtract_DoubleHelper(subLeft, mulResult, scriptContext, result);
- }
- }
- else if(JavascriptNumber::Is_NoTaggedIntCheck(mulLeft) && JavascriptNumber::Is_NoTaggedIntCheck(mulRight))
- {
- double mulResult = JavascriptNumber::GetValue(mulLeft) * JavascriptNumber::GetValue(mulRight);
- return JavascriptMath::Subtract_DoubleHelper(subLeft, mulResult, scriptContext, result);
- }
- Var aMul;
- JavascriptNumber mulTemp(0, scriptContext->GetLibrary()->GetNumberTypeStatic());
- aMul = JavascriptMath::Multiply_InPlace(mulLeft, mulRight, scriptContext, &mulTemp);
- if (result)
- {
- return JavascriptMath::Subtract_InPlace(subLeft, aMul, scriptContext, result);
- }
- else
- {
- return JavascriptMath::Subtract_Full(subLeft, aMul, scriptContext);
- }
- JIT_HELPER_END(Op_MulSubLeft);
- }
- Var JavascriptMath::MulSubRight(Var mulLeft, Var mulRight, Var subRight, ScriptContext* scriptContext, JavascriptNumber* result)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_MulSubRight);
- if(TaggedInt::Is(mulLeft))
- {
- if(TaggedInt::Is(mulRight))
- {
- // Compute the sum using integer addition, then convert to double.
- // That way there's only one int->float conversion.
- JavascriptNumber mulTemp(0, scriptContext->GetLibrary()->GetNumberTypeStatic());
- Var mulResult = TaggedInt::MultiplyInPlace(mulLeft, mulRight, scriptContext, &mulTemp);
- if (result)
- {
- return JavascriptMath::Subtract_InPlace(mulResult, subRight, scriptContext, result);
- }
- else
- {
- return JavascriptMath::Subtract_Full(mulResult, subRight, scriptContext);
- }
- }
- else if(JavascriptNumber::Is_NoTaggedIntCheck(mulRight))
- {
- double mulResult = TaggedInt::ToDouble(mulLeft) * JavascriptNumber::GetValue(mulRight);
- return JavascriptMath::Subtract_DoubleHelper(mulResult, subRight, scriptContext, result);
- }
- }
- else if(TaggedInt::Is(mulRight))
- {
- if(JavascriptNumber::Is_NoTaggedIntCheck(mulLeft))
- {
- double mulResult = JavascriptNumber::GetValue(mulLeft) * TaggedInt::ToDouble(mulRight);
- return JavascriptMath::Subtract_DoubleHelper(mulResult, subRight, scriptContext, result);
- }
- }
- else if(JavascriptNumber::Is_NoTaggedIntCheck(mulLeft) && JavascriptNumber::Is_NoTaggedIntCheck(mulRight))
- {
- double mulResult = JavascriptNumber::GetValue(mulLeft) * JavascriptNumber::GetValue(mulRight);
- return JavascriptMath::Subtract_DoubleHelper(mulResult, subRight, scriptContext, result);
- }
- Var aMul;
- JavascriptNumber mulTemp(0, scriptContext->GetLibrary()->GetNumberTypeStatic());
- aMul = JavascriptMath::Multiply_InPlace(mulLeft, mulRight, scriptContext, &mulTemp);
- if (result)
- {
- return JavascriptMath::Subtract_InPlace(aMul, subRight, scriptContext, result);
- }
- else
- {
- return JavascriptMath::Subtract_Full(aMul, subRight, scriptContext);
- }
- JIT_HELPER_END(Op_MulSubRight);
- }
- Var inline JavascriptMath::Add_DoubleHelper(double dblLeft, Var addRight, ScriptContext* scriptContext, JavascriptNumber*result)
- {
- if (TaggedInt::Is(addRight))
- {
- double sum = dblLeft + TaggedInt::ToDouble(addRight);
- return JavascriptNumber::ToVarMaybeInPlace(sum, scriptContext, result);
- }
- else if (JavascriptNumber::Is_NoTaggedIntCheck(addRight))
- {
- double sum = dblLeft + JavascriptNumber::GetValue(addRight);
- return JavascriptNumber::ToVarMaybeInPlace(sum, scriptContext, result);
- }
- else
- {
- Var aLeft = JavascriptNumber::ToVarMaybeInPlace(dblLeft, scriptContext, result);
- return Add_Full(aLeft, addRight, scriptContext);
- }
- }
- Var inline JavascriptMath::Add_DoubleHelper(Var addLeft, double dblRight, ScriptContext* scriptContext, JavascriptNumber*result)
- {
- if (TaggedInt::Is(addLeft))
- {
- double sum = TaggedInt::ToDouble(addLeft) + dblRight;
- return JavascriptNumber::ToVarMaybeInPlace(sum, scriptContext, result);
- }
- else if (JavascriptNumber::Is_NoTaggedIntCheck(addLeft))
- {
- double sum = JavascriptNumber::GetValue(addLeft) + dblRight;
- return JavascriptNumber::ToVarMaybeInPlace(sum, scriptContext, result);
- }
- else
- {
- Var aRight = JavascriptNumber::ToVarMaybeInPlace(dblRight, scriptContext, result);
- return Add_Full(addLeft, aRight, scriptContext);
- }
- }
- Var inline JavascriptMath::Subtract_DoubleHelper(double dblLeft, Var subRight, ScriptContext* scriptContext, JavascriptNumber* result)
- {
- if (TaggedInt::Is(subRight))
- {
- double sum = dblLeft - TaggedInt::ToDouble(subRight);
- return JavascriptNumber::ToVarMaybeInPlace(sum, scriptContext, result);
- }
- else if (JavascriptNumber::Is_NoTaggedIntCheck(subRight))
- {
- double sum = dblLeft - JavascriptNumber::GetValue(subRight);
- return JavascriptNumber::ToVarMaybeInPlace(sum, scriptContext, result);
- }
- else
- {
- Var aLeft = JavascriptNumber::ToVarMaybeInPlace(dblLeft, scriptContext, result);
- return Subtract_Full(aLeft, subRight, scriptContext);
- }
- }
- Var inline JavascriptMath::Subtract_DoubleHelper(Var subLeft, double dblRight, ScriptContext* scriptContext, JavascriptNumber*result)
- {
- if (TaggedInt::Is(subLeft))
- {
- double sum = TaggedInt::ToDouble(subLeft) - dblRight;
- return JavascriptNumber::ToVarMaybeInPlace(sum, scriptContext, result);
- }
- else if (JavascriptNumber::Is_NoTaggedIntCheck(subLeft))
- {
- double sum = JavascriptNumber::GetValue(subLeft) - dblRight;
- return JavascriptNumber::ToVarMaybeInPlace(sum, scriptContext, result);
- }
- else
- {
- Var aRight = JavascriptNumber::ToVarMaybeInPlace(dblRight, scriptContext, result);
- return Subtract_Full(subLeft, aRight, scriptContext);
- }
- }
- Var JavascriptMath::Subtract_Full(Var aLeft, Var aRight, ScriptContext* scriptContext)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_Subtract_Full);
- Var aLeftToPrim = JavascriptConversion::ToPrimitive<JavascriptHint::HintNumber>(aLeft, scriptContext);
- Var aRightToPrim = JavascriptConversion::ToPrimitive<JavascriptHint::HintNumber>(aRight, scriptContext);
- Js::TypeId typeLeft = JavascriptOperators::GetTypeId(aLeftToPrim);
- Js::TypeId typeRight = JavascriptOperators::GetTypeId(aRightToPrim);
- if (typeLeft == TypeIds_BigInt || typeRight == TypeIds_BigInt)
- {
- if (typeRight != typeLeft)
- {
- JavascriptError::ThrowTypeError(scriptContext, VBSERR_TypeMismatch, _u("Subtract BigInt"));
- }
- return JavascriptBigInt::Sub(aLeftToPrim, aRightToPrim);
- }
- double difference = Subtract_Helper(aLeftToPrim, aRightToPrim, scriptContext);
- return JavascriptNumber::ToVarIntCheck(difference, scriptContext);
- JIT_HELPER_END(Op_Subtract_Full);
- }
- JIT_HELPER_TEMPLATE(Op_Subtract_Full, Op_Subtract)
- Var JavascriptMath::Subtract_InPlace(Var aLeft, Var aRight, ScriptContext* scriptContext, JavascriptNumber* result)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_SubtractInPlace);
- Var aLeftToPrim = JavascriptConversion::ToPrimitive<JavascriptHint::HintNumber>(aLeft, scriptContext);
- Var aRightToPrim = JavascriptConversion::ToPrimitive<JavascriptHint::HintNumber>(aRight, scriptContext);
- Js::TypeId typeLeft = JavascriptOperators::GetTypeId(aLeftToPrim);
- Js::TypeId typeRight = JavascriptOperators::GetTypeId(aRightToPrim);
- if (typeLeft == TypeIds_BigInt || typeRight == TypeIds_BigInt)
- {
- if (typeRight != typeLeft)
- {
- JavascriptError::ThrowTypeError(scriptContext, VBSERR_TypeMismatch, _u("Subtract BigInt"));
- }
- return JavascriptBigInt::Sub(aLeftToPrim, aRightToPrim);
- }
- double difference = Subtract_Helper(aLeftToPrim, aRightToPrim, scriptContext);
- return JavascriptNumber::InPlaceNew(difference, scriptContext, result);
- JIT_HELPER_END(Op_SubtractInPlace);
- }
- Var JavascriptMath::Divide_Full(Var aLeft,Var aRight, ScriptContext* scriptContext)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_Divide_Full);
- // If both arguments are TaggedInt, then try to do integer division
- // This case is not handled by the lowerer.
- if (TaggedInt::IsPair(aLeft, aRight))
- {
- return TaggedInt::Divide(aLeft, aRight, scriptContext);
- }
- return JavascriptNumber::NewInlined( Divide_Helper(aLeft, aRight, scriptContext), scriptContext );
- JIT_HELPER_END(Op_Divide_Full);
- }
- JIT_HELPER_TEMPLATE(Op_Divide_Full, Op_Divide)
- Var JavascriptMath::Exponentiation_Full(Var aLeft, Var aRight, ScriptContext *scriptContext)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_Exponentiation_Full);
- double x = JavascriptConversion::ToNumber(aLeft, scriptContext);
- double y = JavascriptConversion::ToNumber(aRight, scriptContext);
- return JavascriptNumber::ToVarIntCheck(Math::Pow(x, y), scriptContext);
- JIT_HELPER_END(Op_Exponentiation_Full);
- }
- JIT_HELPER_TEMPLATE(Op_Exponentiation_Full, Op_Exponentiation)
- Var JavascriptMath::Exponentiation_InPlace(Var aLeft, Var aRight, ScriptContext* scriptContext, JavascriptNumber* result)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_ExponentiationInPlace);
- // The IEEE 754 floating point spec ensures that NaNs are preserved in all operations
- double dblLeft = JavascriptConversion::ToNumber(aLeft, scriptContext);
- double dblRight = JavascriptConversion::ToNumber(aRight, scriptContext);
- return JavascriptNumber::InPlaceNew(Math::Pow(dblLeft, dblRight), scriptContext, result);
- JIT_HELPER_END(Op_ExponentiationInPlace);
- }
- Var JavascriptMath::Multiply_Full(Var aLeft, Var aRight, ScriptContext* scriptContext)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_Multiply_Full);
- Assert(aLeft != nullptr);
- Assert(aRight != nullptr);
- Assert(scriptContext != nullptr);
- Js::TypeId typeLeft = JavascriptOperators::GetTypeId(aLeft);
- Js::TypeId typeRight = JavascriptOperators::GetTypeId(aRight);
- if (typeLeft == TypeIds_BigInt || typeRight == TypeIds_BigInt)
- {
- if (typeRight != typeLeft)
- {
- JavascriptError::ThrowTypeError(scriptContext, VBSERR_TypeMismatch, _u("Multiply BigInt"));
- }
- return JavascriptBigInt::Mul(aLeft, aRight);
- }
- if(JavascriptNumber::Is(aLeft))
- {
- if(JavascriptNumber::Is(aRight))
- {
- double product = JavascriptNumber::GetValue(aLeft) * JavascriptNumber::GetValue(aRight);
- return JavascriptNumber::ToVarNoCheck(product, scriptContext);
- }
- else if(TaggedInt::Is(aRight))
- {
- double product = TaggedInt::ToDouble(aRight) * JavascriptNumber::GetValue(aLeft);
- return JavascriptNumber::ToVarNoCheck(product, scriptContext);
- }
- }
- else if(JavascriptNumber::Is(aRight))
- {
- if(TaggedInt::Is(aLeft))
- {
- double product = TaggedInt::ToDouble(aLeft) * JavascriptNumber::GetValue(aRight);
- return JavascriptNumber::ToVarNoCheck(product, scriptContext);
- }
- }
- else if(TaggedInt::IsPair(aLeft, aRight))
- {
- return TaggedInt::Multiply(aLeft, aRight, scriptContext);
- }
- double product = Multiply_Helper(aLeft, aRight, scriptContext);
- return JavascriptNumber::ToVarIntCheck(product, scriptContext);
- JIT_HELPER_END(Op_Multiply_Full);
- }
- JIT_HELPER_TEMPLATE(Op_Multiply_Full, Op_Multiply)
- Var JavascriptMath::Multiply_InPlace(Var aLeft, Var aRight, ScriptContext* scriptContext, JavascriptNumber* result)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_MultiplyInPlace);
- Js::TypeId typeLeft = JavascriptOperators::GetTypeId(aLeft);
- Js::TypeId typeRight = JavascriptOperators::GetTypeId(aRight);
- if (typeLeft == TypeIds_BigInt || typeRight == TypeIds_BigInt)
- {
- if (typeRight != typeLeft)
- {
- JavascriptError::ThrowTypeError(scriptContext, VBSERR_TypeMismatch, _u("Multiply BigInt"));
- }
- return JavascriptBigInt::Mul(aLeft, aRight);
- }
- if(JavascriptNumber::Is(aLeft))
- {
- if(JavascriptNumber::Is(aRight))
- {
- return JavascriptNumber::ToVarInPlace(
- JavascriptNumber::GetValue(aLeft) * JavascriptNumber::GetValue(aRight), scriptContext, result);
- }
- else if (TaggedInt::Is(aRight))
- {
- return JavascriptNumber::ToVarInPlace(
- JavascriptNumber::GetValue(aLeft) * TaggedInt::ToDouble(aRight), scriptContext, result);
- }
- }
- else if(JavascriptNumber::Is(aRight))
- {
- if(TaggedInt::Is(aLeft))
- {
- return JavascriptNumber::ToVarInPlace(
- TaggedInt::ToDouble(aLeft) * JavascriptNumber::GetValue(aRight), scriptContext, result);
- }
- }
- else if(TaggedInt::IsPair(aLeft, aRight))
- {
- return TaggedInt::MultiplyInPlace(aLeft, aRight, scriptContext, result);
- }
- double product = Multiply_Helper(aLeft, aRight, scriptContext);
- return JavascriptNumber::InPlaceNew(product, scriptContext, result);
- JIT_HELPER_END(Op_MultiplyInPlace);
- }
- Var JavascriptMath::Divide_InPlace(Var aLeft, Var aRight, ScriptContext* scriptContext, JavascriptNumber* result)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_DivideInPlace);
- // If both arguments are TaggedInt, then try to do integer division
- // This case is not handled by the lowerer.
- if (TaggedInt::IsPair(aLeft, aRight))
- {
- return TaggedInt::DivideInPlace(aLeft, aRight, scriptContext, result);
- }
- double quotient = Divide_Helper(aLeft, aRight, scriptContext);
- return JavascriptNumber::InPlaceNew(quotient, scriptContext, result);
- JIT_HELPER_END(Op_DivideInPlace);
- }
- Var JavascriptMath::Modulus_Full(Var aLeft, Var aRight, ScriptContext* scriptContext)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_Modulus_Full);
- // If both arguments are TaggedInt, then try to do integer modulus.
- // This case is not handled by the lowerer.
- if (TaggedInt::IsPair(aLeft, aRight))
- {
- return TaggedInt::Modulus(aLeft, aRight, scriptContext);
- }
- double remainder = Modulus_Helper(aLeft, aRight, scriptContext);
- return JavascriptNumber::ToVarIntCheck(remainder, scriptContext);
- JIT_HELPER_END(Op_Modulus_Full);
- }
- JIT_HELPER_TEMPLATE(Op_Modulus_Full, Op_Modulus)
- Var JavascriptMath::Modulus_InPlace(Var aLeft, Var aRight, ScriptContext* scriptContext, JavascriptNumber* result)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_ModulusInPlace);
- Assert(aLeft != nullptr);
- Assert(aRight != nullptr);
- Assert(scriptContext != nullptr);
- // If both arguments are TaggedInt, then try to do integer division
- // This case is not handled by the lowerer.
- if (TaggedInt::IsPair(aLeft, aRight))
- {
- return TaggedInt::Modulus(aLeft, aRight, scriptContext);
- }
- double remainder = Modulus_Helper(aLeft, aRight, scriptContext);
- return JavascriptNumber::InPlaceNew(remainder, scriptContext, result);
- JIT_HELPER_END(Op_ModulusInPlace);
- }
- Var JavascriptMath::FinishOddDivByPow2(int32 value, ScriptContext *scriptContext)
- {
- JIT_HELPER_NOT_REENTRANT_NOLOCK_HEADER(Op_FinishOddDivByPow2);
- return JavascriptNumber::New((double)(value + 0.5), scriptContext);
- JIT_HELPER_END(Op_FinishOddDivByPow2);
- }
- Var JavascriptMath::FinishOddDivByPow2_InPlace(int32 value, ScriptContext *scriptContext, JavascriptNumber* result)
- {
- JIT_HELPER_NOT_REENTRANT_NOLOCK_HEADER(Op_FinishOddDivByPow2InPlace);
- return JavascriptNumber::InPlaceNew((double)(value + 0.5), scriptContext, result);
- JIT_HELPER_END(Op_FinishOddDivByPow2InPlace);
- }
- Var JavascriptMath::MaxInAnArray(RecyclableObject * function, CallInfo callInfo, ...)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_MaxInAnArray);
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- Assert(args.Info.Count == 2);
- Var thisArg = args[0];
- Var arrayArg = args[1];
- ScriptContext * scriptContext = function->GetScriptContext();
- TypeId typeId = JavascriptOperators::GetTypeId(arrayArg);
- if (!JavascriptNativeArray::Is(typeId) && !(TypedArrayBase::Is(typeId) && typeId != TypeIds_CharArray && typeId != TypeIds_BoolArray))
- {
- if (JavascriptArray::IsVarArray(typeId) && UnsafeVarTo<JavascriptArray>(arrayArg)->GetLength() == 0)
- {
- return scriptContext->GetLibrary()->GetNegativeInfinite();
- }
- BEGIN_SAFE_REENTRANT_CALL(scriptContext->GetThreadContext())
- {
- return JavascriptFunction::CalloutHelper<false>(function, thisArg, /* overridingNewTarget = */nullptr, arrayArg, scriptContext);
- }
- END_SAFE_REENTRANT_CALL
- }
- if (JavascriptNativeArray::Is(typeId))
- {
- #if ENABLE_COPYONACCESS_ARRAY
- JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray<Var>(arrayArg);
- #endif
- JavascriptNativeArray * argsArray = UnsafeVarTo<JavascriptNativeArray>(arrayArg);
- uint len = argsArray->GetLength();
- if (len == 0)
- {
- return scriptContext->GetLibrary()->GetNegativeInfinite();
- }
- if (argsArray->GetHead()->next != nullptr || !argsArray->HasNoMissingValues() ||
- argsArray->GetHead()->length != len)
- {
- BEGIN_SAFE_REENTRANT_CALL(scriptContext->GetThreadContext())
- {
- return JavascriptFunction::CalloutHelper<false>(function, thisArg, /* overridingNewTarget = */nullptr, arrayArg, scriptContext);
- }
- END_SAFE_REENTRANT_CALL
- }
- return argsArray->FindMinOrMax(scriptContext, true /*findMax*/);
- }
- else
- {
- TypedArrayBase * argsArray = UnsafeVarTo<TypedArrayBase>(arrayArg);
- uint len = argsArray->GetLength();
- if (len == 0)
- {
- return scriptContext->GetLibrary()->GetNegativeInfinite();
- }
- Var max = argsArray->FindMinOrMax(scriptContext, typeId, true /*findMax*/);
- if (max == nullptr)
- {
- BEGIN_SAFE_REENTRANT_CALL(scriptContext->GetThreadContext())
- {
- return JavascriptFunction::CalloutHelper<false>(function, thisArg, /* overridingNewTarget = */nullptr, arrayArg, scriptContext);
- }
- END_SAFE_REENTRANT_CALL
- }
- return max;
- }
- JIT_HELPER_END(Op_MaxInAnArray);
- }
- Var JavascriptMath::MinInAnArray(RecyclableObject * function, CallInfo callInfo, ...)
- {
- JIT_HELPER_REENTRANT_HEADER(Op_MinInAnArray);
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- Assert(args.Info.Count == 2);
- Var thisArg = args[0];
- Var arrayArg = args[1];
- ScriptContext * scriptContext = function->GetScriptContext();
- TypeId typeId = JavascriptOperators::GetTypeId(arrayArg);
- if (!JavascriptNativeArray::Is(typeId) && !(TypedArrayBase::Is(typeId) && typeId != TypeIds_CharArray && typeId != TypeIds_BoolArray))
- {
- if (JavascriptArray::IsNonES5Array(typeId) && UnsafeVarTo<JavascriptArray>(arrayArg)->GetLength() == 0)
- {
- return scriptContext->GetLibrary()->GetPositiveInfinite();
- }
- BEGIN_SAFE_REENTRANT_CALL(scriptContext->GetThreadContext())
- {
- return JavascriptFunction::CalloutHelper<false>(function, thisArg, /* overridingNewTarget = */nullptr, arrayArg, scriptContext);
- }
- END_SAFE_REENTRANT_CALL
- }
- if (JavascriptNativeArray::Is(typeId))
- {
- #if ENABLE_COPYONACCESS_ARRAY
- JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray<Var>(arrayArg);
- #endif
- JavascriptNativeArray * argsArray = UnsafeVarTo<JavascriptNativeArray>(arrayArg);
- uint len = argsArray->GetLength();
- if (len == 0)
- {
- return scriptContext->GetLibrary()->GetPositiveInfinite();
- }
- if (argsArray->GetHead()->next != nullptr || !argsArray->HasNoMissingValues() ||
- argsArray->GetHead()->length != len)
- {
- BEGIN_SAFE_REENTRANT_CALL(scriptContext->GetThreadContext())
- {
- return JavascriptFunction::CalloutHelper<false>(function, thisArg, /* overridingNewTarget = */nullptr, arrayArg, scriptContext);
- }
- END_SAFE_REENTRANT_CALL
- }
- return argsArray->FindMinOrMax(scriptContext, false /*findMax*/);
- }
- else
- {
- TypedArrayBase * argsArray = UnsafeVarTo<TypedArrayBase>(arrayArg);
- uint len = argsArray->GetLength();
- if (len == 0)
- {
- return scriptContext->GetLibrary()->GetPositiveInfinite();
- }
- Var min = argsArray->FindMinOrMax(scriptContext, typeId, false /*findMax*/);
- if (min == nullptr)
- {
- BEGIN_SAFE_REENTRANT_CALL(scriptContext->GetThreadContext())
- {
- return JavascriptFunction::CalloutHelper<false>(function, thisArg, /* overridingNewTarget = */nullptr, arrayArg, scriptContext);
- }
- END_SAFE_REENTRANT_CALL
- }
- return min;
- }
- JIT_HELPER_END(Op_MinInAnArray);
- }
- void InitializeRandomSeeds(uint64 *seed0, uint64 *seed1, ScriptContext *scriptContext)
- {
- #if DBG
- if (CONFIG_FLAG(PRNGSeed0) && CONFIG_FLAG(PRNGSeed1))
- {
- *seed0 = CONFIG_FLAG(PRNGSeed0);
- *seed1 = CONFIG_FLAG(PRNGSeed1);
- }
- else
- #endif
- {
- LARGE_INTEGER s0;
- LARGE_INTEGER s1;
- if (!rand_s(reinterpret_cast<unsigned int*>(&s0.LowPart)) &&
- !rand_s(reinterpret_cast<unsigned int*>(&s0.HighPart)) &&
- !rand_s(reinterpret_cast<unsigned int*>(&s1.LowPart)) &&
- !rand_s(reinterpret_cast<unsigned int*>(&s1.HighPart)))
- {
- *seed0 = s0.QuadPart;
- *seed1 = s1.QuadPart;
- }
- else
- {
- AssertMsg(false, "Unable to initialize PRNG seeds with rand_s. Revert to using entropy.");
- #ifdef ENABLE_CUSTOM_ENTROPY
- ThreadContext *threadContext = scriptContext->GetThreadContext();
- threadContext->GetEntropy().AddThreadCycleTime();
- threadContext->GetEntropy().AddIoCounters();
- *seed0 = threadContext->GetEntropy().GetRand();
- threadContext->GetEntropy().AddThreadCycleTime();
- threadContext->GetEntropy().AddIoCounters();
- *seed1 = threadContext->GetEntropy().GetRand();
- #endif
- }
- }
- }
- double ConvertRandomSeedsToDouble(const uint64 seed0, const uint64 seed1)
- {
- const uint64 mExp = 0x3FF0000000000000;
- const uint64 mMant = 0x000FFFFFFFFFFFFF;
- // Take lower 52 bits of the sum of two seeds to make a double
- // Subtract 1.0 to negate the implicit integer bit of 1. Final range: [0.0, 1.0)
- // See IEEE754 Double-precision floating-point format for details
- // https://en.wikipedia.org/wiki/Double-precision_floating-point_format
- uint64 resplusone_ui64 = ((seed0 + seed1) & mMant) | mExp;
- double res = *(reinterpret_cast<double*>(&resplusone_ui64)) - 1.0;
- return res;
- }
- void Xorshift128plus(uint64 *seed0, uint64 *seed1)
- {
- uint64 s1 = *seed0;
- uint64 s0 = *seed1;
- *seed0 = s0;
- s1 ^= s1 << 23;
- s1 ^= s1 >> 17;
- s1 ^= s0;
- s1 ^= s0 >> 26;
- *seed1 = s1;
- }
- double JavascriptMath::Random(ScriptContext *scriptContext)
- {
- JIT_HELPER_NOT_REENTRANT_NOLOCK_HEADER(DirectMath_Random);
- uint64 seed0;
- uint64 seed1;
- if (!scriptContext->GetLibrary()->IsPRNGSeeded())
- {
- InitializeRandomSeeds(&seed0, &seed1, scriptContext);
- #if DBG_DUMP
- OUTPUT_TRACE(Js::PRNGPhase, _u("[PRNG:%x] INIT %I64x %I64x\n"), scriptContext, seed0, seed1);
- #endif
- scriptContext->GetLibrary()->SetIsPRNGSeeded(true);
- #if ENABLE_TTD
- if(scriptContext->ShouldPerformReplayAction())
- {
- scriptContext->GetThreadContext()->TTDLog->ReplayExternalEntropyRandomEvent(&seed0, &seed1);
- }
- else if(scriptContext->ShouldPerformRecordAction())
- {
- scriptContext->GetThreadContext()->TTDLog->RecordExternalEntropyRandomEvent(seed0, seed1);
- }
- else
- {
- ;
- }
- #endif
- }
- else
- {
- seed0 = scriptContext->GetLibrary()->GetRandSeed0();
- seed1 = scriptContext->GetLibrary()->GetRandSeed1();
- }
- #if DBG_DUMP
- OUTPUT_TRACE(Js::PRNGPhase, _u("[PRNG:%x] SEED %I64x %I64x\n"), scriptContext, seed0, seed1);
- #endif
- Xorshift128plus(&seed0, &seed1);
- //update the seeds in script context
- scriptContext->GetLibrary()->SetRandSeed0(seed0);
- scriptContext->GetLibrary()->SetRandSeed1(seed1);
- double res = ConvertRandomSeedsToDouble(seed0, seed1);
- #if DBG_DUMP
- OUTPUT_TRACE(Js::PRNGPhase, _u("[PRNG:%x] RAND %I64x\n"), scriptContext, *((uint64 *)&res));
- #endif
- return res;
- JIT_HELPER_END(DirectMath_Random);
- }
- uint32 JavascriptMath::ToUInt32(double T1)
- {
- // Same as doing ToInt32 and reinterpret the bits as uint32
- return (uint32)ToInt32Core(T1);
- }
- int32 JavascriptMath::ToInt32(double T1)
- {
- return JavascriptMath::ToInt32Core(T1);
- }
- int32 JavascriptMath::ToInt32_Full(Var aValue, ScriptContext* scriptContext)
- {
- AssertMsg(!TaggedInt::Is(aValue), "Should be detected");
- // This is used when TaggedInt's overflow but remain under int32
- // so Number is our most critical case:
- TypeId typeId = JavascriptOperators::GetTypeId(aValue);
- if (typeId == TypeIds_Number)
- {
- return JavascriptMath::ToInt32Core(JavascriptNumber::GetValue(aValue));
- }
- return JavascriptConversion::ToInt32_Full(aValue, scriptContext);
- }
- // Unable to put JIT_HELPER macro in .inl file, do instantiation here
- JIT_HELPER_TEMPLATE(Conv_ToInt32Core, Conv_ToInt32Core)
- JIT_HELPER_TEMPLATE(Conv_ToInt32_NoObjects, Conv_ToInt32_NoObjects)
- JIT_HELPER_TEMPLATE(Conv_ToInt32, Conv_ToInt32)
- JIT_HELPER_TEMPLATE(Op_ShiftRight, Op_ShiftRight)
- JIT_HELPER_TEMPLATE(Op_ShiftRightU, Op_ShiftRightU)
|