summaryrefslogtreecommitdiffstats
path: root/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp')
-rw-r--r--Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp290
1 files changed, 197 insertions, 93 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp
index 945c98a..87c4234 100644
--- a/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp
@@ -78,7 +78,7 @@ void NonSpeculativeJIT::valueToNumber(JSValueOperand& operand, FPRReg fpr)
// Next handle cells (& other JS immediates)
nonNumeric.link(&m_jit);
- silentSpillAllRegisters(jsValueGpr);
+ silentSpillAllRegisters(fpr, jsValueGpr);
m_jit.move(jsValueReg, JITCompiler::argumentRegister1);
m_jit.move(JITCompiler::callFrameRegister, JITCompiler::argumentRegister0);
appendCallWithExceptionCheck(dfgConvertJSValueToNumber);
@@ -105,7 +105,7 @@ void NonSpeculativeJIT::valueToInt32(JSValueOperand& operand, GPRReg result)
JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueReg, JITCompiler::tagTypeNumberRegister);
// First handle non-integers
- silentSpillAllRegisters(jsValueGpr);
+ silentSpillAllRegisters(result, jsValueGpr);
m_jit.move(jsValueReg, JITCompiler::argumentRegister1);
m_jit.move(JITCompiler::callFrameRegister, JITCompiler::argumentRegister0);
appendCallWithExceptionCheck(dfgConvertJSValueToInt32);
@@ -126,7 +126,7 @@ void NonSpeculativeJIT::numberToInt32(FPRReg fpr, GPRReg gpr)
JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpReg, reg, JITCompiler::BranchIfTruncateSuccessful);
- silentSpillAllRegisters(gpr); // don't really care!
+ silentSpillAllRegisters(gpr);
m_jit.moveDouble(fpReg, JITCompiler::fpArgumentRegister0);
appendCallWithExceptionCheck(toInt32);
@@ -137,6 +137,40 @@ void NonSpeculativeJIT::numberToInt32(FPRReg fpr, GPRReg gpr)
truncatedToInteger.link(&m_jit);
}
+bool NonSpeculativeJIT::isKnownInteger(NodeIndex nodeIndex)
+{
+ GenerationInfo& info = m_generationInfo[m_jit.graph()[nodeIndex].virtualRegister];
+
+ DataFormat registerFormat = info.registerFormat();
+ if (registerFormat != DataFormatNone)
+ return (registerFormat | DataFormatJS) == DataFormatJSInteger;
+
+ DataFormat spillFormat = info.spillFormat();
+ if (spillFormat != DataFormatNone)
+ return (spillFormat | DataFormatJS) == DataFormatJSInteger;
+
+ ASSERT(isConstant(nodeIndex));
+ return isInt32Constant(nodeIndex);
+}
+
+bool NonSpeculativeJIT::isKnownNumeric(NodeIndex nodeIndex)
+{
+ GenerationInfo& info = m_generationInfo[m_jit.graph()[nodeIndex].virtualRegister];
+
+ DataFormat registerFormat = info.registerFormat();
+ if (registerFormat != DataFormatNone)
+ return (registerFormat | DataFormatJS) == DataFormatJSInteger
+ || (registerFormat | DataFormatJS) == DataFormatJSDouble;
+
+ DataFormat spillFormat = info.spillFormat();
+ if (spillFormat != DataFormatNone)
+ return (spillFormat | DataFormatJS) == DataFormatJSInteger
+ || (spillFormat | DataFormatJS) == DataFormatJSDouble;
+
+ ASSERT(isConstant(nodeIndex));
+ return isInt32Constant(nodeIndex) || isDoubleConstant(nodeIndex);
+}
+
void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, Node& node)
{
// ...
@@ -144,7 +178,6 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No
trackEntry(m_jit.label());
checkConsistency();
-
NodeType op = node.op;
switch (op) {
@@ -164,10 +197,20 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No
case JSConstant:
initConstantInfo(m_compileIndex);
break;
-
- case Argument:
- initArgumentInfo(m_compileIndex);
+
+ case GetLocal: {
+ GPRTemporary result(this);
+ m_jit.loadPtr(JITCompiler::addressFor(node.local()), result.registerID());
+ jsValueResult(result.gpr(), m_compileIndex);
break;
+ }
+
+ case SetLocal: {
+ JSValueOperand value(this, node.child1);
+ m_jit.storePtr(value.registerID(), JITCompiler::addressFor(node.local()));
+ noResult(m_compileIndex);
+ break;
+ }
case BitAnd:
case BitOr:
@@ -250,10 +293,8 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No
case NumberToInt32:
case ValueToInt32: {
ASSERT(!isInt32Constant(node.child1));
- GenerationInfo& operandInfo = m_generationInfo[m_jit.graph()[node.child1].virtualRegister];
- switch (operandInfo.registerFormat()) {
- case DataFormatInteger: {
+ if (isKnownInteger(node.child1)) {
IntegerOperand op1(this, node.child1);
GPRTemporary result(this, op1);
m_jit.move(op1.registerID(), result.registerID());
@@ -261,7 +302,7 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No
break;
}
- case DataFormatDouble: {
+ if (isKnownNumeric(node.child1)) {
DoubleOperand op1(this, node.child1);
GPRTemporary result(this);
numberToInt32(op1.fpr(), result.gpr());
@@ -269,84 +310,29 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No
break;
}
- default: {
- JSValueOperand op1(this, node.child1);
- GPRTemporary result(this, op1);
- op1.gpr(); // force op1 to be filled!
- result.gpr(); // force result to be allocated!
-
- switch (operandInfo.registerFormat()) {
- case DataFormatNone:
- case DataFormatInteger:
- case DataFormatDouble:
- // The operand has been filled as a JSValue; it cannot be in a !DataFormatJS state.
- CRASH();
-
- case DataFormatCell:
- case DataFormatJS:
- case DataFormatJSCell: {
- if (op == NumberToInt32) {
- FPRTemporary fpTemp(this);
- FPRReg fpr = fpTemp.fpr();
-
- JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, op1.registerID(), JITCompiler::tagTypeNumberRegister);
-
- m_jit.move(op1.registerID(), result.registerID());
- m_jit.addPtr(JITCompiler::tagTypeNumberRegister, result.registerID());
- m_jit.movePtrToDouble(result.registerID(), fpTemp.registerID());
- numberToInt32(fpr, result.gpr());
- JITCompiler::Jump wasDouble = m_jit.jump();
-
- isInteger.link(&m_jit);
- m_jit.zeroExtend32ToPtr(op1.registerID(), result.registerID());
-
- wasDouble.link(&m_jit);
- } else
- valueToInt32(op1, result.gpr());
- integerResult(result.gpr(), m_compileIndex);
- break;
- }
-
- case DataFormatJSDouble: {
- FPRTemporary fpTemp(this);
- m_jit.move(op1.registerID(), result.registerID());
- m_jit.addPtr(JITCompiler::tagTypeNumberRegister, result.registerID());
- m_jit.movePtrToDouble(result.registerID(), fpTemp.registerID());
- numberToInt32(fpTemp.fpr(), result.gpr());
- integerResult(result.gpr(), m_compileIndex);
- break;
- }
-
- case DataFormatJSInteger: {
- m_jit.move(op1.registerID(), result.registerID());
- jsValueResult(result.gpr(), m_compileIndex, DataFormatJSInteger);
- break;
- }
- }
- }
+ // We should have handled this via isKnownInteger, or isKnownNumeric!
+ ASSERT(op != NumberToInt32);
- }
+ JSValueOperand op1(this, node.child1);
+ GPRTemporary result(this, op1);
+ valueToInt32(op1, result.gpr());
+ integerResult(result.gpr(), m_compileIndex);
break;
}
case ValueToNumber: {
ASSERT(!isInt32Constant(node.child1));
ASSERT(!isDoubleConstant(node.child1));
- GenerationInfo& operandInfo = m_generationInfo[m_jit.graph()[node.child1].virtualRegister];
- switch (operandInfo.registerFormat()) {
- case DataFormatNone:
- case DataFormatCell:
- case DataFormatJS:
- case DataFormatJSCell: {
- JSValueOperand op1(this, node.child1);
+
+ if (isKnownInteger(node.child1)) {
+ IntegerOperand op1(this, node.child1);
FPRTemporary result(this);
- valueToNumber(op1, result.fpr());
+ m_jit.convertInt32ToDouble(op1.registerID(), result.registerID());
doubleResult(result.fpr(), m_compileIndex);
break;
}
- case DataFormatJSDouble:
- case DataFormatDouble: {
+ if (isKnownNumeric(node.child1)) {
DoubleOperand op1(this, node.child1);
FPRTemporary result(this, op1);
m_jit.moveDouble(op1.registerID(), result.registerID());
@@ -354,15 +340,10 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No
break;
}
- case DataFormatJSInteger:
- case DataFormatInteger: {
- IntegerOperand op1(this, node.child1);
- FPRTemporary result(this);
- m_jit.convertInt32ToDouble(op1.registerID(), result.registerID());
- doubleResult(result.fpr(), m_compileIndex);
- break;
- }
- }
+ JSValueOperand op1(this, node.child1);
+ FPRTemporary result(this);
+ valueToNumber(op1, result.fpr());
+ doubleResult(result.fpr(), m_compileIndex);
break;
}
@@ -446,6 +427,80 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No
break;
}
+ case LogicalNot: {
+ JSValueOperand arg1(this, node.child1);
+ GPRReg arg1GPR = arg1.gpr();
+ flushRegisters();
+
+ GPRResult result(this);
+ callOperation(dfgConvertJSValueToBoolean, result.gpr(), arg1GPR);
+
+ // If we add a DataFormatBool, we should use it here.
+ m_jit.xor32(TrustedImm32(ValueTrue), result.registerID());
+ jsValueResult(result.gpr(), m_compileIndex);
+ break;
+ }
+
+ case CompareLess: {
+ JSValueOperand arg1(this, node.child1);
+ JSValueOperand arg2(this, node.child2);
+ GPRReg arg1GPR = arg1.gpr();
+ GPRReg arg2GPR = arg2.gpr();
+ flushRegisters();
+
+ GPRResult result(this);
+ callOperation(operationCompareLess, result.gpr(), arg1GPR, arg2GPR);
+ m_jit.or32(TrustedImm32(ValueFalse), result.registerID());
+
+ jsValueResult(result.gpr(), m_compileIndex);
+ break;
+ }
+
+ case CompareLessEq: {
+ JSValueOperand arg1(this, node.child1);
+ JSValueOperand arg2(this, node.child2);
+ GPRReg arg1GPR = arg1.gpr();
+ GPRReg arg2GPR = arg2.gpr();
+ flushRegisters();
+
+ GPRResult result(this);
+ callOperation(operationCompareLessEq, result.gpr(), arg1GPR, arg2GPR);
+ m_jit.or32(TrustedImm32(ValueFalse), result.registerID());
+
+ jsValueResult(result.gpr(), m_compileIndex);
+ break;
+ }
+
+ case CompareEq: {
+ JSValueOperand arg1(this, node.child1);
+ JSValueOperand arg2(this, node.child2);
+ GPRReg arg1GPR = arg1.gpr();
+ GPRReg arg2GPR = arg2.gpr();
+ flushRegisters();
+
+ GPRResult result(this);
+ callOperation(operationCompareEq, result.gpr(), arg1GPR, arg2GPR);
+ m_jit.or32(TrustedImm32(ValueFalse), result.registerID());
+
+ jsValueResult(result.gpr(), m_compileIndex);
+ break;
+ }
+
+ case CompareStrictEq: {
+ JSValueOperand arg1(this, node.child1);
+ JSValueOperand arg2(this, node.child2);
+ GPRReg arg1GPR = arg1.gpr();
+ GPRReg arg2GPR = arg2.gpr();
+ flushRegisters();
+
+ GPRResult result(this);
+ callOperation(operationCompareStrictEq, result.gpr(), arg1GPR, arg2GPR);
+ m_jit.or32(TrustedImm32(ValueFalse), result.registerID());
+
+ jsValueResult(result.gpr(), m_compileIndex);
+ break;
+ }
+
case GetByVal: {
JSValueOperand arg1(this, node.child1);
JSValueOperand arg2(this, node.child2);
@@ -535,11 +590,43 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No
break;
}
+ case DFG::Jump: {
+ BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
+ if (taken != (m_block + 1))
+ addBranch(m_jit.jump(), taken);
+ noResult(m_compileIndex);
+ break;
+ }
+
+ case Branch: {
+ JSValueOperand value(this, node.child1);
+ GPRReg valueGPR = value.gpr();
+ flushRegisters();
+
+ GPRResult result(this);
+ callOperation(dfgConvertJSValueToBoolean, result.gpr(), valueGPR);
+
+ BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
+ BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
+
+ addBranch(m_jit.branchTest8(MacroAssembler::NonZero, result.registerID()), taken);
+ if (notTaken != (m_block + 1))
+ addBranch(m_jit.jump(), notTaken);
+
+ noResult(m_compileIndex);
+ break;
+ }
+
case Return: {
ASSERT(JITCompiler::callFrameRegister != JITCompiler::regT1);
ASSERT(JITCompiler::regT1 != JITCompiler::returnValueRegister);
ASSERT(JITCompiler::returnValueRegister != JITCompiler::callFrameRegister);
+#if DFG_SUCCESS_STATS
+ static SamplingCounter counter("NonSpeculativeJIT");
+ m_jit.emitCount(counter);
+#endif
+
// Return the result in returnValueRegister.
JSValueOperand op1(this, node.child1);
m_jit.move(op1.registerID(), JITCompiler::returnValueRegister);
@@ -563,23 +650,40 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No
checkConsistency();
}
-void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator)
+void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, BasicBlock& block)
{
- ASSERT(!m_compileIndex);
- Node* nodes = m_jit.graph().begin();
+ ASSERT(m_compileIndex == block.begin);
+ m_blockHeads[m_block] = m_jit.label();
- for (; m_compileIndex < m_jit.graph().size(); ++m_compileIndex) {
-#if DFG_DEBUG_VERBOSE
- fprintf(stderr, "index(%d)\n", (int)m_compileIndex);
+#if DFG_JIT_BREAK_ON_EVERY_BLOCK
+ m_jit.breakpoint();
#endif
- Node& node = nodes[m_compileIndex];
+ for (; m_compileIndex < block.end; ++m_compileIndex) {
+ Node& node = m_jit.graph()[m_compileIndex];
if (!node.refCount)
continue;
+
+#if DFG_DEBUG_VERBOSE
+ fprintf(stderr, "NonSpeculativeJIT generating Node @%d at code offset 0x%x\n", (int)m_compileIndex, m_jit.debugOffset());
+#endif
+#if DFG_JIT_BREAK_ON_EVERY_NODE
+ m_jit.breakpoint();
+#endif
+
compile(checkIterator, node);
}
}
+void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator)
+{
+ ASSERT(!m_compileIndex);
+ Vector<BasicBlock> blocks = m_jit.graph().m_blocks;
+ for (m_block = 0; m_block < blocks.size(); ++m_block)
+ compile(checkIterator, blocks[m_block]);
+ linkBranches();
+}
+
} } // namespace JSC::DFG
#endif