Skip to content
Permalink
Browse files
[BigInt] Implement ValueBitXor into DFG
https://bugs.webkit.org/show_bug.cgi?id=190264

Reviewed by Yusuke Suzuki.

JSTests:

* stress/big-int-bitwise-xor-jit.js: Added.
* stress/big-int-bitwise-xor-memory-stress.js: Added.
* stress/big-int-bitwise-xor-untyped.js: Added.

Source/JavaScriptCore:

This patch is splitting the BitXor node into ArithBitXor and
ValueBitXor. This is necessary due the introduction of
BigInt, since BitXor operations now can result into Int32 or BigInt.
In such case, we use ArithBitXor when operands are Int and fallback to
ValueBitXor when operands are anything else. In the case of
ValueBitXor, we speculate BigInt when op1 and op2 are predicted as
BigInt as well. BigInt specialization consist into call
`operationBigIntBitXor` function, that calls JSBigInt::bitXor.

* bytecode/BytecodeList.rb:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::finishCreation):
(JSC::CodeBlock::arithProfileForPC):
* bytecode/Opcode.h:
(JSC::padOpcodeName):
* bytecompiler/BytecodeGenerator.h:
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGBackwardsPropagationPhase.cpp:
(JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwo):
(JSC::DFG::BackwardsPropagationPhase::propagate):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileValueBitwiseOp):
(JSC::DFG::SpeculativeJIT::compileBitwiseOp):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::bitOp):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::handleNode):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileValueBitXor):
(JSC::FTL::DFG::LowerDFGToB3::compileArithBitXor):
(JSC::FTL::DFG::LowerDFGToB3::compileBitXor): Deleted.
* jit/JITArithmetic.cpp:
(JSC::JIT::emit_op_bitxor):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):


Canonical link: https://commits.webkit.org/206876@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238732 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
caiolima committed Nov 30, 2018
1 parent b39d3fc commit eee9ccecbc83df0bccda152f51533caee66fb02b
Showing 31 changed files with 261 additions and 67 deletions.
@@ -1,3 +1,14 @@
2018-11-30 Caio Lima <ticaiolima@gmail.com>

[BigInt] Implement ValueBitXor into DFG
https://bugs.webkit.org/show_bug.cgi?id=190264

Reviewed by Yusuke Suzuki.

* stress/big-int-bitwise-xor-jit.js: Added.
* stress/big-int-bitwise-xor-memory-stress.js: Added.
* stress/big-int-bitwise-xor-untyped.js: Added.

2018-11-27 Saam barati <sbarati@apple.com>

r238510 broke scopes of size zero
@@ -0,0 +1,25 @@
//@ runBigIntEnabled

let assert = {
sameValue: function(i, e) {
if (i !== e)
throw new Error(m);
}
}

function bigIntBitXor(a, b) {
return (a ^ b) ^ (a ^ 0b11n);

}
noInline(bigIntBitXor);

for (let i = 0; i < 10000; i++) {
let r = bigIntBitXor(0b11n, 0b1010n);
assert.sameValue(r, 0b1001n);
}

for (let i = 0; i < 10000; i++) {
let r = bigIntBitXor(0xfffafafaf19281fefafeafebcn, 0b1010n);
assert.sameValue(r, 0b1001n);
}

@@ -0,0 +1,14 @@
//@ runBigIntEnabled

function assert(a) {
if (!a)
throw new Error("Bad assertion");
}

let a = 0b11n;
for (let i = 0; i < 1000000; i++) {
a ^= 0b01n;
}

assert(a === 0b11n);

@@ -0,0 +1,26 @@
//@ runBigIntEnabled

function assert(v, e) {
if (v !== e)
throw new Error("Expected value: " + e + " but got: " + v)
}

function bigIntOperations(a, b) {
let c = a ^ b;
return a ^ c;
}
noInline(bigIntOperations);

c = 0;
let o = { valueOf: function () {
c++;
return 0b1111n;
}};

for (let i = 0; i < 100000; i++) {
let out = bigIntOperations(o, 0b1010n);
assert(out, 0b1010n);
}

assert(c, 200000);

@@ -1,3 +1,70 @@
2018-11-30 Caio Lima <ticaiolima@gmail.com>

[BigInt] Implement ValueBitXor into DFG
https://bugs.webkit.org/show_bug.cgi?id=190264

Reviewed by Yusuke Suzuki.

This patch is splitting the BitXor node into ArithBitXor and
ValueBitXor. This is necessary due the introduction of
BigInt, since BitXor operations now can result into Int32 or BigInt.
In such case, we use ArithBitXor when operands are Int and fallback to
ValueBitXor when operands are anything else. In the case of
ValueBitXor, we speculate BigInt when op1 and op2 are predicted as
BigInt as well. BigInt specialization consist into call
`operationBigIntBitXor` function, that calls JSBigInt::bitXor.

* bytecode/BytecodeList.rb:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::finishCreation):
(JSC::CodeBlock::arithProfileForPC):
* bytecode/Opcode.h:
(JSC::padOpcodeName):
* bytecompiler/BytecodeGenerator.h:
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGBackwardsPropagationPhase.cpp:
(JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwo):
(JSC::DFG::BackwardsPropagationPhase::propagate):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileValueBitwiseOp):
(JSC::DFG::SpeculativeJIT::compileBitwiseOp):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::bitOp):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::handleNode):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileValueBitXor):
(JSC::FTL::DFG::LowerDFGToB3::compileArithBitXor):
(JSC::FTL::DFG::LowerDFGToB3::compileBitXor): Deleted.
* jit/JITArithmetic.cpp:
(JSC::JIT::emit_op_bitxor):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):

2018-11-29 Justin Michaud <justin_michaud@apple.com>

CSS Painting API should pass 'this' correctly to paint callback, and repaint when properties change.
@@ -240,7 +240,6 @@
:mul,
:div,
:sub,
:bitxor,
],
args: {
dst: VirtualRegister,
@@ -259,6 +258,7 @@
[
:bitand,
:bitor,
:bitxor,
],
args: {
dst: VirtualRegister,
@@ -567,6 +567,7 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
LINK(OpBitand, profile)
LINK(OpBitor, profile)
LINK(OpBitnot, profile)
LINK(OpBitxor, profile)

LINK(OpGetById, profile, hitCountForLLIntCaching)

@@ -592,7 +593,6 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
LINK(OpMul)
LINK(OpDiv)
LINK(OpSub)
LINK(OpBitxor)

LINK(OpNegate)

@@ -2953,8 +2953,6 @@ ArithProfile* CodeBlock::arithProfileForPC(const Instruction* pc)
switch (pc->opcodeID()) {
case op_negate:
return &pc->as<OpNegate>().metadata(this).arithProfile;
case op_bitxor:
return &pc->as<OpBitxor>().metadata(this).arithProfile;
case op_add:
return &pc->as<OpAdd>().metadata(this).arithProfile;
case op_mul:
@@ -110,6 +110,7 @@ IGNORE_WARNINGS_END
macro(OpBitand) \
macro(OpBitor) \
macro(OpBitnot) \
macro(OpBitxor) \

#define FOR_EACH_OPCODE_WITH_ARRAY_PROFILE(macro) \
macro(OpHasIndexedProperty) \
@@ -684,8 +684,9 @@ namespace JSC {

template<typename BinaryOp>
std::enable_if_t<
BinaryOp::opcodeID != op_bitxor && BinaryOp::opcodeID != op_add
&& BinaryOp::opcodeID != op_mul && BinaryOp::opcodeID != op_sub
BinaryOp::opcodeID != op_add
&& BinaryOp::opcodeID != op_mul
&& BinaryOp::opcodeID != op_sub
&& BinaryOp::opcodeID != op_div,
RegisterID*>
emitBinaryOp(RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes)
@@ -696,8 +697,9 @@ namespace JSC {

template<typename BinaryOp>
std::enable_if_t<
BinaryOp::opcodeID == op_bitxor || BinaryOp::opcodeID == op_add
|| BinaryOp::opcodeID == op_mul || BinaryOp::opcodeID == op_sub
BinaryOp::opcodeID == op_add
|| BinaryOp::opcodeID == op_mul
|| BinaryOp::opcodeID == op_sub
|| BinaryOp::opcodeID == op_div,
RegisterID*>
emitBinaryOp(RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes types)
@@ -374,7 +374,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
m_state.operand(data->start.offset() + i).makeHeapTop();
break;
}

case ArithBitNot: {
if (node->child1().useKind() == UntypedUse) {
clobberWorld();
@@ -393,8 +393,9 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
break;
}

case ValueBitOr:
case ValueBitXor:
case ValueBitAnd:
case ValueBitOr:
clobberWorld();
if (node->binaryUseKind() == BigIntUse)
setTypeForNode(node, SpecBigInt);
@@ -404,7 +405,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi

case ArithBitAnd:
case ArithBitOr:
case BitXor:
case ArithBitXor:
case BitRShift:
case BitLShift:
case BitURShift: {
@@ -426,7 +427,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
case ArithBitOr:
setConstant(node, JSValue(a | b));
break;
case BitXor:
case ArithBitXor:
setConstant(node, JSValue(a ^ b));
break;
case BitRShift:
@@ -119,7 +119,7 @@ class BackwardsPropagationPhase : public Phase {
}

case ArithBitOr:
case BitXor:
case ArithBitXor:
case BitLShift: {
return power > 31;
}
@@ -217,7 +217,7 @@ class BackwardsPropagationPhase : public Phase {

case ArithBitAnd:
case ArithBitOr:
case BitXor:
case ArithBitXor:
case BitRShift:
case BitLShift:
case BitURShift:
@@ -4925,8 +4925,11 @@ void ByteCodeParser::parseBlock(unsigned limit)
auto bytecode = currentInstruction->as<OpBitxor>();
Node* op1 = get(bytecode.lhs);
Node* op2 = get(bytecode.rhs);
set(bytecode.dst, addToGraph(BitXor, op1, op2));
NEXT_OPCODE(op_bitxor);
if (isInt32Speculation(getPrediction()))
set(bytecode.dst, addToGraph(ArithBitXor, op1, op2));
else
set(bytecode.dst, addToGraph(ValueBitXor, op1, op2));
NEXT_OPCODE(op_bitor);
}

case op_rshift: {
@@ -273,7 +273,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu

case ArithBitAnd:
case ArithBitOr:
case BitXor:
case ArithBitXor:
case BitLShift:
case BitRShift:
case BitURShift:
@@ -645,6 +645,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
case InById:
case HasOwnProperty:
case ValueBitAnd:
case ValueBitXor:
case ValueBitOr:
case ValueNegate:
case ValueAdd:
@@ -70,7 +70,7 @@ bool doesGC(Graph& graph, Node* node)
case ArithBitNot:
case ArithBitAnd:
case ArithBitOr:
case BitXor:
case ArithBitXor:
case BitLShift:
case BitRShift:
case BitURShift:
@@ -99,6 +99,7 @@ bool doesGC(Graph& graph, Node* node)
case ArithUnary:
case ValueBitAnd:
case ValueBitOr:
case ValueBitXor:
case ValueAdd:
case ValueSub:
case ValueNegate:
@@ -130,6 +130,7 @@ class FixupPhase : public Phase {
break;
}

case ValueBitXor:
case ValueBitOr:
case ValueBitAnd: {
if (Node::shouldSpeculateBigInt(node->child1().node(), node->child2().node())) {
@@ -142,7 +143,7 @@ class FixupPhase : public Phase {
fixEdge<UntypedUse>(node->child2());
break;
}

case ArithBitNot: {
if (node->child1().node()->shouldSpeculateUntypedForBitOps()) {
fixEdge<UntypedUse>(node->child1());
@@ -154,13 +155,16 @@ class FixupPhase : public Phase {
break;
}

case ArithBitXor:
case ArithBitOr:
case ArithBitAnd: {
if (Node::shouldSpeculateUntypedForBitOps(node->child1().node(), node->child2().node())) {
fixEdge<UntypedUse>(node->child1());
fixEdge<UntypedUse>(node->child2());

switch (op) {
case ArithBitXor:
node->setOpAndDefaultFlags(ValueBitXor);
break;
case ArithBitOr:
node->setOpAndDefaultFlags(ValueBitOr);
break;
@@ -171,15 +175,14 @@ class FixupPhase : public Phase {
DFG_CRASH(m_graph, node, "Unexpected node during ArithBit operation fixup");
break;
}

break;
}

fixIntConvertingEdge(node->child1());
fixIntConvertingEdge(node->child2());
break;
}

case BitXor:
case BitRShift:
case BitLShift:
case BitURShift: {
@@ -116,7 +116,8 @@ namespace JSC { namespace DFG {
macro(ArithBitAnd, NodeResultInt32) \
macro(ValueBitOr, NodeResultJS | NodeMustGenerate) \
macro(ArithBitOr, NodeResultInt32) \
macro(BitXor, NodeResultInt32) \
macro(ValueBitXor, NodeResultJS | NodeMustGenerate) \
macro(ArithBitXor, NodeResultInt32) \
macro(BitLShift, NodeResultInt32) \
macro(BitRShift, NodeResultInt32) \
macro(BitURShift, NodeResultInt32) \

0 comments on commit eee9cce

Please sign in to comment.