Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (96992 => 96993)
--- trunk/Source/_javascript_Core/ChangeLog 2011-10-08 00:06:07 UTC (rev 96992)
+++ trunk/Source/_javascript_Core/ChangeLog 2011-10-08 00:06:51 UTC (rev 96993)
@@ -1,3 +1,28 @@
+2011-10-07 Oliver Hunt <[email protected]>
+
+ Support some string intrinsics in the DFG JIT
+ https://bugs.webkit.org/show_bug.cgi?id=69678
+
+ Reviewed by Gavin Barraclough.
+
+ Add support for charAt and charCodeAt intrinsics in the DFG.
+
+ * create_hash_table:
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleIntrinsic):
+ * dfg/DFGIntrinsic.h:
+ * dfg/DFGNode.h:
+ * dfg/DFGPropagator.cpp:
+ (JSC::DFG::Propagator::propagateNodePredictions):
+ (JSC::DFG::Propagator::performNodeCSE):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileGetCharCodeAt):
+ * dfg/DFGSpeculativeJIT.h:
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+
2011-10-07 Mark Hahnenberg <[email protected]>
Add static version of JSCell::put
Modified: trunk/Source/_javascript_Core/create_hash_table (96992 => 96993)
--- trunk/Source/_javascript_Core/create_hash_table 2011-10-08 00:06:07 UTC (rev 96992)
+++ trunk/Source/_javascript_Core/create_hash_table 2011-10-08 00:06:51 UTC (rev 96993)
@@ -280,9 +280,11 @@
my $intrinsic = "DFG::NoIntrinsic";
if ($key eq "charCodeAt") {
$thunkGenerator = "charCodeAtThunkGenerator";
+ $intrinsic = "DFG::CharCodeAtIntrinsic";
}
if ($key eq "charAt") {
$thunkGenerator = "charAtThunkGenerator";
+ $intrinsic = "DFG::CharAtIntrinsic";
}
if ($key eq "fromCharCode") {
$thunkGenerator = "fromCharCodeThunkGenerator";
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (96992 => 96993)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2011-10-08 00:06:07 UTC (rev 96992)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2011-10-08 00:06:51 UTC (rev 96993)
@@ -740,7 +740,27 @@
set(resultOperand, arrayPop);
return true;
}
+
+ case CharCodeAtIntrinsic: {
+ if (firstArg + 1 != lastArg)
+ return false;
+
+ NodeIndex charCode = addToGraph(StringCharCodeAt, get(firstArg), getToInt32(firstArg + 1));
+ if (usesResult)
+ set(resultOperand, charCode);
+ return true;
+ }
+
+ case CharAtIntrinsic: {
+ if (firstArg + 1 != lastArg)
+ return false;
+ NodeIndex charCode = addToGraph(StringCharAt, get(firstArg), getToInt32(firstArg + 1));
+ if (usesResult)
+ set(resultOperand, charCode);
+ return true;
+ }
+
default:
ASSERT(intrinsic == NoIntrinsic);
return false;
Modified: trunk/Source/_javascript_Core/dfg/DFGIntrinsic.h (96992 => 96993)
--- trunk/Source/_javascript_Core/dfg/DFGIntrinsic.h 2011-10-08 00:06:07 UTC (rev 96992)
+++ trunk/Source/_javascript_Core/dfg/DFGIntrinsic.h 2011-10-08 00:06:51 UTC (rev 96993)
@@ -35,7 +35,9 @@
MaxIntrinsic,
SqrtIntrinsic,
ArrayPushIntrinsic,
- ArrayPopIntrinsic
+ ArrayPopIntrinsic,
+ CharCodeAtIntrinsic,
+ CharAtIntrinsic
};
} } // namespace JSC::DFG
Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (96992 => 96993)
--- trunk/Source/_javascript_Core/dfg/DFGNode.h 2011-10-08 00:06:07 UTC (rev 96992)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h 2011-10-08 00:06:51 UTC (rev 96993)
@@ -347,6 +347,10 @@
macro(ArrayPush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
macro(ArrayPop, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
\
+ /* Optimizations for string access */ \
+ macro(StringCharCodeAt, NodeResultInt32) \
+ macro(StringCharAt, NodeResultJS) \
+ \
/* Nodes for comparison operations. */\
macro(CompareLess, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
macro(CompareLessEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
Modified: trunk/Source/_javascript_Core/dfg/DFGPropagator.cpp (96992 => 96993)
--- trunk/Source/_javascript_Core/dfg/DFGPropagator.cpp 2011-10-08 00:06:07 UTC (rev 96992)
+++ trunk/Source/_javascript_Core/dfg/DFGPropagator.cpp 2011-10-08 00:06:51 UTC (rev 96993)
@@ -342,7 +342,11 @@
changed |= mergePrediction(node.getHeapPrediction());
break;
}
-
+
+ case StringCharCodeAt: {
+ changed |= mergePrediction(PredictInt32);
+ }
+
case ArithMod: {
PredictedType left = m_graph[node.child1()].prediction();
PredictedType right = m_graph[node.child2()].prediction();
@@ -534,7 +538,8 @@
changed |= setPrediction(PredictObjectOther);
break;
}
-
+
+ case StringCharAt:
case StrCat: {
changed |= setPrediction(PredictString);
break;
@@ -1270,6 +1275,8 @@
case ArithSqrt:
case GetCallee:
case GetStringLength:
+ case StringCharAt:
+ case StringCharCodeAt:
setReplacement(pureCSE(node));
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (96992 => 96993)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2011-10-08 00:06:07 UTC (rev 96992)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2011-10-08 00:06:51 UTC (rev 96993)
@@ -528,6 +528,35 @@
}
}
+void SpeculativeJIT::compileGetCharCodeAt(Node& node)
+{
+ ASSERT(node.child3() == NoNode);
+ SpeculateCellOperand string(this, node.child1());
+ SpeculateStrictInt32Operand index(this, node.child2());
+
+ GPRReg stringReg = string.gpr();
+ GPRReg indexReg = index.gpr();
+
+ if (!isKnownString(node.child1()))
+ speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(stringReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
+
+ // unsigned comparison so we can filter out negative indices and indices that are too large
+ speculationCheck(m_jit.branch32(MacroAssembler::AboveOrEqual, indexReg, MacroAssembler::Address(stringReg, JSString::offsetOfLength())));
+
+ // Speculate that we're not accessing a rope
+ speculationCheck(m_jit.branchTest32(MacroAssembler::NonZero, MacroAssembler::Address(stringReg, JSString::offsetOfFiberCount())));
+
+ GPRTemporary scratch(this);
+ GPRReg scratchReg = scratch.gpr();
+
+ // Load the character into scratchReg
+ m_jit.loadPtr(MacroAssembler::Address(stringReg, JSString::offsetOfValue()), scratchReg);
+ m_jit.loadPtr(MacroAssembler::Address(scratchReg, StringImpl::dataOffset()), scratchReg);
+ m_jit.load16(MacroAssembler::BaseIndex(scratchReg, indexReg, MacroAssembler::TimesTwo, 0), scratchReg);
+
+ integerResult(scratchReg, m_compileIndex);
+}
+
void SpeculativeJIT::compileGetByValOnString(Node& node)
{
ASSERT(node.child3() == NoNode);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (96992 => 96993)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2011-10-08 00:06:07 UTC (rev 96992)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2011-10-08 00:06:51 UTC (rev 96993)
@@ -456,6 +456,7 @@
void emitObjectOrOtherBranch(NodeIndex value, BlockIndex taken, BlockIndex notTaken, void *vptr);
void emitBranch(Node&);
+ void compileGetCharCodeAt(Node&);
void compileGetByValOnString(Node&);
// It is acceptable to have structure be equal to scratch, so long as you're fine
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (96992 => 96993)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2011-10-08 00:06:07 UTC (rev 96992)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2011-10-08 00:06:51 UTC (rev 96993)
@@ -1251,6 +1251,17 @@
return;
break;
+ case StringCharCodeAt: {
+ compileGetCharCodeAt(node);
+ break;
+ }
+
+ case StringCharAt: {
+ // Relies on StringCharAt node having same basic layout as GetByVal
+ compileGetByValOnString(node);
+ break;
+ }
+
case GetByVal: {
if (at(node.child1()).prediction() == PredictString) {
compileGetByValOnString(node);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (96992 => 96993)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2011-10-08 00:06:07 UTC (rev 96992)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2011-10-08 00:06:51 UTC (rev 96993)
@@ -1371,6 +1371,17 @@
return;
break;
+ case StringCharCodeAt: {
+ compileGetCharCodeAt(node);
+ break;
+ }
+
+ case StringCharAt: {
+ // Relies on StringCharAt node having same basic layout as GetByVal
+ compileGetByValOnString(node);
+ break;
+ }
+
case GetByVal: {
if (at(node.child1()).prediction() == PredictString) {
compileGetByValOnString(node);