Skip to content

Commit aec0bc1

Browse files
committed
Implement GetLength Internal Command
1 parent 134daba commit aec0bc1

File tree

10 files changed

+53
-12
lines changed

10 files changed

+53
-12
lines changed

lib/Backend/GlobOpt.cpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2424,7 +2424,8 @@ void
24242424
GlobOpt::TryReplaceLdLen(IR::Instr *& instr)
24252425
{
24262426
// Change LdLen on objects other than arrays, strings, and 'arguments' to LdFld. Otherwise, convert the SymOpnd to a RegOpnd here.
2427-
if (instr->m_opcode == Js::OpCode::LdLen_A && instr->GetSrc1() && instr->GetSrc1()->IsSymOpnd())
2427+
// Attempt the same optimisation for GetLength as long as the object is not a typed array
2428+
if ((instr->m_opcode == Js::OpCode::LdLen_A || instr->m_opcode == Js::OpCode::GetLength) && instr->GetSrc1() && instr->GetSrc1()->IsSymOpnd())
24282429
{
24292430
IR::SymOpnd * opnd = instr->GetSrc1()->AsSymOpnd();
24302431
Sym *sym = opnd->m_sym;
@@ -2442,15 +2443,19 @@ GlobOpt::TryReplaceLdLen(IR::Instr *& instr)
24422443
(CurrentBlockData()->argObjSyms && CurrentBlockData()->IsArgumentsOpnd(newopnd))
24432444
)
24442445
{
2445-
// We need to properly transfer over the information from the old operand, which is
2446-
// a SymOpnd, to the new one, which is a RegOpnd. Unfortunately, the types mean the
2447-
// normal copy methods won't work here, so we're going to directly copy data.
2448-
newopnd->SetIsJITOptimizedReg(opnd->GetIsJITOptimizedReg());
2449-
newopnd->SetValueType(objectValueInfo->Type());
2450-
newopnd->SetIsDead(opnd->GetIsDead());
2451-
instr->ReplaceSrc1(newopnd);
2446+
// GetLength Op can't be optimised for typed arrays
2447+
if (instr->m_opcode == Js::OpCode::LdLen_A || !objectValueInfo->IsLikelyTypedArray())
2448+
{
2449+
// We need to properly transfer over the information from the old operand, which is
2450+
// a SymOpnd, to the new one, which is a RegOpnd. Unfortunately, the types mean the
2451+
// normal copy methods won't work here, so we're going to directly copy data.
2452+
newopnd->SetIsJITOptimizedReg(opnd->GetIsJITOptimizedReg());
2453+
newopnd->SetValueType(objectValueInfo->Type());
2454+
newopnd->SetIsDead(opnd->GetIsDead());
2455+
instr->ReplaceSrc1(newopnd);
2456+
}
24522457
}
2453-
else
2458+
else if(instr->m_opcode == Js::OpCode::LdLen_A) // retain the GetLength op when not optimising
24542459
{
24552460
// otherwise, change the instruction to an LdFld here.
24562461
instr->m_opcode = Js::OpCode::LdFld;

lib/Backend/IRBuilder.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1862,6 +1862,7 @@ IRBuilder::BuildReg2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::Re
18621862

18631863
case Js::OpCode::ToLength:
18641864
case Js::OpCode::ToInteger:
1865+
case Js::OpCode::GetLength:
18651866
dstOpnd->SetValueType(ValueType::Int.ToLikely());
18661867
break;
18671868

lib/Backend/JnHelperMethodList.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ HELPERCALL_MATH(Op_MinInAnArray, Js::JavascriptMath::MinInAnArray, AttrCanThrow)
138138

139139
HELPERCALLCHK(Op_ToInteger, Js::JavascriptOperators::OP_ToInteger, AttrCanThrow)
140140
HELPERCALLCHK(Op_ToLength, Js::JavascriptOperators::OP_ToLength, AttrCanThrow)
141+
HELPERCALLCHK(Op_GetIterableLength, Js::JavascriptOperators::OP_GetIterableLength, AttrCanThrow)
141142
HELPERCALLCHK(Op_ConvString, Js::JavascriptConversion::ToString, AttrCanThrow)
142143
HELPERCALLCHK(Op_ConvPropertyKey, Js::JavascriptOperators::OP_ToPropertyKey, AttrCanThrow)
143144
HELPERCALLCHK(Op_CoerseString, Js::JavascriptConversion::CoerseString, AttrCanThrow)

lib/Backend/Lower.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3151,6 +3151,10 @@ Lowerer::LowerRange(IR::Instr *instrStart, IR::Instr *instrEnd, bool defaultDoFa
31513151
this->LowerUnaryHelperMem(instr, IR::HelperOp_ToLength);
31523152
break;
31533153

3154+
case Js::OpCode::GetLength:
3155+
this->LowerUnaryHelperMem(instr, IR::HelperOp_GetIterableLength);
3156+
break;
3157+
31543158
#ifdef ENABLE_DEBUG_CONFIG_OPTIONS
31553159
case Js::OpCode::GeneratorOutputBailInTraceLabel:
31563160
#endif

lib/Parser/InternalCommands.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@
1010
Command(Conv_Obj, 1)
1111
Command(ToInteger, 1)
1212
Command(ToLength, 1)
13+
Command(GetLength, 1)
1314

1415
#undef Command

lib/Runtime/ByteCode/OpCodes.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,8 @@ MACRO_EXTEND_WMS( Conv_Str, Reg2, OpOpndHasImplicitCal
335335
MACRO_EXTEND_WMS( Conv_Prop, Reg2, OpOpndHasImplicitCall|OpTempNumberSources|OpTempObjectSources|OpCanCSE|OpPostOpDbgBailOut)
336336

337337
MACRO_EXTEND_WMS( ToInteger, Reg2, OpSideEffect|OpTempNumberProducing|OpTempNumberTransfer|OpTempObjectSources|OpOpndHasImplicitCall|OpProducesNumber)
338-
MACRO_EXTEND_WMS( ToLength, Reg2, OpSideEffect|OpTempNumberProducing|OpTempNumberTransfer|OpTempObjectSources|OpOpndHasImplicitCall|OpProducesNumber)
338+
MACRO_EXTEND_WMS( ToLength, Reg2, OpSideEffect|OpTempNumberProducing|OpTempNumberTransfer|OpTempObjectSources|OpOpndHasImplicitCall|OpProducesNumber)
339+
MACRO_EXTEND_WMS( GetLength, Reg2, OpSideEffect|OpTempNumberProducing|OpTempNumberTransfer|OpTempObjectSources|OpOpndHasImplicitCall|OpProducesNumber)
339340

340341
// Conv_Obj:
341342
// OpSideEffect - May throw exception on null/undefined.

lib/Runtime/Language/InterpreterHandler.inl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ EXDEF2_WMS(A1toA1Mem, Conv_Prop, JavascriptOperat
101101
EXDEF2_WMS(A1toA1Mem, NewUnscopablesWrapperObject,JavascriptOperators::ToUnscopablesWrapperObject)
102102
EXDEF2_WMS(A1toA1Mem, ToInteger, JavascriptOperators::OP_ToInteger)
103103
EXDEF2_WMS(A1toA1Mem, ToLength, JavascriptOperators::OP_ToLength)
104+
EXDEF2_WMS(A1toA1Mem, GetLength, JavascriptOperators::OP_GetIterableLength)
104105
DEF2_WMS(A1toA1Mem, Conv_Num, JavascriptOperators::ToNumber)
105106
DEF2_WMS(A1toA1Mem, Incr_A, JavascriptMath::Increment)
106107
DEF2_WMS(A1toA1Mem, Decr_A, JavascriptMath::Decrement)

lib/Runtime/Language/JavascriptOperators.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10510,6 +10510,33 @@ using namespace Js;
1051010510
JIT_HELPER_END(Op_ToLength);
1051110511
}
1051210512

10513+
Var JavascriptOperators::OP_GetIterableLength(Var iterable, ScriptContext* scriptContext)
10514+
{
10515+
JIT_HELPER_REENTRANT_HEADER(Op_GetIterableLength);
10516+
10517+
if (!VarIs<TypedArrayBase>(iterable))
10518+
{
10519+
Var varLength = JavascriptOperators::OP_GetLength(iterable, scriptContext);
10520+
if (TaggedInt::Is(varLength))
10521+
{
10522+
return varLength;
10523+
}
10524+
return JavascriptNumber::ToVar(JavascriptConversion::ToLength(varLength, scriptContext), scriptContext);
10525+
}
10526+
else
10527+
{
10528+
TypedArrayBase* typedArrayBase = UnsafeVarTo<TypedArrayBase>(iterable);
10529+
if (typedArrayBase->IsDetachedBuffer())
10530+
{
10531+
JavascriptError::ThrowTypeError(scriptContext, JSERR_DetachedTypedArray);
10532+
}
10533+
10534+
return JavascriptNumber::ToVar(typedArrayBase->GetLength(), scriptContext);
10535+
}
10536+
10537+
JIT_HELPER_END(Op_GetIterableLength);
10538+
}
10539+
1051310540
Js::Var
1051410541
JavascriptOperators::BoxStackInstance(Js::Var instance, ScriptContext * scriptContext, bool allowStackFunction, bool deepCopy)
1051510542
{

lib/Runtime/Language/JavascriptOperators.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,7 @@ namespace Js
655655

656656
static Var OP_ToInteger(Var value, ScriptContext* scriptContext);
657657
static Var OP_ToLength(Var value, ScriptContext* scriptContext);
658+
static Var OP_GetIterableLength(Var iterable, ScriptContext* scriptContext);
658659

659660
template <typename T>
660661
static void * JitRecyclerAlloc(DECLSPEC_GUARD_OVERFLOW size_t size, Recycler* recycler)

lib/Runtime/Library/JsBuiltIn/JsBuiltIn.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,8 @@
5454
return { value: undefined, done: true };
5555
} else {
5656
let index = o.__$nextIndex$__;
57-
let len = @@ToLength(a.length);
5857

59-
if (index < len) { // < comparison should happen instead of >= , because len can be NaN
58+
if (index < @@GetLength(a)) { // < comparison should happen instead of >= , because length can be NaN
6059
let itemKind = o.__$kind$__;
6160

6261
o.__$nextIndex$__ = index + 1;

0 commit comments

Comments
 (0)