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

April servicing update for ChakraCore #6087

Merged
merged 8 commits into from
Apr 9, 2019
2 changes: 1 addition & 1 deletion Build/NuGet/.pack-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.11.7
1.11.8
22 changes: 13 additions & 9 deletions lib/Backend/GlobOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3258,10 +3258,14 @@ GlobOpt::OptSrc(IR::Opnd *opnd, IR::Instr * *pInstr, Value **indirIndexValRef, I
}
originalPropertySym = sym->AsPropertySym();

// Dont give a vale to 'arguments' property sym to prevent field copy prop of 'arguments'
// Don't give a value to 'arguments' property sym to prevent field copy prop of 'arguments'
if (originalPropertySym->AsPropertySym()->m_propertyId == Js::PropertyIds::arguments &&
originalPropertySym->AsPropertySym()->m_fieldKind == PropertyKindData)
{
if (opnd->AsSymOpnd()->IsPropertySymOpnd())
{
this->FinishOptPropOp(instr, opnd->AsPropertySymOpnd());
}
return nullptr;
}

Expand Down Expand Up @@ -4813,7 +4817,7 @@ GlobOpt::ValueNumberDst(IR::Instr **pInstr, Value *src1Val, Value *src2Val)
}
else
{
return NewGenericValue(src1ValueInfo->Type().ToDefiniteAnyNumber(), dst);
return NewGenericValue(src1ValueInfo->Type().ToDefiniteAnyNumber().SetCanBeTaggedValue(true), dst);
}
break;

Expand Down Expand Up @@ -4874,7 +4878,7 @@ GlobOpt::ValueNumberDst(IR::Instr **pInstr, Value *src1Val, Value *src2Val)
{
valueType = ValueType::Number;
}
return CreateDstUntransferredValue(valueType, instr, src1Val, src2Val);
return CreateDstUntransferredValue(valueType.SetCanBeTaggedValue(true), instr, src1Val, src2Val);
}

case Js::OpCode::Add_A:
Expand Down Expand Up @@ -4908,12 +4912,12 @@ GlobOpt::ValueNumberDst(IR::Instr **pInstr, Value *src1Val, Value *src2Val)
{
// If one of them is a float, the result probably is a float instead of just int
// but should always be a number.
valueType = ValueType::Float;
valueType = ValueType::Float.SetCanBeTaggedValue(true);
}
else
{
// Could be int, could be number
valueType = ValueType::Number;
valueType = ValueType::Number.SetCanBeTaggedValue(true);
}
}
else if (src1ValueInfo->IsLikelyFloat() || src2ValueInfo->IsLikelyFloat())
Expand All @@ -4937,7 +4941,7 @@ GlobOpt::ValueNumberDst(IR::Instr **pInstr, Value *src1Val, Value *src2Val)
&& (src2Val && src2ValueInfo->IsNotString() && src2ValueInfo->IsPrimitive()))
{
// If src1 and src2 are not strings and primitive, add should yield a number.
valueType = ValueType::Number;
valueType = ValueType::Number.SetCanBeTaggedValue(true);
}
else if((src1Val && src1ValueInfo->IsLikelyString()) || (src2Val && src2ValueInfo->IsLikelyString()))
{
Expand All @@ -4958,7 +4962,7 @@ GlobOpt::ValueNumberDst(IR::Instr **pInstr, Value *src1Val, Value *src2Val)
ValueType divValueType = GetDivValueType(instr, src1Val, src2Val, false);
if (divValueType.IsLikelyInt() || divValueType.IsFloat())
{
return CreateDstUntransferredValue(divValueType, instr, src1Val, src2Val);
return CreateDstUntransferredValue(divValueType.SetCanBeTaggedValue(true), instr, src1Val, src2Val);
}
}
// fall-through
Expand Down Expand Up @@ -4990,11 +4994,11 @@ GlobOpt::ValueNumberDst(IR::Instr **pInstr, Value *src1Val, Value *src2Val)
// This should ideally be NewNumberAndLikelyFloatValue since we know the result is a number but not sure if it will
// be a float value. However, that Number/LikelyFloat value type doesn't exist currently and all the necessary
// checks are done for float values (tagged int checks, etc.) so it's sufficient to just create a float value here.
valueType = ValueType::Float;
valueType = ValueType::Float.SetCanBeTaggedValue(true);
}
else
{
valueType = ValueType::Number;
valueType = ValueType::Number.SetCanBeTaggedValue(true);
}

return CreateDstUntransferredValue(valueType, instr, src1Val, src2Val);
Expand Down
17 changes: 13 additions & 4 deletions lib/Backend/GlobOptFields.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,17 @@ GlobOpt::KillLiveElems(IR::IndirOpnd * indirOpnd, BVSparse<JitArenaAllocator> *
this->KillAllFields(bv); // This also kills all property type values, as the same bit-vector tracks those stack syms
SetAnyPropertyMayBeWrittenTo();
}
else if (inGlobOpt && indexOpnd && !indexOpnd->GetValueType().IsInt() && !currentBlock->globOptData.IsInt32TypeSpecialized(indexOpnd->m_sym))
else if (inGlobOpt)
{
// Write/delete to a non-integer numeric index can't alias a name on the RHS of a dot, but it change object layout
this->KillAllObjectTypes(bv);
Value * indexValue = indexOpnd ? this->currentBlock->globOptData.FindValue(indexOpnd->GetSym()) : nullptr;
ValueInfo * indexValueInfo = indexValue ? indexValue->GetValueInfo() : nullptr;
int indexLowerBound = 0;

if (indirOpnd->GetOffset() < 0 || (indexOpnd && (!indexValueInfo || !indexValueInfo->TryGetIntConstantLowerBound(&indexLowerBound, false) || indexLowerBound < 0)))
{
// Write/delete to a non-integer numeric index can't alias a name on the RHS of a dot, but it change object layout
this->KillAllObjectTypes(bv);
}
}
}

Expand Down Expand Up @@ -487,7 +494,9 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
case Js::OpCode::NewScObjectNoCtor:
if (inGlobOpt)
{
KillObjectHeaderInlinedTypeSyms(this->currentBlock, false);
// Opcodes that make an object into a prototype may break object-header-inlining and final type opt.
// Kill all known object layouts.
KillAllObjectTypes(bv);
}
break;

Expand Down
2 changes: 1 addition & 1 deletion lib/Backend/JITType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ JITType::BuildFromJsType(__in Js::Type * jsType, __out JITType * jitType)

Js::DynamicTypeHandler * handler = dynamicType->GetTypeHandler();
data->handler.isObjectHeaderInlinedTypeHandler = handler->IsObjectHeaderInlinedTypeHandler();
data->handler.isLocked = handler->GetIsLocked();
data->handler.flags = handler->GetFlags();
data->handler.inlineSlotCapacity = handler->GetInlineSlotCapacity();
data->handler.offsetOfInlineSlots = handler->GetOffsetOfInlineSlots();
data->handler.slotCapacity = handler->GetSlotCapacity();
Expand Down
8 changes: 7 additions & 1 deletion lib/Backend/JITTypeHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,13 @@ JITTypeHandler::IsObjectHeaderInlinedTypeHandler() const
bool
JITTypeHandler::IsLocked() const
{
return m_data.isLocked != FALSE;
return Js::DynamicTypeHandler::GetIsLocked(m_data.flags);
}

bool
JITTypeHandler::IsPrototype() const
{
return Js::DynamicTypeHandler::GetIsPrototype(m_data.flags);
}

uint16
Expand Down
1 change: 1 addition & 0 deletions lib/Backend/JITTypeHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class JITTypeHandler

bool IsObjectHeaderInlinedTypeHandler() const;
bool IsLocked() const;
bool IsPrototype() const;

uint16 GetInlineSlotCapacity() const;
uint16 GetOffsetOfInlineSlots() const;
Expand Down
27 changes: 25 additions & 2 deletions lib/Backend/Lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6223,7 +6223,7 @@ Lowerer::GenerateLdFldWithCachedType(IR::Instr * instrLdFld, bool* continueAsHel

// Load the value from the slot, getting the slot ID from the cache.
uint16 index = propertySymOpnd->GetSlotIndex();
Assert(index != -1);
AssertOrFailFast(index != (uint16)-1);

if (opndSlotArray->IsRegOpnd())
{
Expand Down Expand Up @@ -7204,7 +7204,7 @@ Lowerer::GenerateDirectFieldStore(IR::Instr* instrStFld, IR::PropertySymOpnd* pr

// Store the value to the slot, getting the slot index from the cache.
uint16 index = propertySymOpnd->GetSlotIndex();
Assert(index != -1);
AssertOrFailFast(index != (uint16)-1);

#if defined(RECYCLER_WRITE_BARRIER_JIT) && (defined(_M_IX86) || defined(_M_AMD64))
if (opndSlotArray->IsRegOpnd())
Expand Down Expand Up @@ -7353,6 +7353,19 @@ Lowerer::GenerateStFldWithCachedType(IR::Instr *instrStFld, bool* continueAsHelp
{
Assert(labelTypeCheckFailed == nullptr && labelBothTypeChecksFailed == nullptr);
AssertMsg(!instrStFld->HasBailOutInfo(), "Why does a direct field store have bailout?");

if (propertySymOpnd->HasInitialType() && propertySymOpnd->HasFinalType())
{
bool isPrototypeTypeHandler = propertySymOpnd->GetInitialType()->GetTypeHandler()->IsPrototype();
if (isPrototypeTypeHandler)
{
LoadScriptContext(instrStFld);
m_lowererMD.LoadHelperArgument(instrStFld, IR::IntConstOpnd::New(propertySymOpnd->GetPropertyId(), TyInt32, m_func, true));
IR::Instr * invalidateCallInstr = IR::Instr::New(Js::OpCode::Call, m_func);
instrStFld->InsertBefore(invalidateCallInstr);
m_lowererMD.ChangeToHelperCall(invalidateCallInstr, IR::HelperInvalidateProtoCaches);
}
}
instrStFld->Remove();
return true;
}
Expand Down Expand Up @@ -8177,6 +8190,16 @@ Lowerer::GenerateFieldStoreWithTypeChange(IR::Instr * instrStFld, IR::PropertySy

// Now do the store.
GenerateDirectFieldStore(instrStFld, propertySymOpnd);

bool isPrototypeTypeHandler = initialType->GetTypeHandler()->IsPrototype();
if (isPrototypeTypeHandler)
{
LoadScriptContext(instrStFld);
m_lowererMD.LoadHelperArgument(instrStFld, IR::IntConstOpnd::New(propertySymOpnd->GetPropertyId(), TyInt32, m_func, true));
IR::Instr * invalidateCallInstr = IR::Instr::New(Js::OpCode::Call, m_func);
instrStFld->InsertBefore(invalidateCallInstr);
m_lowererMD.ChangeToHelperCall(invalidateCallInstr, IR::HelperInvalidateProtoCaches);
}
}

bool
Expand Down
2 changes: 1 addition & 1 deletion lib/Common/ChakraCoreVersion.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// ChakraCore version number definitions (used in ChakraCore binary metadata)
#define CHAKRA_CORE_MAJOR_VERSION 1
#define CHAKRA_CORE_MINOR_VERSION 11
#define CHAKRA_CORE_PATCH_VERSION 7
#define CHAKRA_CORE_PATCH_VERSION 8
#define CHAKRA_CORE_VERSION_RELEASE_QFE 0 // Redundant with PATCH_VERSION. Keep this value set to 0.

// -------------
Expand Down
2 changes: 1 addition & 1 deletion lib/JITIDL/JITTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ typedef IDL_DEF([ref]) PSCRIPTCONTEXT_HANDLE * PPSCRIPTCONTEXT_HANDLE;
typedef struct TypeHandlerIDL
{
IDL_Field(boolean) isObjectHeaderInlinedTypeHandler;
IDL_Field(boolean) isLocked;
IDL_Field(unsigned char) flags;

IDL_Field(unsigned short) inlineSlotCapacity;
IDL_Field(unsigned short) offsetOfInlineSlots;
Expand Down
5 changes: 5 additions & 0 deletions lib/Runtime/Language/JavascriptOperators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9582,6 +9582,11 @@ using namespace Js;

Var result = CALL_ENTRYPOINT(threadContext, marshalledFunction->GetEntryPoint(), function, CallInfo(flags, 2), thisVar, putValue);
Assert(result);

// Set implicit call flags so we bail out if we're trying to propagate the stored value forward. We can't count on the getter/setter
// to produce the stored value on a LdFld.
threadContext->AddImplicitCallFlags(ImplicitCall_Accessor);

return nullptr;
});
}
Expand Down
4 changes: 4 additions & 0 deletions lib/Runtime/Library/JavascriptRegExpConstructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,10 @@ namespace Js
EnsureValues(); // The last match info relies on the last input. Use it before it is changed.
this->lastInput = tempInput;
}

// Set implicit call flags since we are not necessarily making the original stored value available on re-load
// and are killing the store that backs two exposed properties.
this->GetScriptContext()->GetThreadContext()->AddImplicitCallFlags(ImplicitCall_Accessor);
*result = true;
return true;
case PropertyIds::lastMatch:
Expand Down
2 changes: 1 addition & 1 deletion lib/Runtime/Types/DictionaryTypeHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ namespace Js
PropertyString* propertyString = scriptContext->GetPropertyString(*propertyId);
*propertyStringName = propertyString;
T dataSlot = descriptor.template GetDataPropertyIndex<false>();
if (dataSlot != NoSlots && (attribs & PropertyWritable))
if (dataSlot != NoSlots && (attribs & PropertyWritable) && type == typeToEnumerate)
{
PropertyValueInfo::SetCacheInfo(info, propertyString, propertyString->GetLdElemInlineCache(), false);
SetPropertyValueInfo(info, instance, dataSlot, &descriptor);
Expand Down
2 changes: 1 addition & 1 deletion lib/Runtime/Types/SimpleTypeHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ namespace Js
*propertyStringName = propStr;

PropertyValueInfo::SetCacheInfo(info, propStr, propStr->GetLdElemInlineCache(), false);
if ((attribs & PropertyWritable) == PropertyWritable)
if ((attribs & PropertyWritable) == PropertyWritable && type == typeToEnumerate)
{
PropertyValueInfo::Set(info, instance, index, attribs);
}
Expand Down
8 changes: 6 additions & 2 deletions lib/Runtime/Types/TypeHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,13 +348,17 @@ namespace Js
(v) Seal
(vi) Freeze
*/
bool GetIsLocked() const { return (this->flags & IsLockedFlag) != 0; }
bool GetIsLocked() const { return GetIsLocked(this->flags); }
static bool GetIsLocked(byte flags) { return (flags & IsLockedFlag) != 0; }

bool GetIsShared() const { return (this->flags & IsSharedFlag) != 0; }
bool GetMayBecomeShared() const { return (this->flags & MayBecomeSharedFlag) != 0; }
bool GetIsOrMayBecomeShared() const { return (this->flags & (MayBecomeSharedFlag | IsSharedFlag)) != 0; }
bool GetHasKnownSlot0() const { return (this->flags & HasKnownSlot0Flag) != 0; }
bool GetIsPrototype() const { return (this->flags & IsPrototypeFlag) != 0; }

bool GetIsPrototype() const { return GetIsPrototype(this->flags); }
static bool GetIsPrototype(byte flags) { return (flags & IsPrototypeFlag) != 0; }

bool GetIsInlineSlotCapacityLocked() const { return (this->propertyTypes & PropertyTypesInlineSlotCapacityLocked) != 0; }

void LockTypeHandler() { Assert(IsLockable()); SetFlags(IsLockedFlag); }
Expand Down