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

[JSC] Inline op_to_this for global object case #15134

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
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