The StringFromCharCode DFG intrinsic should support untyped operands.
https://bugs.webkit.org/show_bug.cgi?id=153046
Reviewed by Geoffrey Garen.
Source/JavaScriptCore:
The current StringFromCharCode DFG intrinsic assumes that its operand charCode
must be an Int32. This results in 26000+ BadType OSR exits in the LongSpider
crypto-aes benchmark. With support for Untyped operands, the number of OSR
exits drops to 202.
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileFromCharCode):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
* dfg/DFGValidate.cpp:
(JSC::DFG::Validate::validate):
* runtime/JSCJSValueInlines.h:
(JSC::JSValue::toUInt32):
LayoutTests:
* js/regress/ftl-polymorphic-StringFromCharCode-expected.txt: Added.
* js/regress/ftl-polymorphic-StringFromCharCode.html: Added.
* js/regress/script-tests/ftl-polymorphic-StringFromCharCode.js: Added.
(o1.valueOf):
(foo):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@194996 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index c7b37ac..56ddc3d 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,5 +1,32 @@
2016-01-13 Mark Lam <mark.lam@apple.com>
+ The StringFromCharCode DFG intrinsic should support untyped operands.
+ https://bugs.webkit.org/show_bug.cgi?id=153046
+
+ Reviewed by Geoffrey Garen.
+
+ The current StringFromCharCode DFG intrinsic assumes that its operand charCode
+ must be an Int32. This results in 26000+ BadType OSR exits in the LongSpider
+ crypto-aes benchmark. With support for Untyped operands, the number of OSR
+ exits drops to 202.
+
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileFromCharCode):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::callOperation):
+ * dfg/DFGValidate.cpp:
+ (JSC::DFG::Validate::validate):
+ * runtime/JSCJSValueInlines.h:
+ (JSC::JSValue::toUInt32):
+
+2016-01-13 Mark Lam <mark.lam@apple.com>
+
Use DFG Graph::binary/unaryArithShouldSpeculateInt32/MachineInt() functions consistently.
https://bugs.webkit.org/show_bug.cgi?id=153080
diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.h b/Source/JavaScriptCore/dfg/DFGClobberize.h
index 72b24c7..343a6de 100644
--- a/Source/JavaScriptCore/dfg/DFGClobberize.h
+++ b/Source/JavaScriptCore/dfg/DFGClobberize.h
@@ -135,7 +135,6 @@
case GetScope:
case SkipScope:
case StringCharCodeAt:
- case StringFromCharCode:
case CompareStrictEq:
case IsUndefined:
case IsBoolean:
@@ -258,6 +257,20 @@
return;
}
+ case StringFromCharCode:
+ switch (node->child1().useKind()) {
+ case Int32Use:
+ def(PureValue(node));
+ return;
+ case UntypedUse:
+ read(World);
+ write(Heap);
+ return;
+ default:
+ DFG_CRASH(graph, node, "Bad use kind");
+ }
+ return;
+
case ArithAdd:
case ArithNegate:
case ArithMod:
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index 3d58530..c9d5abf 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -602,6 +602,10 @@
}
case StringFromCharCode:
+ if (node->child1()->shouldSpeculateUntypedForArithmetic()) {
+ fixEdge<UntypedUse>(node->child1());
+ break;
+ }
fixEdge<Int32Use>(node->child1());
break;
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp
index fc781eb..2fd5dbd 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp
@@ -1313,6 +1313,15 @@
return JSC::stringFromCharCode(exec, op1);
}
+EncodedJSValue JIT_OPERATION operationStringFromCharCodeUntyped(ExecState* exec, EncodedJSValue encodedValue)
+{
+ VM* vm = &exec->vm();
+ NativeCallFrameTracer tracer(vm, exec);
+ JSValue charValue = JSValue::decode(encodedValue);
+ int32_t chInt = charValue.toUInt32(exec);
+ return JSValue::encode(JSC::stringFromCharCode(exec, chInt));
+}
+
int64_t JIT_OPERATION operationConvertBoxedDoubleToInt52(EncodedJSValue encodedValue)
{
JSValue value = JSValue::decode(encodedValue);
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h
index 5a48065..409629f 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.h
+++ b/Source/JavaScriptCore/dfg/DFGOperations.h
@@ -38,6 +38,7 @@
extern "C" {
JSCell* JIT_OPERATION operationStringFromCharCode(ExecState*, int32_t) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationStringFromCharCodeUntyped(ExecState*, EncodedJSValue) WTF_INTERNAL;
// These routines are provide callbacks out to C++ implementations of operations too complex to JIT.
JSCell* JIT_OPERATION operationCreateThis(ExecState*, JSObject* constructor, int32_t inlineCapacity) WTF_INTERNAL;
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index bbabe26..ccce791 100755
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -1871,7 +1871,27 @@
void SpeculativeJIT::compileFromCharCode(Node* node)
{
- SpeculateStrictInt32Operand property(this, node->child1());
+ Edge& child = node->child1();
+ if (child.useKind() == UntypedUse) {
+ JSValueOperand opr(this, child);
+ JSValueRegs oprRegs = opr.jsValueRegs();
+#if USE(JSVALUE64)
+ GPRTemporary result(this);
+ JSValueRegs resultRegs = JSValueRegs(result.gpr());
+#else
+ GPRTemporary resultTag(this);
+ GPRTemporary resultPayload(this);
+ JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
+#endif
+ flushRegisters();
+ callOperation(operationStringFromCharCodeUntyped, resultRegs, oprRegs);
+ m_jit.exceptionCheck();
+
+ jsValueResult(resultRegs, node);
+ return;
+ }
+
+ SpeculateStrictInt32Operand property(this, child);
GPRReg propertyReg = property.gpr();
GPRTemporary smallStrings(this);
GPRTemporary scratch(this);
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index 0322bb7..5312c8d 100755
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -1409,6 +1409,10 @@
m_jit.setupArgumentsWithExecState(arg1);
return appendCallSetResult(operation, result);
}
+ JITCompiler::Call callOperation(J_JITOperation_EJ operation, JSValueRegs result, JSValueRegs arg1)
+ {
+ return callOperation(operation, result.payloadGPR(), arg1.payloadGPR());
+ }
JITCompiler::Call callOperation(J_JITOperation_EJ operation, GPRReg result, GPRReg arg1)
{
m_jit.setupArgumentsWithExecState(arg1);
@@ -1610,6 +1614,10 @@
m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallSetResult(operation, resultPayload, resultTag);
}
+ JITCompiler::Call callOperation(J_JITOperation_EJ operation, JSValueRegs result, JSValueRegs arg1)
+ {
+ return callOperation(operation, result.tagGPR(), result.payloadGPR(), arg1.tagGPR(), arg1.payloadGPR());
+ }
JITCompiler::Call callOperation(J_JITOperation_EJ operation, GPRReg resultPayload, GPRReg resultTag, GPRReg arg1)
{
m_jit.setupArgumentsWithExecState(arg1);
diff --git a/Source/JavaScriptCore/dfg/DFGValidate.cpp b/Source/JavaScriptCore/dfg/DFGValidate.cpp
index de68e63..3fe1da2 100644
--- a/Source/JavaScriptCore/dfg/DFGValidate.cpp
+++ b/Source/JavaScriptCore/dfg/DFGValidate.cpp
@@ -264,6 +264,7 @@
VALIDATE((node), !!node->child2());
break;
case CheckStructure:
+ case StringFromCharCode:
VALIDATE((node), !!node->child1());
break;
case PutStructure:
diff --git a/Source/JavaScriptCore/runtime/JSCJSValueInlines.h b/Source/JavaScriptCore/runtime/JSCJSValueInlines.h
index c8f1f08..2bff86b 100644
--- a/Source/JavaScriptCore/runtime/JSCJSValueInlines.h
+++ b/Source/JavaScriptCore/runtime/JSCJSValueInlines.h
@@ -46,7 +46,7 @@
inline uint32_t JSValue::toUInt32(ExecState* exec) const
{
- // See comment on JSC::toUInt32, above.
+ // See comment on JSC::toUInt32, in JSCJSValue.h.
return toInt32(exec);
}