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

ChakraCore Servicing Release for 1903 #6016

Merged
merged 8 commits into from
Mar 12, 2019
Merged
Show file tree
Hide file tree
Changes from all 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
33 changes: 25 additions & 8 deletions lib/Backend/BailOut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1403,6 +1403,7 @@ BailOutRecord::BailOutHelper(Js::JavascriptCallStackLayout * layout, Js::ScriptF
//
Js::Arguments generatorArgs = generator->GetArguments();
Js::InterpreterStackFrame::Setup setup(function, generatorArgs, true, isInlinee);
Assert(setup.GetStackAllocationVarCount() == 0);
size_t varAllocCount = setup.GetAllocationVarCount();
size_t varSizeInBytes = varAllocCount * sizeof(Js::Var);
DWORD_PTR stackAddr = reinterpret_cast<DWORD_PTR>(&generator); // as mentioned above, use any stack address from this frame to ensure correct debugging functionality
Expand All @@ -1415,11 +1416,14 @@ BailOutRecord::BailOutHelper(Js::JavascriptCallStackLayout * layout, Js::ScriptF
// Allocate invalidVar on GC instead of stack since this InterpreterStackFrame will out live the current real frame
Js::Var invalidVar = (Js::RecyclableObject*)RecyclerNewPlusLeaf(functionScriptContext->GetRecycler(), sizeof(Js::RecyclableObject), Js::Var);
memset(invalidVar, 0xFE, sizeof(Js::RecyclableObject));
newInstance = setup.InitializeAllocation(allocation, false, false, loopHeaderArray, stackAddr, invalidVar);
#else
newInstance = setup.InitializeAllocation(allocation, false, false, loopHeaderArray, stackAddr);
#endif

newInstance = setup.InitializeAllocation(allocation, nullptr, false, false, loopHeaderArray, stackAddr
#if DBG
, invalidVar
#endif
);

newInstance->m_reader.Create(executeFunction);

generator->SetFrame(newInstance, varSizeInBytes);
Expand All @@ -1429,18 +1433,28 @@ BailOutRecord::BailOutHelper(Js::JavascriptCallStackLayout * layout, Js::ScriptF
{
Js::InterpreterStackFrame::Setup setup(function, args, true, isInlinee);
size_t varAllocCount = setup.GetAllocationVarCount();
size_t varSizeInBytes = varAllocCount * sizeof(Js::Var);
size_t stackVarAllocCount = setup.GetStackAllocationVarCount();
size_t varSizeInBytes;
Js::Var *stackAllocation = nullptr;

// If the locals area exceeds a certain limit, allocate it from a private arena rather than
// this frame. The current limit is based on an old assert on the number of locals we would allow here.
if (varAllocCount > Js::InterpreterStackFrame::LocalsThreshold)
if ((varAllocCount + stackVarAllocCount) > Js::InterpreterStackFrame::LocalsThreshold)
{
ArenaAllocator *tmpAlloc = nullptr;
fReleaseAlloc = functionScriptContext->EnsureInterpreterArena(&tmpAlloc);
varSizeInBytes = varAllocCount * sizeof(Js::Var);
allocation = (Js::Var*)tmpAlloc->Alloc(varSizeInBytes);
if (stackVarAllocCount != 0)
{
size_t stackVarSizeInBytes = stackVarAllocCount * sizeof(Js::Var);
PROBE_STACK_PARTIAL_INITIALIZED_BAILOUT_FRAME(functionScriptContext, Js::Constants::MinStackInterpreter + stackVarSizeInBytes, returnAddress);
stackAllocation = (Js::Var*)_alloca(stackVarSizeInBytes);
}
}
else
{
varSizeInBytes = (varAllocCount + stackVarAllocCount) * sizeof(Js::Var);
PROBE_STACK_PARTIAL_INITIALIZED_BAILOUT_FRAME(functionScriptContext, Js::Constants::MinStackInterpreter + varSizeInBytes, returnAddress);
allocation = (Js::Var*)_alloca(varSizeInBytes);
}
Expand All @@ -1465,11 +1479,14 @@ BailOutRecord::BailOutHelper(Js::JavascriptCallStackLayout * layout, Js::ScriptF
#if DBG
Js::Var invalidStackVar = (Js::RecyclableObject*)_alloca(sizeof(Js::RecyclableObject));
memset(invalidStackVar, 0xFE, sizeof(Js::RecyclableObject));
newInstance = setup.InitializeAllocation(allocation, false, false, loopHeaderArray, frameStackAddr, invalidStackVar);
#else
newInstance = setup.InitializeAllocation(allocation, false, false, loopHeaderArray, frameStackAddr);
#endif

newInstance = setup.InitializeAllocation(allocation, stackAllocation, false, false, loopHeaderArray, frameStackAddr
#if DBG
, invalidStackVar
#endif
);

newInstance->m_reader.Create(executeFunction);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/Backend/EmitBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ bool EmitBufferManager<TAlloc, TPreReservedAlloc, SyncObject>::ProtectBufferWith
template <typename TAlloc, typename TPreReservedAlloc, class SyncObject>
bool EmitBufferManager<TAlloc, TPreReservedAlloc, SyncObject>::CommitBufferForInterpreter(TEmitBufferAllocation* allocation, _In_reads_bytes_(bufferSize) BYTE* pBuffer, _In_ size_t bufferSize)
{
Assert(this->criticalSection.IsLocked());
AutoRealOrFakeCriticalSection<SyncObject> autoCs(&this->criticalSection);

Assert(allocation != nullptr);
allocation->bytesUsed += bufferSize;
Expand Down
2 changes: 1 addition & 1 deletion lib/Backend/FlowGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5266,7 +5266,7 @@ BasicBlock::MergePredBlocksValueMaps(GlobOpt* globOpt)
}
if(symsRequiringCompensationToMergedValueInfoMap.Count() != 0)
{
globOpt->InsertValueCompensation(pred, &symsRequiringCompensationToMergedValueInfoMap);
globOpt->InsertValueCompensation(pred, this, &symsRequiringCompensationToMergedValueInfoMap);
}
}
} NEXT_PREDECESSOR_EDGE_EDITING;
Expand Down
7 changes: 5 additions & 2 deletions lib/Backend/GlobOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ GlobOpt::OptBlock(BasicBlock *block)

if (block->loop->symsRequiringCompensationToMergedValueInfoMap)
{
InsertValueCompensation(block, block->loop->symsRequiringCompensationToMergedValueInfoMap);
InsertValueCompensation(block, succ, block->loop->symsRequiringCompensationToMergedValueInfoMap);
}

// Now that we're done with the liveFields within this loop, trim the set to those syms
Expand Down Expand Up @@ -1156,9 +1156,12 @@ void GlobOpt::FieldPRE(Loop *loop)

void GlobOpt::InsertValueCompensation(
BasicBlock *const predecessor,
BasicBlock *const successor,
const SymToValueInfoMap *symsRequiringCompensationToMergedValueInfoMap)
{
Assert(predecessor);
Assert(successor);
AssertOrFailFast(predecessor != successor);
Assert(symsRequiringCompensationToMergedValueInfoMap->Count() != 0);

IR::Instr *insertBeforeInstr = predecessor->GetLastInstr();
Expand All @@ -1182,7 +1185,7 @@ void GlobOpt::InsertValueCompensation(
}

GlobOptBlockData &predecessorBlockData = predecessor->globOptData;
GlobOptBlockData &successorBlockData = *CurrentBlockData();
GlobOptBlockData &successorBlockData = successor->globOptData;
struct DelayChangeValueInfo
{
Value* predecessorValue;
Expand Down
2 changes: 1 addition & 1 deletion lib/Backend/GlobOpt.h
Original file line number Diff line number Diff line change
Expand Up @@ -737,7 +737,7 @@ class GlobOpt
void PreLowerCanonicalize(IR::Instr *instr, Value **pSrc1Val, Value **pSrc2Val);
void ProcessKills(IR::Instr *instr);
void InsertCloneStrs(BasicBlock *toBlock, GlobOptBlockData *toData, GlobOptBlockData *fromData);
void InsertValueCompensation(BasicBlock *const predecessor, const SymToValueInfoMap *symsRequiringCompensationToMergedValueInfoMap);
void InsertValueCompensation(BasicBlock *const predecessor, BasicBlock *const successor, const SymToValueInfoMap *symsRequiringCompensationToMergedValueInfoMap);
IR::Instr * ToVarUses(IR::Instr *instr, IR::Opnd *opnd, bool isDst, Value *val);
void ToVar(BVSparse<JitArenaAllocator> *bv, BasicBlock *block);
IR::Instr * ToVar(IR::Instr *instr, IR::RegOpnd *regOpnd, BasicBlock *block, Value *val, bool needsUpdate);
Expand Down
15 changes: 15 additions & 0 deletions lib/Backend/GlobOptFields.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -450,9 +450,24 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
break;

case IR::JnHelperMethod::HelperRegExp_Exec:
case IR::JnHelperMethod::HelperRegExp_ExecResultNotUsed:
case IR::JnHelperMethod::HelperRegExp_ExecResultUsed:
case IR::JnHelperMethod::HelperRegExp_ExecResultUsedAndMayBeTemp:
case IR::JnHelperMethod::HelperRegExp_MatchResultNotUsed:
case IR::JnHelperMethod::HelperRegExp_MatchResultUsed:
case IR::JnHelperMethod::HelperRegExp_MatchResultUsedAndMayBeTemp:
case IR::JnHelperMethod::HelperRegExp_ReplaceStringResultUsed:
case IR::JnHelperMethod::HelperRegExp_ReplaceStringResultNotUsed:
case IR::JnHelperMethod::HelperRegExp_SplitResultNotUsed:
case IR::JnHelperMethod::HelperRegExp_SplitResultUsed:
case IR::JnHelperMethod::HelperRegExp_SplitResultUsedAndMayBeTemp:
case IR::JnHelperMethod::HelperRegExp_SymbolSearch:
case IR::JnHelperMethod::HelperString_Match:
case IR::JnHelperMethod::HelperString_Search:
case IR::JnHelperMethod::HelperString_Split:
case IR::JnHelperMethod::HelperString_Replace:
// Consider: We may not need to kill all fields here.
// We need to kill all the built-in properties that can be written, though, and there are a lot of those.
this->KillAllFields(bv);
break;
}
Expand Down
6 changes: 5 additions & 1 deletion lib/Backend/GlobOptIntBounds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2985,7 +2985,11 @@ void GlobOpt::DetermineArrayBoundCheckHoistability(
{
// The loop count is constant, fold (indexOffset + loopCountMinusOne * maxMagnitudeChange)
TRACE_PHASE_VERBOSE(Js::Phase::BoundCheckHoistPhase, 3, _u("Loop count is constant, folding\n"));
if(Int32Math::Mul(loopCount->LoopCountMinusOneConstantValue(), maxMagnitudeChange, &offset) ||

int loopCountMinusOnePlusOne = 0;

if (Int32Math::Add(loopCount->LoopCountMinusOneConstantValue(), 1, &loopCountMinusOnePlusOne) ||
Int32Math::Mul(loopCountMinusOnePlusOne, maxMagnitudeChange, &offset) ||
Int32Math::Add(offset, indexOffset, &offset))
{
TRACE_PHASE_VERBOSE(Js::Phase::BoundCheckHoistPhase, 4, _u("Folding failed\n"));
Expand Down
4 changes: 2 additions & 2 deletions lib/Backend/IRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1758,7 +1758,7 @@ IRBuilder::BuildReg1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0)
}

case Js::OpCode::NewScObjectSimple:
dstValueType = ValueType::GetObject(ObjectType::UninitializedObject);
dstValueType = ValueType::GetObject(ObjectType::Object);
// fall-through
case Js::OpCode::LdFuncExpr:
m_func->DisableCanDoInlineArgOpt();
Expand Down Expand Up @@ -5050,7 +5050,7 @@ IRBuilder::BuildAuxiliary(Js::OpCode newOpcode, uint32 offset)
// lower take it from there...
srcOpnd = IR::IntConstOpnd::New(auxInsn->Offset, TyUint32, m_func);
dstOpnd = this->BuildDstOpnd(dstRegSlot);
dstOpnd->SetValueType(ValueType::GetObject(ObjectType::UninitializedObject));
dstOpnd->SetValueType(ValueType::GetObject(ObjectType::Object));
instr = IR::Instr::New(newOpcode, dstOpnd, srcOpnd, m_func);

// Because we're going to be making decisions based off the value, we have to defer
Expand Down
9 changes: 6 additions & 3 deletions lib/Backend/ServerScriptContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ ServerScriptContext::IsClosed() const
void
ServerScriptContext::AddToDOMFastPathHelperMap(intptr_t funcInfoAddr, IR::JnHelperMethod helper)
{
AutoCriticalSection cs(&m_cs);
m_domFastPathHelperMap->Add(funcInfoAddr, helper);
}

Expand All @@ -327,7 +328,7 @@ ServerScriptContext::DecommitEmitBufferManager(bool asmJsManager)
GetEmitBufferManager(asmJsManager)->Decommit();
}

OOPEmitBufferManager *
OOPEmitBufferManagerWithLock *
ServerScriptContext::GetEmitBufferManager(bool asmJsManager)
{
if (asmJsManager)
Expand All @@ -343,11 +344,11 @@ ServerScriptContext::GetEmitBufferManager(bool asmJsManager)
IR::JnHelperMethod
ServerScriptContext::GetDOMFastPathHelper(intptr_t funcInfoAddr)
{
AutoCriticalSection cs(&m_cs);

IR::JnHelperMethod helper = IR::HelperInvalid;

m_domFastPathHelperMap->LockResize();
m_domFastPathHelperMap->TryGetValue(funcInfoAddr, &helper);
m_domFastPathHelperMap->UnlockResize();

return helper;
}
Expand Down Expand Up @@ -392,6 +393,7 @@ ServerScriptContext::GetCodeGenAllocators()
Field(Js::Var)*
ServerScriptContext::GetModuleExportSlotArrayAddress(uint moduleIndex, uint slotIndex)
{
AutoCriticalSection cs(&m_cs);
AssertOrFailFast(m_moduleRecords.ContainsKey(moduleIndex));
auto record = m_moduleRecords.Item(moduleIndex);
return record->localExportSlotsAddr;
Expand All @@ -406,6 +408,7 @@ ServerScriptContext::SetIsPRNGSeeded(bool value)
void
ServerScriptContext::AddModuleRecordInfo(unsigned int moduleId, __int64 localExportSlotsAddr)
{
AutoCriticalSection cs(&m_cs);
Js::ServerSourceTextModuleRecord* record = HeapNewStructZ(Js::ServerSourceTextModuleRecord);
record->moduleId = moduleId;
record->localExportSlotsAddr = (Field(Js::Var)*)localExportSlotsAddr;
Expand Down
7 changes: 4 additions & 3 deletions lib/Backend/ServerScriptContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class ServerScriptContext : public ScriptContextInfo
void SetIsPRNGSeeded(bool value);
void AddModuleRecordInfo(unsigned int moduleId, __int64 localExportSlotsAddr);
void UpdateGlobalObjectThisAddr(intptr_t globalThis);
OOPEmitBufferManager * GetEmitBufferManager(bool asmJsManager);
OOPEmitBufferManagerWithLock * GetEmitBufferManager(bool asmJsManager);
void DecommitEmitBufferManager(bool asmJsManager);
#ifdef PROFILE_EXEC
Js::ScriptContextProfiler* GetCodeGenProfiler(_In_ PageAllocator* pageAllocator);
Expand All @@ -100,10 +100,11 @@ class ServerScriptContext : public ScriptContextInfo
Js::ScriptContextProfiler * codeGenProfiler;
CriticalSection profilerCS;
#endif
CriticalSection m_cs;
ArenaAllocator m_sourceCodeArena;

OOPEmitBufferManager m_interpreterThunkBufferManager;
OOPEmitBufferManager m_asmJsInterpreterThunkBufferManager;
OOPEmitBufferManagerWithLock m_interpreterThunkBufferManager;
OOPEmitBufferManagerWithLock m_asmJsInterpreterThunkBufferManager;

ScriptContextDataIDL m_contextData;
intptr_t m_globalThisAddr;
Expand Down
19 changes: 16 additions & 3 deletions lib/JITIDL/ChakraJIT.acf
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,26 @@
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------

typedef [context_handle_noserialize] PTHREADCONTEXT_HANDLE;
typedef [context_handle_noserialize] PSCRIPTCONTEXT_HANDLE;

[
type_strict_context_handle
]
interface IChakraJIT
{
UpdatePropertyRecordMap([context_handle_noserialize] threadContextInfoAddress);
AddDOMFastPathHelper([context_handle_noserialize] scriptContextInfoAddress);
AddModuleRecordInfo([context_handle_noserialize] scriptContextInfoAddress);
SetWellKnownHostTypeId([context_handle_noserialize] threadContextInfoAddress);
CloseScriptContext([context_handle_noserialize] scriptContextInfoAddress);
FreeAllocation([context_handle_noserialize] scriptContextInfoAddress);
NewInterpreterThunkBlock([context_handle_noserialize] scriptContextInfoAddress);
DecommitInterpreterBufferManager([context_handle_noserialize] scriptContextInfoAddress);
IsNativeAddr([context_handle_noserialize] threadContextInfoAddress);
SetIsPRNGSeeded([context_handle_noserialize] scriptContextInfoAddress);
RemoteCodeGen([context_handle_noserialize] scriptContextInfoAddress);

#if DBG
IsInterpreterThunkAddr([context_handle_noserialize] scriptContextInfoAddress);
#endif

typedef [encode, decode] pCodeGenWorkItemIDL;
}
4 changes: 2 additions & 2 deletions lib/JITServer/JITServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ ServerNewInterpreterThunkBlock(
ServerThreadContext * threadContext;
} localAlloc(threadContext);

OOPEmitBufferManager * emitBufferManager = scriptContext->GetEmitBufferManager(thunkInput->asmJsThunk != FALSE);
OOPEmitBufferManagerWithLock * emitBufferManager = scriptContext->GetEmitBufferManager(thunkInput->asmJsThunk != FALSE);

BYTE* runtimeAddress;
EmitBufferAllocation<SectionAllocWrapper, PreReservedSectionAllocWrapper> * alloc = emitBufferManager->AllocateBuffer(InterpreterThunkEmitter::BlockSize, &runtimeAddress);
Expand Down Expand Up @@ -573,7 +573,7 @@ ServerIsInterpreterThunkAddr(
*result = false;
return RPC_S_INVALID_ARG;
}
OOPEmitBufferManager * manager = context->GetEmitBufferManager(asmjsThunk != FALSE);
OOPEmitBufferManagerWithLock * manager = context->GetEmitBufferManager(asmjsThunk != FALSE);
if (manager == nullptr)
{
*result = false;
Expand Down
5 changes: 5 additions & 0 deletions lib/Runtime/Base/ScriptContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1485,6 +1485,11 @@ namespace Js
this->GetThreadContext()->RegisterScriptContext(this);
}

bool ScriptContext::ExceedsStackNestedFuncCount(uint count)
{
return count >= (InterpreterStackFrame::LocalsThreshold / (sizeof(StackScriptFunction) / sizeof(Var)));
}

#ifdef ENABLE_SCRIPT_DEBUGGING
ArenaAllocator* ScriptContext::AllocatorForDiagnostics()
{
Expand Down
2 changes: 2 additions & 0 deletions lib/Runtime/Base/ScriptContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,8 @@ namespace Js
ScriptConfiguration const * GetConfig(void) const { return &config; }
CharClassifier const * GetCharClassifier(void) const;

static bool ExceedsStackNestedFuncCount(uint count);

ThreadContext * GetThreadContext() const { return threadContext; }

static const int MaxEvalSourceSize = 400;
Expand Down
3 changes: 2 additions & 1 deletion lib/Runtime/ByteCode/ByteCodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1839,7 +1839,8 @@ bool ByteCodeGenerator::CanStackNestedFunc(FuncInfo * funcInfo, bool trace)
Assert(!funcInfo->IsGlobalFunction());
bool const doStackNestedFunc = !funcInfo->HasMaybeEscapedNestedFunc() && !IsInDebugMode()
&& !funcInfo->byteCodeFunction->IsCoroutine()
&& !funcInfo->byteCodeFunction->IsModule();
&& !funcInfo->byteCodeFunction->IsModule()
&& !Js::ScriptContext::ExceedsStackNestedFuncCount(funcInfo->root->nestedCount);
if (!doStackNestedFunc)
{
return false;
Expand Down
Loading