Changeset 94629 in webkit for trunk/Source/JavaScriptCore/dfg
- Timestamp:
- Sep 6, 2011, 7:47:51 PM (14 years ago)
- Location:
- trunk/Source/JavaScriptCore/dfg
- Files:
-
- 1 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r94559 r94629 476 476 ASSERT(profile); 477 477 #if DFG_DEBUG_VERBOSE 478 printf("Dynamic pr ediction[%u, %u]: ", nodeIndex, bytecodeIndex);478 printf("Dynamic profile [%u, %u]: ", nodeIndex, bytecodeIndex); 479 479 profile->dump(stdout); 480 480 printf("\n"); 481 481 #endif 482 482 m_graph[nodeIndex].predict(makePrediction(*m_globalData, *profile), StrongPrediction); 483 #if DFG_DEBUG_VERBOSE 484 printf(" Prediction: %s\n", predictionToString(m_graph[nodeIndex].getPrediction())); 485 #endif 483 486 #else 484 487 UNUSED_PARAM(nodeIndex); -
trunk/Source/JavaScriptCore/dfg/DFGGenerationInfo.h
r92986 r94629 43 43 DataFormatInteger = 1, 44 44 DataFormatDouble = 2, 45 DataFormatCell = 3, 45 DataFormatBoolean = 3, 46 DataFormatCell = 4, 46 47 DataFormatJS = 8, 47 48 DataFormatJSInteger = DataFormatJS | DataFormatInteger, 48 49 DataFormatJSDouble = DataFormatJS | DataFormatDouble, 49 50 DataFormatJSCell = DataFormatJS | DataFormatCell, 51 DataFormatJSBoolean = DataFormatJS | DataFormatBoolean 50 52 }; 51 53 … … 62 64 case DataFormatCell: 63 65 return "Cell"; 66 case DataFormatBoolean: 67 return "Boolean"; 64 68 case DataFormatJS: 65 69 return "JS"; … … 70 74 case DataFormatJSCell: 71 75 return "JSCell"; 76 case DataFormatJSBoolean: 77 return "JSBoolean"; 72 78 default: 73 79 return "Unknown"; … … 89 95 case DataFormatJSDouble: 90 96 case DataFormatJSCell: 97 case DataFormatJSBoolean: 91 98 switch (to) { 92 99 case DataFormatInteger: … … 98 105 case DataFormatJSDouble: 99 106 case DataFormatJSCell: 107 case DataFormatJSBoolean: 100 108 return false; 101 109 default: 110 // This captures DataFormatBoolean, which is currently unused. 102 111 ASSERT_NOT_REACHED(); 103 112 } 104 113 default: 114 // This captures DataFormatBoolean, which is currently unused. 105 115 ASSERT_NOT_REACHED(); 106 116 } -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r94559 r94629 53 53 54 54 unsigned refCount = node.refCount(); 55 if (!refCount) 55 if (!refCount) { 56 printf("% 4d:\tskipped %s\n", (int)nodeIndex, opName(op)); 56 57 return; 58 } 57 59 bool mustGenerate = node.mustGenerate(); 58 60 if (mustGenerate) … … 194 196 { 195 197 if (exec) { 196 size_t numberOfArguments = std::min(exec->argumentCountIncludingThis(), m_ argumentPredictions.size());198 size_t numberOfArguments = std::min(exec->argumentCountIncludingThis(), m_predictions.numberOfArguments()); 197 199 198 200 for (size_t arg = 1; arg < numberOfArguments; ++arg) { 199 201 JSValue argumentValue = exec->argument(arg - 1); 200 202 if (argumentValue.isInt32()) 201 m_ argumentPredictions[arg].m_value |= PredictInt32;203 m_predictions.predictArgument(arg, PredictInt32, WeakPrediction); 202 204 else if (argumentValue.isDouble()) 203 m_ argumentPredictions[arg].m_value |= PredictDouble;205 m_predictions.predictArgument(arg, PredictDouble, WeakPrediction); 204 206 } 205 207 } … … 223 225 #endif 224 226 225 m ergePrediction(m_argumentPredictions[arg].m_value, makePrediction(globalData, *profile));227 m_predictions.predictArgument(arg, makePrediction(globalData, *profile) & ~PredictionTagMask, StrongPrediction); 226 228 227 229 #if DFG_DEBUG_VERBOSE 228 printf(" Prediction: %s\n", predictionToString(m_ argumentPredictions[arg].m_value));230 printf(" Prediction: %s\n", predictionToString(m_predictions.getArgumentPrediction(arg))); 229 231 #endif 230 232 } -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r94559 r94629 31 31 #include "CodeBlock.h" 32 32 #include "DFGNode.h" 33 #include "DFGPredictionTracker.h" 33 34 #include "RegisterFile.h" 34 35 #include <wtf/HashMap.h> … … 42 43 43 44 namespace DFG { 44 45 // helper function to distinguish vars & temporaries from arguments.46 inline bool operandIsArgument(int operand) { return operand < 0; }47 48 struct PredictionSlot {49 public:50 PredictionSlot()51 : m_value(PredictNone)52 {53 }54 PredictedType m_value;55 };56 45 57 46 typedef uint32_t BlockIndex; … … 104 93 public: 105 94 Graph(unsigned numArguments, unsigned numVariables) 106 : m_argumentPredictions(numArguments) 107 , m_variablePredictions(numVariables) 95 : m_predictions(numArguments, numVariables) 108 96 { 109 97 } … … 136 124 return *m_blocks[blockIndexForBytecodeOffset(bytecodeBegin)]; 137 125 } 138 126 127 PredictionTracker& predictions() 128 { 129 return m_predictions; 130 } 131 139 132 bool predict(int operand, PredictedType prediction, PredictionSource source) 140 133 { 141 if (operandIsArgument(operand)) { 142 unsigned argument = operand + m_argumentPredictions.size() + RegisterFile::CallFrameHeaderSize; 143 return mergePrediction(m_argumentPredictions[argument].m_value, makePrediction(prediction, source)); 144 } 145 146 if ((unsigned)operand >= m_variablePredictions.size()) { 147 ASSERT(operand >= 0); 148 m_variablePredictions.resize(operand + 1); 149 } 150 151 return mergePrediction(m_variablePredictions[operand].m_value, makePrediction(prediction, source)); 134 return m_predictions.predict(operand, prediction, source); 152 135 } 153 136 154 137 bool predictGlobalVar(unsigned varNumber, PredictedType prediction, PredictionSource source) 155 138 { 156 HashMap<unsigned, PredictionSlot>::iterator iter = m_globalVarPredictions.find(varNumber + 1); 157 if (iter == m_globalVarPredictions.end()) { 158 PredictionSlot predictionSlot; 159 bool result = mergePrediction(predictionSlot.m_value, makePrediction(prediction, source)); 160 m_globalVarPredictions.add(varNumber + 1, predictionSlot); 161 return result; 162 } else 163 return mergePrediction(iter->second.m_value, makePrediction(prediction, source)); 139 return m_predictions.predictGlobalVar(varNumber, prediction, source); 164 140 } 165 141 166 142 bool predict(Node& node, PredictedType prediction, PredictionSource source) 167 143 { 168 switch (node.op) { 169 case GetLocal: 170 return predict(node.local(), prediction, source); 171 break; 172 case GetGlobalVar: 173 return predictGlobalVar(node.varNumber(), prediction, source); 174 case GetById: 175 case GetMethod: 176 case GetByVal: 177 case Call: 178 case Construct: 179 return node.predict(prediction, source); 180 default: 181 return false; 182 } 144 return m_predictions.predict(node, prediction, source); 183 145 } 184 146 185 147 PredictedType getPrediction(int operand) 186 148 { 187 if (operandIsArgument(operand)) { 188 unsigned argument = operand + m_argumentPredictions.size() + RegisterFile::CallFrameHeaderSize; 189 return m_argumentPredictions[argument].m_value; 190 } 191 if ((unsigned)operand < m_variablePredictions.size()) 192 return m_variablePredictions[operand].m_value; 193 return PredictNone; 149 return m_predictions.getPrediction(operand); 194 150 } 195 151 196 152 PredictedType getGlobalVarPrediction(unsigned varNumber) 197 153 { 198 HashMap<unsigned, PredictionSlot>::iterator iter = m_globalVarPredictions.find(varNumber + 1); 199 if (iter == m_globalVarPredictions.end()) 200 return PredictNone; 201 return iter->second.m_value; 154 return m_predictions.getGlobalVarPrediction(varNumber); 202 155 } 203 156 … … 212 165 nodePtr = &(*this)[nodePtr->child1()]; 213 166 214 switch (nodePtr->op) { 215 case GetLocal: 216 return getPrediction(nodePtr->local()); 217 case GetGlobalVar: 218 return getGlobalVarPrediction(nodePtr->varNumber()); 219 case GetById: 220 case GetMethod: 221 case GetByVal: 222 case Call: 223 case Construct: 224 return nodePtr->getPrediction(); 225 default: 226 return PredictNone; 227 } 167 return m_predictions.getPrediction(*nodePtr); 228 168 } 229 169 … … 245 185 return at(nodeIndex).isDoubleConstant(codeBlock); 246 186 } 187 bool isBooleanConstant(CodeBlock* codeBlock, NodeIndex nodeIndex) 188 { 189 return at(nodeIndex).isBooleanConstant(codeBlock); 190 } 247 191 // Helper methods get constant values from nodes. 248 192 JSValue valueOfJSConstant(CodeBlock* codeBlock, NodeIndex nodeIndex) … … 257 201 { 258 202 return at(nodeIndex).valueOfDoubleConstant(codeBlock); 203 } 204 bool valueOfBooleanConstant(CodeBlock* codeBlock, NodeIndex nodeIndex) 205 { 206 return at(nodeIndex).valueOfBooleanConstant(codeBlock); 259 207 } 260 208 … … 272 220 void refChildren(NodeIndex); 273 221 274 Vector<PredictionSlot, 16> m_argumentPredictions; 275 Vector<PredictionSlot, 16> m_variablePredictions; 276 HashMap<unsigned, PredictionSlot> m_globalVarPredictions; 222 PredictionTracker m_predictions; 277 223 }; 278 224 -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp
r93934 r94629 81 81 case DataFormatCell: 82 82 case DataFormatJSCell: 83 case DataFormatBoolean: 84 case DataFormatJSBoolean: 83 85 // Should only be calling this function if we know this operand to be integer. 84 86 ASSERT_NOT_REACHED(); … … 154 156 case DataFormatCell: 155 157 case DataFormatJSCell: 158 case DataFormatBoolean: 159 case DataFormatJSBoolean: 156 160 // Should only be calling this function if we know this operand to be numeric. 157 161 ASSERT_NOT_REACHED(); … … 296 300 case DataFormatJSInteger: 297 301 case DataFormatJSDouble: 298 case DataFormatJSCell: { 302 case DataFormatJSCell: 303 case DataFormatJSBoolean: { 299 304 GPRReg gpr = info.gpr(); 300 305 m_gprs.lock(gpr); 301 306 return gpr; 302 307 } 308 309 case DataFormatBoolean: 310 // this type currently never occurs 311 ASSERT_NOT_REACHED(); 303 312 } 304 313 … … 407 416 return (info.registerFormat() | DataFormatJS) == DataFormatJSDouble 408 417 || (info.registerFormat() | DataFormatJS) == DataFormatJSCell 418 || (info.registerFormat() | DataFormatJS) == DataFormatJSBoolean 409 419 || (node.isConstant() && !valueOfJSConstant(nodeIndex).isInt32()); 420 } 421 422 bool JITCodeGenerator::isKnownBoolean(NodeIndex nodeIndex) 423 { 424 Node& node = m_jit.graph()[nodeIndex]; 425 if (node.hasBooleanResult()) 426 return true; 427 428 if (isBooleanConstant(nodeIndex)) 429 return true; 430 431 VirtualRegister virtualRegister = node.virtualRegister(); 432 GenerationInfo& info = m_generationInfo[virtualRegister]; 433 434 return (info.registerFormat() | DataFormatJS) == DataFormatJSBoolean 435 || (info.spillFormat() | DataFormatJS) == DataFormatJSBoolean; 410 436 } 411 437 … … 589 615 590 616 m_jit.or32(TrustedImm32(ValueFalse), resultGPR); 591 jsValueResult(resultGPR, m_compileIndex );617 jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean); 592 618 } 593 619 … … 744 770 745 771 m_jit.or32(TrustedImm32(ValueFalse), resultGPR); 746 jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);772 jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly); 747 773 } else { 748 774 GPRTemporary result(this, arg2); … … 778 804 m_jit.or32(TrustedImm32(ValueFalse), resultGPR); 779 805 780 jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);806 jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly); 781 807 } 782 808 } … … 940 966 } 941 967 942 jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);968 jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly); 943 969 } 944 970 … … 969 995 GPRReg valueGPR = value.gpr(); 970 996 971 GPRTemporary result(this);972 GPRReg resultGPR = result.gpr();973 974 value.use();975 976 997 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset()); 977 998 BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset()); 978 979 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsNumber(0)))), notTaken); 980 addBranch(m_jit.branchPtr(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister), taken); 981 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken); 982 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true)))), taken); 983 984 silentSpillAllRegisters(resultGPR); 985 m_jit.move(valueGPR, GPRInfo::argumentGPR1); 986 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 987 appendCallWithExceptionCheck(dfgConvertJSValueToBoolean); 988 m_jit.move(GPRInfo::returnValueGPR, resultGPR); 989 silentFillAllRegisters(resultGPR); 990 991 addBranch(m_jit.branchTest8(MacroAssembler::NonZero, resultGPR), taken); 992 if (notTaken != (m_block + 1)) 993 addBranch(m_jit.jump(), notTaken); 994 995 noResult(m_compileIndex, UseChildrenCalledExplicitly); 999 1000 if (isKnownBoolean(node.child1())) { 1001 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero; 1002 1003 if (taken == (m_block + 1)) { 1004 condition = MacroAssembler::Zero; 1005 BlockIndex tmp = taken; 1006 taken = notTaken; 1007 notTaken = tmp; 1008 } 1009 1010 addBranch(m_jit.branchTest32(condition, valueGPR, TrustedImm32(true)), taken); 1011 if (notTaken != (m_block + 1)) 1012 addBranch(m_jit.jump(), notTaken); 1013 1014 noResult(m_compileIndex); 1015 } else { 1016 GPRTemporary result(this); 1017 GPRReg resultGPR = result.gpr(); 1018 1019 bool predictBoolean = isBooleanPrediction(m_jit.graph().getPrediction(m_jit.graph()[node.child1()])); 1020 1021 if (predictBoolean) { 1022 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken); 1023 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true)))), taken); 1024 } 1025 1026 if (m_isSpeculative && predictBoolean) { 1027 speculationCheck(m_jit.jump()); 1028 value.use(); 1029 } else { 1030 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsNumber(0)))), notTaken); 1031 addBranch(m_jit.branchPtr(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister), taken); 1032 1033 if (!predictBoolean) { 1034 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken); 1035 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true)))), taken); 1036 } 1037 1038 value.use(); 1039 1040 silentSpillAllRegisters(resultGPR); 1041 m_jit.move(valueGPR, GPRInfo::argumentGPR1); 1042 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 1043 appendCallWithExceptionCheck(dfgConvertJSValueToBoolean); 1044 m_jit.move(GPRInfo::returnValueGPR, resultGPR); 1045 silentFillAllRegisters(resultGPR); 1046 1047 addBranch(m_jit.branchTest8(MacroAssembler::NonZero, resultGPR), taken); 1048 if (notTaken != (m_block + 1)) 1049 addBranch(m_jit.jump(), notTaken); 1050 } 1051 1052 noResult(m_compileIndex, UseChildrenCalledExplicitly); 1053 } 996 1054 } 997 1055 … … 1080 1138 1081 1139 m_jit.addJSCall(fastCall, slowCall, targetToCheck, isCall, m_jit.graph()[m_compileIndex].exceptionInfo); 1140 } 1141 1142 void JITCodeGenerator::speculationCheck(MacroAssembler::Jump jumpToFail) 1143 { 1144 ASSERT(m_isSpeculative); 1145 static_cast<SpeculativeJIT*>(this)->speculationCheck(jumpToFail); 1082 1146 } 1083 1147 … … 1288 1352 } 1289 1353 1354 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateBooleanOperand& op1) 1355 : m_jit(jit) 1356 , m_gpr(InvalidGPRReg) 1357 { 1358 if (m_jit->canReuse(op1.index())) 1359 m_gpr = m_jit->reuse(op1.gpr()); 1360 else 1361 m_gpr = m_jit->allocate(); 1362 } 1363 1290 1364 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, JSValueOperand& op1) 1291 1365 : m_jit(jit) -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h
r93934 r94629 42 42 class SpeculateDoubleOperand; 43 43 class SpeculateCellOperand; 44 class SpeculateBooleanOperand; 44 45 45 46 … … 411 412 bool isKnownNotInteger(NodeIndex); 412 413 414 bool isKnownBoolean(NodeIndex); 415 413 416 // Checks/accessors for constant values. 414 417 bool isConstant(NodeIndex nodeIndex) { return m_jit.isConstant(nodeIndex); } … … 416 419 bool isInt32Constant(NodeIndex nodeIndex) { return m_jit.isInt32Constant(nodeIndex); } 417 420 bool isDoubleConstant(NodeIndex nodeIndex) { return m_jit.isDoubleConstant(nodeIndex); } 421 bool isBooleanConstant(NodeIndex nodeIndex) { return m_jit.isBooleanConstant(nodeIndex); } 418 422 int32_t valueOfInt32Constant(NodeIndex nodeIndex) { return m_jit.valueOfInt32Constant(nodeIndex); } 419 423 double valueOfDoubleConstant(NodeIndex nodeIndex) { return m_jit.valueOfDoubleConstant(nodeIndex); } 420 424 JSValue valueOfJSConstant(NodeIndex nodeIndex) { return m_jit.valueOfJSConstant(nodeIndex); } 425 bool valueOfBooleanConstant(NodeIndex nodeIndex) { return m_jit.valueOfBooleanConstant(nodeIndex); } 421 426 bool isNullConstant(NodeIndex nodeIndex) 422 427 { … … 576 581 577 582 void emitCall(Node&); 583 584 void speculationCheck(MacroAssembler::Jump jumpToFail); 578 585 579 586 // Called once a node has completed code generation but prior to setting … … 1122 1129 GPRTemporary(JITCodeGenerator*, IntegerOperand&, IntegerOperand&); 1123 1130 GPRTemporary(JITCodeGenerator*, SpeculateCellOperand&); 1131 GPRTemporary(JITCodeGenerator*, SpeculateBooleanOperand&); 1124 1132 GPRTemporary(JITCodeGenerator*, JSValueOperand&); 1125 1133 -
trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
r94559 r94629 489 489 breakpoint(); 490 490 #endif 491 492 #if DFG_VERBOSE_SPECULATION_FAILURE 493 SpeculationFailureDebugInfo* debugInfo = new SpeculationFailureDebugInfo; 494 debugInfo->codeBlock = m_codeBlock; 495 debugInfo->debugOffset = debugOffset(); 496 497 debugCall(debugOperationPrintSpeculationFailure, debugInfo); 498 #endif 491 499 492 500 // Does this speculation check require any additional recovery to be performed, … … 494 502 // non-speculative path. 495 503 if (recovery) { 496 // The only additional recovery we currently support is for integer add operation 497 ASSERT(recovery->type() == SpeculativeAdd); 498 ASSERT(check.m_gprInfo[GPRInfo::toIndex(recovery->dest())].nodeIndex != NoNode); 499 // Revert the add. 500 sub32(recovery->src(), recovery->dest()); 501 502 // If recovery->dest() should have been boxed prior to the addition, then rebox 503 // it. 504 DataFormat format = check.m_gprInfo[GPRInfo::toIndex(recovery->dest())].format; 505 ASSERT(format == DataFormatInteger || format == DataFormatJSInteger || format == DataFormatJS); 506 if (format != DataFormatInteger) 507 orPtr(GPRInfo::tagTypeNumberRegister, recovery->dest()); 504 switch (recovery->type()) { 505 case SpeculativeAdd: { 506 ASSERT(check.m_gprInfo[GPRInfo::toIndex(recovery->dest())].nodeIndex != NoNode); 507 // Revert the add. 508 sub32(recovery->src(), recovery->dest()); 509 510 // If recovery->dest() should have been boxed prior to the addition, then rebox 511 // it. 512 DataFormat format = check.m_gprInfo[GPRInfo::toIndex(recovery->dest())].format; 513 ASSERT(format == DataFormatInteger || format == DataFormatJSInteger || format == DataFormatJS); 514 if (format != DataFormatInteger) 515 orPtr(GPRInfo::tagTypeNumberRegister, recovery->dest()); 516 break; 517 } 518 519 case BooleanSpeculationCheck: { 520 ASSERT(check.m_gprInfo[GPRInfo::toIndex(recovery->dest())].nodeIndex != NoNode); 521 // Rebox the (non-)boolean 522 xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), recovery->dest()); 523 break; 524 } 525 526 default: 527 ASSERT_NOT_REACHED(); 528 break; 529 } 508 530 } 509 531 … … 876 898 // Link the code, populate data in CodeBlock data structures. 877 899 #if DFG_DEBUG_VERBOSE 878 fprintf(stderr, "JIT code start at [%p, %p)\n", linkBuffer.debugAddress(), static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize());900 fprintf(stderr, "JIT code for %p start at [%p, %p)\n", m_codeBlock, linkBuffer.debugAddress(), static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize()); 879 901 #endif 880 902 -
trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h
r94559 r94629 55 55 struct SpeculationCheck; 56 56 57 #ifndef NDEBUG 58 typedef void (*V_DFGDebugOperation_EP)(ExecState*, void*); 59 #endif 60 61 #if DFG_VERBOSE_SPECULATION_FAILURE 62 struct SpeculationFailureDebugInfo { 63 CodeBlock* codeBlock; 64 unsigned debugOffset; 65 }; 66 #endif 67 57 68 // === CallRecord === 58 69 // … … 206 217 return functionCall; 207 218 } 219 220 #ifndef NDEBUG 221 // Add a debug call. This call has no effect on JIT code execution state. 222 void debugCall(V_DFGDebugOperation_EP function, void* argument) 223 { 224 for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) 225 storePtr(GPRInfo::toRegister(i), m_globalData->debugDataBuffer + i); 226 for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) { 227 move(TrustedImmPtr(m_globalData->debugDataBuffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0); 228 storeDouble(FPRInfo::toRegister(i), GPRInfo::regT0); 229 } 230 move(TrustedImmPtr(argument), GPRInfo::argumentGPR1); 231 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 232 move(TrustedImmPtr(reinterpret_cast<void*>(function)), GPRInfo::regT0); 233 call(GPRInfo::regT0); 234 for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) { 235 move(TrustedImmPtr(m_globalData->debugDataBuffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0); 236 loadDouble(GPRInfo::regT0, FPRInfo::toRegister(i)); 237 } 238 for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) 239 loadPtr(m_globalData->debugDataBuffer + i, GPRInfo::toRegister(i)); 240 } 241 #endif 208 242 209 243 // Helper methods to check nodes for constants. … … 212 246 bool isInt32Constant(NodeIndex nodeIndex) { return graph().isInt32Constant(codeBlock(), nodeIndex); } 213 247 bool isDoubleConstant(NodeIndex nodeIndex) { return graph().isDoubleConstant(codeBlock(), nodeIndex); } 248 bool isBooleanConstant(NodeIndex nodeIndex) { return graph().isBooleanConstant(codeBlock(), nodeIndex); } 214 249 // Helper methods get constant values from nodes. 215 250 JSValue valueOfJSConstant(NodeIndex nodeIndex) { return graph().valueOfJSConstant(codeBlock(), nodeIndex); } 216 251 int32_t valueOfInt32Constant(NodeIndex nodeIndex) { return graph().valueOfInt32Constant(codeBlock(), nodeIndex); } 217 252 double valueOfDoubleConstant(NodeIndex nodeIndex) { return graph().valueOfDoubleConstant(codeBlock(), nodeIndex); } 253 bool valueOfBooleanConstant(NodeIndex nodeIndex) { return graph().valueOfBooleanConstant(codeBlock(), nodeIndex); } 218 254 219 255 // These methods JIT generate dynamic, debug-only checks - akin to ASSERTs. -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r94559 r94629 45 45 // Emit a breakpoint into the speculation failure code. 46 46 #define DFG_JIT_BREAK_ON_SPECULATION_FAILURE 0 47 // Log every speculation failure. 48 #define DFG_VERBOSE_SPECULATION_FAILURE 0 47 49 // Disable the DFG JIT without having to touch Platform.h! 48 50 #define DFG_DEBUG_LOCAL_DISBALE 0 … … 90 92 #define NodeResultDouble 0x2000 91 93 #define NodeResultInt32 0x3000 94 #define NodeResultBoolean 0x4000 92 95 93 96 // This macro defines a set of information about all known node types, used to populate NodeId, NodeType below. … … 141 144 \ 142 145 /* Nodes for comparison operations. */\ 143 macro(CompareLess, NodeResult JS| NodeMustGenerate) \144 macro(CompareLessEq, NodeResult JS| NodeMustGenerate) \145 macro(CompareGreater, NodeResult JS| NodeMustGenerate) \146 macro(CompareGreaterEq, NodeResult JS| NodeMustGenerate) \147 macro(CompareEq, NodeResult JS| NodeMustGenerate) \148 macro(CompareStrictEq, NodeResult JS) \146 macro(CompareLess, NodeResultBoolean | NodeMustGenerate) \ 147 macro(CompareLessEq, NodeResultBoolean | NodeMustGenerate) \ 148 macro(CompareGreater, NodeResultBoolean | NodeMustGenerate) \ 149 macro(CompareGreaterEq, NodeResultBoolean | NodeMustGenerate) \ 150 macro(CompareEq, NodeResultBoolean | NodeMustGenerate) \ 151 macro(CompareStrictEq, NodeResultBoolean) \ 149 152 \ 150 153 /* Calls. */\ … … 160 163 macro(Breakpoint, NodeMustGenerate) \ 161 164 macro(CheckHasInstance, NodeMustGenerate) \ 162 macro(InstanceOf, NodeResult JS) \163 macro(LogicalNot, NodeResult JS) \165 macro(InstanceOf, NodeResultBoolean) \ 166 macro(LogicalNot, NodeResultBoolean) \ 164 167 \ 165 168 /* Block terminals. */\ … … 199 202 static const PredictedType PredictDouble = 0x08; 200 203 static const PredictedType PredictNumber = 0x0c; 201 static const PredictedType PredictTop = 0x0f; 204 static const PredictedType PredictBoolean = 0x10; 205 static const PredictedType PredictTop = 0x1f; 202 206 static const PredictedType StrongPredictionTag = 0x80; 203 207 static const PredictedType PredictionTagMask = 0x80; … … 228 232 { 229 233 return !!(value & PredictNumber) && !(value & ~(PredictNumber | PredictionTagMask)); 234 } 235 236 inline bool isBooleanPrediction(PredictedType value) 237 { 238 return (value & ~PredictionTagMask) == PredictBoolean; 230 239 } 231 240 … … 249 258 case PredictInt32: 250 259 return "p-strong-int32"; 260 case PredictDouble: 261 return "p-strong-double"; 251 262 case PredictNumber: 252 263 return "p-strong-number"; 264 case PredictBoolean: 265 return "p-strong-boolean"; 253 266 default: 254 267 return "p-strong-top"; … … 264 277 case PredictInt32: 265 278 return "p-weak-int32"; 279 case PredictDouble: 280 return "p-weak-double"; 266 281 case PredictNumber: 267 282 return "p-weak-number"; 283 case PredictBoolean: 284 return "p-weak-boolean"; 268 285 default: 269 286 return "p-weak-top"; … … 326 343 if (statistics.cells == statistics.samples) 327 344 return StrongPredictionTag | PredictCell; 345 346 if (statistics.booleans == statistics.samples) 347 return StrongPredictionTag | PredictBoolean; 328 348 329 349 return StrongPredictionTag | PredictTop; … … 424 444 } 425 445 446 bool isBooleanConstant(CodeBlock* codeBlock) 447 { 448 return isConstant() && valueOfJSConstant(codeBlock).isBoolean(); 449 } 450 426 451 int32_t valueOfInt32Constant(CodeBlock* codeBlock) 427 452 { … … 434 459 ASSERT(isDoubleConstant(codeBlock)); 435 460 return valueOfJSConstant(codeBlock).uncheckedGetNumber(); 461 } 462 463 bool valueOfBooleanConstant(CodeBlock* codeBlock) 464 { 465 ASSERT(isBooleanConstant(codeBlock)); 466 return valueOfJSConstant(codeBlock).getBoolean(); 436 467 } 437 468 … … 493 524 return (op & NodeResultMask) == NodeResultJS; 494 525 } 526 527 bool hasBooleanResult() 528 { 529 return (op & NodeResultMask) == NodeResultBoolean; 530 } 495 531 496 532 // Check for integers or doubles. 497 533 bool hasNumericResult() 498 534 { 499 // This check will need updating if more result types are added. 500 ASSERT((hasInt32Result() || hasDoubleResult()) == !hasJSResult()); 501 return !hasJSResult(); 535 return hasInt32Result() || hasDoubleResult(); 502 536 } 503 537 … … 564 598 ASSERT(source == StrongPrediction); 565 599 566 PredictedType newPrediction = StrongPredictionTag | prediction ;600 PredictedType newPrediction = StrongPredictionTag | prediction | m_opInfo2; 567 601 bool result = m_opInfo2 != newPrediction; 568 m_opInfo2 |= newPrediction;602 m_opInfo2 = newPrediction; 569 603 return result; 570 604 } -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r93375 r94629 679 679 } 680 680 681 #if DFG_VERBOSE_SPECULATION_FAILURE 682 void debugOperationPrintSpeculationFailure(ExecState*, void* debugInfoRaw) 683 { 684 SpeculationFailureDebugInfo* debugInfo = static_cast<SpeculationFailureDebugInfo*>(debugInfoRaw); 685 printf("Speculation failure in %p at 0x%x!\n", debugInfo->codeBlock, debugInfo->debugOffset); 686 } 687 #endif 688 681 689 } // extern "C" 682 690 } } // namespace JSC::DFG -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r93070 r94629 116 116 RegisterSizedBoolean dfgConvertJSValueToBoolean(ExecState*, EncodedJSValue); 117 117 118 #if DFG_VERBOSE_SPECULATION_FAILURE 119 void debugOperationPrintSpeculationFailure(ExecState*, void*); 120 #endif 121 118 122 } // extern "C" 119 123 } } // namespace JSC::DFG -
trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp
r94559 r94629 41 41 , m_profiledBlock(profiledBlock) 42 42 { 43 // Predictions is a forward flow property that propagates the values seen at 44 // a particular value source to their various uses, ensuring that uses perform 45 // speculation that does not contravene the expected values. 43 46 m_predictions.resize(m_graph.size()); 44 for (NodeIndex i = 0; i < m_graph.size(); ++i) 47 48 // Uses is a backward flow property that propagates the hard expectations at 49 // certain uses to their value sources, ensuring that predictions about 50 // values do not contravene the code itself. This comes up only in the 51 // cases of obvious cell uses, like GetById and friends as well as Call. 52 // We're essentially statically speculating that if the value profile indicates 53 // that only booleans (for example) flow into a GetById, then the value 54 // profile is simply wrong due to insufficient coverage and needs to be 55 // adjusted accordingly. The alternatives would be to assume either 56 // that the GetById never executes, or always executes on a boolean leading 57 // to whatever bizarre behavior that's supposed to cause. 58 m_uses.resize(m_graph.size()); 59 m_variableUses.initializeSimilarTo(m_graph.predictions()); 60 61 for (unsigned i = 0; i < m_graph.size(); ++i) { 45 62 m_predictions[i] = PredictNone; 63 m_uses[i] = PredictNone; 64 } 46 65 } 47 66 … … 52 71 #endif 53 72 do { 73 m_changed = false; 74 54 75 // Forward propagation is near-optimal for both topologically-sorted and 55 76 // DFS-sorted code. 56 m_changed = false;57 77 propagateForward(); 58 78 if (!m_changed) … … 65 85 m_changed = false; 66 86 propagateBackward(); 67 if (!m_changed)68 break;69 70 // Do another forward pass because forward passes are on average more71 // profitable.72 m_changed = false;73 propagateForward();74 87 } while (m_changed); 75 88 } 76 89 77 90 private: 78 void setPrediction(PredictedType prediction) 79 { 91 bool setPrediction(PredictedType prediction) 92 { 93 ASSERT(m_graph[m_compileIndex].hasResult()); 94 80 95 if (m_predictions[m_compileIndex] == prediction) 81 return ;96 return false; 82 97 83 98 m_predictions[m_compileIndex] = prediction; 84 m_changed = true; 85 } 86 87 void mergePrediction(PredictedType prediction) 88 { 89 if (DFG::mergePrediction(m_predictions[m_compileIndex], prediction)) 90 m_changed = true; 99 return true; 100 } 101 102 bool mergeUse(NodeIndex nodeIndex, PredictedType prediction) 103 { 104 ASSERT(m_graph[nodeIndex].hasResult()); 105 106 return DFG::mergePrediction(m_uses[nodeIndex], prediction); 107 } 108 109 bool mergePrediction(PredictedType prediction) 110 { 111 ASSERT(m_graph[m_compileIndex].hasResult()); 112 113 return DFG::mergePrediction(m_predictions[m_compileIndex], prediction); 91 114 } 92 115 … … 97 120 98 121 NodeType op = node.op; 122 123 #if DFG_DEBUG_VERBOSE 124 printf(" %s[%u]: ", Graph::opName(op), m_compileIndex); 125 #endif 126 127 bool changed = false; 128 99 129 switch (op) { 100 130 case JSConstant: { 101 131 JSValue value = node.valueOfJSConstant(m_codeBlock); 102 132 if (value.isInt32()) 103 setPrediction(makePrediction(PredictInt32, StrongPrediction));133 changed |= setPrediction(makePrediction(PredictInt32, StrongPrediction)); 104 134 else if (value.isDouble()) 105 setPrediction(makePrediction(PredictDouble, StrongPrediction));135 changed |= setPrediction(makePrediction(PredictDouble, StrongPrediction)); 106 136 else if (value.isCell()) { 107 137 JSCell* cell = value.asCell(); 108 138 if (isJSArray(&m_globalData, cell)) 109 setPrediction(makePrediction(PredictArray, StrongPrediction));139 changed |= setPrediction(makePrediction(PredictArray, StrongPrediction)); 110 140 else 111 setPrediction(makePrediction(PredictCell, StrongPrediction)); 112 } else 113 setPrediction(makePrediction(PredictTop, StrongPrediction)); 141 changed |= setPrediction(makePrediction(PredictCell, StrongPrediction)); 142 } else if (value.isBoolean()) 143 changed |= setPrediction(makePrediction(PredictBoolean, StrongPrediction)); 144 else 145 changed |= setPrediction(makePrediction(PredictTop, StrongPrediction)); 114 146 break; 115 147 } 116 148 117 149 case GetLocal: { 150 changed |= m_graph.predict(node.local(), m_uses[m_compileIndex] & ~PredictionTagMask, StrongPrediction); 151 changed |= m_variableUses.predict(node.local(), m_uses[m_compileIndex] & ~PredictionTagMask, StrongPrediction); 152 118 153 PredictedType prediction = m_graph.getPrediction(node.local()); 119 154 if (isStrongPrediction(prediction)) 120 mergePrediction(prediction);155 changed |= mergePrediction(prediction); 121 156 break; 122 157 } 123 158 124 159 case SetLocal: { 125 m_changed |= m_graph.predict(node.local(), m_predictions[node.child1()] & ~PredictionTagMask, StrongPrediction); 160 changed |= m_graph.predict(node.local(), m_predictions[node.child1()] & ~PredictionTagMask, StrongPrediction); 161 changed |= mergeUse(node.child1(), m_variableUses.getPrediction(node.local())); 126 162 break; 127 163 } … … 136 172 case ValueToInt32: 137 173 case ArithMod: { 138 setPrediction(makePrediction(PredictInt32, StrongPrediction));174 changed |= setPrediction(makePrediction(PredictInt32, StrongPrediction)); 139 175 break; 140 176 } … … 145 181 if (isStrongPrediction(prediction)) { 146 182 if (isNumberPrediction(prediction)) 147 mergePrediction(prediction);183 changed |= mergePrediction(prediction); 148 184 else 149 mergePrediction(makePrediction(PredictNumber, StrongPrediction));185 changed |= mergePrediction(makePrediction(PredictNumber, StrongPrediction)); 150 186 } 187 151 188 break; 152 189 } … … 159 196 if (isNumberPrediction(left) && isNumberPrediction(right)) { 160 197 if (isInt32Prediction(mergePredictions(left, right))) 161 mergePrediction(makePrediction(PredictInt32, StrongPrediction));198 changed |= mergePrediction(makePrediction(PredictInt32, StrongPrediction)); 162 199 else 163 mergePrediction(makePrediction(PredictDouble, StrongPrediction));200 changed |= mergePrediction(makePrediction(PredictDouble, StrongPrediction)); 164 201 } else 165 mergePrediction(makePrediction(PredictTop, StrongPrediction));202 changed |= mergePrediction(makePrediction(PredictTop, StrongPrediction)); 166 203 } 167 204 break; … … 176 213 if (isStrongPrediction(left) && isStrongPrediction(right)) { 177 214 if (isInt32Prediction(mergePredictions(left, right))) 178 mergePrediction(makePrediction(PredictInt32, StrongPrediction));215 changed |= mergePrediction(makePrediction(PredictInt32, StrongPrediction)); 179 216 else 180 mergePrediction(makePrediction(PredictDouble, StrongPrediction));217 changed |= mergePrediction(makePrediction(PredictDouble, StrongPrediction)); 181 218 } 182 219 break; … … 184 221 185 222 case ArithDiv: { 186 setPrediction(makePrediction(PredictDouble, StrongPrediction));223 changed |= setPrediction(makePrediction(PredictDouble, StrongPrediction)); 187 224 break; 188 225 } … … 196 233 case CompareStrictEq: 197 234 case InstanceOf: { 198 // This is sad, as we don't have a boolean prediction, even though we easily 199 // could. 200 setPrediction(makePrediction(PredictTop, StrongPrediction)); 235 changed |= setPrediction(makePrediction(PredictBoolean, StrongPrediction)); 201 236 break; 202 237 } … … 204 239 case GetById: 205 240 case GetMethod: 206 case GetByVal: 241 case GetByVal: { 242 changed |= mergeUse(node.child1(), PredictCell | StrongPredictionTag); 243 changed |= node.predict(m_uses[m_compileIndex] & ~PredictionTagMask, StrongPrediction); 244 if (isStrongPrediction(node.getPrediction())) 245 changed |= setPrediction(node.getPrediction()); 246 break; 247 } 248 207 249 case Call: 208 250 case Construct: { 251 changed |= mergeUse(m_graph.m_varArgChildren[node.firstChild()], PredictCell | StrongPredictionTag); 252 changed |= node.predict(m_uses[m_compileIndex] & ~PredictionTagMask, StrongPrediction); 209 253 if (isStrongPrediction(node.getPrediction())) 210 setPrediction(node.getPrediction());254 changed |= setPrediction(node.getPrediction()); 211 255 break; 212 256 } 213 257 214 258 case ConvertThis: { 215 setPrediction(makePrediction(PredictCell, StrongPrediction));259 changed |= setPrediction(makePrediction(PredictCell, StrongPrediction)); 216 260 break; 217 261 } 218 262 219 263 case GetGlobalVar: { 264 changed |= m_variableUses.predictGlobalVar(node.varNumber(), m_uses[m_compileIndex] & ~PredictionTagMask, StrongPrediction); 220 265 PredictedType prediction = m_graph.getGlobalVarPrediction(node.varNumber()); 221 266 if (isStrongPrediction(prediction)) 222 mergePrediction(prediction);267 changed |= mergePrediction(prediction); 223 268 break; 224 269 } 225 270 226 271 case PutGlobalVar: { 227 m_changed |= m_graph.predictGlobalVar(node.varNumber(), m_predictions[node.child1()] & ~PredictionTagMask, StrongPrediction); 228 break; 229 } 230 272 changed |= m_graph.predictGlobalVar(node.varNumber(), m_predictions[node.child1()] & ~PredictionTagMask, StrongPrediction); 273 changed |= mergeUse(node.child1(), m_variableUses.getGlobalVarPrediction(node.varNumber())); 274 break; 275 } 276 277 case PutByVal: 278 case PutByValAlias: 279 case PutById: 280 case PutByIdDirect: 281 changed |= mergeUse(node.child1(), PredictCell | StrongPredictionTag); 282 break; 283 231 284 #ifndef NDEBUG 232 285 // These get ignored because they don't return anything. 233 case PutByVal:234 case PutByValAlias:235 286 case DFG::Jump: 236 287 case Branch: 237 288 case Return: 238 case PutById:239 case PutByIdDirect:240 289 case CheckHasInstance: 241 290 case Phi: … … 256 305 #endif 257 306 } 307 308 #if DFG_DEBUG_VERBOSE 309 printf("expect(%s) use(%s) %s\n", predictionToString(m_predictions[m_compileIndex]), predictionToString(m_uses[m_compileIndex]), changed ? "CHANGED" : ""); 310 #endif 311 312 m_changed |= changed; 258 313 } 259 314 … … 284 339 285 340 Vector<PredictedType, 16> m_predictions; 341 Vector<PredictedType, 16> m_uses; 342 343 PredictionTracker m_variableUses; 286 344 287 345 #if DFG_DEBUG_VERBOSE -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r93934 r94629 129 129 case DataFormatDouble: 130 130 case DataFormatCell: 131 case DataFormatBoolean: 131 132 case DataFormatJSDouble: 132 case DataFormatJSCell: { 133 case DataFormatJSCell: 134 case DataFormatJSBoolean: { 133 135 terminateSpeculativeExecution(); 134 136 returnFormat = DataFormatInteger; … … 224 226 225 227 switch (info.registerFormat()) { 226 case DataFormatNone: 227 // Should have filled, above.228 case DataFormatNone: // Should have filled, above. 229 case DataFormatBoolean: // This type never occurs. 228 230 ASSERT_NOT_REACHED(); 229 231 230 232 case DataFormatCell: 231 233 case DataFormatJSCell: 232 case DataFormatJS: { 234 case DataFormatJS: 235 case DataFormatJSBoolean: { 233 236 GPRReg jsValueGpr = info.gpr(); 234 237 m_gprs.lock(jsValueGpr); … … 350 353 case DataFormatInteger: 351 354 case DataFormatJSDouble: 352 case DataFormatDouble: { 355 case DataFormatDouble: 356 case DataFormatJSBoolean: 357 case DataFormatBoolean: { 358 terminateSpeculativeExecution(); 359 return allocate(); 360 } 361 } 362 363 ASSERT_NOT_REACHED(); 364 return InvalidGPRReg; 365 } 366 367 GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex) 368 { 369 Node& node = m_jit.graph()[nodeIndex]; 370 VirtualRegister virtualRegister = node.virtualRegister(); 371 GenerationInfo& info = m_generationInfo[virtualRegister]; 372 373 switch (info.registerFormat()) { 374 case DataFormatNone: { 375 GPRReg gpr = allocate(); 376 377 if (node.isConstant()) { 378 JSValue jsValue = valueOfJSConstant(nodeIndex); 379 if (jsValue.isBoolean()) { 380 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 381 m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsValue)), gpr); 382 info.fillJSValue(gpr, DataFormatJSBoolean); 383 return gpr; 384 } 385 terminateSpeculativeExecution(); 386 return gpr; 387 } 388 ASSERT(info.spillFormat() & DataFormatJS); 389 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 390 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr); 391 392 info.fillJSValue(gpr, DataFormatJS); 393 if (info.spillFormat() != DataFormatJSBoolean) { 394 m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr); 395 speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg)); 396 m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr); 397 } 398 info.fillJSValue(gpr, DataFormatJSBoolean); 399 return gpr; 400 } 401 402 case DataFormatBoolean: 403 case DataFormatJSBoolean: { 404 GPRReg gpr = info.gpr(); 405 m_gprs.lock(gpr); 406 return gpr; 407 } 408 409 case DataFormatJS: { 410 GPRReg gpr = info.gpr(); 411 m_gprs.lock(gpr); 412 m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr); 413 speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg)); 414 m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr); 415 info.fillJSValue(gpr, DataFormatJSBoolean); 416 return gpr; 417 } 418 419 case DataFormatJSInteger: 420 case DataFormatInteger: 421 case DataFormatJSDouble: 422 case DataFormatDouble: 423 case DataFormatJSCell: 424 case DataFormatCell: { 353 425 terminateSpeculativeExecution(); 354 426 return allocate(); … … 529 601 // If we add a DataFormatBool, we should use it here. 530 602 m_jit.or32(TrustedImm32(ValueFalse), result.gpr()); 531 jsValueResult(result.gpr(), m_compileIndex );603 jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean); 532 604 } 533 605 … … 562 634 VirtualRegister virtualRegister = node.virtualRegister(); 563 635 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS); 564 m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), result.gpr(), isArrayPrediction(prediction) ? DataFormatJSCell : DataFormatJS); 636 637 DataFormat format; 638 if (isArrayPrediction(prediction)) 639 format = DataFormatJSCell; 640 else if (isBooleanPrediction(prediction)) 641 format = DataFormatJSBoolean; 642 else 643 format = DataFormatJS; 644 645 m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), result.gpr(), format); 565 646 } 566 647 break; … … 579 660 m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local())); 580 661 noResult(m_compileIndex); 662 } else if (isBooleanPrediction(predictedType)) { 663 SpeculateBooleanOperand boolean(this, node.child1()); 664 m_jit.storePtr(boolean.gpr(), JITCompiler::addressFor(node.local())); 665 noResult(m_compileIndex); 581 666 } else { 582 667 JSValueOperand value(this, node.child1()); … … 842 927 843 928 case LogicalNot: { 929 if (isKnownBoolean(node.child1())) { 930 SpeculateBooleanOperand value(this, node.child1()); 931 GPRTemporary result(this, value); 932 933 m_jit.move(value.gpr(), result.gpr()); 934 m_jit.xorPtr(TrustedImm32(true), result.gpr()); 935 936 jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean); 937 break; 938 } 939 844 940 JSValueOperand value(this, node.child1()); 845 941 GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add). … … 851 947 852 948 // If we add a DataFormatBool, we should use it here. 853 jsValueResult(result.gpr(), m_compileIndex );949 jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean); 854 950 break; 855 951 } … … 1228 1324 1229 1325 putResult.link(&m_jit); 1230 jsValueResult(scratchReg, m_compileIndex );1326 jsValueResult(scratchReg, m_compileIndex, DataFormatJSBoolean); 1231 1327 break; 1232 1328 } -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r92593 r94629 38 38 // may need be performed should a speculation check fail. 39 39 enum SpeculationRecoveryType { 40 SpeculativeAdd 40 SpeculativeAdd, 41 BooleanSpeculationCheck 41 42 }; 42 43 … … 133 134 FPRReg fillSpeculateDouble(NodeIndex); 134 135 GPRReg fillSpeculateCell(NodeIndex); 135 136 private: 136 GPRReg fillSpeculateBoolean(NodeIndex); 137 138 private: 139 friend class JITCodeGenerator; 140 137 141 void compile(Node&); 138 142 void compile(BasicBlock&); … … 409 413 }; 410 414 415 class SpeculateBooleanOperand { 416 public: 417 explicit SpeculateBooleanOperand(SpeculativeJIT* jit, NodeIndex index) 418 : m_jit(jit) 419 , m_index(index) 420 , m_gprOrInvalid(InvalidGPRReg) 421 { 422 ASSERT(m_jit); 423 if (jit->isFilled(index)) 424 gpr(); 425 } 426 427 ~SpeculateBooleanOperand() 428 { 429 ASSERT(m_gprOrInvalid != InvalidGPRReg); 430 m_jit->unlock(m_gprOrInvalid); 431 } 432 433 NodeIndex index() const 434 { 435 return m_index; 436 } 437 438 GPRReg gpr() 439 { 440 if (m_gprOrInvalid == InvalidGPRReg) 441 m_gprOrInvalid = m_jit->fillSpeculateBoolean(index()); 442 return m_gprOrInvalid; 443 } 444 445 void use() 446 { 447 m_jit->use(m_index); 448 } 449 450 private: 451 SpeculativeJIT* m_jit; 452 NodeIndex m_index; 453 GPRReg m_gprOrInvalid; 454 }; 455 411 456 412 457 // === SpeculationCheckIndexIterator ===
Note:
See TracChangeset
for help on using the changeset viewer.