Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

November, 2018 Servicing Update #5827

Merged
merged 10 commits into from
Nov 13, 2018
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/Backend/GlobOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13375,6 +13375,7 @@ GlobOpt::CheckJsArrayKills(IR::Instr *const instr)
case IR::HelperArray_Shift:
case IR::HelperArray_Splice:
case IR::HelperArray_Unshift:
case IR::HelperArray_Concat:
kills.SetKillsArrayHeadSegments();
kills.SetKillsArrayHeadSegmentLengths();
break;
Expand Down Expand Up @@ -13404,6 +13405,7 @@ GlobOpt::CheckJsArrayKills(IR::Instr *const instr)
//case IR::HelperArray_Sort:
case IR::HelperArray_Splice:
case IR::HelperArray_Unshift:
case IR::HelperArray_Concat:
kills.SetKillsNativeArrays();
break;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Backend/GlobOptBailOut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1306,7 +1306,7 @@ GlobOpt::MayNeedBailOnImplicitCall(IR::Instr const * instr, Value const * src1Va
return
!(
baseValueType.IsString() ||
(baseValueType.IsAnyArray() && baseValueType.GetObjectType() != ObjectType::ObjectWithArray) ||
baseValueType.IsArray() ||
(instr->HasBailOutInfo() && instr->GetBailOutKindNoBits() == IR::BailOutOnIrregularLength) // guarantees no implicit calls
);
}
Expand Down
1 change: 1 addition & 0 deletions lib/Backend/GlobOptExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,7 @@ GlobOpt::ProcessArrayValueKills(IR::Instr *instr)
case IR::HelperArray_Shift:
case IR::HelperArray_Unshift:
case IR::HelperArray_Splice:
case IR::HelperArray_Concat:
this->currentBlock->globOptData.liveArrayValues->ClearAll();
break;
}
Expand Down
16 changes: 2 additions & 14 deletions lib/Backend/GlobOptFields.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1900,20 +1900,8 @@ GlobOpt::UpdateObjPtrValueType(IR::Opnd * opnd, IR::Instr * instr)
switch (typeId)
{
default:
if (typeId > Js::TypeIds_LastStaticType)
{
Assert(typeId != Js::TypeIds_Proxy);
if (objValueType.IsLikelyArrayOrObjectWithArray())
{
// If we have likely object with array before, we can't make it definite object with array
// since we have only proved that it is an object.
// Keep the likely array or object with array.
}
else
{
newValueType = ValueType::GetObject(ObjectType::Object);
}
}
// Can't mark as definite object because it may actually be object-with-array.
// Consider: a value type that subsumes object, array, and object-with-array.
break;
case Js::TypeIds_NativeIntArray:
case Js::TypeIds_NativeFloatArray:
Expand Down
22 changes: 19 additions & 3 deletions lib/Backend/IRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3749,7 +3749,7 @@ IRBuilder::BuildElementSlotI1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
IR::Opnd*
IRBuilder::GetEnvironmentOperand(uint32 offset)
{
SymID symID;
StackSym* sym = nullptr;
// The byte code doesn't refer directly to a closure environment. Get the implicit one
// that's pointed to by the function body.
if (m_func->DoStackFrameDisplay() && m_func->GetLocalFrameDisplaySym())
Expand All @@ -3760,19 +3760,35 @@ IRBuilder::GetEnvironmentOperand(uint32 offset)
this->AddInstr(
IR::Instr::New(Js::OpCode::LdSlotArr, regOpnd, fieldOpnd, m_func),
offset);
symID = regOpnd->m_sym->m_id;
sym = regOpnd->m_sym;
}
else
{
SymID symID;
symID = this->GetEnvRegForInnerFrameDisplay();
Assert(symID != Js::Constants::NoRegister);
if (IsLoopBody() && !RegIsConstant(symID))
{
this->EnsureLoopBodyLoadSlot(symID);
}

if (m_func->DoStackNestedFunc() && symID == GetEnvReg())
{
// Environment is not guaranteed constant during this function because it could become boxed during execution,
// so load the environment every time you need it.
IR::RegOpnd *regOpnd = IR::RegOpnd::New(TyVar, m_func);
this->AddInstr(
IR::Instr::New(Js::OpCode::LdEnv, regOpnd, m_func),
offset);
sym = regOpnd->m_sym;
}
else
{
sym = StackSym::FindOrCreate(symID, (Js::RegSlot)symID, m_func);
}
}

return IR::RegOpnd::New(StackSym::FindOrCreate(symID, (Js::RegSlot)symID, m_func), TyVar, m_func);
return IR::RegOpnd::New(sym, TyVar, m_func);
}

template <typename SizePolicy>
Expand Down
4 changes: 4 additions & 0 deletions lib/Backend/Inline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5146,6 +5146,10 @@ Inline::MapFormals(Func *inlinee,
else
{
instr->SetSrc1(funcObjOpnd);

// This usage doesn't correspond with any byte code register, since interpreter stack frames
// get their function reference via this->function rather than from a register.
instr->GetSrc1()->SetIsJITOptimizedReg(true);
}
}
else
Expand Down
39 changes: 17 additions & 22 deletions lib/Backend/Lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3765,13 +3765,11 @@ Lowerer::GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteI
GenerateMemInit(dstOpnd, Js::JavascriptNativeFloatArray::GetOffsetOfWeakFuncRef(), IR::AddrOpnd::New(weakFuncRef, IR::AddrOpndKindDynamicFunctionBodyWeakRef, m_func), instr, isZeroed);
// Js::JavascriptArray::MissingItem is a Var, so it may be 32-bit or 64 bit.
uint const offsetStart = sizeof(Js::SparseArraySegmentBase);
uint const missingItemCount = size * sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
i = i * sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
for (; i < missingItemCount; i++)
for (; i < size; i++)
{
GenerateMemInit(
headOpnd, offsetStart + i * sizeof(Js::JavascriptArray::MissingItem),
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true),
headOpnd, offsetStart + i * sizeof(double),
GetMissingItemOpndForAssignment(TyFloat64, m_func),
instr, isZeroed);
}
}
Expand All @@ -3788,7 +3786,7 @@ Lowerer::GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteI
{
GenerateMemInit(
headOpnd, offsetStart + i * sizeof(Js::Var),
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true),
GetMissingItemOpndForAssignment(TyVar, m_func),
instr, isZeroed);
}
}
Expand Down Expand Up @@ -4111,12 +4109,11 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi

// Js::JavascriptArray::MissingItem is a Var, so it may be 32-bit or 64 bit.
uint const offsetStart = sizeof(Js::SparseArraySegmentBase);
uint const missingItemCount = size * sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
for (uint i = 0; i < missingItemCount; i++)
for (uint i = 0; i < size; i++)
{
GenerateMemInit(
headOpnd, offsetStart + i * sizeof(Js::JavascriptArray::MissingItem),
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true),
headOpnd, offsetStart + i * sizeof(double),
GetMissingItemOpndForAssignment(TyFloat64, m_func),
instr, isZeroed);
}
}
Expand All @@ -4126,9 +4123,9 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
headOpnd = GenerateArrayObjectsAlloc<Js::JavascriptArray>(instr, &size, arrayInfo, &isZeroed, isNoArgs);
for (uint i = 0; i < size; i++)
{
GenerateMemInit(
GenerateMemInit(
headOpnd, offsetStart + i * sizeof(Js::Var),
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true),
GetMissingItemOpndForAssignment(TyVar, m_func),
instr, isZeroed);
}
}
Expand Down Expand Up @@ -4159,8 +4156,8 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
uint allocationBucketsCount = ArrayType::AllocationBucketsCount;
uint(*allocationBuckets)[Js::JavascriptArray::AllocationBucketsInfoSize];
allocationBuckets = ArrayType::allocationBuckets;
uint sizeFactor = 1;
IRType missingItemType = (arrayInfo && arrayInfo->IsNativeIntArray()) ? IRType::TyInt32 : IRType::TyVar;

IRType missingItemType = (arrayInfo ? arrayInfo->IsNativeIntArray() ? IRType::TyInt32 : arrayInfo->IsNativeFloatArray() ? IRType::TyFloat64 : IRType::TyVar : IRType::TyVar);
IR::LabelInstr * arrayInitDone = IR::LabelInstr::New(Js::OpCode::Label, func);

bool isNativeArray = arrayInfo && (arrayInfo->IsNativeIntArray() || arrayInfo->IsNativeFloatArray());
Expand All @@ -4172,9 +4169,7 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
}
else if (arrayInfo && arrayInfo->IsNativeFloatArray())
{
// Js::JavascriptArray::MissingItem is a Var, so it may be 32-bit or 64 bit.
sizeFactor = sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
sizeOfElement = sizeof(Js::JavascriptArray::MissingItem);
sizeOfElement = sizeof(double);
GenerateArrayInfoIsNativeFloatAndNotIntArrayTest(instr, arrayInfo, arrayInfoAddr, helperLabel);
}
else
Expand Down Expand Up @@ -4204,7 +4199,7 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi

for (uint8 i = 0;i < allocationBucketsCount;i++)
{
missingItemCount = allocationBuckets[i][Js::JavascriptArray::MissingElementsCountIndex] * sizeFactor;
missingItemCount = allocationBuckets[i][Js::JavascriptArray::MissingElementsCountIndex];

if (i > 0)
{
Expand Down Expand Up @@ -4235,7 +4230,7 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
// Ensure no. of missingItems written are same
Assert(missingItemIndex == missingItemInitializedSoFar);
// Ensure no. of missingItems match what present in allocationBuckets
Assert(missingItemIndex == allocationBuckets[allocationBucketsCount - 1][Js::JavascriptArray::MissingElementsCountIndex] * sizeFactor);
Assert(missingItemIndex == allocationBuckets[allocationBucketsCount - 1][Js::JavascriptArray::MissingElementsCountIndex]);

instr->InsertBefore(arrayInitDone);

Expand Down Expand Up @@ -4363,11 +4358,11 @@ Lowerer::GenerateProfiledNewScFloatArrayFastPath(IR::Instr *instr, Js::ArrayCall

// Js::JavascriptArray::MissingItem is a Var, so it may be 32-bit or 64 bit.
uint const offsetStart = sizeof(Js::SparseArraySegmentBase) + doubles->count * sizeof(double);
uint const missingItem = (size - doubles->count) * sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
uint const missingItem = (size - doubles->count);
for (uint i = 0; i < missingItem; i++)
{
GenerateMemInit(headOpnd, offsetStart + i * sizeof(Js::JavascriptArray::MissingItem),
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true), instr, isHeadSegmentZeroed);
GenerateMemInit(headOpnd, offsetStart + i * sizeof(double),
GetMissingItemOpndForAssignment(TyFloat64, m_func), instr, isHeadSegmentZeroed);
}
// Skip pass the helper call
IR::LabelInstr * doneLabel = IR::LabelInstr::New(Js::OpCode::Label, func);
Expand Down
17 changes: 14 additions & 3 deletions lib/Parser/Scan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,20 +193,30 @@ void Scanner<EncodingPolicy>::PrepareForBackgroundParse(Js::ScriptContext *scrip
// This is used to determine a length of BSTR, which can't contain a NUL character.
//-----------------------------------------------------------------------------
template <typename EncodingPolicy>
charcount_t Scanner<EncodingPolicy>::LineLength(EncodedCharPtr first, EncodedCharPtr last)
charcount_t Scanner<EncodingPolicy>::LineLength(EncodedCharPtr first, EncodedCharPtr last, size_t* cb)
{
Assert(cb != nullptr);

charcount_t result = 0;
EncodedCharPtr p = first;

for (;;)
{
EncodedCharPtr prev = p;
switch( this->template ReadFull<false>(p, last) )
{
case kchNWL: // _C_NWL
case kchRET:
case kchLS:
case kchPS:
case kchNUL: // _C_NUL
// p is now advanced past the line terminator character.
// We need to know the number of bytes making up the line, not including the line terminator character.
// To avoid subtracting a variable number of bytes because the line terminator characters are different
// number of bytes long (plus there may be multiple valid encodings for these characters) just keep
// track of the first byte of the line terminator character in prev.
Assert(prev >= first);
*cb = prev - first;
return result;
}
result++;
Expand Down Expand Up @@ -2313,10 +2323,11 @@ HRESULT Scanner<EncodingPolicy>::SysAllocErrorLine(int32 ichMinLine, __out BSTR*
typename EncodingPolicy::EncodedCharPtr pStart = static_cast<size_t>(ichMinLine) == IchMinLine() ? m_pchMinLine : m_pchBase + this->CharacterOffsetToUnitOffset(m_pchBase, m_currentCharacter, m_pchLast, ichMinLine);

// Determine the length by scanning for the next newline
charcount_t cch = LineLength(pStart, m_pchLast);
size_t cb = 0;
charcount_t cch = LineLength(pStart, m_pchLast, &cb);
Assert(cch <= LONG_MAX);

typename EncodingPolicy::EncodedCharPtr pEnd = static_cast<size_t>(ichMinLine) == IchMinLine() ? m_pchMinLine + cch : m_pchBase + this->CharacterOffsetToUnitOffset(m_pchBase, m_currentCharacter, m_pchLast, cch);
typename EncodingPolicy::EncodedCharPtr pEnd = static_cast<size_t>(ichMinLine) == IchMinLine() ? m_pchMinLine + cb : m_pchBase + this->CharacterOffsetToUnitOffset(m_pchBase, m_currentCharacter, m_pchLast, cch);

*pbstrLine = SysAllocStringLen(NULL, cch);
if (!*pbstrLine)
Expand Down
2 changes: 1 addition & 1 deletion lib/Parser/Scan.h
Original file line number Diff line number Diff line change
Expand Up @@ -780,7 +780,7 @@ class Scanner : public IScanner, public EncodingPolicy

void ScanNewLine(uint ch);
void NotifyScannedNewLine();
charcount_t LineLength(EncodedCharPtr first, EncodedCharPtr last);
charcount_t LineLength(EncodedCharPtr first, EncodedCharPtr last, size_t* cb);

tokens ScanIdentifier(bool identifyKwds, EncodedCharPtr *pp);
BOOL FastIdentifierContinue(EncodedCharPtr&p, EncodedCharPtr last);
Expand Down
4 changes: 4 additions & 0 deletions lib/Runtime/Language/InterpreterStackFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6727,6 +6727,10 @@ namespace Js
// Finally exited with LeaveNull, We don't throw for early returns
if (finallyEndOffset == 0 && exceptionObj)
{
if (scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr() != nullptr)
{
JavascriptExceptionOperators::WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr, scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr());
}
JavascriptExceptionOperators::DoThrow(const_cast<Js::JavascriptExceptionObject *>(exceptionObj), scriptContext);
}
if (finallyEndOffset != 0)
Expand Down
Loading