Skip to content

Commit

Permalink
[JSC] Inline op_to_this for global object case
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=258343
rdar://problem/111089057

Reviewed by Alexey Shvayka.

This patch inlines non-object-allocating simple ToThis operation in DFG and FTL.
And we drop OverridesToThis bit, which is no longer necessary.

* Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::isToThisAnIdentity):
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:
* Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileToThis):
* Source/JavaScriptCore/runtime/JSBigInt.h:
* Source/JavaScriptCore/runtime/JSCast.h:
* Source/JavaScriptCore/runtime/JSScope.h:
* Source/JavaScriptCore/runtime/JSString.h:
* Source/JavaScriptCore/runtime/JSType.h:
* Source/JavaScriptCore/runtime/JSTypeInfo.h:
(JSC::TypeInfo::perCellBit):
(JSC::TypeInfo::overridesToThis const): Deleted.
* Source/JavaScriptCore/runtime/Symbol.h:

Canonical link: https://commits.webkit.org/265373@main
  • Loading branch information
Constellation committed Jun 21, 2023
1 parent a91a550 commit 5b9fce6
Show file tree
Hide file tree
Showing 10 changed files with 46 additions and 33 deletions.
2 changes: 1 addition & 1 deletion Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ inline ToThisResult isToThisAnIdentity(ECMAMode ecmaMode, AbstractValue& valueFo
// We don't need to worry about strings/symbols here since either:
// 1) We are in strict mode and strings/symbols are not wrapped
// 2) The AI has proven that the type of this is a subtype of object
if (type.isObject() && type.overridesToThis())
if (type.isObject() && (FirstScopeType <= type.type() && type.type() <= LastScopeType))
overridesToThis = true;

// If all the structures are JSScope's ones, we know the details of JSScope::toThis() operation.
Expand Down
22 changes: 14 additions & 8 deletions Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15087,20 +15087,26 @@ void SpeculativeJIT::compileToThis(Node* node)

JumpList slowCases;
slowCases.append(branchIfNotCell(thisValueRegs));
slowCases.append(
branchTest8(
NonZero,
Address(thisValueRegs.payloadGPR(), JSCell::typeInfoFlagsOffset()),
TrustedImm32(OverridesToThis)));
slowCases.append(branchIfNotObject(thisValueRegs.payloadGPR()));

moveValueRegs(thisValueRegs, tempRegs);
auto notScope = branchIfNotType(thisValueRegs.payloadGPR(), JSC::JSTypeRange { JSType(FirstScopeType), JSType(LastScopeType) });
if (node->ecmaMode().isStrict())
moveTrustedValue(jsUndefined(), tempRegs);
else {
loadLinkableConstant(LinkableConstant::globalObject(*this, node), tempRegs.payloadGPR());
loadPtr(Address(tempRegs.payloadGPR(), JSGlobalObject::offsetOfGlobalThis()), tempRegs.payloadGPR());
#if USE(JSVALUE32_64)
move(TrustedImm32(JSValue::CellTag), tempRegs.tagGPR());
#endif
}

J_JITOperation_GJ function;
auto function = &operationToThis;
if (node->ecmaMode().isStrict())
function = operationToThisStrict;
else
function = operationToThis;
addSlowPathGenerator(slowPathCall(slowCases, this, function, tempRegs, LinkableConstant::globalObject(*this, node), thisValueRegs));

notScope.link(this);
jsValueResult(tempRegs, node);
}

Expand Down
40 changes: 23 additions & 17 deletions Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2307,33 +2307,39 @@ class LowerDFGToB3 {
JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);

LValue value = lowJSValue(m_node->child1());

LBasicBlock isCellCase = m_out.newBlock();
LBasicBlock isObjectCase = m_out.newBlock();
LBasicBlock scopeCase = m_out.newBlock();
LBasicBlock slowCase = m_out.newBlock();
LBasicBlock continuation = m_out.newBlock();

m_out.branch(
isCell(value, provenType(m_node->child1())), usually(isCellCase), rarely(slowCase));

LBasicBlock lastNext = m_out.appendTo(isCellCase, slowCase);

m_out.branch(isCell(value, provenType(m_node->child1())), usually(isCellCase), rarely(slowCase));

LBasicBlock lastNext = m_out.appendTo(isCellCase, isObjectCase);
m_out.branch(isObject(value, provenType(m_node->child1()) & SpecCellCheck), usually(isObjectCase), rarely(slowCase));

m_out.appendTo(isObjectCase, scopeCase);
ValueFromBlock fastResult = m_out.anchor(value);
m_out.branch(
m_out.testIsZero32(
m_out.load8ZeroExt32(value, m_heaps.JSCell_typeInfoFlags),
m_out.constInt32(OverridesToThis)),
usually(continuation), rarely(slowCase));

m_out.branch(isType(value, JSTypeRange { JSType(FirstScopeType), JSType(LastScopeType) }), unsure(scopeCase), unsure(continuation));

m_out.appendTo(scopeCase, slowCase);
ValueFromBlock scopeResult;
if (m_node->ecmaMode().isStrict())
scopeResult = m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined())));
else
scopeResult = m_out.anchor(m_out.loadPtr(m_out.absolute(globalObject->addressOfGlobalThis())));
m_out.jump(continuation);

m_out.appendTo(slowCase, continuation);
J_JITOperation_GJ function;
auto function = &operationToThis;
if (m_node->ecmaMode().isStrict())
function = operationToThisStrict;
else
function = operationToThis;
ValueFromBlock slowResult = m_out.anchor(vmCall(Int64, function, weakPointer(globalObject), value));
m_out.jump(continuation);

m_out.appendTo(continuation, lastNext);
setJSValue(m_out.phi(Int64, fastResult, slowResult));
setJSValue(m_out.phi(Int64, fastResult, scopeResult, slowResult));
}

void compileValueAdd()
Expand Down
2 changes: 1 addition & 1 deletion Source/JavaScriptCore/runtime/JSBigInt.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class JSBigInt final : public JSCell {
using Base = JSCell;
using Digit = UCPURegister;

static constexpr unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal | OverridesToThis | OverridesPut;
static constexpr unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal | OverridesPut;
friend class CachedBigInt;

DECLARE_VISIT_CHILDREN;
Expand Down
2 changes: 1 addition & 1 deletion Source/JavaScriptCore/runtime/JSCast.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ using JSResizableOrGrowableSharedBigUint64Array = JSGenericResizableOrGrowableSh
macro(JSModuleEnvironment, JSType::ModuleEnvironmentType, JSType::ModuleEnvironmentType) \
macro(JSLexicalEnvironment, JSType::LexicalEnvironmentType, JSType::ModuleEnvironmentType) \
macro(JSSymbolTableObject, JSType::GlobalObjectType, JSType::ModuleEnvironmentType) \
macro(JSScope, JSType::GlobalObjectType, JSType::WithScopeType) \
macro(JSScope, FirstScopeType, LastScopeType) \
macro(StringObject, JSType::StringObjectType, JSType::DerivedStringObjectType) \
macro(ShadowRealmObject, JSType::ShadowRealmType, JSType::ShadowRealmType) \
macro(JSDataView, JSType::DataViewType, JSType::DataViewType) \
Expand Down
2 changes: 1 addition & 1 deletion Source/JavaScriptCore/runtime/JSScope.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ using TDZEnvironment = HashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash>;
class JSScope : public JSNonFinalObject {
public:
using Base = JSNonFinalObject;
static constexpr unsigned StructureFlags = Base::StructureFlags | OverridesToThis;
static constexpr unsigned StructureFlags = Base::StructureFlags;

template<typename, SubspaceAccess>
static void subspaceFor(VM&)
Expand Down
2 changes: 1 addition & 1 deletion Source/JavaScriptCore/runtime/JSString.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class JSString : public JSCell {
// FIXME: https://bugs.webkit.org/show_bug.cgi?id=212956
// Do we really need InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero?
// FIXME: https://bugs.webkit.org/show_bug.cgi?id=212958
static constexpr unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | StructureIsImmortal | OverridesToThis | OverridesPut;
static constexpr unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | StructureIsImmortal | OverridesPut;

static constexpr bool needsDestruction = true;
static ALWAYS_INLINE void destroy(JSCell* cell)
Expand Down
3 changes: 3 additions & 0 deletions Source/JavaScriptCore/runtime/JSType.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ static constexpr uint32_t LastTypedArrayTypeExcludingDataView = LastTypedArrayTy
static constexpr uint32_t FirstObjectType = ObjectType;
static constexpr uint32_t LastObjectType = MaxJSType;

static constexpr uint32_t FirstScopeType = GlobalObjectType;
static constexpr uint32_t LastScopeType = WithScopeType;

static constexpr uint32_t NumberOfTypedArrayTypes = LastTypedArrayType - FirstTypedArrayType + 1;
static constexpr uint32_t NumberOfTypedArrayTypesExcludingDataView = NumberOfTypedArrayTypes - 1;
static constexpr uint32_t NumberOfTypedArrayTypesExcludingBigIntArraysAndDataView = NumberOfTypedArrayTypes - 3;
Expand Down
2 changes: 0 additions & 2 deletions Source/JavaScriptCore/runtime/JSTypeInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ static constexpr unsigned MasqueradesAsUndefined = 1; // WebCore uses Masquerade
static constexpr unsigned ImplementsDefaultHasInstance = 1 << 1;
static constexpr unsigned OverridesGetCallData = 1 << 2; // Need this flag if you implement [[Callable]] interface, which means overriding getCallData. The object may not be callable since getCallData can say it is not callable.
static constexpr unsigned OverridesGetOwnPropertySlot = 1 << 3;
static constexpr unsigned OverridesToThis = 1 << 4; // If this is false then this returns something other than 'this'. Non-object cells that are visible to JS have this set as do some exotic objects.
static constexpr unsigned HasStaticPropertyTable = 1 << 5;
static constexpr unsigned TypeInfoPerCellBit = 1 << 7; // Unlike other inline flags, this will only be set on the cell itself and will not be set on the Structure.

Expand Down Expand Up @@ -99,7 +98,6 @@ class TypeInfo {
static bool overridesGetOwnPropertySlot(InlineTypeFlags flags) { return flags & OverridesGetOwnPropertySlot; }
static bool hasStaticPropertyTable(InlineTypeFlags flags) { return flags & HasStaticPropertyTable; }
static bool perCellBit(InlineTypeFlags flags) { return flags & TypeInfoPerCellBit; }
bool overridesToThis() const { return isSetOnFlags1<OverridesToThis>(); }
bool structureIsImmortal() const { return isSetOnFlags2<StructureIsImmortal>(); }
bool overridesGetOwnPropertyNames() const { return isSetOnFlags2<OverridesGetOwnPropertyNames>(); }
bool overridesGetOwnSpecialPropertyNames() const { return isSetOnFlags2<OverridesGetOwnSpecialPropertyNames>(); }
Expand Down
2 changes: 1 addition & 1 deletion Source/JavaScriptCore/runtime/Symbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ namespace JSC {
class Symbol final : public JSCell {
public:
typedef JSCell Base;
static constexpr unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal | OverridesToThis | OverridesPut;
static constexpr unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal | OverridesPut;

DECLARE_EXPORT_INFO;

Expand Down

0 comments on commit 5b9fce6

Please sign in to comment.