Skip to content

Commit

Permalink
[JSC] Bracket compound assignment should resolve property key at most…
Browse files Browse the repository at this point in the history
… once

https://bugs.webkit.org/show_bug.cgi?id=270563

Reviewed by Yusuke Suzuki.

Just as we did for `obj[prop]++` (275531@main), we need to make sure `obj[prop] += 1;` doesn't double-evaluate `prop`.

The existing solution, however, is not of reasonable performance when `prop` is a Number value -- it is, of course,
unacceptable for `arr[i]++` to be slow. To this end, this patch also introduces OpToPropertyKeyOrNumber, which will
return numbers unchanged, just as it does with strings and symbols.

* JSTests/test262/expectations.yaml: Mark 22 test cases as passing.
* Source/JavaScriptCore/bytecode/BytecodeList.rb:
* Source/JavaScriptCore/bytecode/BytecodeUseDef.cpp:
* Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:
* Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h:
* Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp:
(JSC::PostfixNode::emitBracket):
(JSC::PrefixNode::emitBracket):
(JSC::ReadModifyBracketNode::emitBytecode):
(JSC::ShortCircuitReadModifyBracketNode::emitBytecode):
(JSC::ObjectPatternNode::bindValue const):
* Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h:
* Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:
* Source/JavaScriptCore/dfg/DFGClobberize.h:
* Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp:
* Source/JavaScriptCore/dfg/DFGDoesGC.cpp:
* Source/JavaScriptCore/dfg/DFGFixupPhase.cpp:
* Source/JavaScriptCore/dfg/DFGNode.h:
* Source/JavaScriptCore/dfg/DFGNodeType.h:
* Source/JavaScriptCore/dfg/DFGOperations.cpp:
* Source/JavaScriptCore/dfg/DFGOperations.h:
* Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp:
* Source/JavaScriptCore/dfg/DFGSafeToExecute.h:
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h:
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp:
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp:
* Source/JavaScriptCore/ftl/FTLCapabilities.cpp:
* Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:
* Source/JavaScriptCore/jit/JIT.cpp:
* Source/JavaScriptCore/jit/JIT.h:
* Source/JavaScriptCore/jit/JITOpcodes.cpp:
* Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm:
* Source/JavaScriptCore/llint/LowLevelInterpreter64.asm:
* Source/JavaScriptCore/runtime/CommonSlowPaths.cpp:
* Source/JavaScriptCore/runtime/CommonSlowPaths.h:

Canonical link: https://commits.webkit.org/276014@main
  • Loading branch information
rkirsling committed Mar 13, 2024
1 parent 0ea5e70 commit 3645b1d
Show file tree
Hide file tree
Showing 31 changed files with 260 additions and 47 deletions.
33 changes: 0 additions & 33 deletions JSTests/test262/expectations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -959,39 +959,6 @@ test/language/expressions/class/elements/nested-direct-eval-err-contains-argumen
test/language/expressions/class/elements/nested-private-direct-eval-err-contains-arguments.js:
default: 'Test262Error: Expected a SyntaxError but got a ReferenceError'
strict mode: 'Test262Error: Expected a SyntaxError but got a ReferenceError'
test/language/expressions/compound-assignment/S11.13.2_A7.10_T4.js:
default: 'Test262Error: Expected true but got false'
strict mode: 'Test262Error: Expected true but got false'
test/language/expressions/compound-assignment/S11.13.2_A7.11_T4.js:
default: 'Test262Error: Expected true but got false'
strict mode: 'Test262Error: Expected true but got false'
test/language/expressions/compound-assignment/S11.13.2_A7.1_T4.js:
default: 'Test262Error: Expected true but got false'
strict mode: 'Test262Error: Expected true but got false'
test/language/expressions/compound-assignment/S11.13.2_A7.2_T4.js:
default: 'Test262Error: Expected true but got false'
strict mode: 'Test262Error: Expected true but got false'
test/language/expressions/compound-assignment/S11.13.2_A7.3_T4.js:
default: 'Test262Error: Expected true but got false'
strict mode: 'Test262Error: Expected true but got false'
test/language/expressions/compound-assignment/S11.13.2_A7.4_T4.js:
default: 'Test262Error: Expected true but got false'
strict mode: 'Test262Error: Expected true but got false'
test/language/expressions/compound-assignment/S11.13.2_A7.5_T4.js:
default: 'Test262Error: Expected true but got false'
strict mode: 'Test262Error: Expected true but got false'
test/language/expressions/compound-assignment/S11.13.2_A7.6_T4.js:
default: 'Test262Error: Expected true but got false'
strict mode: 'Test262Error: Expected true but got false'
test/language/expressions/compound-assignment/S11.13.2_A7.7_T4.js:
default: 'Test262Error: Expected true but got false'
strict mode: 'Test262Error: Expected true but got false'
test/language/expressions/compound-assignment/S11.13.2_A7.8_T4.js:
default: 'Test262Error: Expected true but got false'
strict mode: 'Test262Error: Expected true but got false'
test/language/expressions/compound-assignment/S11.13.2_A7.9_T4.js:
default: 'Test262Error: Expected true but got false'
strict mode: 'Test262Error: Expected true but got false'
test/language/expressions/dynamic-import/for-await-resolution-and-error-agen-yield.js:
default: 'Test262:AsyncTestFailure:Test262Error: Test262Error: f Expected SameValue(«null», «foo») to be true'
strict mode: 'Test262:AsyncTestFailure:Test262Error: Test262Error: f Expected SameValue(«null», «foo») to be true'
Expand Down
6 changes: 6 additions & 0 deletions Source/JavaScriptCore/bytecode/BytecodeList.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,12 @@
src: VirtualRegister,
}

op :to_property_key_or_number,
args: {
dst: VirtualRegister,
src: VirtualRegister,
}

op :put_to_arguments,
args: {
arguments: VirtualRegister,
Expand Down
2 changes: 2 additions & 0 deletions Source/JavaScriptCore/bytecode/BytecodeUseDef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ void computeUsesForBytecodeIndexImpl(const JSInstruction* instruction, Checkpoin
USES(OpGetFromScope, scope)
USES(OpToPrimitive, src)
USES(OpToPropertyKey, src)
USES(OpToPropertyKeyOrNumber, src)
USES(OpTryGetById, base)
USES(OpGetById, base)
USES(OpGetByIdDirect, base)
Expand Down Expand Up @@ -440,6 +441,7 @@ void computeDefsForBytecodeIndexImpl(unsigned numVars, const JSInstruction* inst
DEFS(OpStrcat, dst)
DEFS(OpToPrimitive, dst)
DEFS(OpToPropertyKey, dst)
DEFS(OpToPropertyKeyOrNumber, dst)
DEFS(OpCreateThis, dst)
DEFS(OpCreatePromise, dst)
DEFS(OpCreateGenerator, dst)
Expand Down
6 changes: 6 additions & 0 deletions Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3913,6 +3913,12 @@ RegisterID* BytecodeGenerator::emitToPropertyKey(RegisterID* dst, RegisterID* sr
return dst;
}

RegisterID* BytecodeGenerator::emitToPropertyKeyOrNumber(RegisterID* dst, RegisterID* src)
{
OpToPropertyKeyOrNumber::emit(this, dst, src);
return dst;
}

void BytecodeGenerator::emitGetScope()
{
OpGetScope::emit(this, scopeRegister());
Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,7 @@ namespace JSC {
RegisterID* emitStrcat(RegisterID* dst, RegisterID* src, int count);
void emitToPrimitive(RegisterID* dst, RegisterID* src);
RegisterID* emitToPropertyKey(RegisterID* dst, RegisterID* src);
RegisterID* emitToPropertyKeyOrNumber(RegisterID* dst, RegisterID* src);

ResolveType resolveType();
RegisterID* emitResolveConstantLocal(RegisterID* dst, const Variable&);
Expand Down
20 changes: 16 additions & 4 deletions Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2581,7 +2581,7 @@ RegisterID* PostfixNode::emitBracket(BytecodeGenerator& generator, RegisterID* d
// Never double-evaluate the subscript expression;
// don't even evaluate it once if the base isn't subscriptable.
generator.emitRequireObjectCoercible(base.get(), "Cannot access property of undefined or null"_s);
property = generator.emitToPropertyKey(generator.newTemporary(), property.get());
property = generator.emitToPropertyKeyOrNumber(generator.newTemporary(), property.get());
}

generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
Expand Down Expand Up @@ -2877,7 +2877,7 @@ RegisterID* PrefixNode::emitBracket(BytecodeGenerator& generator, RegisterID* ds
// Never double-evaluate the subscript expression;
// don't even evaluate it once if the base isn't subscriptable.
generator.emitRequireObjectCoercible(base.get(), "Cannot access property of undefined or null"_s);
property = generator.emitToPropertyKey(generator.newTemporary(), property.get());
property = generator.emitToPropertyKeyOrNumber(generator.newTemporary(), property.get());
}
RefPtr<RegisterID> propDst = generator.tempDestination(dst);

Expand Down Expand Up @@ -3952,6 +3952,12 @@ RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, Re
{
RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
RefPtr<RegisterID> property = generator.emitNodeForLeftHandSideForProperty(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
if (!m_subscript->isNumber() && !m_subscript->isString()) {
// Never double-evaluate the subscript expression;
// don't even evaluate it once if the base isn't subscriptable.
generator.emitRequireObjectCoercible(base.get(), "Cannot access property of undefined or null"_s);
property = generator.emitToPropertyKeyOrNumber(generator.newTemporary(), property.get());
}

generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
RefPtr<RegisterID> value;
Expand Down Expand Up @@ -3979,8 +3985,14 @@ RegisterID* ShortCircuitReadModifyBracketNode::emitBytecode(BytecodeGenerator& g
{
RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
RefPtr<RegisterID> property = generator.emitNodeForLeftHandSideForProperty(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
RefPtr<RegisterID> thisValue;
if (!m_subscript->isNumber() && !m_subscript->isString()) {
// Never double-evaluate the subscript expression;
// don't even evaluate it once if the base isn't subscriptable.
generator.emitRequireObjectCoercible(base.get(), "Cannot access property of undefined or null"_s);
property = generator.emitToPropertyKeyOrNumber(generator.newTemporary(), property.get());
}

RefPtr<RegisterID> thisValue;
RefPtr<RegisterID> result = generator.tempDestination(dst);

generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
Expand Down Expand Up @@ -5685,7 +5697,7 @@ void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs)
// And @copyDataProperties performs ToPropertyKey internally.
// And for Number case, passing it to GetByVal is better for performance.
if (!target.propertyExpression->isNumber() && !target.propertyExpression->isString())
propertyName = generator.emitToPropertyKey(propertyName.get(), propertyName.get());
propertyName = generator.emitToPropertyKeyOrNumber(propertyName.get(), propertyName.get());
} else
propertyName = generator.emitNodeForProperty(target.propertyExpression);
generator.emitGetByVal(temp.get(), rhs, propertyName.get());
Expand Down
9 changes: 9 additions & 0 deletions Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Original file line number Diff line number Diff line change
Expand Up @@ -2948,6 +2948,15 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
break;
}

case ToPropertyKeyOrNumber: {
JSValue childConst = forNode(node->child1()).value();
if (childConst && childConst.isNumber()) {
didFoldClobberWorld();
setConstant(node, childConst);
break;
}
FALLTHROUGH;
}
case ToPropertyKey: {
if (!(forNode(node->child1()).m_type & ~(SpecString | SpecSymbol))) {
m_state.setShouldTryConstantFolding(true);
Expand Down
7 changes: 7 additions & 0 deletions Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6914,6 +6914,13 @@ void ByteCodeParser::parseBlock(unsigned limit)
NEXT_OPCODE(op_to_property_key);
}

case op_to_property_key_or_number: {
auto bytecode = currentInstruction->as<OpToPropertyKeyOrNumber>();
Node* value = get(bytecode.m_src);
set(bytecode.m_dst, addToGraph(ToPropertyKeyOrNumber, value));
NEXT_OPCODE(op_to_property_key_or_number);
}

case op_strcat: {
auto bytecode = currentInstruction->as<OpStrcat>();
int startOperand = bytecode.m_src.offset();
Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/dfg/DFGClobberize.h
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
case CallCustomAccessorSetter:
case ToPrimitive:
case ToPropertyKey:
case ToPropertyKeyOrNumber:
case InByVal:
case InByValMegamorphic:
case EnumeratorInByVal:
Expand Down
9 changes: 9 additions & 0 deletions Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,15 @@ class ConstantFoldingPhase : public Phase {
break;
}

case ToPropertyKeyOrNumber: {
if (m_state.forNode(node->child1()).m_type & ~(SpecFullNumber | SpecString | SpecSymbol))
break;

node->convertToIdentity();
changed = true;
break;
}

case ToThis: {
ToThisResult result = isToThisAnIdentity(node->ecmaMode(), m_state.forNode(node->child1()));
if (result == ToThisResult::Identity) {
Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/dfg/DFGDoesGC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ bool doesGC(Graph& graph, Node* node)
case ToObject:
case ToPrimitive:
case ToPropertyKey:
case ToPropertyKeyOrNumber:
case ToThis:
case TryGetById:
case CreateThis:
Expand Down
23 changes: 22 additions & 1 deletion Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1732,11 +1732,32 @@ class FixupPhase : public Phase {
break;
}

case ToPropertyKeyOrNumber: {
if (node->child1()->shouldSpeculateInt32()) {
fixEdge<Int32Use>(node->child1());
node->convertToIdentity();
return;
}

if (node->child1()->shouldSpeculateInt52()) {
fixEdge<Int52RepUse>(node->child1());
node->convertToIdentity();
node->setResult(NodeResultInt52);
return;
}

if (node->child1()->shouldSpeculateNumber()) {
fixEdge<DoubleRepUse>(node->child1());
node->convertToIdentity();
node->setResult(NodeResultDouble);
return;
}
FALLTHROUGH;
}
case ToPropertyKey: {
if (node->child1()->shouldSpeculateString()) {
fixEdge<StringUse>(node->child1());
node->convertToIdentity();

return;
}

Expand Down
2 changes: 1 addition & 1 deletion Source/JavaScriptCore/dfg/DFGNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,7 @@ struct Node {

void convertToToString()
{
ASSERT(m_op == ToPrimitive || m_op == StringValueOf || m_op == ToPropertyKey);
ASSERT(m_op == ToPrimitive || m_op == StringValueOf || m_op == ToPropertyKey || m_op == ToPropertyKeyOrNumber);
m_op = ToString;
}

Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/dfg/DFGNodeType.h
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ namespace JSC { namespace DFG {
macro(LogicalNot, NodeResultBoolean) \
macro(ToPrimitive, NodeResultJS | NodeMustGenerate) \
macro(ToPropertyKey, NodeResultJS | NodeMustGenerate) \
macro(ToPropertyKeyOrNumber, NodeResultJS | NodeMustGenerate) \
macro(ToString, NodeResultJS | NodeMustGenerate) \
macro(ToNumber, NodeResultJS | NodeMustGenerate) \
macro(ToNumeric, NodeResultJS | NodeMustGenerate) \
Expand Down
10 changes: 10 additions & 0 deletions Source/JavaScriptCore/dfg/DFGOperations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1718,6 +1718,16 @@ JSC_DEFINE_JIT_OPERATION(operationToPropertyKey, EncodedJSValue, (JSGlobalObject
return JSValue::encode(JSValue::decode(value).toPropertyKeyValue(globalObject));
}

JSC_DEFINE_JIT_OPERATION(operationToPropertyKeyOrNumber, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue value))
{
VM& vm = globalObject->vm();
CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
JITOperationPrologueCallFrameTracer tracer(vm, callFrame);

JSValue jsValue = JSValue::decode(value);
return JSValue::encode(jsValue.isNumber() ? jsValue : jsValue.toPropertyKeyValue(globalObject));
}

JSC_DEFINE_JIT_OPERATION(operationToNumber, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue value))
{
VM& vm = globalObject->vm();
Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/dfg/DFGOperations.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ JSC_DECLARE_JIT_OPERATION(operationGetByValObjectString, EncodedJSValue, (JSGlob
JSC_DECLARE_JIT_OPERATION(operationGetByValObjectSymbol, EncodedJSValue, (JSGlobalObject*, JSCell*, JSCell* symbol));
JSC_DECLARE_JIT_OPERATION(operationToPrimitive, EncodedJSValue, (JSGlobalObject*, EncodedJSValue));
JSC_DECLARE_JIT_OPERATION(operationToPropertyKey, EncodedJSValue, (JSGlobalObject*, EncodedJSValue));
JSC_DECLARE_JIT_OPERATION(operationToPropertyKeyOrNumber, EncodedJSValue, (JSGlobalObject*, EncodedJSValue));
JSC_DECLARE_JIT_OPERATION(operationToNumber, EncodedJSValue, (JSGlobalObject*, EncodedJSValue));
JSC_DECLARE_JIT_OPERATION(operationToNumberString, EncodedJSValue, (JSGlobalObject*, JSString*));
JSC_DECLARE_JIT_OPERATION(operationToNumeric, EncodedJSValue, (JSGlobalObject*, EncodedJSValue));
Expand Down
20 changes: 20 additions & 0 deletions Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,13 @@ class PredictionPropagationPhase : public Phase {
break;
}

case ToPropertyKeyOrNumber: {
SpeculatedType child = node->child1()->prediction();
if (child)
changed |= mergePrediction(resultOfToPropertyKeyOrNumber(child));
break;
}

case NormalizeMapKey: {
SpeculatedType prediction = node->child1()->prediction();
if (prediction)
Expand Down Expand Up @@ -1470,6 +1477,7 @@ class PredictionPropagationPhase : public Phase {
case ToThis:
case ToPrimitive:
case ToPropertyKey:
case ToPropertyKeyOrNumber:
case NormalizeMapKey:
case AtomicsAdd:
case AtomicsAnd:
Expand Down Expand Up @@ -1705,6 +1713,18 @@ class PredictionPropagationPhase : public Phase {
return SpecString | SpecSymbol;
}

SpeculatedType resultOfToPropertyKeyOrNumber(SpeculatedType type)
{
// Propagate the prediction of the source directly if already proven to be a property key or number.
if (type && !(type & ~(SpecFullNumber | SpecString | SpecSymbol)))
return type;

if (type & SpecStringObject && m_graph.canOptimizeStringObjectAccess(m_currentNode->origin.semantic))
return mergeSpeculations(type & SpecSymbol, SpecString);

return SpecFullNumber | SpecString | SpecSymbol;
}

Vector<Node*> m_dependentNodes;
Vector<SpeculatedType, 16> m_tupleSpeculations;
Node* m_currentNode;
Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/dfg/DFGSafeToExecute.h
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,7 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node, bool igno
case CallObjectConstructor:
case ToPrimitive:
case ToPropertyKey:
case ToPropertyKeyOrNumber:
case ToNumber:
case ToNumeric:
case ToObject:
Expand Down
29 changes: 29 additions & 0 deletions Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15881,6 +15881,35 @@ void SpeculativeJIT::compileToPropertyKey(Node* node)
jsValueResult(resultRegs, node, DataFormatJSCell, UseChildrenCalledExplicitly);
}

void SpeculativeJIT::compileToPropertyKeyOrNumber(Node* node)
{
DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse, node->child1().useKind());
JSValueOperand argument(this, node->child1());
JSValueRegsTemporary result(this, Reuse, argument);
GPRTemporary temp(this);

JSValueRegs argumentRegs = argument.jsValueRegs();
JSValueRegs resultRegs = result.regs();
GPRReg tempGPR = temp.gpr();

argument.use();

JumpList alreadyPropertyKey;
JumpList slowCases;

alreadyPropertyKey.append(branchIfNumber(argumentRegs, tempGPR));
slowCases.append(branchIfNotCell(argumentRegs));
alreadyPropertyKey.append(branchIfSymbol(argumentRegs.payloadGPR()));
slowCases.append(branchIfNotString(argumentRegs.payloadGPR()));

alreadyPropertyKey.link(this);
moveValueRegs(argumentRegs, resultRegs);

addSlowPathGenerator(slowPathCall(slowCases, this, operationToPropertyKeyOrNumber, resultRegs, LinkableConstant::globalObject(*this, node), argumentRegs));

jsValueResult(resultRegs, node, DataFormatJSCell, UseChildrenCalledExplicitly);
}

void SpeculativeJIT::compileToNumeric(Node* node)
{
DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse, node->child1().useKind());
Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Original file line number Diff line number Diff line change
Expand Up @@ -1625,6 +1625,7 @@ class SpeculativeJIT : public JITCompiler {
void compileNewInternalFieldObject(Node*);
void compileToPrimitive(Node*);
void compileToPropertyKey(Node*);
void compileToPropertyKeyOrNumber(Node*);
void compileToNumeric(Node*);
void compileCallNumberConstructor(Node*);
void compileLogShadowChickenPrologue(Node*);
Expand Down
5 changes: 5 additions & 0 deletions Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3068,6 +3068,11 @@ void SpeculativeJIT::compile(Node* node)
break;
}

case ToPropertyKeyOrNumber: {
compileToPropertyKeyOrNumber(node);
break;
}

case ToNumber: {
switch (node->child1().useKind()) {
case StringUse: {
Expand Down

0 comments on commit 3645b1d

Please sign in to comment.