diff --git a/lib/Backend/JnHelperMethodList.h b/lib/Backend/JnHelperMethodList.h index 8fe8d497945..a07f4f9bfcb 100644 --- a/lib/Backend/JnHelperMethodList.h +++ b/lib/Backend/JnHelperMethodList.h @@ -74,8 +74,8 @@ HELPERCALLCHK(Op_ConvObject, Js::JavascriptOperators::ToObject, AttrCanThrow | A HELPERCALLCHK(Op_NewUnscopablesWrapperObject, Js::JavascriptOperators::ToUnscopablesWrapperObject, AttrCanThrow | AttrCanNotBeReentrant) HELPERCALLCHK(SetComputedNameVar, Js::JavascriptOperators::OP_SetComputedNameVar, AttrCanNotBeReentrant) HELPERCALLCHK(Op_UnwrapWithObj, Js::JavascriptOperators::OP_UnwrapWithObj, AttrCanNotBeReentrant) -HELPERCALLCHK(Op_ConvNumber_Full, Js::JavascriptOperators::ToNumber, AttrCanThrow) -HELPERCALLCHK(Op_ConvNumberInPlace, Js::JavascriptOperators::ToNumberInPlace, AttrCanThrow) +HELPERCALLCHK(Op_ConvNumber_Full, Js::JavascriptOperators::ToNumeric, AttrCanThrow) +HELPERCALLCHK(Op_ConvNumberInPlace, Js::JavascriptOperators::ToNumericInPlace, AttrCanThrow) HELPERCALLCHK(Op_ConvNumber_Helper, Js::JavascriptConversion::ToNumber_Helper, 0) HELPERCALLCHK(Op_ConvFloat_Helper, Js::JavascriptConversion::ToFloat_Helper, 0) HELPERCALLCHK(Op_ConvNumber_FromPrimitive, Js::JavascriptConversion::ToNumber_FromPrimitive, 0) diff --git a/lib/Backend/Lower.cpp b/lib/Backend/Lower.cpp index 5339d0dedc3..b561fc5e0af 100644 --- a/lib/Backend/Lower.cpp +++ b/lib/Backend/Lower.cpp @@ -988,10 +988,12 @@ Lowerer::LowerRange(IR::Instr *instrStart, IR::Instr *instrEnd, bool defaultDoFa this->LowerUnaryHelperMem(instr, IR::HelperOp_ToSpreadedFunctionArgument); break; + case Js::OpCode::Conv_Numeric: case Js::OpCode::Conv_Num: this->LowerConvNum(instr, noMathFastPath); break; + case Js::OpCode::Incr_Num_A: case Js::OpCode::Incr_A: if (PHASE_OFF(Js::MathFastPathPhase, this->m_func) || noMathFastPath) { @@ -1006,6 +1008,7 @@ Lowerer::LowerRange(IR::Instr *instrStart, IR::Instr *instrEnd, bool defaultDoFa } break; + case Js::OpCode::Decr_Num_A: case Js::OpCode::Decr_A: if (PHASE_OFF(Js::MathFastPathPhase, this->m_func) || noMathFastPath) { diff --git a/lib/Runtime/ByteCode/ByteCodeEmitter.cpp b/lib/Runtime/ByteCode/ByteCodeEmitter.cpp index 5a61839f401..f13ba4ee56b 100644 --- a/lib/Runtime/ByteCode/ByteCodeEmitter.cpp +++ b/lib/Runtime/ByteCode/ByteCodeEmitter.cpp @@ -10438,7 +10438,16 @@ void Emit(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator, FuncInfo *func if (pnode->isUsed || fReturnValue) { byteCodeGenerator->StartStatement(pnode); - const Js::OpCode op = (pnode->nop == knopDecPost) ? Js::OpCode::Sub_A : Js::OpCode::Add_A; + bool isESBigIntEnabled = byteCodeGenerator->GetScriptContext()->GetConfig()->IsESBigIntEnabled(); + Js::OpCode op1; + if (isESBigIntEnabled) + { + op1 = (pnode->nop == knopDecPost) ? Js::OpCode::Decr_Num_A : Js::OpCode::Incr_Num_A; + } + else + { + op1 = (pnode->nop == knopDecPost) ? Js::OpCode::Sub_A : Js::OpCode::Add_A; + } ParseNode* pnode1 = pnode->AsParseNodeUni()->pnode1; // Grab a register for the expression result. @@ -10446,7 +10455,8 @@ void Emit(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator, FuncInfo *func // Load the initial value, convert it (this is the expression result), and increment it. EmitLoad(pnode1, byteCodeGenerator, funcInfo); - byteCodeGenerator->Writer()->Reg2(Js::OpCode::Conv_Num, pnode->location, pnode1->location); + const Js::OpCode op2 = isESBigIntEnabled ? Js::OpCode::Conv_Numeric : Js::OpCode::Conv_Num; + byteCodeGenerator->Writer()->Reg2(op2, pnode->location, pnode1->location); // Use temporary register if lhs cannot be assigned Js::RegSlot incDecResult = pnode1->location; @@ -10455,10 +10465,17 @@ void Emit(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator, FuncInfo *func { incDecResult = funcInfo->AcquireTmpRegister(); } - - Js::RegSlot oneReg = funcInfo->constantToRegister.LookupWithKey(1, Js::Constants::NoRegister); - Assert(oneReg != Js::Constants::NoRegister); - byteCodeGenerator->Writer()->Reg3(op, incDecResult, pnode->location, oneReg); + + if (isESBigIntEnabled) + { + byteCodeGenerator->Writer()->Reg2(op1, incDecResult, pnode->location); + } + else + { + Js::RegSlot oneReg = funcInfo->constantToRegister.LookupWithKey(1, Js::Constants::NoRegister); + Assert(oneReg != Js::Constants::NoRegister); + byteCodeGenerator->Writer()->Reg3(op1, incDecResult, pnode->location, oneReg); + } // Store the incremented value. EmitAssignment(nullptr, pnode1, incDecResult, byteCodeGenerator, funcInfo); diff --git a/lib/Runtime/ByteCode/OpCodes.h b/lib/Runtime/ByteCode/OpCodes.h index 0b70e81507d..d4316d23b51 100755 --- a/lib/Runtime/ByteCode/OpCodes.h +++ b/lib/Runtime/ByteCode/OpCodes.h @@ -836,6 +836,9 @@ MACRO_EXTEND_WMS( Restify, Reg4, OpSideEffect|OpHasIm MACRO_EXTEND_WMS( NewPropIdArrForCompProps, Reg1Unsigned1, OpSideEffect) MACRO_BACKEND_ONLY(BigIntLiteral, Empty, None) // Load BigInt literal +MACRO_EXTEND_WMS(Conv_Numeric, Reg2, OpSideEffect | OpTempNumberProducing | OpTempNumberTransfer | OpTempObjectSources | OpOpndHasImplicitCall | OpProducesNumber) // Convert to Numeric. [[ToNumeric()]] +MACRO_EXTEND_WMS(Incr_Num_A, Reg2, OpTempNumberProducing | OpOpndHasImplicitCall | OpDoNotTransfer | OpTempNumberSources | OpTempObjectSources | OpCanCSE | OpPostOpDbgBailOut | OpProducesNumber) // Increment Numeric +MACRO_EXTEND_WMS(Decr_Num_A, Reg2, OpTempNumberProducing | OpOpndHasImplicitCall | OpDoNotTransfer | OpTempNumberSources | OpTempObjectSources | OpCanCSE | OpPostOpDbgBailOut | OpProducesNumber) // Increment Numeric // All SIMD ops are backend only for non-asmjs. #define MACRO_SIMD(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr, ...) MACRO_BACKEND_ONLY(opcode, Empty, OpCodeAttr) diff --git a/lib/Runtime/Language/InterpreterHandler.inl b/lib/Runtime/Language/InterpreterHandler.inl index f2cae8e7a6b..78dc401ccf8 100644 --- a/lib/Runtime/Language/InterpreterHandler.inl +++ b/lib/Runtime/Language/InterpreterHandler.inl @@ -402,6 +402,9 @@ EXDEF2_WMS(A2A2NonVartoXXMem, Restify, JavascriptObject EXDEF2_WMS(SET_ELEM_SLOTMem, StPropIdArrFromVar, OP_StPropIdArrFromVar) EXDEF2_WMS(SIZEtoA1MemNonVar, NewPropIdArrForCompProps, OP_NewPropIdArrForCompProps) +EXDEF2_WMS(A1toA1Mem, Conv_Numeric, JavascriptOperators::ToNumeric) +EXDEF2_WMS(A1toA1Mem, Incr_Num_A, JavascriptMath::Increment_Numeric) +EXDEF2_WMS(A1toA1Mem, Decr_Num_A, JavascriptMath::Decrement_Numeric) #endif diff --git a/lib/Runtime/Language/JavascriptOperators.cpp b/lib/Runtime/Language/JavascriptOperators.cpp index 5f4d61172d0..b37a0dd4002 100644 --- a/lib/Runtime/Language/JavascriptOperators.cpp +++ b/lib/Runtime/Language/JavascriptOperators.cpp @@ -308,6 +308,15 @@ using namespace Js; JIT_HELPER_END(Op_ConvNumberInPlace); } + Var JavascriptOperators::ToNumericInPlace(Var aRight, ScriptContext* scriptContext, JavascriptNumber* result) + { + if (JavascriptOperators::GetTypeId(aRight) == TypeIds_BigInt) + { + return aRight; + } + return JavascriptOperators::ToNumberInPlace(aRight, scriptContext, result); + } + Var JavascriptOperators::Typeof(Var var, ScriptContext* scriptContext) { JIT_HELPER_REENTRANT_HEADER(Op_Typeof); @@ -10648,6 +10657,15 @@ using namespace Js; JIT_HELPER_END(Op_ConvNumber_Full); } + Var JavascriptOperators::ToNumeric(Var aRight, ScriptContext* scriptContext) + { + if (JavascriptOperators::GetTypeId(aRight) == TypeIds_BigInt) + { + return aRight; + } + return JavascriptOperators::ToNumber(aRight, scriptContext); + } + BOOL JavascriptOperators::IsObject(_In_ RecyclableObject* instance) { return GetTypeId(instance) > TypeIds_LastJavascriptPrimitiveType; diff --git a/lib/Runtime/Language/JavascriptOperators.h b/lib/Runtime/Language/JavascriptOperators.h index 7bf340679b1..55052300a04 100644 --- a/lib/Runtime/Language/JavascriptOperators.h +++ b/lib/Runtime/Language/JavascriptOperators.h @@ -126,6 +126,8 @@ namespace Js static Var OP_LdCustomSpreadIteratorList(Var aRight, ScriptContext* scriptContext); static Var ToNumber(Var aRight,ScriptContext* scriptContext); static Var ToNumberInPlace(Var aRight,ScriptContext* scriptContext, JavascriptNumber* result); + static Var ToNumeric(Var aRight, ScriptContext* scriptContext); + static Var ToNumericInPlace(Var aRight, ScriptContext* scriptContext, JavascriptNumber* result); #ifdef _M_IX86 static Var Int32ToVar(int32 value, ScriptContext* scriptContext); static Var Int32ToVarInPlace(int32 value, ScriptContext* scriptContext, JavascriptNumber *result); diff --git a/lib/Runtime/Math/JavascriptMath.cpp b/lib/Runtime/Math/JavascriptMath.cpp index e04f956846b..2d868f8c457 100644 --- a/lib/Runtime/Math/JavascriptMath.cpp +++ b/lib/Runtime/Math/JavascriptMath.cpp @@ -125,6 +125,24 @@ using namespace Js; } JIT_HELPER_TEMPLATE(Op_Decrement_Full, Op_Decrement) + Var JavascriptMath::Increment_Numeric(Var aRight, ScriptContext* scriptContext) + { + if (VarIs(aRight)) + { + return JavascriptBigInt::Increment(aRight); + } + return JavascriptMath::Add(aRight, TaggedInt::ToVarUnchecked(1), scriptContext); + } + + Var JavascriptMath::Decrement_Numeric(Var aRight, ScriptContext* scriptContext) + { + if (VarIs(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); diff --git a/lib/Runtime/Math/JavascriptMath.h b/lib/Runtime/Math/JavascriptMath.h index 74727035d37..5aa5deb3c4e 100644 --- a/lib/Runtime/Math/JavascriptMath.h +++ b/lib/Runtime/Math/JavascriptMath.h @@ -26,6 +26,9 @@ namespace Js static Var Decrement_Full(Var aRight,ScriptContext* scriptContext); static Var Decrement_InPlace(Var aRight,ScriptContext* scriptContext, JavascriptNumber* result); + static Var Increment_Numeric(Var aRight, ScriptContext* scriptContext); + static Var Decrement_Numeric(Var aRight, ScriptContext* scriptContext); + static Var Negate(Var aRight,ScriptContext* scriptContext); static Var Negate_Full(Var aRight,ScriptContext* scriptContext); static Var Negate_InPlace(Var aRight,ScriptContext* scriptContext, JavascriptNumber* result); diff --git a/test/BigInt/decrement.js b/test/BigInt/decrement.js index 4cb1951c91a..65d899a8b15 100644 --- a/test/BigInt/decrement.js +++ b/test/BigInt/decrement.js @@ -97,6 +97,18 @@ var tests = [ assert.isTrue(x == y); } }, + { + name: "With assign", + body: function () { + var x = 3n; + var y = x--; + assert.isTrue(x == 2n); + assert.isTrue(y == 3n); + y = --x; + assert.isTrue(x == 1n); + assert.isTrue(y == 1n); + } + }, ]; testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" }); diff --git a/test/BigInt/increment.js b/test/BigInt/increment.js index ec0f4a7f1d2..344db980c88 100644 --- a/test/BigInt/increment.js +++ b/test/BigInt/increment.js @@ -97,6 +97,18 @@ var tests = [ assert.isTrue(x == y); } }, + { + name: "With assign", + body: function () { + var x = 3n; + var y = x++; + assert.isTrue(x == 4n); + assert.isTrue(y == 3n); + y = ++x; + assert.isTrue(x == 5n); + assert.isTrue(y == 5n); + } + }, ]; testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });