Diff
Modified: releases/WebKitGTK/webkit-2.12/LayoutTests/ChangeLog (197759 => 197760)
--- releases/WebKitGTK/webkit-2.12/LayoutTests/ChangeLog 2016-03-08 13:35:32 UTC (rev 197759)
+++ releases/WebKitGTK/webkit-2.12/LayoutTests/ChangeLog 2016-03-08 13:57:58 UTC (rev 197760)
@@ -1,3 +1,19 @@
+2016-03-03 Filip Pizlo <[email protected]>
+
+ DFG should be able to compile StringReplace
+ https://bugs.webkit.org/show_bug.cgi?id=154979
+
+ Reviewed by Benjamin Poulain.
+
+ Add a microbenchmark for a case of StringReplace that we hadn't covered with a microbenchmark
+ yet: using something absurd for the replace value. This is interesting for implementing the
+ 32_64 version of StringReplace, which gets really weird in the absurd case because of how it
+ consumes the entire register file while making the call on x86-32.
+
+ * js/regress/script-tests/string-replace-generic.js: Added.
+ * js/regress/string-replace-generic-expected.txt: Added.
+ * js/regress/string-replace-generic.html: Added.
+
2016-03-02 Zalan Bujtas <[email protected]>
Paint table borders on empty cells even in quirks mode.
Added: releases/WebKitGTK/webkit-2.12/LayoutTests/js/regress/script-tests/string-replace-generic.js (0 => 197760)
--- releases/WebKitGTK/webkit-2.12/LayoutTests/js/regress/script-tests/string-replace-generic.js (rev 0)
+++ releases/WebKitGTK/webkit-2.12/LayoutTests/js/regress/script-tests/string-replace-generic.js 2016-03-08 13:57:58 UTC (rev 197760)
@@ -0,0 +1,8 @@
+(function() {
+ var result;
+ for (var i = 0; i < 400000; ++i) {
+ result = "foo".replace(/f/g, 42);
+ }
+ if (result != "42oo")
+ throw "Error: bad result: "+ result;
+})();
Added: releases/WebKitGTK/webkit-2.12/LayoutTests/js/regress/string-replace-generic-expected.txt (0 => 197760)
--- releases/WebKitGTK/webkit-2.12/LayoutTests/js/regress/string-replace-generic-expected.txt (rev 0)
+++ releases/WebKitGTK/webkit-2.12/LayoutTests/js/regress/string-replace-generic-expected.txt 2016-03-08 13:57:58 UTC (rev 197760)
@@ -0,0 +1,10 @@
+JSRegress/string-replace-generic
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: releases/WebKitGTK/webkit-2.12/LayoutTests/js/regress/string-replace-generic.html (0 => 197760)
--- releases/WebKitGTK/webkit-2.12/LayoutTests/js/regress/string-replace-generic.html (rev 0)
+++ releases/WebKitGTK/webkit-2.12/LayoutTests/js/regress/string-replace-generic.html 2016-03-08 13:57:58 UTC (rev 197760)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Modified: releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/ChangeLog (197759 => 197760)
--- releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/ChangeLog 2016-03-08 13:35:32 UTC (rev 197759)
+++ releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/ChangeLog 2016-03-08 13:57:58 UTC (rev 197760)
@@ -1,3 +1,26 @@
+2016-03-03 Filip Pizlo <[email protected]>
+
+ DFG should be able to compile StringReplace
+ https://bugs.webkit.org/show_bug.cgi?id=154979
+
+ Reviewed by Benjamin Poulain.
+
+ Adds support for StringReplace to the DFG tier. This is a 3% speed-up on Octane/regexp.
+
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::speculateFinalObject):
+ (JSC::DFG::SpeculativeJIT::speculateRegExpObject):
+ (JSC::DFG::SpeculativeJIT::speculateObjectOrOther):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::callOperation):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * jit/JITOperations.h:
+
2016-03-02 Filip Pizlo <[email protected]>
RegExpExec/RegExpTest should not unconditionally speculate cell
Modified: releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (197759 => 197760)
--- releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-03-08 13:35:32 UTC (rev 197759)
+++ releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-03-08 13:57:58 UTC (rev 197760)
@@ -2190,12 +2190,6 @@
}
case StringPrototypeReplaceIntrinsic: {
- if (!isFTL(m_graph.m_plan.mode)) {
- // This is a marginally profitable intrinsic. We've only the work to make it an
- // intrinsic on the fourth tier.
- return false;
- }
-
if (argumentCountIncludingThis != 3)
return false;
Modified: releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (197759 => 197760)
--- releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2016-03-08 13:35:32 UTC (rev 197759)
+++ releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2016-03-08 13:57:58 UTC (rev 197760)
@@ -6623,13 +6623,18 @@
speculateCellType(edge, operand.gpr(), SpecFinalObject, FinalObjectType);
}
+void SpeculativeJIT::speculateRegExpObject(Edge edge, GPRReg cell)
+{
+ speculateCellType(edge, cell, SpecRegExpObject, RegExpObjectType);
+}
+
void SpeculativeJIT::speculateRegExpObject(Edge edge)
{
if (!needsTypeCheck(edge, SpecRegExpObject))
return;
SpeculateCellOperand operand(this, edge);
- speculateCellType(edge, operand.gpr(), SpecRegExpObject, RegExpObjectType);
+ speculateRegExpObject(edge, operand.gpr());
}
void SpeculativeJIT::speculateObjectOrOther(Edge edge)
Modified: releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (197759 => 197760)
--- releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2016-03-08 13:35:32 UTC (rev 197759)
+++ releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2016-03-08 13:57:58 UTC (rev 197760)
@@ -1272,6 +1272,16 @@
m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallSetResult(operation, result);
}
+ JITCompiler::Call callOperation(J_JITOperation_EJssReo operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2);
+ return appendCallSetResult(operation, result);
+ }
+ JITCompiler::Call callOperation(J_JITOperation_EJssReoJss operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
+ return appendCallSetResult(operation, result);
+ }
JITCompiler::Call callOperation(J_JITOperation_EJssZ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
{
m_jit.setupArgumentsWithExecState(arg1, arg2);
@@ -1435,20 +1445,25 @@
m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallSetResult(operation, result);
}
- JITCompiler::Call callOperation(J_JITOperation_EJJ operation, GPRReg result, GPRReg arg1, MacroAssembler::TrustedImm32 imm)
+ JITCompiler::Call callOperation(J_JITOperation_EJJ operation, GPRReg result, GPRReg arg1, int32_t imm)
{
- m_jit.setupArgumentsWithExecState(arg1, MacroAssembler::TrustedImm64(JSValue::encode(jsNumber(imm.m_value))));
+ m_jit.setupArgumentsWithExecState(arg1, MacroAssembler::TrustedImm64(JSValue::encode(jsNumber(imm))));
return appendCallSetResult(operation, result);
}
- JITCompiler::Call callOperation(J_JITOperation_EJJ operation, GPRReg result, MacroAssembler::TrustedImm32 imm, GPRReg arg2)
+ JITCompiler::Call callOperation(J_JITOperation_EJJ operation, GPRReg result, int32_t imm, GPRReg arg2)
{
- m_jit.setupArgumentsWithExecState(MacroAssembler::TrustedImm64(JSValue::encode(jsNumber(imm.m_value))), arg2);
+ m_jit.setupArgumentsWithExecState(MacroAssembler::TrustedImm64(JSValue::encode(jsNumber(imm))), arg2);
return appendCallSetResult(operation, result);
}
JITCompiler::Call callOperation(J_JITOperation_EJJ operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2)
{
return callOperation(operation, result.payloadGPR(), arg1.payloadGPR(), arg2.payloadGPR());
}
+ JITCompiler::Call callOperation(J_JITOperation_EJJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
+ return appendCallSetResult(operation, result);
+ }
JITCompiler::Call callOperation(J_JITOperation_ECC operation, GPRReg result, GPRReg arg1, GPRReg arg2)
{
m_jit.setupArgumentsWithExecState(arg1, arg2);
@@ -1634,6 +1649,16 @@
m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallSetResult(operation, resultPayload, resultTag);
}
+ JITCompiler::Call callOperation(J_JITOperation_EJssReo operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2);
+ return appendCallSetResult(operation, resultPayload, resultTag);
+ }
+ JITCompiler::Call callOperation(J_JITOperation_EJssReoJss operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2, GPRReg arg3)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
+ return appendCallSetResult(operation, resultPayload, resultTag);
+ }
JITCompiler::Call callOperation(J_JITOperation_EPS operation, GPRReg resultTag, GPRReg resultPayload, void* pointer, size_t size)
{
m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer), TrustedImmPtr(size));
@@ -1791,6 +1816,11 @@
{
return callOperation(operation, result.tagGPR(), result.payloadGPR(), arg1.tagGPR(), arg1.payloadGPR(), arg2.tagGPR(), arg2.payloadGPR());
}
+ JITCompiler::Call callOperation(J_JITOperation_EJJJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload, GPRReg arg3Tag, GPRReg arg3Payload)
+ {
+ m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, arg2Payload, arg2Tag, arg3Payload, arg3Tag);
+ return appendCallSetResult(operation, resultPayload, resultTag);
+ }
JITCompiler::Call callOperation(J_JITOperation_ECJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload)
{
@@ -2470,6 +2500,7 @@
void speculateObject(Edge);
void speculateFunction(Edge);
void speculateFinalObject(Edge);
+ void speculateRegExpObject(Edge, GPRReg cell);
void speculateRegExpObject(Edge);
void speculateObjectOrOther(Edge);
void speculateString(Edge edge, GPRReg cell);
Modified: releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (197759 => 197760)
--- releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2016-03-08 13:35:32 UTC (rev 197759)
+++ releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2016-03-08 13:57:58 UTC (rev 197760)
@@ -2902,7 +2902,75 @@
booleanResult(result.gpr(), node);
break;
}
+
+ case StringReplace: {
+ if (node->child1().useKind() == StringUse
+ && node->child2().useKind() == RegExpObjectUse
+ && node->child3().useKind() == StringUse) {
+ if (JSString* replace = node->child3()->dynamicCastConstant<JSString*>()) {
+ if (!replace->length()) {
+ SpeculateCellOperand string(this, node->child1());
+ SpeculateCellOperand regExp(this, node->child2());
+ GPRReg stringGPR = string.gpr();
+ GPRReg regExpGPR = regExp.gpr();
+ speculateString(node->child1(), stringGPR);
+ speculateRegExpObject(node->child2(), regExpGPR);
+
+ flushRegisters();
+ GPRFlushedCallResult2 resultTag(this);
+ GPRFlushedCallResult resultPayload(this);
+ callOperation(
+ operationStringProtoFuncReplaceRegExpEmptyStr, resultTag.gpr(),
+ resultPayload.gpr(), stringGPR, regExpGPR);
+ m_jit.exceptionCheck();
+ cellResult(resultPayload.gpr(), node);
+ break;
+ }
+ }
+
+ SpeculateCellOperand string(this, node->child1());
+ SpeculateCellOperand regExp(this, node->child2());
+ SpeculateCellOperand replace(this, node->child3());
+ GPRReg stringGPR = string.gpr();
+ GPRReg regExpGPR = regExp.gpr();
+ GPRReg replaceGPR = replace.gpr();
+ speculateString(node->child1(), stringGPR);
+ speculateRegExpObject(node->child2(), regExpGPR);
+ speculateString(node->child3(), replaceGPR);
+
+ flushRegisters();
+ GPRFlushedCallResult2 resultTag(this);
+ GPRFlushedCallResult resultPayload(this);
+ callOperation(
+ operationStringProtoFuncReplaceRegExpString, resultTag.gpr(), resultPayload.gpr(),
+ stringGPR, regExpGPR, replaceGPR);
+ m_jit.exceptionCheck();
+ cellResult(resultPayload.gpr(), node);
+ break;
+ }
+ JSValueOperand string(this, node->child1());
+ JSValueOperand regExp(this, node->child2());
+ JSValueOperand replace(this, node->child3());
+ GPRReg stringTagGPR = string.tagGPR();
+ GPRReg stringPayloadGPR = string.payloadGPR();
+ GPRReg regExpTagGPR = regExp.tagGPR();
+ GPRReg regExpPayloadGPR = regExp.payloadGPR();
+ GPRReg replaceTagGPR = replace.tagGPR();
+ GPRReg replacePayloadGPR = replace.payloadGPR();
+
+ flushRegisters();
+ GPRFlushedCallResult2 resultTag(this);
+ GPRFlushedCallResult resultPayload(this);
+ callOperation(
+ operationStringProtoFuncReplaceGeneric, resultTag.gpr(), resultPayload.gpr(),
+ stringTagGPR, stringPayloadGPR, regExpTagGPR, regExpPayloadGPR, replaceTagGPR,
+ replacePayloadGPR);
+ m_jit.exceptionCheck();
+ cellResult(resultPayload.gpr(), node);
+ break;
+ }
+
case ArrayPush: {
ASSERT(node->arrayMode().isJSArray());
@@ -4862,7 +4930,6 @@
case KillStack:
case GetStack:
case GetMyArgumentByVal:
- case StringReplace:
DFG_CRASH(m_jit.graph(), node, "unexpected node in DFG backend");
break;
}
Modified: releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (197759 => 197760)
--- releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2016-03-08 13:35:32 UTC (rev 197759)
+++ releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2016-03-08 13:57:58 UTC (rev 197760)
@@ -44,6 +44,7 @@
#include "ObjectPrototype.h"
#include "SetupVarargsFrame.h"
#include "SpillRegistersMode.h"
+#include "StringPrototype.h"
#include "TypeProfilerLog.h"
#include "Watchdog.h"
@@ -3025,7 +3026,68 @@
jsValueResult(result.gpr(), node, DataFormatJSBoolean);
break;
}
+
+ case StringReplace: {
+ if (node->child1().useKind() == StringUse
+ && node->child2().useKind() == RegExpObjectUse
+ && node->child3().useKind() == StringUse) {
+ if (JSString* replace = node->child3()->dynamicCastConstant<JSString*>()) {
+ if (!replace->length()) {
+ SpeculateCellOperand string(this, node->child1());
+ SpeculateCellOperand regExp(this, node->child2());
+ GPRReg stringGPR = string.gpr();
+ GPRReg regExpGPR = regExp.gpr();
+ speculateString(node->child1(), stringGPR);
+ speculateRegExpObject(node->child2(), regExpGPR);
+
+ flushRegisters();
+ GPRFlushedCallResult result(this);
+ callOperation(
+ operationStringProtoFuncReplaceRegExpEmptyStr, result.gpr(), stringGPR,
+ regExpGPR);
+ m_jit.exceptionCheck();
+ cellResult(result.gpr(), node);
+ break;
+ }
+ }
+
+ SpeculateCellOperand string(this, node->child1());
+ SpeculateCellOperand regExp(this, node->child2());
+ SpeculateCellOperand replace(this, node->child3());
+ GPRReg stringGPR = string.gpr();
+ GPRReg regExpGPR = regExp.gpr();
+ GPRReg replaceGPR = replace.gpr();
+ speculateString(node->child1(), stringGPR);
+ speculateRegExpObject(node->child2(), regExpGPR);
+ speculateString(node->child3(), replaceGPR);
+
+ flushRegisters();
+ GPRFlushedCallResult result(this);
+ callOperation(
+ operationStringProtoFuncReplaceRegExpString, result.gpr(), stringGPR, regExpGPR,
+ replaceGPR);
+ m_jit.exceptionCheck();
+ cellResult(result.gpr(), node);
+ break;
+ }
+ JSValueOperand string(this, node->child1());
+ JSValueOperand regExp(this, node->child2());
+ JSValueOperand replace(this, node->child3());
+ GPRReg stringGPR = string.gpr();
+ GPRReg regExpGPR = regExp.gpr();
+ GPRReg replaceGPR = replace.gpr();
+
+ flushRegisters();
+ GPRFlushedCallResult result(this);
+ callOperation(
+ operationStringProtoFuncReplaceGeneric, result.gpr(), stringGPR, regExpGPR,
+ replaceGPR);
+ m_jit.exceptionCheck();
+ cellResult(result.gpr(), node);
+ break;
+ }
+
case ArrayPush: {
ASSERT(node->arrayMode().isJSArray());
@@ -4914,7 +4976,6 @@
case PutStack:
case KillStack:
case GetStack:
- case StringReplace:
DFG_CRASH(m_jit.graph(), node, "Unexpected node");
break;
}
Modified: releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/jit/JITOperations.h (197759 => 197760)
--- releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/jit/JITOperations.h 2016-03-08 13:35:32 UTC (rev 197759)
+++ releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/jit/JITOperations.h 2016-03-08 13:57:58 UTC (rev 197760)
@@ -45,6 +45,7 @@
class JSFunction;
class JSLexicalEnvironment;
class JSScope;
+class RegExpObject;
class Register;
class StructureStubInfo;
class SymbolTable;
@@ -94,6 +95,7 @@
Pc: Instruction* i.e. bytecode PC
Q: int64_t
R: Register
+ Reo: RegExpObject*
S: size_t
Sprt: SlowPathReturnType
Ssi: StructureStubInfo*
@@ -128,9 +130,13 @@
typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJI)(ExecState*, EncodedJSValue, UniquedStringImpl*);
typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJIdc)(ExecState*, EncodedJSValue, const Identifier*);
typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
+typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue);
typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJJAp)(ExecState*, EncodedJSValue, EncodedJSValue, ArrayProfile*);
typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJJBy)(ExecState*, EncodedJSValue, EncodedJSValue, ByValInfo*);
+typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue);
typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJssZ)(ExecState*, JSString*, int32_t);
+typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJssReo)(ExecState*, JSString*, RegExpObject*);
+typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJssReoJss)(ExecState*, JSString*, RegExpObject*, JSString*);
typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJP)(ExecState*, EncodedJSValue, void*);
typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EP)(ExecState*, void*);
typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EPP)(ExecState*, void*, void*);