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);
 }