Diff
Modified: trunk/JSTests/ChangeLog (231223 => 231224)
--- trunk/JSTests/ChangeLog 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/JSTests/ChangeLog 2018-05-02 05:51:33 UTC (rev 231224)
@@ -1,3 +1,37 @@
+2018-05-01 Yusuke Suzuki <[email protected]>
+
+ [JSC] Add SameValue DFG node
+ https://bugs.webkit.org/show_bug.cgi?id=185065
+
+ Reviewed by Saam Barati.
+
+ * microbenchmarks/object-is.js: Added.
+ (incognito):
+ (sameValue):
+ (test1):
+ (test2):
+ (test3):
+ (test4):
+ (test5):
+ (test6):
+ * stress/object-is.js: Added.
+ (shouldBe):
+ (is1):
+ (is2):
+ (is3):
+ (is4):
+ (is5):
+ (is6):
+ (is7):
+ (is8):
+ (is9):
+ (is10):
+ (is11):
+ (is12):
+ (is13):
+ (is14):
+ (is15):
+
2018-05-01 Robin Morisset <[email protected]>
Correctly detect string overflow when using the 'Function' constructor
Added: trunk/JSTests/microbenchmarks/object-is.js (0 => 231224)
--- trunk/JSTests/microbenchmarks/object-is.js (rev 0)
+++ trunk/JSTests/microbenchmarks/object-is.js 2018-05-02 05:51:33 UTC (rev 231224)
@@ -0,0 +1,82 @@
+function incognito(value) {
+ var array = [];
+ array.push(value);
+ array.push("ignore me");
+ array.push(value);
+ array.push({ ignore: "me" });
+ return array[((Math.random() * 2) | 0) * 2];
+}
+
+// cached Object.is
+var objectIs = Object.is;
+
+// pure JS version of Object.is
+function sameValue(a, b) {
+ return (a === b) ?
+ (a !== 0 || (1 / a === 1 / b)) :
+ (a !== a && b !== b);
+}
+
+var testFiveA = incognito("back5");
+var testFiveB = incognito("2back5".substring(1));
+var testPi = incognito("PI");
+var testNaN = incognito(NaN);
+var testNaN_2 = incognito(NaN);
+
+var result;
+
+function test1()
+{
+ return testFiveA === testFiveB;
+}
+noInline(test1);
+
+function test2()
+{
+ return Object.is(testFiveA, testFiveB);
+}
+noInline(test2);
+
+function test3()
+{
+ return sameValue(testFiveA, testFiveB);
+}
+noInline(test3);
+
+function test4()
+{
+ return testFiveA === testPi;
+}
+noInline(test4);
+
+function test5()
+{
+ return Object.is(testFiveA, testPi);
+}
+noInline(test5);
+
+function test6()
+{
+ return sameValue(testFiveA, testPi);
+}
+noInline(test6);
+
+var verbose = false;
+var tests = [
+// test1,
+ test2,
+// test3,
+// test4,
+ test5,
+// test6,
+];
+for (let test of tests) {
+ if (verbose)
+ var time = Date.now();
+
+ for (let i = 0; i < 2e7; ++i)
+ test();
+
+ if (verbose)
+ print(Date.now() - time);
+}
Added: trunk/JSTests/stress/object-is.js (0 => 231224)
--- trunk/JSTests/stress/object-is.js (rev 0)
+++ trunk/JSTests/stress/object-is.js 2018-05-02 05:51:33 UTC (rev 231224)
@@ -0,0 +1,72 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+function is1(a, b) { return Object.is(a, b); }
+noInline(is1);
+function is2(a, b) { return Object.is(a, b); }
+noInline(is2);
+function is3(a, b) { return Object.is(a, b); }
+noInline(is3);
+function is4(a, b) { return Object.is(a, b); }
+noInline(is4);
+function is5(a, b) { return Object.is(a, b); }
+noInline(is5);
+function is6(a, b) { return Object.is(a, b); }
+noInline(is6);
+function is7(a, b) { return Object.is(a, b); }
+noInline(is7);
+function is8(a, b) { return Object.is(a, b); }
+noInline(is8);
+function is9(a, b) { return Object.is(a, b); }
+noInline(is9);
+function is10(a, b) { return Object.is(a, b); }
+noInline(is10);
+function is11(a, b) { return Object.is(a, b); }
+noInline(is11);
+function is12(a, b) { return Object.is(a, b); }
+noInline(is12);
+function is13(a, b) { return Object.is(a, b); }
+noInline(is13);
+function is14(a, b) { return Object.is(a, b); }
+noInline(is14);
+function is15(a, b) { return Object.is(a, b); }
+noInline(is15);
+
+for (var i = 0; i < 1e5; ++i) {
+ shouldBe(Object.is(NaN, NaN), true);
+ shouldBe(Object.is(null, null), true);
+ shouldBe(Object.is(null), false);
+ shouldBe(Object.is(undefined, undefined), true);
+ shouldBe(Object.is(true, true), true);
+ shouldBe(Object.is(false, false), true);
+ shouldBe(Object.is('abc', 'abc'), true);
+ shouldBe(Object.is(Infinity, Infinity), true);
+ shouldBe(Object.is(0, 0), true);
+ shouldBe(Object.is(-0, -0), true);
+ shouldBe(Object.is(0, -0), false);
+ shouldBe(Object.is(-0, 0), false);
+ var obj = {};
+ shouldBe(Object.is(obj, obj), true);
+ var arr = [];
+ shouldBe(Object.is(arr, arr), true);
+ var sym = Symbol();
+ shouldBe(Object.is(sym, sym), true);
+
+ shouldBe(is1(NaN, NaN), true);
+ shouldBe(is2(null, null), true);
+ shouldBe(is3(null), false);
+ shouldBe(is4(undefined, undefined), true);
+ shouldBe(is5(true, true), true);
+ shouldBe(is6(false, false), true);
+ shouldBe(is7('abc', 'abc'), true);
+ shouldBe(is8(Infinity, Infinity), true);
+ shouldBe(is9(0, 0), true);
+ shouldBe(is10(-0, -0), true);
+ shouldBe(is11(0, -0), false);
+ shouldBe(is12(-0, 0), false);
+ shouldBe(is13(obj, obj), true);
+ shouldBe(is14(arr, arr), true);
+ shouldBe(is15(sym, sym), true);
+}
Modified: trunk/Source/_javascript_Core/ChangeLog (231223 => 231224)
--- trunk/Source/_javascript_Core/ChangeLog 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-05-02 05:51:33 UTC (rev 231224)
@@ -1,3 +1,73 @@
+2018-05-01 Yusuke Suzuki <[email protected]>
+
+ [JSC] Add SameValue DFG node
+ https://bugs.webkit.org/show_bug.cgi?id=185065
+
+ Reviewed by Saam Barati.
+
+ This patch adds Object.is handling in DFG and FTL. Object.is is converted to SameValue DFG node.
+ And DFG fixup phase attempts to convert SameValue node to CompareStrictEq with type filter edges
+ if possible. Since SameValue(Untyped, Untyped) and SameValue(Double, Double) have different semantics
+ from CompareStrictEq, we do not convert SameValue to CompareStrictEq for them. DFG and FTL have
+ implementations for these SameValue nodes.
+
+ This old MacroAssemblerX86Common::compareDouble was dead code since the derived class, "MacroAssembler"
+ has a generalized compareDouble, which just uses branchDouble. Since this was not used, this function
+ was broken. This patch fixes issues and move compareDouble to MacroAssemblerX86Common, and remove a
+ generalized compareDouble for x86 arch to use this specialized efficient version instead. The fixes are
+ correctly using set32 to zero-extending the result, and setting the initial value of `dest` register
+ correctly for DoubleEqual and DoubleNotEqualOrUnordered cases.
+
+ Added microbenchmark shows performance improvement.
+
+ object-is 651.0053+-38.8204 ^ 241.3467+-15.8753 ^ definitely 2.6974x faster
+
+ * assembler/MacroAssembler.h:
+ * assembler/MacroAssemblerX86Common.h:
+ (JSC::MacroAssemblerX86Common::compareDouble):
+ * assembler/MacroAssemblerX86_64.h:
+ (JSC::MacroAssemblerX86_64::compareDouble): Deleted.
+ * assembler/testmasm.cpp:
+ (JSC::doubleOperands):
+ (JSC::testCompareDouble):
+ (JSC::run):
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::foldConstants):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ (JSC::DFG::FixupPhase::fixupCompareStrictEqAndSameValue):
+ * dfg/DFGNodeType.h:
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileSameValue):
+ * dfg/DFGSpeculativeJIT.h:
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGValidate.cpp:
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+ (JSC::FTL::DFG::LowerDFGToB3::compileSameValue):
+ * runtime/Intrinsic.cpp:
+ (JSC::intrinsicName):
+ * runtime/Intrinsic.h:
+ * runtime/ObjectConstructor.cpp:
+
2018-04-30 Filip Pizlo <[email protected]>
B3::demoteValues should be able to handle patchpoint terminals
Modified: trunk/Source/_javascript_Core/assembler/MacroAssembler.h (231223 => 231224)
--- trunk/Source/_javascript_Core/assembler/MacroAssembler.h 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/assembler/MacroAssembler.h 2018-05-02 05:51:33 UTC (rev 231224)
@@ -1459,9 +1459,10 @@
#endif // !CPU(X86_64)
-#if ENABLE(B3_JIT)
// We should implement this the right way eventually, but for now, it's fine because it arises so
// infrequently.
+
+#if !CPU(X86) && !CPU(X86_64)
void compareDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID dest)
{
move(TrustedImm32(0), dest);
@@ -1469,6 +1470,9 @@
move(TrustedImm32(1), dest);
falseCase.link(this);
}
+#endif
+
+#if ENABLE(B3_JIT)
void compareFloat(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID dest)
{
move(TrustedImm32(0), dest);
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (231223 => 231224)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h 2018-05-02 05:51:33 UTC (rev 231224)
@@ -2014,6 +2014,48 @@
return jumpAfterFloatingPointCompare(cond, left, right);
}
+ void compareDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID dest)
+ {
+ if (cond & DoubleConditionBitSpecial) {
+ ASSERT(!(cond & DoubleConditionBitInvert));
+ if (cond == DoubleEqual) {
+ if (left == right) {
+ m_assembler.ucomisd_rr(right, left);
+ set32(X86Assembler::ConditionNP, dest);
+ return;
+ }
+
+ move(TrustedImm32(0), dest);
+ m_assembler.ucomisd_rr(right, left);
+ Jump isUnordered = m_assembler.jp();
+ set32(X86Assembler::ConditionE, dest);
+ isUnordered.link(this);
+ return;
+ }
+ if (cond == DoubleNotEqualOrUnordered) {
+ if (left == right) {
+ m_assembler.ucomisd_rr(right, left);
+ set32(X86Assembler::ConditionP, dest);
+ return;
+ }
+
+ move(TrustedImm32(1), dest);
+ m_assembler.ucomisd_rr(right, left);
+ Jump isUnordered = m_assembler.jp();
+ set32(X86Assembler::ConditionNE, dest);
+ isUnordered.link(this);
+ return;
+ }
+ return;
+ }
+
+ if (cond & DoubleConditionBitInvert)
+ m_assembler.ucomisd_rr(left, right);
+ else
+ m_assembler.ucomisd_rr(right, left);
+ set32(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits), dest);
+ }
+
// Truncates 'src' to an integer, and places the resulting 'dest'.
// If the result is not representable as a 32 bit value, branch.
// May also branch for some values that are representable in 32 bits
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h (231223 => 231224)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h 2018-05-02 05:51:33 UTC (rev 231224)
@@ -983,40 +983,6 @@
set32(x86Condition(cond), dest);
}
- void compareDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID dest)
- {
- if (cond & DoubleConditionBitInvert)
- m_assembler.ucomisd_rr(left, right);
- else
- m_assembler.ucomisd_rr(right, left);
-
- if (cond == DoubleEqual) {
- if (left == right) {
- m_assembler.setnp_r(dest);
- return;
- }
-
- Jump isUnordered(m_assembler.jp());
- m_assembler.sete_r(dest);
- isUnordered.link(this);
- return;
- }
-
- if (cond == DoubleNotEqualOrUnordered) {
- if (left == right) {
- m_assembler.setp_r(dest);
- return;
- }
-
- m_assembler.setp_r(dest);
- m_assembler.setne_r(dest);
- return;
- }
-
- ASSERT(!(cond & DoubleConditionBitSpecial));
- m_assembler.setCC_r(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits), dest);
- }
-
Jump branch64(RelationalCondition cond, RegisterID left, RegisterID right)
{
m_assembler.cmpq_rr(right, left);
Modified: trunk/Source/_javascript_Core/assembler/testmasm.cpp (231223 => 231224)
--- trunk/Source/_javascript_Core/assembler/testmasm.cpp 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/assembler/testmasm.cpp 2018-05-02 05:51:33 UTC (rev 231224)
@@ -227,6 +227,67 @@
}
+static Vector<double> doubleOperands()
+{
+ return Vector<double> {
+ 0,
+ -0,
+ 1,
+ -1,
+ 42,
+ -42,
+ std::numeric_limits<double>::max(),
+ std::numeric_limits<double>::min(),
+ std::numeric_limits<double>::lowest(),
+ std::numeric_limits<double>::quiet_NaN(),
+ std::numeric_limits<double>::infinity(),
+ -std::numeric_limits<double>::infinity(),
+ };
+}
+
+
+void testCompareDouble(MacroAssembler::DoubleCondition condition)
+{
+ double arg1 = 0;
+ double arg2 = 0;
+
+ auto compareDouble = compile([&, condition] (CCallHelpers& jit) {
+ jit.emitFunctionPrologue();
+
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
+ jit.move(CCallHelpers::TrustedImm32(-1), GPRInfo::returnValueGPR);
+ jit.compareDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, GPRInfo::returnValueGPR);
+
+ jit.emitFunctionEpilogue();
+ jit.ret();
+ });
+
+ auto compareDoubleGeneric = compile([&, condition] (CCallHelpers& jit) {
+ jit.emitFunctionPrologue();
+
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+ jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
+ jit.move(CCallHelpers::TrustedImm32(1), GPRInfo::returnValueGPR);
+ auto jump = jit.branchDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
+ jit.move(CCallHelpers::TrustedImm32(0), GPRInfo::returnValueGPR);
+ jump.link(&jit);
+
+ jit.emitFunctionEpilogue();
+ jit.ret();
+ });
+
+ auto operands = doubleOperands();
+ for (auto a : operands) {
+ for (auto b : operands) {
+ arg1 = a;
+ arg2 = b;
+ CHECK_EQ(invoke<int>(compareDouble), invoke<int>(compareDoubleGeneric));
+ }
+ }
+}
+
+
#if ENABLE(MASM_PROBE)
void testProbeReadsArgumentRegisters()
{
@@ -787,6 +848,19 @@
// reset to check a conversion result
RUN(testBranchTruncateDoubleToInt32(123, 123));
+ RUN(testCompareDouble(MacroAssembler::DoubleEqual));
+ RUN(testCompareDouble(MacroAssembler::DoubleNotEqual));
+ RUN(testCompareDouble(MacroAssembler::DoubleGreaterThan));
+ RUN(testCompareDouble(MacroAssembler::DoubleGreaterThanOrEqual));
+ RUN(testCompareDouble(MacroAssembler::DoubleLessThan));
+ RUN(testCompareDouble(MacroAssembler::DoubleLessThanOrEqual));
+ RUN(testCompareDouble(MacroAssembler::DoubleEqualOrUnordered));
+ RUN(testCompareDouble(MacroAssembler::DoubleNotEqualOrUnordered));
+ RUN(testCompareDouble(MacroAssembler::DoubleGreaterThanOrUnordered));
+ RUN(testCompareDouble(MacroAssembler::DoubleGreaterThanOrEqualOrUnordered));
+ RUN(testCompareDouble(MacroAssembler::DoubleLessThanOrUnordered));
+ RUN(testCompareDouble(MacroAssembler::DoubleLessThanOrEqualOrUnordered));
+
#if ENABLE(MASM_PROBE)
RUN(testProbeReadsArgumentRegisters());
RUN(testProbeWritesArgumentRegisters());
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (231223 => 231224)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2018-05-02 05:51:33 UTC (rev 231224)
@@ -1673,7 +1673,8 @@
break;
}
- case CompareStrictEq: {
+ case CompareStrictEq:
+ case SameValue: {
Node* leftNode = node->child1().node();
Node* rightNode = node->child2().node();
JSValue left = forNode(leftNode).value();
@@ -1689,7 +1690,10 @@
break;
}
} else {
- setConstant(node, jsBoolean(JSValue::strictEqual(0, left, right)));
+ if (node->op() == CompareStrictEq)
+ setConstant(node, jsBoolean(JSValue::strictEqual(nullptr, left, right)));
+ else
+ setConstant(node, jsBoolean(sameValue(nullptr, left, right)));
break;
}
}
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (231223 => 231224)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2018-05-02 05:51:33 UTC (rev 231224)
@@ -2648,6 +2648,15 @@
return true;
}
+ case ObjectIsIntrinsic: {
+ if (argumentCountIncludingThis < 3)
+ return false;
+
+ insertChecks();
+ set(VirtualRegister(resultOperand), addToGraph(SameValue, get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset))));
+ return true;
+ }
+
case ReflectGetPrototypeOfIntrinsic: {
if (argumentCountIncludingThis != 2)
return false;
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (231223 => 231224)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2018-05-02 05:51:33 UTC (rev 231224)
@@ -165,6 +165,7 @@
case GetGlobalObject:
case StringCharCodeAt:
case CompareStrictEq:
+ case SameValue:
case IsEmpty:
case IsUndefined:
case IsBoolean:
Modified: trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp (231223 => 231224)
--- trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp 2018-05-02 05:51:33 UTC (rev 231224)
@@ -140,7 +140,8 @@
break;
}
- case CompareStrictEq: {
+ case CompareStrictEq:
+ case SameValue: {
if (node->isBinaryUseKind(UntypedUse)) {
JSValue child1Constant = m_state.forNode(node->child1().node()).value();
JSValue child2Constant = m_state.forNode(node->child2().node()).value();
Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (231223 => 231224)
--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2018-05-02 05:51:33 UTC (rev 231224)
@@ -154,6 +154,7 @@
case CompareEq:
case CompareStrictEq:
case CompareEqPtr:
+ case SameValue:
case Call:
case DirectCall:
case TailCallInlinedCaller:
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (231223 => 231224)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2018-05-02 05:51:33 UTC (rev 231224)
@@ -589,106 +589,12 @@
break;
}
- case CompareStrictEq: {
- if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
- fixEdge<BooleanUse>(node->child1());
- fixEdge<BooleanUse>(node->child2());
- break;
- }
- if (Node::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
- fixEdge<Int32Use>(node->child1());
- fixEdge<Int32Use>(node->child2());
- break;
- }
- if (enableInt52()
- && Node::shouldSpeculateAnyInt(node->child1().node(), node->child2().node())) {
- fixEdge<Int52RepUse>(node->child1());
- fixEdge<Int52RepUse>(node->child2());
- break;
- }
- if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
- fixEdge<DoubleRepUse>(node->child1());
- fixEdge<DoubleRepUse>(node->child2());
- break;
- }
- if (Node::shouldSpeculateSymbol(node->child1().node(), node->child2().node())) {
- fixEdge<SymbolUse>(node->child1());
- fixEdge<SymbolUse>(node->child2());
- break;
- }
- if (Node::shouldSpeculateBigInt(node->child1().node(), node->child2().node())) {
- fixEdge<BigIntUse>(node->child1());
- fixEdge<BigIntUse>(node->child2());
- break;
- }
- if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
- fixEdge<StringIdentUse>(node->child1());
- fixEdge<StringIdentUse>(node->child2());
- break;
- }
- if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 7) || isFTL(m_graph.m_plan.mode))) {
- fixEdge<StringUse>(node->child1());
- fixEdge<StringUse>(node->child2());
- break;
- }
- WatchpointSet* masqueradesAsUndefinedWatchpoint = m_graph.globalObjectFor(node->origin.semantic)->masqueradesAsUndefinedWatchpoint();
- if (masqueradesAsUndefinedWatchpoint->isStillValid()) {
-
- if (node->child1()->shouldSpeculateObject()) {
- m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
- fixEdge<ObjectUse>(node->child1());
- break;
- }
- if (node->child2()->shouldSpeculateObject()) {
- m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
- fixEdge<ObjectUse>(node->child2());
- break;
- }
-
- } else if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
- fixEdge<ObjectUse>(node->child1());
- fixEdge<ObjectUse>(node->child2());
- break;
- }
- if (node->child1()->shouldSpeculateSymbol()) {
- fixEdge<SymbolUse>(node->child1());
- break;
- }
- if (node->child2()->shouldSpeculateSymbol()) {
- fixEdge<SymbolUse>(node->child2());
- break;
- }
- if (node->child1()->shouldSpeculateMisc()) {
- fixEdge<MiscUse>(node->child1());
- break;
- }
- if (node->child2()->shouldSpeculateMisc()) {
- fixEdge<MiscUse>(node->child2());
- break;
- }
- if (node->child1()->shouldSpeculateStringIdent()
- && node->child2()->shouldSpeculateNotStringVar()) {
- fixEdge<StringIdentUse>(node->child1());
- fixEdge<NotStringVarUse>(node->child2());
- break;
- }
- if (node->child2()->shouldSpeculateStringIdent()
- && node->child1()->shouldSpeculateNotStringVar()) {
- fixEdge<StringIdentUse>(node->child2());
- fixEdge<NotStringVarUse>(node->child1());
- break;
- }
- if (node->child1()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 8) || isFTL(m_graph.m_plan.mode))) {
- fixEdge<StringUse>(node->child1());
- break;
- }
- if (node->child2()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 8) || isFTL(m_graph.m_plan.mode))) {
- fixEdge<StringUse>(node->child2());
- break;
- }
+ case CompareStrictEq:
+ case SameValue: {
+ fixupCompareStrictEqAndSameValue(node);
break;
}
-
+
case StringFromCharCode:
if (node->child1()->shouldSpeculateInt32()) {
fixEdge<Int32Use>(node->child1());
@@ -3478,6 +3384,138 @@
}
}
+ void fixupCompareStrictEqAndSameValue(Node* node)
+ {
+ ASSERT(node->op() == SameValue || node->op() == CompareStrictEq);
+
+ if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
+ fixEdge<BooleanUse>(node->child1());
+ fixEdge<BooleanUse>(node->child2());
+ node->setOpAndDefaultFlags(CompareStrictEq);
+ return;
+ }
+ if (Node::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
+ fixEdge<Int32Use>(node->child1());
+ fixEdge<Int32Use>(node->child2());
+ node->setOpAndDefaultFlags(CompareStrictEq);
+ return;
+ }
+ if (enableInt52()
+ && Node::shouldSpeculateAnyInt(node->child1().node(), node->child2().node())) {
+ fixEdge<Int52RepUse>(node->child1());
+ fixEdge<Int52RepUse>(node->child2());
+ node->setOpAndDefaultFlags(CompareStrictEq);
+ return;
+ }
+ if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
+ fixEdge<DoubleRepUse>(node->child1());
+ fixEdge<DoubleRepUse>(node->child2());
+ // Do not convert SameValue to CompareStrictEq in this case since SameValue(NaN, NaN) and SameValue(-0, +0)
+ // are not the same to CompareStrictEq(NaN, NaN) and CompareStrictEq(-0, +0).
+ return;
+ }
+ if (Node::shouldSpeculateSymbol(node->child1().node(), node->child2().node())) {
+ fixEdge<SymbolUse>(node->child1());
+ fixEdge<SymbolUse>(node->child2());
+ node->setOpAndDefaultFlags(CompareStrictEq);
+ return;
+ }
+ if (Node::shouldSpeculateBigInt(node->child1().node(), node->child2().node())) {
+ fixEdge<BigIntUse>(node->child1());
+ fixEdge<BigIntUse>(node->child2());
+ node->setOpAndDefaultFlags(CompareStrictEq);
+ return;
+ }
+ if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
+ fixEdge<StringIdentUse>(node->child1());
+ fixEdge<StringIdentUse>(node->child2());
+ node->setOpAndDefaultFlags(CompareStrictEq);
+ return;
+ }
+ if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 7) || isFTL(m_graph.m_plan.mode))) {
+ fixEdge<StringUse>(node->child1());
+ fixEdge<StringUse>(node->child2());
+ node->setOpAndDefaultFlags(CompareStrictEq);
+ return;
+ }
+
+ if (node->op() == SameValue) {
+ if (node->child1()->shouldSpeculateObject()) {
+ fixEdge<ObjectUse>(node->child1());
+ node->setOpAndDefaultFlags(CompareStrictEq);
+ return;
+ }
+ if (node->child2()->shouldSpeculateObject()) {
+ fixEdge<ObjectUse>(node->child2());
+ node->setOpAndDefaultFlags(CompareStrictEq);
+ return;
+ }
+ } else {
+ WatchpointSet* masqueradesAsUndefinedWatchpoint = m_graph.globalObjectFor(node->origin.semantic)->masqueradesAsUndefinedWatchpoint();
+ if (masqueradesAsUndefinedWatchpoint->isStillValid()) {
+ if (node->child1()->shouldSpeculateObject()) {
+ m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
+ fixEdge<ObjectUse>(node->child1());
+ return;
+ }
+ if (node->child2()->shouldSpeculateObject()) {
+ m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
+ fixEdge<ObjectUse>(node->child2());
+ return;
+ }
+ } else if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
+ fixEdge<ObjectUse>(node->child1());
+ fixEdge<ObjectUse>(node->child2());
+ return;
+ }
+ }
+
+ if (node->child1()->shouldSpeculateSymbol()) {
+ fixEdge<SymbolUse>(node->child1());
+ node->setOpAndDefaultFlags(CompareStrictEq);
+ return;
+ }
+ if (node->child2()->shouldSpeculateSymbol()) {
+ fixEdge<SymbolUse>(node->child2());
+ node->setOpAndDefaultFlags(CompareStrictEq);
+ return;
+ }
+ if (node->child1()->shouldSpeculateMisc()) {
+ fixEdge<MiscUse>(node->child1());
+ node->setOpAndDefaultFlags(CompareStrictEq);
+ return;
+ }
+ if (node->child2()->shouldSpeculateMisc()) {
+ fixEdge<MiscUse>(node->child2());
+ node->setOpAndDefaultFlags(CompareStrictEq);
+ return;
+ }
+ if (node->child1()->shouldSpeculateStringIdent()
+ && node->child2()->shouldSpeculateNotStringVar()) {
+ fixEdge<StringIdentUse>(node->child1());
+ fixEdge<NotStringVarUse>(node->child2());
+ node->setOpAndDefaultFlags(CompareStrictEq);
+ return;
+ }
+ if (node->child2()->shouldSpeculateStringIdent()
+ && node->child1()->shouldSpeculateNotStringVar()) {
+ fixEdge<StringIdentUse>(node->child2());
+ fixEdge<NotStringVarUse>(node->child1());
+ node->setOpAndDefaultFlags(CompareStrictEq);
+ return;
+ }
+ if (node->child1()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 8) || isFTL(m_graph.m_plan.mode))) {
+ fixEdge<StringUse>(node->child1());
+ node->setOpAndDefaultFlags(CompareStrictEq);
+ return;
+ }
+ if (node->child2()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 8) || isFTL(m_graph.m_plan.mode))) {
+ fixEdge<StringUse>(node->child2());
+ node->setOpAndDefaultFlags(CompareStrictEq);
+ return;
+ }
+ }
+
void fixupChecksInBlock(BasicBlock* block)
{
if (!block)
Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (231223 => 231224)
--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2018-05-02 05:51:33 UTC (rev 231224)
@@ -295,6 +295,7 @@
macro(CompareEq, NodeResultBoolean | NodeMustGenerate) \
macro(CompareStrictEq, NodeResultBoolean) \
macro(CompareEqPtr, NodeResultBoolean) \
+ macro(SameValue, NodeResultBoolean) \
\
/* Calls. */\
macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (231223 => 231224)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2018-05-02 05:51:33 UTC (rev 231224)
@@ -1237,6 +1237,14 @@
return JSValue::strictEqualSlowCaseInline(exec, op1, op2);
}
+size_t JIT_OPERATION operationSameValue(ExecState* exec, EncodedJSValue arg1, EncodedJSValue arg2)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+
+ return sameValue(exec, JSValue::decode(arg1), JSValue::decode(arg2));
+}
+
EncodedJSValue JIT_OPERATION operationToPrimitive(ExecState* exec, EncodedJSValue value)
{
VM* vm = &exec->vm();
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (231223 => 231224)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.h 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h 2018-05-02 05:51:33 UTC (rev 231224)
@@ -161,6 +161,7 @@
size_t JIT_OPERATION operationRegExpTest(ExecState*, JSGlobalObject*, RegExpObject*, EncodedJSValue) WTF_INTERNAL;
size_t JIT_OPERATION operationRegExpTestGeneric(ExecState*, JSGlobalObject*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
size_t JIT_OPERATION operationCompareStrictEqCell(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
+size_t JIT_OPERATION operationSameValue(ExecState*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
JSCell* JIT_OPERATION operationCreateActivationDirect(ExecState*, Structure*, JSScope*, SymbolTable*, EncodedJSValue);
JSCell* JIT_OPERATION operationCreateDirectArguments(ExecState*, Structure*, uint32_t length, uint32_t minCapacity);
JSCell* JIT_OPERATION operationCreateDirectArgumentsDuringExit(ExecState*, InlineCallFrame*, JSFunction*, uint32_t argumentCount);
Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (231223 => 231224)
--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2018-05-02 05:51:33 UTC (rev 231224)
@@ -851,6 +851,7 @@
case CompareEq:
case CompareStrictEq:
case CompareEqPtr:
+ case SameValue:
case OverridesHasInstance:
case InstanceOf:
case InstanceOfCustom:
Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (231223 => 231224)
--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2018-05-02 05:51:33 UTC (rev 231224)
@@ -279,6 +279,7 @@
case CompareEq:
case CompareStrictEq:
case CompareEqPtr:
+ case SameValue:
case Call:
case DirectCall:
case TailCallInlinedCaller:
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (231223 => 231224)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2018-05-02 05:51:33 UTC (rev 231224)
@@ -6365,6 +6365,72 @@
unblessedBooleanResult(resultGPR, node);
}
+void SpeculativeJIT::compileSameValue(Node* node)
+{
+ if (node->isBinaryUseKind(DoubleRepUse)) {
+ SpeculateDoubleOperand arg1(this, node->child1());
+ SpeculateDoubleOperand arg2(this, node->child2());
+ GPRTemporary result(this);
+ GPRTemporary temp(this);
+ GPRTemporary temp2(this);
+
+ FPRReg arg1FPR = arg1.fpr();
+ FPRReg arg2FPR = arg2.fpr();
+ GPRReg resultGPR = result.gpr();
+ GPRReg tempGPR = temp.gpr();
+ GPRReg temp2GPR = temp2.gpr();
+
+#if USE(JSVALUE64)
+ m_jit.moveDoubleTo64(arg1FPR, tempGPR);
+ m_jit.moveDoubleTo64(arg2FPR, temp2GPR);
+ auto trueCase = m_jit.branch64(CCallHelpers::Equal, tempGPR, temp2GPR);
+#else
+ GPRTemporary temp3(this);
+ GPRTemporary temp4(this);
+
+ GPRReg temp3GPR = temp.gpr();
+ GPRReg temp4GPR = temp2.gpr();
+
+ m_jit.moveDoubleToInts(arg1FPR, tempGPR, temp2GPR);
+ m_jit.moveDoubleToInts(arg2FPR, temp3GPR, temp4GPR);
+ auto notEqual = m_jit.branch32(CCallHelpers::NotEqual, tempGPR, temp3GPR);
+ auto trueCase = m_jit.branch32(CCallHelpers::Equal, temp2GPR, temp4GPR);
+ notEqual.link(&m_jit);
+#endif
+
+ m_jit.compareDouble(CCallHelpers::DoubleNotEqualOrUnordered, arg1FPR, arg1FPR, tempGPR);
+ m_jit.compareDouble(CCallHelpers::DoubleNotEqualOrUnordered, arg2FPR, arg2FPR, temp2GPR);
+ m_jit.and32(tempGPR, temp2GPR, resultGPR);
+ auto done = m_jit.jump();
+
+ trueCase.link(&m_jit);
+ m_jit.move(CCallHelpers::TrustedImm32(1), resultGPR);
+ done.link(&m_jit);
+
+ unblessedBooleanResult(resultGPR, node);
+ return;
+ }
+
+ ASSERT(node->isBinaryUseKind(UntypedUse));
+
+ JSValueOperand arg1(this, node->child1());
+ JSValueOperand arg2(this, node->child2());
+ JSValueRegs arg1Regs = arg1.jsValueRegs();
+ JSValueRegs arg2Regs = arg2.jsValueRegs();
+
+ arg1.use();
+ arg2.use();
+
+ flushRegisters();
+
+ GPRFlushedCallResult result(this);
+ GPRReg resultGPR = result.gpr();
+ callOperation(operationSameValue, resultGPR, arg1Regs, arg2Regs);
+ m_jit.exceptionCheck();
+
+ unblessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
+}
+
void SpeculativeJIT::compileStringZeroLength(Node* node)
{
SpeculateCellOperand str(this, node->child1());
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (231223 => 231224)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2018-05-02 05:51:33 UTC (rev 231224)
@@ -1263,6 +1263,8 @@
void compileStringIdentCompare(Node*, MacroAssembler::RelationalCondition);
bool compileStrictEq(Node*);
+
+ void compileSameValue(Node*);
void compileAllocatePropertyStorage(Node*);
void compileReallocatePropertyStorage(Node*);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (231223 => 231224)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2018-05-02 05:51:33 UTC (rev 231224)
@@ -2211,6 +2211,10 @@
compileCompareEqPtr(node);
break;
+ case SameValue:
+ compileSameValue(node);
+ break;
+
case StringCharCodeAt: {
compileGetCharCodeAt(node);
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (231223 => 231224)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2018-05-02 05:51:33 UTC (rev 231224)
@@ -2377,6 +2377,10 @@
compileCompareEqPtr(node);
break;
+ case SameValue:
+ compileSameValue(node);
+ break;
+
case StringCharCodeAt: {
compileGetCharCodeAt(node);
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGValidate.cpp (231223 => 231224)
--- trunk/Source/_javascript_Core/dfg/DFGValidate.cpp 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/dfg/DFGValidate.cpp 2018-05-02 05:51:33 UTC (rev 231224)
@@ -271,6 +271,7 @@
case CompareBelowEq:
case CompareEq:
case CompareStrictEq:
+ case SameValue:
case StrCat:
VALIDATE((node), !!node->child1());
VALIDATE((node), !!node->child2());
Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (231223 => 231224)
--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2018-05-02 05:51:33 UTC (rev 231224)
@@ -314,6 +314,7 @@
case CompareBelow:
case CompareBelowEq:
case CompareStrictEq:
+ case SameValue:
case DefineDataProperty:
case DefineAccessorProperty:
case StringSlice:
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (231223 => 231224)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2018-05-02 05:51:33 UTC (rev 231224)
@@ -987,6 +987,9 @@
case CompareEqPtr:
compileCompareEqPtr();
break;
+ case SameValue:
+ compileSameValue();
+ break;
case LogicalNot:
compileLogicalNot();
break;
@@ -7072,6 +7075,45 @@
{
setBoolean(m_out.belowOrEqual(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
}
+
+ void compileSameValue()
+ {
+ if (m_node->isBinaryUseKind(DoubleRepUse)) {
+ LValue arg1 = lowDouble(m_node->child1());
+ LValue arg2 = lowDouble(m_node->child2());
+
+ LBasicBlock numberCase = m_out.newBlock();
+ LBasicBlock continuation = m_out.newBlock();
+
+ PatchpointValue* patchpoint = m_out.patchpoint(Int32);
+ patchpoint->append(arg1, ValueRep::SomeRegister);
+ patchpoint->append(arg2, ValueRep::SomeRegister);
+ patchpoint->numGPScratchRegisters = 1;
+ patchpoint->setGenerator(
+ [] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+ GPRReg scratchGPR = params.gpScratch(0);
+ jit.moveDoubleTo64(params[1].fpr(), scratchGPR);
+ jit.moveDoubleTo64(params[2].fpr(), params[0].gpr());
+ jit.compare64(CCallHelpers::Equal, scratchGPR, params[0].gpr(), params[0].gpr());
+ });
+ patchpoint->effects = Effects::none();
+ ValueFromBlock compareResult = m_out.anchor(patchpoint);
+ m_out.branch(patchpoint, unsure(continuation), unsure(numberCase));
+
+ LBasicBlock lastNext = m_out.appendTo(numberCase, continuation);
+ LValue isArg1NaN = m_out.doubleNotEqualOrUnordered(arg1, arg1);
+ LValue isArg2NaN = m_out.doubleNotEqualOrUnordered(arg2, arg2);
+ ValueFromBlock nanResult = m_out.anchor(m_out.bitAnd(isArg1NaN, isArg2NaN));
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ setBoolean(m_out.phi(Int32, compareResult, nanResult));
+ return;
+ }
+
+ ASSERT(m_node->isBinaryUseKind(UntypedUse));
+ setBoolean(vmCall(Int32, m_out.operation(operationSameValue), m_callFrame, lowJSValue(m_node->child1()), lowJSValue(m_node->child2())));
+ }
void compileLogicalNot()
{
Modified: trunk/Source/_javascript_Core/runtime/Intrinsic.cpp (231223 => 231224)
--- trunk/Source/_javascript_Core/runtime/Intrinsic.cpp 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/runtime/Intrinsic.cpp 2018-05-02 05:51:33 UTC (rev 231224)
@@ -115,6 +115,8 @@
return "RegExpMatchFastIntrinsic";
case ObjectGetPrototypeOfIntrinsic:
return "ObjectGetPrototypeOfIntrinsic";
+ case ObjectIsIntrinsic:
+ return "ObjectIsIntrinsic";
case ReflectGetPrototypeOfIntrinsic:
return "ReflectGetPrototypeOfIntrinsic";
case StringPrototypeValueOfIntrinsic:
Modified: trunk/Source/_javascript_Core/runtime/Intrinsic.h (231223 => 231224)
--- trunk/Source/_javascript_Core/runtime/Intrinsic.h 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/runtime/Intrinsic.h 2018-05-02 05:51:33 UTC (rev 231224)
@@ -70,6 +70,7 @@
RegExpTestFastIntrinsic,
RegExpMatchFastIntrinsic,
ObjectGetPrototypeOfIntrinsic,
+ ObjectIsIntrinsic,
ReflectGetPrototypeOfIntrinsic,
StringPrototypeValueOfIntrinsic,
StringPrototypeReplaceIntrinsic,
Modified: trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp (231223 => 231224)
--- trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp 2018-05-02 04:32:33 UTC (rev 231223)
+++ trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp 2018-05-02 05:51:33 UTC (rev 231224)
@@ -83,7 +83,7 @@
isSealed objectConstructorIsSealed DontEnum|Function 1
isFrozen objectConstructorIsFrozen DontEnum|Function 1
isExtensible objectConstructorIsExtensible DontEnum|Function 1
- is objectConstructorIs DontEnum|Function 2
+ is objectConstructorIs DontEnum|Function 2 ObjectIsIntrinsic
assign objectConstructorAssign DontEnum|Function 2
values objectConstructorValues DontEnum|Function 1
entries JSBuiltin DontEnum|Function 1