Diff
Modified: trunk/JSTests/ChangeLog (283094 => 283095)
--- trunk/JSTests/ChangeLog 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/JSTests/ChangeLog 2021-09-27 04:14:23 UTC (rev 283095)
@@ -1,3 +1,14 @@
+2021-09-26 Yusuke Suzuki <ysuz...@apple.com>
+
+ [JSC] Optimize PutByVal with for-in
+ https://bugs.webkit.org/show_bug.cgi?id=230801
+
+ Reviewed by Saam Barati.
+
+ * stress/for-in-sentinel.js: Added.
+ (shouldBe):
+ (test):
+
2021-09-24 Rick Waldron <waldron.r...@gmail.com>
[JSC] Add checkScriptSyntax function to jsc host environment
Added: trunk/JSTests/stress/for-in-sentinel.js (0 => 283095)
--- trunk/JSTests/stress/for-in-sentinel.js (rev 0)
+++ trunk/JSTests/stress/for-in-sentinel.js 2021-09-27 04:14:23 UTC (rev 283095)
@@ -0,0 +1,22 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+var object = {
+ $: 32,
+ test: 33,
+ hey: 34,
+};
+
+function test(object) {
+ var count = 0;
+ for (var i in object) {
+ ++count;
+ }
+ return count;
+}
+noInline(test);
+
+for (var i = 0; i < 1e6; ++i)
+ shouldBe(test(object), 3);
Modified: trunk/Source/_javascript_Core/ChangeLog (283094 => 283095)
--- trunk/Source/_javascript_Core/ChangeLog 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/ChangeLog 2021-09-27 04:14:23 UTC (rev 283095)
@@ -1,3 +1,108 @@
+2021-09-26 Yusuke Suzuki <ysuz...@apple.com>
+
+ [JSC] Optimize PutByVal with for-in
+ https://bugs.webkit.org/show_bug.cgi?id=230801
+
+ Reviewed by Saam Barati.
+
+ We found that some of Speedometer2 subtests are heavily using for-in with PutByVal or the other DFG nodes.
+ And we also found that we are using polluted non-good type for the property names from for-in: String | Other.
+ The reason is that we are returning null when op_enumerator_next finishes instead of string. And this design
+ forces DFG and FTL to return null from EnumeratorNextUpdatePropertyName at the end of iteration. This pollutes
+ the type of property names as String | Other instead of String, and leading to suboptimal DFG nodes.
+
+ In this patch, we add special sentinel string in vm.smallString.sentinelString(). We know that this string cell
+ pointer will be never returned from EnumeratorNextUpdatePropertyName in the normal for-in iteration. This is easy
+ since we are always allocating a JSString when creating JSPropertyNameEnumerator. So this string cell (not the content)
+ is always different from pre-allocated vm.smallString.sentinelString(). So, we use this special string pointer
+ as a sentinel instead of null so that we can avoid polluting return type of EnumeratorNextUpdatePropertyName.
+
+ To check the sentinel in LLInt / Baseline, this patch adds jeq_ptr, which performs cell pointer comparison and do
+ not check string content equality. We do not need to have an implementation in DFG since we already have CompareEqPtr
+ for existing jneq_ptr bytecode.
+
+ We also clean up DFG operation related to PutByVal.
+
+ ----------------------------------------------------------------------------------------------------------------------------------
+ | subtest | ms | ms | b / a | pValue (significance using False Discovery Rate) |
+ ----------------------------------------------------------------------------------------------------------------------------------
+ | Elm-TodoMVC |116.010000 |112.701667 |0.971482 | 0.000000 (significant) |
+ | VueJS-TodoMVC |22.995000 |23.023333 |1.001232 | 0.907086 |
+ | EmberJS-TodoMVC |125.498333 |125.525000 |1.000212 | 0.932546 |
+ | BackboneJS-TodoMVC |45.700000 |45.975000 |1.006018 | 0.084799 |
+ | Preact-TodoMVC |16.681667 |16.610000 |0.995704 | 0.722758 |
+ | AngularJS-TodoMVC |123.753333 |123.740000 |0.999892 | 0.971431 |
+ | Vanilla-ES2015-TodoMVC |61.255000 |61.380000 |1.002041 | 0.300654 |
+ | Inferno-TodoMVC |58.646667 |58.948333 |1.005144 | 0.267611 |
+ | Flight-TodoMVC |73.283333 |72.801667 |0.993427 | 0.207389 |
+ | Angular2-TypeScript-TodoMVC |39.746667 |40.015000 |1.006751 | 0.449821 |
+ | VanillaJS-TodoMVC |50.096667 |49.823333 |0.994544 | 0.162020 |
+ | jQuery-TodoMVC |212.870000 |213.196667 |1.001535 | 0.371944 |
+ | EmberJS-Debug-TodoMVC |331.878333 |332.710000 |1.002506 | 0.094499 |
+ | React-TodoMVC |83.078333 |82.726667 |0.995767 | 0.076143 |
+ | React-Redux-TodoMVC |136.018333 |133.935000 |0.984683 | 0.000000 (significant) |
+ | Vanilla-ES2015-Babel-Webpack-TodoMVC |59.743333 |59.643333 |0.998326 | 0.393671 |
+ ----------------------------------------------------------------------------------------------------------------------------------
+ a mean = 271.75873
+ b mean = 272.45804
+ pValue = 0.0263030803
+ (Bigger means are better.)
+ 1.003 times better
+ Results ARE significant
+
+ * builtins/BuiltinNames.h:
+ * bytecode/BytecodeList.rb:
+ * bytecode/BytecodeUseDef.cpp:
+ (JSC::computeUsesForBytecodeIndexImpl):
+ (JSC::computeDefsForBytecodeIndexImpl):
+ * bytecode/LinkTimeConstant.h:
+ * bytecode/Opcode.h:
+ (JSC::isBranch):
+ * bytecode/PreciseJumpTargetsInlines.h:
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::GenericLabel<JSGeneratorTraits>::setLocation):
+ (JSC::BytecodeGenerator::emitJumpIfSentinelString):
+ * bytecompiler/BytecodeGenerator.h:
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::ForInNode::emitBytecode):
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGCapabilities.cpp:
+ (JSC::DFG::capabilityLevel):
+ * dfg/DFGOperations.cpp:
+ (JSC::DFG::putByVal):
+ (JSC::DFG::putByValInternal):
+ (JSC::DFG::putByValCellInternal):
+ (JSC::DFG::JSC_DEFINE_JIT_OPERATION):
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileEnumeratorNextUpdatePropertyName):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ * jit/JIT.h:
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_jeq_ptr):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_jeq_ptr):
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emit_op_enumerator_next):
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+ * runtime/CommonSlowPaths.cpp:
+ (JSC::JSC_DEFINE_COMMON_SLOW_PATH):
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::init):
+ * runtime/SmallStrings.cpp:
+ (JSC::SmallStrings::initializeCommonStrings):
+ (JSC::SmallStrings::visitStrongReferences):
+ * runtime/SmallStrings.h:
+ (JSC::SmallStrings::sentinelString const):
+
2021-09-26 Commit Queue <commit-qu...@webkit.org>
Unreviewed, reverting r283083 and r283088.
Modified: trunk/Source/_javascript_Core/builtins/BuiltinNames.h (283094 => 283095)
--- trunk/Source/_javascript_Core/builtins/BuiltinNames.h 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/builtins/BuiltinNames.h 2021-09-27 04:14:23 UTC (rev 283095)
@@ -182,7 +182,7 @@
macro(createPrivateSymbol) \
macro(entries) \
macro(outOfLineReactionCounts) \
- macro(emptyPropertyNameEnumerator)
+ macro(emptyPropertyNameEnumerator) \
namespace Symbols {
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.rb (283094 => 283095)
--- trunk/Source/_javascript_Core/bytecode/BytecodeList.rb 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.rb 2021-09-27 04:14:23 UTC (rev 283095)
@@ -762,6 +762,13 @@
targetLabel: BoundLabel,
}
+op :jeq_ptr,
+ args: {
+ value: VirtualRegister,
+ specialPointer: VirtualRegister,
+ targetLabel: BoundLabel,
+ }
+
op :jneq_ptr,
args: {
value: VirtualRegister,
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.cpp (283094 => 283095)
--- trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.cpp 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.cpp 2021-09-27 04:14:23 UTC (rev 283095)
@@ -80,7 +80,6 @@
// No uses.
case op_new_regexp:
case op_debug:
- case op_jneq_ptr:
case op_loop_hint:
case op_jmp:
case op_new_object:
@@ -135,6 +134,9 @@
USES(OpJnstricteq, lhs, rhs)
USES(OpJbelow, lhs, rhs)
USES(OpJbeloweq, lhs, rhs)
+ USES(OpJeqPtr, value, specialPointer)
+ USES(OpJneqPtr, value, specialPointer)
+
USES(OpSetFunctionName, function, name)
USES(OpLogShadowChickenTail, thisValue, scope)
@@ -365,6 +367,7 @@
case op_jneq_null:
case op_jundefined_or_null:
case op_jnundefined_or_null:
+ case op_jeq_ptr:
case op_jneq_ptr:
case op_jless:
case op_jlesseq:
Modified: trunk/Source/_javascript_Core/bytecode/Opcode.h (283094 => 283095)
--- trunk/Source/_javascript_Core/bytecode/Opcode.h 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/bytecode/Opcode.h 2021-09-27 04:14:23 UTC (rev 283095)
@@ -199,6 +199,7 @@
case op_jneq_null:
case op_jundefined_or_null:
case op_jnundefined_or_null:
+ case op_jeq_ptr:
case op_jneq_ptr:
case op_jless:
case op_jlesseq:
Modified: trunk/Source/_javascript_Core/bytecode/PreciseJumpTargetsInlines.h (283094 => 283095)
--- trunk/Source/_javascript_Core/bytecode/PreciseJumpTargetsInlines.h 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/bytecode/PreciseJumpTargetsInlines.h 2021-09-27 04:14:23 UTC (rev 283095)
@@ -43,6 +43,7 @@
CASE_OP(OpJneqNull) \
CASE_OP(OpJundefinedOrNull) \
CASE_OP(OpJnundefinedOrNull) \
+ CASE_OP(OpJeqPtr) \
CASE_OP(OpJneqPtr) \
\
CASE_OP(OpJless) \
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (283094 => 283095)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2021-09-27 04:14:23 UTC (rev 283095)
@@ -105,6 +105,7 @@
CASE(OpJeq)
CASE(OpJstricteq)
CASE(OpJneq)
+ CASE(OpJeqPtr)
CASE(OpJneqPtr)
CASE(OpJnstricteq)
CASE(OpJless)
@@ -1497,6 +1498,11 @@
OpJneqPtr::emit(this, cond, moveLinkTimeConstant(nullptr, LinkTimeConstant::applyFunction), target.bind(this));
}
+void BytecodeGenerator::emitJumpIfSentinelString(RegisterID* cond, Label& target)
+{
+ OpJeqPtr::emit(this, cond, emitLoad(nullptr, JSValue(vm().smallStrings.sentinelString())), target.bind(this));
+}
+
unsigned BytecodeGenerator::emitWideJumpIfNotFunctionHasOwnProperty(RegisterID* cond, Label& target)
{
OpJneqPtr::emit<OpcodeSize::Wide32>(this, cond, moveLinkTimeConstant(nullptr, LinkTimeConstant::hasOwnPropertyFunction), target.bind(this));
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (283094 => 283095)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2021-09-27 04:14:23 UTC (rev 283095)
@@ -858,6 +858,7 @@
void emitJumpIfFalse(RegisterID* cond, Label& target);
void emitJumpIfNotFunctionCall(RegisterID* cond, Label& target);
void emitJumpIfNotFunctionApply(RegisterID* cond, Label& target);
+ void emitJumpIfSentinelString(RegisterID* cond, Label& target);
unsigned emitWideJumpIfNotFunctionHasOwnProperty(RegisterID* cond, Label& target);
void recordHasOwnPropertyInForInLoop(ForInContext&, unsigned branchOffset, Label& genericPath);
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (283094 => 283095)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2021-09-27 04:14:23 UTC (rev 283095)
@@ -4227,10 +4227,8 @@
// FIXME: We should have a way to see if anyone is actually using the propertyName for something other than a get_by_val. If not, we could eliminate the toString in this opcode.
generator.emitEnumeratorNext(propertyName.get(), mode.get(), index.get(), base.get(), enumerator.get());
+ generator.emitJumpIfSentinelString(propertyName.get(), scope->breakTarget());
- // Note, choosing undefined or null helps please DFG's Abstract Interpreter as it doesn't distinguish null and undefined as types (via SpecOther).
- generator.emitJumpIfTrue(generator.emitIsUndefinedOrNull(generator.newTemporary(), propertyName.get()), scope->breakTarget());
-
this->emitLoopHeader(generator, propertyName.get());
generator.emitProfileControlFlow(profilerStartOffset);
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (283094 => 283095)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2021-09-27 04:14:23 UTC (rev 283095)
@@ -4323,7 +4323,7 @@
}
case EnumeratorNextUpdatePropertyName: {
- setTypeForNode(node, SpecString | SpecOther);
+ setTypeForNode(node, SpecStringIdent);
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (283094 => 283095)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2021-09-27 04:14:23 UTC (rev 283095)
@@ -7632,6 +7632,16 @@
NEXT_OPCODE(op_iterator_next);
}
+ case op_jeq_ptr: {
+ auto bytecode = currentInstruction->as<OpJeqPtr>();
+ FrozenValue* frozenPointer = m_graph.freezeStrong(m_inlineStackTop->m_codeBlock->getConstant(bytecode.m_specialPointer));
+ unsigned relativeOffset = jumpTarget(bytecode.m_targetLabel);
+ Node* child = get(bytecode.m_value);
+ Node* condition = addToGraph(CompareEqPtr, OpInfo(frozenPointer), child);
+ addToGraph(Branch, OpInfo(branchData(m_currentIndex.offset() + relativeOffset, m_currentIndex.offset() + currentInstruction->size())), condition);
+ LAST_OPCODE(op_jeq_ptr);
+ }
+
case op_jneq_ptr: {
auto bytecode = currentInstruction->as<OpJneqPtr>();
FrozenValue* frozenPointer = m_graph.freezeStrong(m_inlineStackTop->m_codeBlock->getConstant(bytecode.m_specialPointer));
Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (283094 => 283095)
--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp 2021-09-27 04:14:23 UTC (rev 283095)
@@ -240,6 +240,7 @@
case op_get_from_arguments:
case op_put_to_arguments:
case op_get_argument:
+ case op_jeq_ptr:
case op_jneq_ptr:
case op_typeof:
case op_to_number:
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (283094 => 283095)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2021-09-27 04:14:23 UTC (rev 283095)
@@ -86,10 +86,10 @@
namespace JSC { namespace DFG {
template<bool strict, bool direct>
-static inline void putByVal(JSGlobalObject* globalObject, VM& vm, JSValue baseValue, uint32_t index, JSValue value)
+static ALWAYS_INLINE void putByVal(JSGlobalObject* globalObject, VM& vm, JSValue baseValue, uint32_t index, JSValue value)
{
ASSERT(isIndex(index));
- if (direct) {
+ if constexpr (direct) {
RELEASE_ASSERT(baseValue.isObject());
asObject(baseValue)->putDirectIndex(globalObject, index, value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
return;
@@ -128,7 +128,7 @@
RETURN_IF_EXCEPTION(scope, void());
PutPropertySlot slot(baseValue, strict);
- if (direct) {
+ if constexpr (direct) {
RELEASE_ASSERT(baseValue.isObject());
JSObject* baseObject = asObject(baseValue);
if (std::optional<uint32_t> index = parseIndex(propertyName)) {
@@ -148,7 +148,7 @@
ALWAYS_INLINE static void putByValCellInternal(JSGlobalObject* globalObject, VM& vm, JSCell* base, PropertyName propertyName, JSValue value)
{
PutPropertySlot slot(base, strict);
- if (direct) {
+ if constexpr (direct) {
RELEASE_ASSERT(base->isObject());
JSObject* baseObject = asObject(base);
if (std::optional<uint32_t> index = parseIndex(propertyName)) {
@@ -2486,7 +2486,7 @@
return JSValue::encode(result);
}
-JSC_DEFINE_JIT_OPERATION(operationEnumeratorNextUpdatePropertyName, EncodedJSValue, (JSGlobalObject* globalObject, uint32_t index, int32_t modeNumber, JSPropertyNameEnumerator* enumerator))
+JSC_DEFINE_JIT_OPERATION(operationEnumeratorNextUpdatePropertyName, JSString*, (JSGlobalObject* globalObject, uint32_t index, int32_t modeNumber, JSPropertyNameEnumerator* enumerator))
{
VM& vm = globalObject->vm();
CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
@@ -2494,15 +2494,15 @@
if (modeNumber == JSPropertyNameEnumerator::IndexedMode) {
if (index < enumerator->indexedLength())
- return JSValue::encode(jsString(vm, Identifier::from(vm, index).string()));
- return JSValue::encode(jsNull());
+ return jsString(vm, Identifier::from(vm, index).string());
+ return vm.smallStrings.sentinelString();
}
JSString* result = enumerator->propertyNameAtIndex(index);
if (!result)
- return JSValue::encode(jsNull());
+ return vm.smallStrings.sentinelString();
- return JSValue::encode(result);
+ return result;
}
JSC_DEFINE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* base, uint32_t index, JSPropertyNameEnumerator* enumerator))
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (283094 => 283095)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.h 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h 2021-09-27 04:14:23 UTC (rev 283095)
@@ -108,7 +108,7 @@
JSC_DECLARE_JIT_OPERATION(operationGetPropertyEnumerator, JSCell*, (JSGlobalObject*, EncodedJSValue));
JSC_DECLARE_JIT_OPERATION(operationGetPropertyEnumeratorCell, JSCell*, (JSGlobalObject*, JSCell*));
JSC_DECLARE_JIT_OPERATION(operationEnumeratorNextUpdateIndexAndMode, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, uint32_t, int32_t, JSPropertyNameEnumerator*));
-JSC_DECLARE_JIT_OPERATION(operationEnumeratorNextUpdatePropertyName, EncodedJSValue, (JSGlobalObject*, uint32_t, int32_t, JSPropertyNameEnumerator*));
+JSC_DECLARE_JIT_OPERATION(operationEnumeratorNextUpdatePropertyName, JSString*, (JSGlobalObject*, uint32_t, int32_t, JSPropertyNameEnumerator*));
JSC_DECLARE_JIT_OPERATION(operationEnumeratorInByVal, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t));
JSC_DECLARE_JIT_OPERATION(operationEnumeratorHasOwnProperty, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t));
JSC_DECLARE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject*, JSCell*, uint32_t, JSPropertyNameEnumerator*));
Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (283094 => 283095)
--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2021-09-27 04:14:23 UTC (rev 283095)
@@ -1233,7 +1233,7 @@
}
case EnumeratorNextUpdatePropertyName: {
- setPrediction(SpecString | SpecOther);
+ setPrediction(SpecStringIdent);
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (283094 => 283095)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2021-09-27 04:14:23 UTC (rev 283095)
@@ -13646,12 +13646,12 @@
SpeculateStrictInt32Operand indexOperand(this, node->child1());
SpeculateStrictInt32Operand modeOperand(this, node->child2());
SpeculateCellOperand enumeratorOperand(this, node->child3());
- JSValueRegsTemporary resultTemp(this);
+ GPRTemporary result(this);
GPRReg index = indexOperand.gpr();
GPRReg mode = modeOperand.gpr();
GPRReg enumerator = enumeratorOperand.gpr();
- JSValueRegs resultRegs = resultTemp.regs();
+ GPRReg resultGPR = result.gpr();
OptionSet seenModes = node->enumeratorMetadata();
@@ -13667,24 +13667,21 @@
auto outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, index, MacroAssembler::Address(enumerator, JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));
- m_jit.loadPtr(MacroAssembler::Address(enumerator, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), resultRegs.payloadGPR());
- m_jit.loadPtr(MacroAssembler::BaseIndex(resultRegs.payloadGPR(), index, MacroAssembler::ScalePtr), resultRegs.payloadGPR());
-#if USE(JSVALUE32_64)
- m_jit.move(TrustedImm32(JSValue::CellTag), resultRegs.tagGPR());
-#endif
+ m_jit.loadPtr(MacroAssembler::Address(enumerator, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), resultGPR);
+ m_jit.loadPtr(MacroAssembler::BaseIndex(resultGPR, index, MacroAssembler::ScalePtr), resultGPR);
doneCases.append(m_jit.jump());
outOfBounds.link(&m_jit);
- m_jit.moveTrustedValue(jsNull(), resultRegs);
+ m_jit.move(TrustedImmPtr::weakPointer(m_graph, vm().smallStrings.sentinelString()), resultGPR);
doneCases.append(m_jit.jump());
operationCall.link(&m_jit);
}
- callOperation(operationEnumeratorNextUpdatePropertyName, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), index, mode, enumerator);
+ callOperation(operationEnumeratorNextUpdatePropertyName, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), index, mode, enumerator);
m_jit.exceptionCheck();
doneCases.link(&m_jit);
- jsValueResult(resultRegs, node);
+ cellResult(resultGPR, node);
}
template<typename SlowPathFunctionType>
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (283094 => 283095)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2021-09-27 04:14:23 UTC (rev 283095)
@@ -13526,7 +13526,7 @@
{
m_out.appendTo(outOfBoundsBlock);
- results.append(m_out.anchor(m_out.constInt64(JSValue::encode(jsNull()))));
+ results.append(m_out.anchor(weakPointer(vm().smallStrings.sentinelString())));
m_out.jump(continuation);
}
@@ -13533,7 +13533,7 @@
{
m_out.appendTo(loadPropertyNameBlock);
LValue namesVector = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector);
- results.append(m_out.anchor(m_out.zeroExtPtr(m_out.loadPtr(m_out.baseIndex(m_heaps.WriteBarrierBuffer_bufferContents.atAnyIndex(), namesVector, m_out.zeroExt(index, Int64), ScalePtr)))));
+ results.append(m_out.anchor(m_out.loadPtr(m_out.baseIndex(m_heaps.WriteBarrierBuffer_bufferContents.atAnyIndex(), namesVector, m_out.zeroExt(index, Int64), ScalePtr))));
m_out.jump(continuation);
}
}
@@ -13541,7 +13541,7 @@
if (operationBlock)
m_out.appendTo(operationBlock);
// Note: We can't omit the operation because we have no guarantee that the mode will match what we profiled.
- results.append(m_out.anchor(vmCall(Int64, operationEnumeratorNextUpdatePropertyName, weakPointer(globalObject), index, mode, enumerator)));
+ results.append(m_out.anchor(vmCall(pointerType(), operationEnumeratorNextUpdatePropertyName, weakPointer(globalObject), index, mode, enumerator)));
if (continuation) {
m_out.jump(continuation);
m_out.appendTo(continuation);
@@ -13548,7 +13548,7 @@
}
ASSERT(results.size());
- LValue result = m_out.phi(Int64, results);
+ LValue result = m_out.phi(pointerType(), results);
setJSValue(result);
}
Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (283094 => 283095)
--- trunk/Source/_javascript_Core/jit/JIT.cpp 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp 2021-09-27 04:14:23 UTC (rev 283095)
@@ -387,6 +387,7 @@
DEFINE_OP(op_jneq_null)
DEFINE_OP(op_jundefined_or_null)
DEFINE_OP(op_jnundefined_or_null)
+ DEFINE_OP(op_jeq_ptr)
DEFINE_OP(op_jneq_ptr)
DEFINE_OP(op_jless)
DEFINE_OP(op_jlesseq)
Modified: trunk/Source/_javascript_Core/jit/JIT.h (283094 => 283095)
--- trunk/Source/_javascript_Core/jit/JIT.h 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/jit/JIT.h 2021-09-27 04:14:23 UTC (rev 283095)
@@ -461,6 +461,7 @@
void emit_op_jneq_null(const Instruction*);
void emit_op_jundefined_or_null(const Instruction*);
void emit_op_jnundefined_or_null(const Instruction*);
+ void emit_op_jeq_ptr(const Instruction*);
void emit_op_jneq_ptr(const Instruction*);
void emit_op_jless(const Instruction*);
void emit_op_jlesseq(const Instruction*);
Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (283094 => 283095)
--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp 2021-09-27 04:14:23 UTC (rev 283095)
@@ -579,6 +579,18 @@
addJump(branch64(NotEqual, regT0, TrustedImm64(JSValue::encode(jsNull()))), target);
}
+void JIT::emit_op_jeq_ptr(const Instruction* currentInstruction)
+{
+ auto bytecode = currentInstruction->as<OpJeqPtr>();
+ VirtualRegister src = ""
+ JSValue specialPointer = getConstantOperand(bytecode.m_specialPointer);
+ ASSERT(specialPointer.isCell());
+ unsigned target = jumpTarget(currentInstruction, bytecode.m_targetLabel);
+
+ emitGetVirtualRegister(src, regT0);
+ addJump(branchPtr(Equal, regT0, TrustedImmPtr(specialPointer.asCell())), target);
+}
+
void JIT::emit_op_jneq_ptr(const Instruction* currentInstruction)
{
auto bytecode = currentInstruction->as<OpJneqPtr>();
Modified: trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (283094 => 283095)
--- trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp 2021-09-27 04:14:23 UTC (rev 283095)
@@ -501,6 +501,21 @@
addJump(branchIfNotNull(regT0), target);
}
+void JIT::emit_op_jeq_ptr(const Instruction* currentInstruction)
+{
+ auto bytecode = currentInstruction->as<OpJeqPtr>();
+ auto& metadata = bytecode.metadata(m_profiledCodeBlock);
+ VirtualRegister src = ""
+ JSValue specialPointer = getConstantOperand(bytecode.m_specialPointer);
+ ASSERT(specialPointer.isCell());
+ unsigned target = jumpTarget(currentInstruction, bytecode.m_targetLabel);
+
+ emitLoad(src, regT1, regT0);
+ Jump notCell = branchIfNotCell(regT1);
+ addJump(branchPtr(Equal, regT0, TrustedImmPtr(specialPointer.asCell())), target);
+ notCell.link(this);
+}
+
void JIT::emit_op_jneq_ptr(const Instruction* currentInstruction)
{
auto bytecode = currentInstruction->as<OpJneqPtr>();
Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp (283094 => 283095)
--- trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp 2021-09-27 04:14:23 UTC (rev 283095)
@@ -2866,7 +2866,7 @@
done.append(jump());
outOfBounds.link(this);
- storeTrustedValue(jsNull(), addressFor(propertyName));
+ storeTrustedValue(vm().smallStrings.sentinelString(), addressFor(propertyName));
done.append(jump());
}
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (283094 => 283095)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm 2021-09-27 04:14:23 UTC (rev 283095)
@@ -1944,6 +1944,20 @@
undefinedOrNullJumpOp(jnundefined_or_null, OpJnundefinedOrNull,
macro (value, target) bineq value, NullTag, target end)
+llintOpWithReturn(op_jeq_ptr, OpJeqPtr, macro (size, get, dispatch, return)
+ get(m_value, t0)
+ get(m_specialPointer, t1)
+ loadConstant(size, t1, t3, t2)
+ bineq TagOffset[cfr, t0, 8], CellTag, .opJeqPtrFallThrough
+ bpneq PayloadOffset[cfr, t0, 8], t2, .opJeqPtrFallThrough
+.opJeqPtrBranch:
+ get(m_targetLabel, t0)
+ jumpImpl(dispatchIndirect, t0)
+.opJeqPtrFallThrough:
+ dispatch()
+end)
+
+
llintOpWithMetadata(op_jneq_ptr, OpJneqPtr, macro (size, get, dispatch, metadata, return)
get(m_value, t0)
get(m_specialPointer, t1)
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (283094 => 283095)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2021-09-27 04:14:23 UTC (rev 283095)
@@ -2072,6 +2072,19 @@
undefinedOrNullJumpOp(jnundefined_or_null, OpJnundefinedOrNull,
macro (value, target) bqneq value, ValueNull, target end)
+llintOpWithReturn(op_jeq_ptr, OpJeqPtr, macro (size, get, dispatch, return)
+ get(m_value, t0)
+ get(m_specialPointer, t1)
+ loadConstant(size, t1, t2)
+ bpeq t2, [cfr, t0, 8], .opJeqPtrTarget
+ dispatch()
+
+.opJeqPtrTarget:
+ get(m_targetLabel, t0)
+ jumpImpl(dispatchIndirect, t0)
+end)
+
+
llintOpWithMetadata(op_jneq_ptr, OpJneqPtr, macro (size, get, dispatch, metadata, return)
get(m_value, t0)
get(m_specialPointer, t1)
Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (283094 => 283095)
--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2021-09-27 04:14:23 UTC (rev 283095)
@@ -1001,7 +1001,7 @@
metadata.m_enumeratorMetadata |= static_cast<uint8_t>(mode);
modeRegister = jsNumber(static_cast<uint8_t>(mode));
indexRegister = jsNumber(index);
- nameRegister = name ? name : jsNull();
+ nameRegister = name ? name : vm.smallStrings.sentinelString();
END();
}
Modified: trunk/Source/_javascript_Core/runtime/SmallStrings.cpp (283094 => 283095)
--- trunk/Source/_javascript_Core/runtime/SmallStrings.cpp 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/runtime/SmallStrings.cpp 2021-09-27 04:14:23 UTC (rev 283095)
@@ -62,6 +62,7 @@
initialize(&vm, m_notEqualString, "not-equal");
initialize(&vm, m_timedOutString, "timed-out");
initialize(&vm, m_okString, "ok");
+ initialize(&vm, m_sentinelString, "$");
setIsInitialized(true);
}
@@ -83,6 +84,7 @@
visitor.appendUnbarriered(m_notEqualString);
visitor.appendUnbarriered(m_timedOutString);
visitor.appendUnbarriered(m_okString);
+ visitor.appendUnbarriered(m_sentinelString);
}
template void SmallStrings::visitStrongReferences(AbstractSlotVisitor&);
Modified: trunk/Source/_javascript_Core/runtime/SmallStrings.h (283094 => 283095)
--- trunk/Source/_javascript_Core/runtime/SmallStrings.h 2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/runtime/SmallStrings.h 2021-09-27 04:14:23 UTC (rev 283095)
@@ -119,6 +119,7 @@
JSString* notEqualString() const { return m_notEqualString; }
JSString* timedOutString() const { return m_timedOutString; }
JSString* okString() const { return m_okString; }
+ JSString* sentinelString() const { return m_sentinelString; }
bool needsToBeVisited(CollectionScope scope) const
{
@@ -143,6 +144,7 @@
JSString* m_notEqualString { nullptr };
JSString* m_timedOutString { nullptr };
JSString* m_okString { nullptr };
+ JSString* m_sentinelString { nullptr };
JSString* m_singleCharacterStrings[singleCharacterStringCount] { nullptr };
bool m_needsToBeVisited { true };
bool m_isInitialized { false };