Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (101297 => 101298)
--- trunk/Source/_javascript_Core/ChangeLog 2011-11-28 23:48:37 UTC (rev 101297)
+++ trunk/Source/_javascript_Core/ChangeLog 2011-11-28 23:51:51 UTC (rev 101298)
@@ -1,3 +1,28 @@
+2011-11-28 Filip Pizlo <fpi...@apple.com>
+
+ GetById should not always speculate cell
+ https://bugs.webkit.org/show_bug.cgi?id=73181
+
+ Reviewed by Gavin Barraclough.
+
+ GetById will now speculate cell if the predictions of the base are cell.
+ Otherwise it will do like the old JIT (and like the old non-speculative
+ DFG JIT): if not cell, go straight to slow-path but otherwise don't OSR
+ out. This is a 1% speed-up on SunSpider.
+
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::setupArgumentsWithExecState):
+ (JSC::DFG::SpeculativeJIT::callOperation):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::cachedGetById):
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+
2011-11-28 Oliver Hunt <oli...@apple.com>
Move typed array implementations into wtf
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp (101297 => 101298)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp 2011-11-28 23:48:37 UTC (rev 101297)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp 2011-11-28 23:51:51 UTC (rev 101298)
@@ -563,7 +563,8 @@
m_isValid = false;
break;
}
- forNode(node.child1()).filter(PredictCell);
+ if (isCellPrediction(m_graph[node.child1()].prediction()))
+ forNode(node.child1()).filter(PredictCell);
clobberStructures(nodeIndex);
forNode(nodeIndex).makeTop();
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (101297 => 101298)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2011-11-28 23:48:37 UTC (rev 101297)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2011-11-28 23:51:51 UTC (rev 101298)
@@ -48,6 +48,7 @@
);
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rsi)
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rcx)
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rcx)
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, r8)
#elif CPU(X86)
@@ -62,6 +63,7 @@
);
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 8)
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 16)
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 20)
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 24)
#elif COMPILER(GCC) && CPU(ARM_THUMB2)
@@ -92,6 +94,19 @@
"b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
);
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function) \
+ asm ( \
+ ".text" "\n" \
+ ".align 2" "\n" \
+ ".globl " SYMBOL_STRING(function) "\n" \
+ HIDE_SYMBOL(function) "\n" \
+ ".thumb" "\n" \
+ ".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
+ SYMBOL_STRING(function) ":" "\n" \
+ "str lr, [sp, #0]" "\n" \
+ "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
+ );
+
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) \
asm ( \
".text" "\n" \
@@ -115,6 +130,10 @@
EncodedJSValue DFG_OPERATION function##WithReturnAddress(ExecState*, JSCell*, Identifier*, ReturnAddressPtr); \
FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function)
+#define J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function) \
+EncodedJSValue DFG_OPERATION function##WithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr); \
+FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function)
+
#define V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) \
void DFG_OPERATION function##WithReturnAddress(ExecState*, EncodedJSValue, JSCell*, Identifier*, ReturnAddressPtr); \
FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function)
@@ -312,17 +331,17 @@
return JSValue::encode(JSValue(base).get(exec, ident));
}
-EncodedJSValue DFG_OPERATION operationGetById(ExecState* exec, JSCell* base, Identifier* propertyName)
+EncodedJSValue DFG_OPERATION operationGetById(ExecState* exec, EncodedJSValue base, Identifier* propertyName)
{
- JSValue baseValue(base);
+ JSValue baseValue = JSValue::decode(base);
PropertySlot slot(baseValue);
return JSValue::encode(baseValue.get(exec, *propertyName, slot));
}
-J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(operationGetByIdBuildList);
-EncodedJSValue DFG_OPERATION operationGetByIdBuildListWithReturnAddress(ExecState* exec, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
+J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(operationGetByIdBuildList);
+EncodedJSValue DFG_OPERATION operationGetByIdBuildListWithReturnAddress(ExecState* exec, EncodedJSValue base, Identifier* propertyName, ReturnAddressPtr returnAddress)
{
- JSValue baseValue(base);
+ JSValue baseValue = JSValue::decode(base);
PropertySlot slot(baseValue);
JSValue result = baseValue.get(exec, *propertyName, slot);
@@ -332,10 +351,10 @@
return JSValue::encode(result);
}
-J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(operationGetByIdProtoBuildList);
-EncodedJSValue DFG_OPERATION operationGetByIdProtoBuildListWithReturnAddress(ExecState* exec, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
+J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(operationGetByIdProtoBuildList);
+EncodedJSValue DFG_OPERATION operationGetByIdProtoBuildListWithReturnAddress(ExecState* exec, EncodedJSValue base, Identifier* propertyName, ReturnAddressPtr returnAddress)
{
- JSValue baseValue(base);
+ JSValue baseValue = JSValue::decode(base);
PropertySlot slot(baseValue);
JSValue result = baseValue.get(exec, *propertyName, slot);
@@ -345,10 +364,10 @@
return JSValue::encode(result);
}
-J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(operationGetByIdOptimize);
-EncodedJSValue DFG_OPERATION operationGetByIdOptimizeWithReturnAddress(ExecState* exec, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
+J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(operationGetByIdOptimize);
+EncodedJSValue DFG_OPERATION operationGetByIdOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue base, Identifier* propertyName, ReturnAddressPtr returnAddress)
{
- JSValue baseValue(base);
+ JSValue baseValue = JSValue::decode(base);
PropertySlot slot(baseValue);
JSValue result = baseValue.get(exec, *propertyName, slot);
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (101297 => 101298)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.h 2011-11-28 23:48:37 UTC (rev 101297)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h 2011-11-28 23:51:51 UTC (rev 101298)
@@ -72,6 +72,7 @@
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJ)(ExecState*, EncodedJSValue);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJP)(ExecState*, EncodedJSValue, void*);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECI)(ExecState*, JSCell*, Identifier*);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJI)(ExecState*, EncodedJSValue, Identifier*);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EP)(ExecState*, void*);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EPP)(ExecState*, void*, void*);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EGI)(ExecState*, GlobalResolveInfo*, Identifier*);
@@ -99,10 +100,11 @@
EncodedJSValue DFG_OPERATION operationValueAddNotNumber(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
EncodedJSValue DFG_OPERATION operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty);
EncodedJSValue DFG_OPERATION operationGetByValCell(ExecState*, JSCell*, EncodedJSValue encodedProperty);
-EncodedJSValue DFG_OPERATION operationGetById(ExecState*, JSCell*, Identifier*);
-EncodedJSValue DFG_OPERATION operationGetByIdBuildList(ExecState*, JSCell*, Identifier*);
-EncodedJSValue DFG_OPERATION operationGetByIdProtoBuildList(ExecState*, JSCell*, Identifier*);
-EncodedJSValue DFG_OPERATION operationGetByIdOptimize(ExecState*, JSCell*, Identifier*);
+EncodedJSValue DFG_OPERATION operationGetById(ExecState*, EncodedJSValue, Identifier*);
+EncodedJSValue DFG_OPERATION operationGetByIdBuildList(ExecState*, EncodedJSValue, Identifier*);
+EncodedJSValue DFG_OPERATION operationGetByIdProtoBuildList(ExecState*, EncodedJSValue, Identifier*);
+EncodedJSValue DFG_OPERATION operationGetByIdOptimize(ExecState*, EncodedJSValue, Identifier*);
+EncodedJSValue DFG_OPERATION operationGetMethodOptimize(ExecState*, EncodedJSValue, Identifier*);
EncodedJSValue DFG_OPERATION operationResolve(ExecState*, Identifier*);
EncodedJSValue DFG_OPERATION operationResolveBase(ExecState*, Identifier*);
EncodedJSValue DFG_OPERATION operationResolveBaseStrictPut(ExecState*, Identifier*);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (101297 => 101298)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2011-11-28 23:48:37 UTC (rev 101297)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2011-11-28 23:51:51 UTC (rev 101298)
@@ -871,7 +871,7 @@
JITCompiler::Call cachedGetById(GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
void cachedPutById(GPRReg base, GPRReg value, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
#elif USE(JSVALUE32_64)
- JITCompiler::Call cachedGetById(GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
+ JITCompiler::Call cachedGetById(GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
void cachedPutById(GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
#endif
@@ -1150,6 +1150,15 @@
addCallArgument(arg3);
}
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ addCallArgument(arg3);
+ }
+
ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4)
{
resetCallArguments();
@@ -1423,6 +1432,14 @@
m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
}
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImm32 arg3)
+ {
+ m_jit.move(arg1, GPRInfo::argumentGPR1);
+ m_jit.move(arg2, GPRInfo::argumentGPR2);
+ m_jit.move(arg3, GPRInfo::argumentGPR3);
+ m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3)
{
setupStubArguments(arg1, arg2);
@@ -1527,6 +1544,11 @@
setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
return appendCallWithExceptionCheckSetResult(operation, result);
}
+ JITCompiler::Call callOperation(J_DFGOperation_EJI operation, GPRReg result, GPRReg arg1, Identifier* identifier)
+ {
+ setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
+ return appendCallWithExceptionCheckSetResult(operation, result);
+ }
JITCompiler::Call callOperation(J_DFGOperation_EJA operation, GPRReg result, GPRReg arg1, GPRReg arg2)
{
setupArgumentsWithExecState(arg1, arg2);
@@ -1685,6 +1707,16 @@
setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
+ JITCompiler::Call callOperation(J_DFGOperation_EJI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, Identifier* identifier)
+ {
+ setupArgumentsWithExecState(arg1Payload, arg1Tag, TrustedImmPtr(identifier));
+ return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+ }
+ JITCompiler::Call callOperation(J_DFGOperation_EJI operation, GPRReg resultTag, GPRReg resultPayload, int32_t arg1Tag, GPRReg arg1Payload, Identifier* identifier)
+ {
+ setupArgumentsWithExecState(arg1Payload, TrustedImm32(arg1Tag), TrustedImmPtr(identifier));
+ return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+ }
JITCompiler::Call callOperation(J_DFGOperation_EJA operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2)
{
setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (101297 => 101298)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2011-11-28 23:48:37 UTC (rev 101297)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2011-11-28 23:51:51 UTC (rev 101298)
@@ -839,7 +839,7 @@
jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
}
-JITCompiler::Call SpeculativeJIT::cachedGetById(GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget)
+JITCompiler::Call SpeculativeJIT::cachedGetById(GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget)
{
m_jit.beginUninterruptedSequence();
JITCompiler::DataLabelPtr structureToCompare;
@@ -860,7 +860,11 @@
JITCompiler::Label slowCase = m_jit.label();
silentSpillAllRegisters(resultTagGPR, resultPayloadGPR);
- JITCompiler::Call functionCall = callOperation(operationGetByIdOptimize, resultTagGPR, resultPayloadGPR, basePayloadGPR, identifier(identifierNumber));
+ JITCompiler::Call functionCall;
+ if (baseTagGPROrNone == InvalidGPRReg)
+ functionCall = callOperation(operationGetByIdOptimize, resultTagGPR, resultPayloadGPR, JSValue::CellTag, basePayloadGPR, identifier(identifierNumber));
+ else
+ functionCall = callOperation(operationGetByIdOptimize, resultTagGPR, resultPayloadGPR, baseTagGPROrNone, basePayloadGPR, identifier(identifierNumber));
silentFillAllRegisters(resultTagGPR, resultPayloadGPR);
done.link(&m_jit);
@@ -3299,24 +3303,50 @@
break;
}
- SpeculateCellOperand base(this, node.child1());
+ if (isCellPrediction(at(node.child1()).prediction())) {
+ SpeculateCellOperand base(this, node.child1());
+ GPRTemporary resultTag(this, base);
+ GPRTemporary resultPayload(this);
+
+ GPRReg baseGPR = base.gpr();
+ GPRReg resultTagGPR = resultTag.gpr();
+ GPRReg resultPayloadGPR = resultPayload.gpr();
+ GPRReg scratchGPR;
+
+ if (resultTagGPR == baseGPR)
+ scratchGPR = resultPayloadGPR;
+ else
+ scratchGPR = resultTagGPR;
+
+ base.use();
+
+ cachedGetById(InvalidGPRReg, baseGPR, resultTagGPR, resultPayloadGPR, scratchGPR, node.identifierNumber());
+
+ jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
+ break;
+ }
+
+ JSValueOperand base(this, node.child1());
GPRTemporary resultTag(this, base);
GPRTemporary resultPayload(this);
- GPRReg baseGPR = base.gpr();
+ GPRReg baseTagGPR = base.tagGPR();
+ GPRReg basePayloadGPR = base.payloadGPR();
GPRReg resultTagGPR = resultTag.gpr();
GPRReg resultPayloadGPR = resultPayload.gpr();
GPRReg scratchGPR;
-
- if (resultTagGPR == baseGPR)
+
+ if (resultTagGPR == basePayloadGPR)
scratchGPR = resultPayloadGPR;
else
scratchGPR = resultTagGPR;
base.use();
-
- cachedGetById(baseGPR, resultTagGPR, resultPayloadGPR, scratchGPR, node.identifierNumber());
-
+
+ JITCompiler::Jump notCell = m_jit.branch32(JITCompiler::NotEqual, baseTagGPR, TrustedImm32(JSValue::CellTag));
+
+ cachedGetById(baseTagGPR, basePayloadGPR, resultTagGPR, resultPayloadGPR, scratchGPR, node.identifierNumber(), notCell);
+
jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (101297 => 101298)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2011-11-28 23:48:37 UTC (rev 101297)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2011-11-28 23:51:51 UTC (rev 101298)
@@ -3248,7 +3248,28 @@
break;
}
- SpeculateCellOperand base(this, node.child1());
+ if (isCellPrediction(at(node.child1()).prediction())) {
+ SpeculateCellOperand base(this, node.child1());
+ GPRTemporary result(this, base);
+
+ GPRReg baseGPR = base.gpr();
+ GPRReg resultGPR = result.gpr();
+ GPRReg scratchGPR;
+
+ if (resultGPR == baseGPR)
+ scratchGPR = tryAllocate();
+ else
+ scratchGPR = resultGPR;
+
+ base.use();
+
+ cachedGetById(baseGPR, resultGPR, scratchGPR, node.identifierNumber());
+
+ jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
+ break;
+ }
+
+ JSValueOperand base(this, node.child1());
GPRTemporary result(this, base);
GPRReg baseGPR = base.gpr();
@@ -3261,10 +3282,13 @@
scratchGPR = resultGPR;
base.use();
-
- cachedGetById(baseGPR, resultGPR, scratchGPR, node.identifierNumber());
-
+
+ JITCompiler::Jump notCell = m_jit.branchTestPtr(JITCompiler::NonZero, baseGPR, GPRInfo::tagMaskRegister);
+
+ cachedGetById(baseGPR, resultGPR, scratchGPR, node.identifierNumber(), notCell);
+
jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
+
break;
}