Changeset 118555 in webkit
- Timestamp:
- May 25, 2012 1:19:55 PM (12 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r118484 r118555 1 2012-05-21 Filip Pizlo <fpizlo@apple.com> 2 3 DFG ConvertThis should just be a CheckStructure if the structure is known 4 https://bugs.webkit.org/show_bug.cgi?id=87057 5 6 Reviewed by Gavin Barraclough. 7 8 Merged r118021 from dfgopt. 9 10 This gives ValueProfile the ability to track singleton values - i.e. profiling 11 sites that always see the same value. 12 13 That is then used to profile the structure in op_convert_this. 14 15 This is then used to optimize op_convert_this into a CheckStructure if the 16 structure is always the same. 17 18 That then results in better CSE in inlined code that uses 'this', since 19 previously we couldn't CSE accesses on 'this' from different inline call frames. 20 21 Also fixed a bug where we were unnecessarily flushing 'this'. 22 23 * bytecode/CodeBlock.cpp: 24 (JSC::CodeBlock::dump): 25 (JSC::CodeBlock::stronglyVisitStrongReferences): 26 * bytecode/LazyOperandValueProfile.cpp: 27 (JSC::CompressedLazyOperandValueProfileHolder::computeUpdatedPredictions): 28 * bytecode/LazyOperandValueProfile.h: 29 (CompressedLazyOperandValueProfileHolder): 30 * bytecode/Opcode.h: 31 (JSC): 32 (JSC::padOpcodeName): 33 * bytecode/ValueProfile.h: 34 (JSC::ValueProfileBase::ValueProfileBase): 35 (JSC::ValueProfileBase::dump): 36 (JSC::ValueProfileBase::computeUpdatedPrediction): 37 (ValueProfileBase): 38 * bytecompiler/BytecodeGenerator.cpp: 39 (JSC::BytecodeGenerator::BytecodeGenerator): 40 * dfg/DFGByteCodeParser.cpp: 41 (JSC::DFG::ByteCodeParser::setArgument): 42 (JSC::DFG::ByteCodeParser::parseBlock): 43 * jit/JITOpcodes.cpp: 44 (JSC::JIT::emit_op_convert_this): 45 (JSC::JIT::emitSlow_op_convert_this): 46 * jit/JITOpcodes32_64.cpp: 47 (JSC::JIT::emit_op_convert_this): 48 (JSC::JIT::emitSlow_op_convert_this): 49 * llint/LLIntSlowPaths.cpp: 50 (JSC::LLInt::LLINT_SLOW_PATH_DECL): 51 * llint/LowLevelInterpreter32_64.asm: 52 * llint/LowLevelInterpreter64.asm: 53 * runtime/JSValue.h: 54 (JSValue): 55 * runtime/Structure.h: 56 (JSC::JSValue::structureOrUndefined): 57 (JSC): 58 1 59 2012-05-24 Tim Horton <timothy_horton@apple.com> 2 60 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r118270 r118555 671 671 int r0 = (++it)->u.operand; 672 672 dataLog("[%4d] convert_this\t %s\n", location, registerName(exec, r0).data()); 673 ++it; // Skip value profile. 673 674 break; 674 675 } … … 2086 2087 } 2087 2088 2088 m_lazyOperandValueProfiles.computeUpdatedPredictions( );2089 m_lazyOperandValueProfiles.computeUpdatedPredictions(Collection); 2089 2090 #endif 2090 2091 2091 2092 #if ENABLE(VALUE_PROFILER) 2092 2093 for (unsigned profileIndex = 0; profileIndex < numberOfArgumentValueProfiles(); ++profileIndex) 2093 valueProfileForArgument(profileIndex)->computeUpdatedPrediction( );2094 valueProfileForArgument(profileIndex)->computeUpdatedPrediction(Collection); 2094 2095 for (unsigned profileIndex = 0; profileIndex < numberOfValueProfiles(); ++profileIndex) 2095 valueProfile(profileIndex)->computeUpdatedPrediction( );2096 valueProfile(profileIndex)->computeUpdatedPrediction(Collection); 2096 2097 #endif 2097 2098 } -
trunk/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.cpp
r108677 r118555 34 34 CompressedLazyOperandValueProfileHolder::~CompressedLazyOperandValueProfileHolder() { } 35 35 36 void CompressedLazyOperandValueProfileHolder::computeUpdatedPredictions( )36 void CompressedLazyOperandValueProfileHolder::computeUpdatedPredictions(OperationInProgress operation) 37 37 { 38 38 if (!m_data) … … 40 40 41 41 for (unsigned i = 0; i < m_data->size(); ++i) 42 m_data->at(i).computeUpdatedPrediction( );42 m_data->at(i).computeUpdatedPrediction(operation); 43 43 } 44 44 -
trunk/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.h
r108677 r118555 156 156 ~CompressedLazyOperandValueProfileHolder(); 157 157 158 void computeUpdatedPredictions( );158 void computeUpdatedPredictions(OperationInProgress); 159 159 160 160 LazyOperandValueProfile* add(const LazyOperandValueProfileKey& key); -
trunk/Source/JavaScriptCore/bytecode/Opcode.h
r116673 r118555 44 44 macro(op_create_arguments, 2) \ 45 45 macro(op_create_this, 2) \ 46 macro(op_convert_this, 2) \46 macro(op_convert_this, 3) \ 47 47 \ 48 48 macro(op_new_object, 2) \ -
trunk/Source/JavaScriptCore/bytecode/ValueProfile.h
r108677 r118555 34 34 #if ENABLE(VALUE_PROFILER) 35 35 36 #include "Heap.h" 36 37 #include "JSArray.h" 37 38 #include "PredictedType.h" … … 52 53 , m_prediction(PredictNone) 53 54 , m_numberOfSamplesInPrediction(0) 55 , m_singletonValueIsTop(false) 54 56 { 55 57 for (unsigned i = 0; i < totalNumberOfBuckets; ++i) … … 61 63 , m_prediction(PredictNone) 62 64 , m_numberOfSamplesInPrediction(0) 65 , m_singletonValueIsTop(false) 63 66 { 64 67 for (unsigned i = 0; i < totalNumberOfBuckets; ++i) … … 113 116 totalNumberOfSamples(), 114 117 predictionToString(m_prediction)); 118 fprintf(out, ", value = "); 119 if (m_singletonValueIsTop) 120 fprintf(out, "TOP"); 121 else 122 fprintf(out, "%s", m_singletonValue.description()); 115 123 bool first = true; 116 124 for (unsigned i = 0; i < totalNumberOfBuckets; ++i) { … … 128 136 129 137 // Updates the prediction and returns the new one. 130 PredictedType computeUpdatedPrediction( )138 PredictedType computeUpdatedPrediction(OperationInProgress operation = NoOperation) 131 139 { 132 140 for (unsigned i = 0; i < totalNumberOfBuckets; ++i) { … … 138 146 mergePrediction(m_prediction, predictionFromValue(value)); 139 147 148 if (!m_singletonValueIsTop && !!value) { 149 if (!m_singletonValue) 150 m_singletonValue = value; 151 else if (m_singletonValue != value) 152 m_singletonValueIsTop = true; 153 } 154 140 155 m_buckets[i] = JSValue::encode(JSValue()); 141 156 } 142 157 158 if (operation == Collection 159 && !m_singletonValueIsTop 160 && !!m_singletonValue 161 && m_singletonValue.isCell() 162 && !Heap::isMarked(m_singletonValue.asCell())) 163 m_singletonValueIsTop = true; 164 143 165 return m_prediction; 144 166 } … … 149 171 unsigned m_numberOfSamplesInPrediction; 150 172 173 bool m_singletonValueIsTop; 174 JSValue m_singletonValue; 175 151 176 EncodedJSValue m_buckets[totalNumberOfBuckets]; 152 177 }; -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r117198 r118555 446 446 instructions().append(m_thisRegister.index()); 447 447 } else if (!codeBlock->isStrictMode() && (functionBody->usesThis() || codeBlock->usesEval() || m_shouldEmitDebugHooks)) { 448 emitOpcode(op_convert_this);448 ValueProfile* profile = emitProfiledOpcode(op_convert_this); 449 449 instructions().append(m_thisRegister.index()); 450 instructions().append(profile); 450 451 } 451 452 } -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r118468 r118555 351 351 NodeIndex nodeIndex = addToGraph(SetLocal, OpInfo(variableAccessData), value); 352 352 m_currentBlock->variablesAtTail.argument(argument) = nodeIndex; 353 // Always flush arguments. 354 addToGraph(Flush, OpInfo(variableAccessData), nodeIndex); 353 // Always flush arguments, except for 'this'. 354 if (argument) 355 addToGraph(Flush, OpInfo(variableAccessData), nodeIndex); 355 356 } 356 357 … … 1583 1584 case op_convert_this: { 1584 1585 NodeIndex op1 = getThis(); 1585 if (m_graph[op1].op() == ConvertThis) 1586 setThis(op1); 1587 else 1588 setThis(addToGraph(ConvertThis, op1)); 1586 if (m_graph[op1].op() != ConvertThis) { 1587 ValueProfile* profile = 1588 m_inlineStackTop->m_profiledBlock->valueProfileForBytecodeOffset(m_currentProfilingIndex); 1589 profile->computeUpdatedPrediction(); 1590 #if DFG_ENABLE(DEBUG_VERBOSE) 1591 dataLog("[@%lu bc#%u]: profile %p: ", m_graph.size(), m_currentProfilingIndex, profile); 1592 profile->dump(WTF::dataFile()); 1593 dataLog("\n"); 1594 #endif 1595 if (profile->m_singletonValueIsTop 1596 || !profile->m_singletonValue 1597 || !profile->m_singletonValue.isCell() 1598 || profile->m_singletonValue.asCell()->classInfo() != &Structure::s_info) 1599 setThis(addToGraph(ConvertThis, op1)); 1600 else { 1601 addToGraph( 1602 CheckStructure, 1603 OpInfo(m_graph.addStructureSet(jsCast<Structure*>(profile->m_singletonValue.asCell()))), 1604 op1); 1605 } 1606 } 1589 1607 NEXT_OPCODE(op_convert_this); 1590 1608 } -
trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp
r118323 r118555 1258 1258 void JIT::emit_op_convert_this(Instruction* currentInstruction) 1259 1259 { 1260 emitGetVirtualRegister(currentInstruction[1].u.operand, regT0); 1261 1262 emitJumpSlowCaseIfNotJSCell(regT0); 1263 addSlowCase(branchPtr(Equal, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info))); 1260 emitGetVirtualRegister(currentInstruction[1].u.operand, regT1); 1261 1262 emitJumpSlowCaseIfNotJSCell(regT1); 1263 if (shouldEmitProfiling()) { 1264 loadPtr(Address(regT1, JSCell::structureOffset()), regT0); 1265 emitValueProfilingSite(); 1266 } 1267 addSlowCase(branchPtr(Equal, Address(regT1, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info))); 1264 1268 } 1265 1269 … … 1316 1320 1317 1321 linkSlowCase(iter); 1318 Jump isNotUndefined = branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(jsUndefined()))); 1322 if (shouldEmitProfiling()) 1323 move(TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(jsUndefined()))), regT0); 1324 Jump isNotUndefined = branchPtr(NotEqual, regT1, TrustedImmPtr(JSValue::encode(jsUndefined()))); 1325 emitValueProfilingSite(); 1319 1326 move(TrustedImmPtr(globalThis), regT0); 1320 1327 emitPutVirtualRegister(currentInstruction[1].u.operand, regT0); 1321 1328 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_convert_this)); 1322 1329 1330 linkSlowCase(iter); 1331 if (shouldEmitProfiling()) 1332 move(TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(m_globalData->stringStructure.get()))), regT0); 1323 1333 isNotUndefined.link(this); 1324 linkSlowCase(iter);1334 emitValueProfilingSite(); 1325 1335 JITStubCall stubCall(this, cti_op_convert_this); 1326 stubCall.addArgument(regT 0);1336 stubCall.addArgument(regT1); 1327 1337 stubCall.call(currentInstruction[1].u.operand); 1328 1338 } -
trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
r118112 r118555 1549 1549 unsigned thisRegister = currentInstruction[1].u.operand; 1550 1550 1551 emitLoad(thisRegister, regT1, regT0); 1552 1553 addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag))); 1554 addSlowCase(branchPtr(Equal, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info))); 1555 1556 map(m_bytecodeOffset + OPCODE_LENGTH(op_convert_this), thisRegister, regT1, regT0); 1551 emitLoad(thisRegister, regT3, regT2); 1552 1553 addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::CellTag))); 1554 if (shouldEmitProfiling()) { 1555 loadPtr(Address(regT2, JSCell::structureOffset()), regT0); 1556 move(regT3, regT1); 1557 emitValueProfilingSite(); 1558 } 1559 addSlowCase(branchPtr(Equal, Address(regT2, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info))); 1557 1560 } 1558 1561 … … 1563 1566 1564 1567 linkSlowCase(iter); 1565 Jump isNotUndefined = branch32(NotEqual, regT1, TrustedImm32(JSValue::UndefinedTag)); 1568 if (shouldEmitProfiling()) { 1569 move(TrustedImm32(JSValue::UndefinedTag), regT1); 1570 move(TrustedImm32(0), regT0); 1571 } 1572 Jump isNotUndefined = branch32(NotEqual, regT3, TrustedImm32(JSValue::UndefinedTag)); 1573 emitValueProfilingSite(); 1566 1574 move(TrustedImmPtr(globalThis), regT0); 1567 1575 move(TrustedImm32(JSValue::CellTag), regT1); … … 1569 1577 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_convert_this)); 1570 1578 1579 linkSlowCase(iter); 1580 if (shouldEmitProfiling()) { 1581 move(TrustedImm32(JSValue::CellTag), regT1); 1582 move(TrustedImmPtr(m_globalData->stringStructure.get()), regT0); 1583 } 1571 1584 isNotUndefined.link(this); 1572 linkSlowCase(iter);1585 emitValueProfilingSite(); 1573 1586 JITStubCall stubCall(this, cti_op_convert_this); 1574 stubCall.addArgument(regT 1, regT0);1587 stubCall.addArgument(regT3, regT2); 1575 1588 stubCall.call(thisRegister); 1576 1589 } -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
r117859 r118555 468 468 JSValue v1 = LLINT_OP(1).jsValue(); 469 469 ASSERT(v1.isPrimitive()); 470 pc[OPCODE_LENGTH(op_convert_this) - 1].u.profile->m_buckets[0] = 471 JSValue::encode(v1.structureOrUndefined()); 470 472 LLINT_RETURN(v1.toThisObject(exec)); 471 473 } -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
r118112 r118555 365 365 loadp JSCell::m_structure[t0], t0 366 366 bbb Structure::m_typeInfo + TypeInfo::m_type[t0], ObjectType, .opConvertThisSlow 367 dispatch(2) 367 loadi 8[PC], t1 368 valueProfile(CellTag, t0, t1) 369 dispatch(3) 368 370 369 371 .opConvertThisSlow: 370 372 callSlowPath(_llint_slow_path_convert_this) 371 dispatch( 2)373 dispatch(3) 372 374 373 375 -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r118112 r118555 242 242 loadp JSCell::m_structure[t0], t0 243 243 bbb Structure::m_typeInfo + TypeInfo::m_type[t0], ObjectType, .opConvertThisSlow 244 dispatch(2) 244 loadp 16[PB, PC, 8], t1 245 valueProfile(t0, t1) 246 dispatch(3) 245 247 246 248 .opConvertThisSlow: 247 249 callSlowPath(_llint_slow_path_convert_this) 248 dispatch( 2)250 dispatch(3) 249 251 250 252 -
trunk/Source/JavaScriptCore/runtime/JSValue.h
r117646 r118555 240 240 JSCell* asCell() const; 241 241 JS_EXPORT_PRIVATE bool isValidCallee(); 242 243 JSValue structureOrUndefined() const; 242 244 243 245 char* description() const; -
trunk/Source/JavaScriptCore/runtime/Structure.h
r117859 r118555 333 333 } 334 334 335 inline JSValue JSValue::structureOrUndefined() const 336 { 337 if (isCell()) 338 return JSValue(asCell()->structure()); 339 return jsUndefined(); 340 } 341 335 342 inline bool JSCell::isObject() const 336 343 {
Note: See TracChangeset
for help on using the changeset viewer.