Changeset 95865 in webkit
- Timestamp:
- Sep 23, 2011 3:05:24 PM (13 years ago)
- Location:
- trunk/Source
- Files:
-
- 2 added
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r95864 r95865 1 2011-09-23 Oliver Hunt <oliver@apple.com> 2 3 Make write barriers actually do something when enabled 4 https://bugs.webkit.org/show_bug.cgi?id=68717 5 6 Reviewed by Geoffrey Garen. 7 8 Add a basic card marking style write barrier to JSC (currently 9 turned off). This requires two scratch registers in the JIT 10 so there was some register re-arranging to satisfy that requirement. 11 Happily this produced a minor perf bump in sunspider (~0.5%). 12 13 Turning the barriers on causes an overall regression of around 1.5% 14 15 * JavaScriptCore.exp: 16 * JavaScriptCore.xcodeproj/project.pbxproj: 17 * assembler/MacroAssemblerX86Common.h: 18 (JSC::MacroAssemblerX86Common::store8): 19 * assembler/X86Assembler.h: 20 (JSC::X86Assembler::movb_i8m): 21 * dfg/DFGJITCodeGenerator.cpp: 22 (JSC::DFG::JITCodeGenerator::isKnownNotCell): 23 (JSC::DFG::JITCodeGenerator::writeBarrier): 24 (JSC::DFG::JITCodeGenerator::markCellCard): 25 (JSC::DFG::JITCodeGenerator::cachedPutById): 26 * dfg/DFGJITCodeGenerator.h: 27 * dfg/DFGRepatch.cpp: 28 (JSC::DFG::tryCachePutByID): 29 * dfg/DFGSpeculativeJIT.cpp: 30 (JSC::DFG::SpeculativeJIT::compile): 31 * heap/CardSet.h: Added. 32 (JSC::CardSet::CardSet): 33 (JSC::::cardForAtom): 34 (JSC::::cardMarkedForAtom): 35 (JSC::::markCardForAtom): 36 * heap/Heap.cpp: 37 * heap/Heap.h: 38 (JSC::Heap::addressOfCardFor): 39 (JSC::Heap::writeBarrierFastCase): 40 * heap/MarkedBlock.h: 41 (JSC::MarkedBlock::setDirtyObject): 42 (JSC::MarkedBlock::addressOfCardFor): 43 (JSC::MarkedBlock::offsetOfCards): 44 * jit/JIT.h: 45 * jit/JITPropertyAccess.cpp: 46 (JSC::JIT::emit_op_put_by_val): 47 (JSC::JIT::emit_op_put_by_id): 48 (JSC::JIT::privateCompilePutByIdTransition): 49 (JSC::JIT::emit_op_put_scoped_var): 50 (JSC::JIT::emit_op_put_global_var): 51 (JSC::JIT::emitWriteBarrier): 52 * jit/JITPropertyAccess32_64.cpp: 53 (JSC::JIT::emit_op_put_by_val): 54 (JSC::JIT::emit_op_put_by_id): 55 (JSC::JIT::emitSlow_op_put_by_id): 56 (JSC::JIT::privateCompilePutByIdTransition): 57 (JSC::JIT::emit_op_put_scoped_var): 58 (JSC::JIT::emit_op_put_global_var): 59 1 60 2011-09-23 Thouraya ANDOLSI <thouraya.andolsi@st.com> 2 61 -
trunk/Source/JavaScriptCore/JavaScriptCore.exp
r95849 r95865 241 241 __ZN3JSC4Heap19setActivityCallbackEN3WTF10PassOwnPtrINS_18GCActivityCallbackEEE 242 242 __ZN3JSC4Heap20protectedObjectCountEv 243 __ZN3JSC4Heap20writeBarrierSlowCaseEPKNS_6JSCellEPS1_244 243 __ZN3JSC4Heap25protectedObjectTypeCountsEv 245 244 __ZN3JSC4Heap26protectedGlobalObjectCountEv -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r95751 r95865 430 430 A7482E93116A7CAD003B0712 /* JSWeakObjectMapRefInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = A7482E37116A697B003B0712 /* JSWeakObjectMapRefInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; 431 431 A74DE1D0120B875600D40D5B /* ARMv7Assembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A74DE1CB120B86D600D40D5B /* ARMv7Assembler.cpp */; }; 432 A7521E131429169A003C8D0C /* CardSet.h in Headers */ = {isa = PBXBuildFile; fileRef = A7521E121429169A003C8D0C /* CardSet.h */; settings = {ATTRIBUTES = (); }; }; 432 433 A75706DE118A2BCF0057F88F /* JITArithmetic32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A75706DD118A2BCF0057F88F /* JITArithmetic32_64.cpp */; }; 433 434 A766B44F0EE8DCD1009518CA /* ExecutableAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 1214 1215 A7482E37116A697B003B0712 /* JSWeakObjectMapRefInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWeakObjectMapRefInternal.h; sourceTree = "<group>"; }; 1215 1216 A74DE1CB120B86D600D40D5B /* ARMv7Assembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ARMv7Assembler.cpp; sourceTree = "<group>"; }; 1217 A7521E121429169A003C8D0C /* CardSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CardSet.h; sourceTree = "<group>"; }; 1216 1218 A75706DD118A2BCF0057F88F /* JITArithmetic32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITArithmetic32_64.cpp; sourceTree = "<group>"; }; 1217 1219 A76C51741182748D00715B05 /* JSInterfaceJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSInterfaceJIT.h; sourceTree = "<group>"; }; … … 1634 1636 0FD82F281426CA5A00179C94 /* JettisonedCodeBlocks.cpp */, 1635 1637 0FD82F291426CA5A00179C94 /* JettisonedCodeBlocks.h */, 1638 A70456AE1427FB030037DA68 /* AllocationSpace.cpp */, 1636 1639 A70456AF1427FB150037DA68 /* AllocationSpace.h */, 1637 A70456AE1427FB030037DA68 /* AllocationSpace.cpp */, 1638 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */, 1639 0FC815141405118D00CFA603 /* VTableSpectrum.h */, 1640 0FC815121405118600CFA603 /* VTableSpectrum.cpp */, 1641 0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */, 1642 0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */, 1640 A7521E121429169A003C8D0C /* CardSet.h */, 1643 1641 146B14DB12EB5B12001BEC1B /* ConservativeRoots.cpp */, 1644 1642 149DAAF212EB559D0083B12B /* ConservativeRoots.h */, … … 1666 1664 142E3132134FF0A600AFADB5 /* Strong.h */, 1667 1665 141448CC13A1783700F5BA1A /* TinyBloomFilter.h */, 1666 0FC815121405118600CFA603 /* VTableSpectrum.cpp */, 1667 0FC815141405118D00CFA603 /* VTableSpectrum.h */, 1668 1668 142E3133134FF0A600AFADB5 /* Weak.h */, 1669 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */, 1670 0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */, 1671 0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */, 1669 1672 ); 1670 1673 path = heap; … … 2819 2822 A70456B01427FB910037DA68 /* AllocationSpace.h in Headers */, 2820 2823 86FA9E92142BBB2E001773B7 /* JSBoundFunction.h in Headers */, 2824 A7521E131429169A003C8D0C /* CardSet.h in Headers */, 2821 2825 ); 2822 2826 runOnlyForDeploymentPostprocessing = 0; -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h
r94981 r95865 510 510 { 511 511 m_assembler.movl_i32m(imm.m_value, address.offset, address.base); 512 } 513 514 void store8(TrustedImm32 imm, Address address) 515 { 516 ASSERT(-128 <= imm.m_value && imm.m_value < 128); 517 m_assembler.movb_i8m(imm.m_value, address.offset, address.base); 518 } 519 520 void store8(TrustedImm32 imm, BaseIndex address) 521 { 522 ASSERT(-128 <= imm.m_value && imm.m_value < 128); 523 m_assembler.movb_i8m(imm.m_value, address.offset, address.base, address.index, address.scale); 512 524 } 513 525 -
trunk/Source/JavaScriptCore/assembler/X86Assembler.h
r95692 r95865 146 146 OP_GROUP2_EvIb = 0xC1, 147 147 OP_RET = 0xC3, 148 OP_GROUP11_EvIb = 0xC6, 148 149 OP_GROUP11_EvIz = 0xC7, 149 150 OP_INT3 = 0xCC, … … 1056 1057 m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, offset); 1057 1058 m_formatter.immediate32(imm); 1059 } 1060 1061 void movb_i8m(int imm, int offset, RegisterID base) 1062 { 1063 ASSERT(-128 <= imm && imm < 128); 1064 m_formatter.oneByteOp(OP_GROUP11_EvIb, GROUP11_MOV, base, offset); 1065 m_formatter.immediate8(imm); 1066 } 1067 1068 void movb_i8m(int imm, int offset, RegisterID base, RegisterID index, int scale) 1069 { 1070 ASSERT(-128 <= imm && imm < 128); 1071 m_formatter.oneByteOp(OP_GROUP11_EvIb, GROUP11_MOV, base, index, scale, offset); 1072 m_formatter.immediate8(imm); 1058 1073 } 1059 1074 -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp
r95563 r95865 430 430 } 431 431 432 bool JITCodeGenerator::isKnownNotCell(NodeIndex nodeIndex) 433 { 434 Node& node = m_jit.graph()[nodeIndex]; 435 VirtualRegister virtualRegister = node.virtualRegister(); 436 GenerationInfo& info = m_generationInfo[virtualRegister]; 437 if (node.hasConstant() && !valueOfJSConstant(nodeIndex).isCell()) 438 return true; 439 return !(info.isJSCell() || info.isUnknownJS()); 440 } 441 432 442 bool JITCodeGenerator::isKnownNotInteger(NodeIndex nodeIndex) 433 443 { … … 1167 1177 } 1168 1178 1169 void JITCodeGenerator::writeBarrier(MacroAssembler& jit, GPRReg owner, GPRReg scratch , WriteBarrierUseKind useKind)1179 void JITCodeGenerator::writeBarrier(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2, WriteBarrierUseKind useKind) 1170 1180 { 1171 1181 UNUSED_PARAM(jit); 1172 1182 UNUSED_PARAM(owner); 1173 UNUSED_PARAM(scratch); 1183 UNUSED_PARAM(scratch1); 1184 UNUSED_PARAM(scratch2); 1174 1185 UNUSED_PARAM(useKind); 1175 ASSERT(owner != scratch); 1186 ASSERT(owner != scratch1); 1187 ASSERT(owner != scratch2); 1188 ASSERT(scratch1 != scratch2); 1176 1189 1177 1190 #if ENABLE(WRITE_BARRIER_PROFILING) 1178 1191 JITCompiler::emitCount(jit, WriteBarrierCounters::jitCounterFor(useKind)); 1179 1192 #endif 1180 } 1181 1182 void JITCodeGenerator::cachedPutById(GPRReg baseGPR, GPRReg valueGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget) 1183 { 1193 markCellCard(jit, owner, scratch1, scratch2); 1194 } 1195 1196 void JITCodeGenerator::markCellCard(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2) 1197 { 1198 UNUSED_PARAM(jit); 1199 UNUSED_PARAM(owner); 1200 UNUSED_PARAM(scratch1); 1201 UNUSED_PARAM(scratch2); 1202 1203 #if ENABLE(GGC) 1204 jit.move(owner, scratch1); 1205 jit.andPtr(TrustedImm32(static_cast<int32_t>(MarkedBlock::blockMask)), scratch1); 1206 jit.move(owner, scratch2); 1207 jit.andPtr(TrustedImm32(static_cast<int32_t>(~MarkedBlock::blockMask)), scratch2); 1208 jit.rshift32(TrustedImm32(MarkedBlock::log2CardSize), scratch2); 1209 jit.store8(TrustedImm32(1), MacroAssembler::BaseIndex(scratch1, scratch2, MacroAssembler::TimesOne, MarkedBlock::offsetOfCards())); 1210 #endif 1211 } 1212 1213 void JITCodeGenerator::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2) 1214 { 1215 UNUSED_PARAM(ownerGPR); 1216 UNUSED_PARAM(valueGPR); 1217 UNUSED_PARAM(scratch1); 1218 UNUSED_PARAM(scratch2); 1219 UNUSED_PARAM(useKind); 1220 1221 if (isKnownNotCell(valueIndex)) 1222 return; 1223 1224 #if ENABLE(WRITE_BARRIER_PROFILING) 1225 JITCompiler::emitCount(jit, WriteBarrierCounters::jitCounterFor(useKind)); 1226 #endif 1227 1228 #if ENABLE(GGC) 1229 JITCompiler::Jump rhsNotCell; 1230 bool hadCellCheck = false; 1231 if (!isKnownCell(valueIndex) && !isCellPrediction(m_jit.graph().getPrediction(m_jit.graph()[valueIndex]))) { 1232 hadCellCheck = true; 1233 rhsNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister); 1234 } 1235 1236 GPRTemporary temp1; 1237 GPRTemporary temp2; 1238 if (scratch1 == InvalidGPRReg) { 1239 GPRTemporary scratchGPR(this); 1240 temp1.adopt(scratchGPR); 1241 scratch1 = temp1.gpr(); 1242 } 1243 if (scratch2 == InvalidGPRReg) { 1244 GPRTemporary scratchGPR(this); 1245 temp2.adopt(scratchGPR); 1246 scratch2 = temp2.gpr(); 1247 } 1248 1249 markCellCard(m_jit, ownerGPR, scratch1, scratch2); 1250 if (hadCellCheck) 1251 rhsNotCell.link(&m_jit); 1252 #endif 1253 } 1254 1255 void JITCodeGenerator::writeBarrier(JSCell* owner, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind useKind, GPRReg scratch) 1256 { 1257 UNUSED_PARAM(owner); 1258 UNUSED_PARAM(valueGPR); 1259 UNUSED_PARAM(scratch); 1260 UNUSED_PARAM(useKind); 1261 1262 if (isKnownNotCell(valueIndex)) 1263 return; 1264 1265 #if ENABLE(WRITE_BARRIER_PROFILING) 1266 JITCompiler::emitCount(jit, WriteBarrierCounters::jitCounterFor(useKind)); 1267 #endif 1268 1269 #if ENABLE(GGC) 1270 JITCompiler::Jump rhsNotCell; 1271 bool hadCellCheck = false; 1272 if (!isKnownCell(valueIndex) && !isCellPrediction(m_jit.graph().getPrediction(m_jit.graph()[valueIndex]))) { 1273 hadCellCheck = true; 1274 rhsNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister); 1275 } 1276 1277 GPRTemporary temp; 1278 if (scratch == InvalidGPRReg) { 1279 GPRTemporary scratchGPR(this); 1280 temp.adopt(scratchGPR); 1281 scratch = temp.gpr(); 1282 } 1283 1284 uint8_t* cardAddress = Heap::addressOfCardFor(owner); 1285 m_jit.move(JITCompiler::TrustedImmPtr(cardAddress), scratch); 1286 m_jit.store8(JITCompiler::TrustedImm32(1), JITCompiler::Address(scratch)); 1287 1288 if (hadCellCheck) 1289 rhsNotCell.link(&m_jit); 1290 #endif 1291 } 1292 1293 void JITCodeGenerator::cachedPutById(GPRReg baseGPR, GPRReg valueGPR, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget) 1294 { 1295 1184 1296 JITCompiler::DataLabelPtr structureToCompare; 1185 1297 JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1))); 1186 1187 writeBarrier( m_jit, baseGPR, scratchGPR, WriteBarrierForPropertyAccess);1298 1299 writeBarrier(baseGPR, valueGPR, valueIndex, WriteBarrierForPropertyAccess, scratchGPR); 1188 1300 1189 1301 m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR); … … 1978 2090 #endif 1979 2091 2092 GPRTemporary::GPRTemporary() 2093 : m_jit(0) 2094 , m_gpr(InvalidGPRReg) 2095 { 2096 } 2097 1980 2098 GPRTemporary::GPRTemporary(JITCodeGenerator* jit) 1981 2099 : m_jit(jit) … … 2086 2204 } 2087 2205 2206 void GPRTemporary::adopt(GPRTemporary& other) 2207 { 2208 ASSERT(!m_jit); 2209 ASSERT(m_gpr == InvalidGPRReg); 2210 ASSERT(other.m_jit); 2211 ASSERT(other.m_gpr != InvalidGPRReg); 2212 m_jit = other.m_jit; 2213 m_gpr = other.m_gpr; 2214 other.m_jit = 0; 2215 other.m_gpr = InvalidGPRReg; 2216 } 2217 2088 2218 FPRTemporary::FPRTemporary(JITCodeGenerator* jit) 2089 2219 : m_jit(jit) -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h
r95758 r95865 182 182 } 183 183 184 static void writeBarrier(MacroAssembler&, GPRReg ownerGPR, GPRReg scratchGPR, WriteBarrierUseKind); 184 static void markCellCard(MacroAssembler&, GPRReg ownerGPR, GPRReg scratchGPR1, GPRReg scratchGPR2); 185 static void writeBarrier(MacroAssembler&, GPRReg ownerGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, WriteBarrierUseKind); 186 187 void writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg, GPRReg scratchGPR2 = InvalidGPRReg); 188 void writeBarrier(JSCell* owner, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg); 185 189 186 190 static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg) … … 434 438 435 439 bool isKnownBoolean(NodeIndex); 440 441 bool isKnownNotCell(NodeIndex); 436 442 437 443 // Checks/accessors for constant values. … … 619 625 620 626 JITCompiler::Call cachedGetById(GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), NodeType = GetById); 621 void cachedPutById(GPRReg base GPR, GPRReg valueGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());627 void cachedPutById(GPRReg base, GPRReg value, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump()); 622 628 void cachedGetMethod(GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump()); 623 629 … … 1248 1254 class GPRTemporary { 1249 1255 public: 1256 GPRTemporary(); 1250 1257 GPRTemporary(JITCodeGenerator*); 1251 1258 GPRTemporary(JITCodeGenerator*, GPRReg specific); … … 1260 1267 GPRTemporary(JITCodeGenerator*, StorageOperand&); 1261 1268 1269 void adopt(GPRTemporary&); 1270 1262 1271 ~GPRTemporary() 1263 1272 { 1264 m_jit->unlock(gpr()); 1273 if (m_jit) 1274 m_jit->unlock(gpr()); 1265 1275 } 1266 1276 -
trunk/Source/JavaScriptCore/dfg/DFGRepatch.cpp
r95447 r95865 518 518 testPrototype(stubJit, scratchGPR, (*it)->storedPrototype(), failureCases); 519 519 } 520 521 JITCodeGenerator::writeBarrier(stubJit, baseGPR, scratchGPR, WriteBarrierForPropertyAccess); 522 520 521 #if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING) 522 // Must always emit this write barrier as the structure transition itself requires it 523 GPRReg scratch2 = JITCodeGenerator::selectScratchGPR(baseGPR, valueGPR, scratchGPR); 524 stubJit.push(scratch2); 525 JITCodeGenerator::writeBarrier(stubJit, baseGPR, scratchGPR, scratch2, WriteBarrierForPropertyAccess); 526 stubJit.pop(scratch2); 527 #endif 528 523 529 stubJit.storePtr(MacroAssembler::TrustedImmPtr(structure), MacroAssembler::Address(baseGPR, JSCell::structureOffset())); 524 530 if (structure->isUsingInlineStorage()) -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r95840 r95865 25 25 26 26 #include "config.h" 27 27 28 #include "DFGSpeculativeJIT.h" 28 29 … … 1405 1406 if (!m_compileOkay) 1406 1407 return; 1407 1408 writeBarrier( m_jit, baseReg, scratchReg, WriteBarrierForPropertyAccess);1408 1409 writeBarrier(baseReg, value.gpr(), node.child3(), WriteBarrierForPropertyAccess, scratchReg); 1409 1410 1410 1411 // Check that base is an array, and that property is contained within m_vector (< m_vectorLength). … … 1465 1466 GPRReg scratchReg = scratch.gpr(); 1466 1467 1467 writeBarrier( m_jit, baseReg, scratchReg, WriteBarrierForPropertyAccess);1468 writeBarrier(base.gpr(), value.gpr(), node.child3(), WriteBarrierForPropertyAccess, scratchReg); 1468 1469 1469 1470 // Get the array storage. … … 1796 1797 JSValueOperand value(this, node.child2()); 1797 1798 m_jit.storePtr(value.gpr(), JITCompiler::Address(scratchGPR, node.varNumber() * sizeof(Register))); 1798 writeBarrier( m_jit, scopeChain.gpr(), scratchGPR, WriteBarrierForVariableAccess);1799 writeBarrier(scopeChain.gpr(), value.gpr(), node.child2(), WriteBarrierForVariableAccess, scratchGPR); 1799 1800 break; 1800 1801 } … … 1902 1903 value.use(); 1903 1904 1904 cachedPutById(baseGPR, valueGPR, scratchGPR, node.identifierNumber(), NotDirect);1905 cachedPutById(baseGPR, valueGPR, node.child2(), scratchGPR, node.identifierNumber(), NotDirect); 1905 1906 1906 1907 noResult(m_compileIndex, UseChildrenCalledExplicitly); … … 1920 1921 value.use(); 1921 1922 1922 cachedPutById(baseGPR, valueGPR, scratchGPR, node.identifierNumber(), Direct);1923 cachedPutById(baseGPR, valueGPR, node.child2(), scratchGPR, node.identifierNumber(), Direct); 1923 1924 1924 1925 noResult(m_compileIndex, UseChildrenCalledExplicitly); … … 1947 1948 m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.codeBlock()->globalObject()), globalObjectReg); 1948 1949 1949 writeBarrier(m_jit , globalObjectReg, scratchReg, WriteBarrierForVariableAccess);1950 writeBarrier(m_jit.codeBlock()->globalObject(), value.gpr(), node.child1(), WriteBarrierForVariableAccess, scratchReg); 1950 1951 1951 1952 m_jit.loadPtr(MacroAssembler::Address(globalObjectReg, JSVariableObject::offsetOfRegisters()), scratchReg); -
trunk/Source/JavaScriptCore/heap/Heap.cpp
r95681 r95865 683 683 } 684 684 685 #if ENABLE(GGC)686 void Heap::writeBarrierSlowCase(const JSCell* owner, JSCell* cell)687 {688 }689 690 #else691 692 void Heap::writeBarrierSlowCase(const JSCell*, JSCell*)693 {694 }695 #endif696 697 685 } // namespace JSC -
trunk/Source/JavaScriptCore/heap/Heap.h
r95681 r95865 75 75 static void writeBarrier(const JSCell*, JSValue); 76 76 static void writeBarrier(const JSCell*, JSCell*); 77 static uint8_t* addressOfCardFor(JSCell*); 77 78 78 79 Heap(JSGlobalData*, HeapSize); … … 132 133 static const size_t minExtraCost = 256; 133 134 static const size_t maxExtraCost = 1024 * 1024; 134 135 #if ENABLE(GGC)136 static void writeBarrierFastCase(const JSCell* owner, JSCell*);137 #endif138 135 139 136 bool isValidAllocation(size_t); … … 158 155 RegisterFile& registerFile(); 159 156 160 static void writeBarrierSlowCase(const JSCell*, JSCell*);161 162 157 void waitForRelativeTimeWhileHoldingLock(double relative); 163 158 void waitForRelativeTime(double relative); … … 240 235 241 236 #if ENABLE(GGC) 242 inline void Heap::writeBarrierFastCase(const JSCell* owner, JSCell* cell) 243 { 244 if (MarkedBlock::blockFor(owner)->inNewSpace()) 245 return; 246 writeBarrierSlowCase(owner, cell); 247 } 248 249 inline void Heap::writeBarrier(const JSCell* owner, JSCell* cell) 237 inline uint8_t* Heap::addressOfCardFor(JSCell* cell) 238 { 239 return MarkedBlock::blockFor(cell)->addressOfCardFor(cell); 240 } 241 242 inline void Heap::writeBarrier(const JSCell* owner, JSCell*) 250 243 { 251 244 WriteBarrierCounters::countWriteBarrier(); 252 writeBarrierFastCase(owner, cell);245 MarkedBlock::blockFor(owner)->setDirtyObject(owner); 253 246 } 254 247 255 248 inline void Heap::writeBarrier(const JSCell* owner, JSValue value) 256 249 { 257 WriteBarrierCounters::countWriteBarrier();258 250 if (!value) 259 251 return; 260 252 if (!value.isCell()) 261 253 return; 262 writeBarrier FastCase(owner, value.asCell());254 writeBarrier(owner, value.asCell()); 263 255 } 264 256 #else -
trunk/Source/JavaScriptCore/heap/MarkedBlock.h
r95596 r95865 23 23 #define MarkedBlock_h 24 24 25 #include "CardSet.h" 26 25 27 #include <wtf/Bitmap.h> 26 28 #include <wtf/DoublyLinkedList.h> … … 66 68 static const size_t atomSize = 4 * sizeof(void*); 67 69 static const size_t blockSize = 16 * KB; 68 static const size_t atomsPerBlock = blockSize / atomSize; // ~0.4% overhead for mark bits. 70 static const size_t blockMask = ~(blockSize - 1); // blockSize must be a power of two. 71 72 static const size_t atomsPerBlock = blockSize / atomSize; // ~0.4% overhead 73 static const size_t bytesPerCard = 512; // 1.6% overhead 74 static const int log2CardSize = 9; 69 75 70 76 struct FreeCell { … … 133 139 bool testAndClearMarked(const void*); 134 140 void setMarked(const void*); 141 142 #if ENABLE(GGC) 143 void setDirtyObject(const void* atom) 144 { 145 m_cards.markCardForAtom(atom); 146 } 147 148 uint8_t* addressOfCardFor(const void* atom) 149 { 150 return &m_cards.cardForAtom(atom); 151 } 152 153 static inline size_t offsetOfCards() 154 { 155 return OBJECT_OFFSETOF(MarkedBlock, m_cards); 156 } 157 #endif 135 158 136 159 template <typename Functor> void forEachCell(Functor&); 137 160 138 161 private: 139 static const size_t blockMask = ~(blockSize - 1); // blockSize must be a power of two.140 162 static const size_t atomMask = ~(atomSize - 1); // atomSize must be a power of two. 141 163 … … 170 192 return static_cast<DestructorState>(m_destructorState); 171 193 } 172 194 195 #if ENABLE(GGC) 196 CardSet<bytesPerCard, blockSize> m_cards; 197 #endif 198 173 199 size_t m_endAtom; // This is a fuzzy end. Always test for < m_endAtom. 174 200 size_t m_atomsPerCell; … … 301 327 } 302 328 } 303 329 304 330 } // namespace JSC 305 331 -
trunk/Source/JavaScriptCore/jit/JIT.h
r95676 r95865 317 317 void testPrototype(JSValue, JumpList& failureCases); 318 318 319 void emitWriteBarrier(RegisterID owner, RegisterID scratch, WriteBarrierUseKind); 319 enum WriteBarrierMode { UnconditionalWriteBarrier, ShouldFilterImmediates }; 320 // value register in write barrier is used before any scratch registers 321 // so may safely be the same as either of the scratch registers. 322 void emitWriteBarrier(RegisterID owner, RegisterID valueTag, RegisterID scratch, RegisterID scratch2, WriteBarrierMode, WriteBarrierUseKind); 323 void emitWriteBarrier(JSCell* owner, RegisterID value, RegisterID scratch, WriteBarrierMode, WriteBarrierUseKind); 320 324 321 325 template<typename ClassType, typename StructureType> void emitAllocateBasicJSObject(StructureType, void* vtable, RegisterID result, RegisterID storagePtr); -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
r95786 r95865 208 208 209 209 Label storeResult(this); 210 emitGetVirtualRegister(value, regT 0);211 storePtr(regT 0, BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));210 emitGetVirtualRegister(value, regT3); 211 storePtr(regT3, BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); 212 212 Jump end = jump(); 213 213 … … 216 216 branch32(Below, regT1, Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length))).linkTo(storeResult, this); 217 217 218 move(regT1, regT0); 219 add32(TrustedImm32(1), regT0); 220 store32(regT0, Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length))); 218 add32(TrustedImm32(1), Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length))); 221 219 jump().linkTo(storeResult, this); 222 220 223 221 end.link(this); 222 223 emitWriteBarrier(regT0, regT3, regT1, regT3, ShouldFilterImmediates, WriteBarrierForPropertyAccess); 224 224 } 225 225 … … 440 440 emitJumpSlowCaseIfNotJSCell(regT0, baseVReg); 441 441 442 emitWriteBarrier(regT0, regT2, WriteBarrierForPropertyAccess);443 444 442 BEGIN_UNINTERRUPTED_SEQUENCE(sequencePutById); 445 443 … … 454 452 ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetPutByIdStructure); 455 453 456 loadPtr(Address(regT0, JSObject::offsetOfPropertyStorage()), regT 0);457 DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(regT1, Address(regT 0, patchPutByIdDefaultOffset));454 loadPtr(Address(regT0, JSObject::offsetOfPropertyStorage()), regT2); 455 DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(regT1, Address(regT2, patchPutByIdDefaultOffset)); 458 456 459 457 END_UNINTERRUPTED_SEQUENCE(sequencePutById); 458 459 emitWriteBarrier(regT0, regT1, regT2, regT3, ShouldFilterImmediates, WriteBarrierForPropertyAccess); 460 460 461 461 ASSERT_JIT_OFFSET_UNUSED(displacementLabel, differenceBetween(hotPathBegin, displacementLabel), patchOffsetPutByIdPropertyMapOffset); … … 538 538 restoreReturnAddressBeforeReturn(regT3); 539 539 } 540 541 emitWriteBarrier(regT0, regT2, WriteBarrierForPropertyAccess); 540 541 // Planting the new structure triggers the write barrier so we need 542 // an unconditional barrier here. 543 emitWriteBarrier(regT0, regT1, regT2, regT3, UnconditionalWriteBarrier, WriteBarrierForPropertyAccess); 542 544 543 545 storePtr(TrustedImmPtr(newStructure), Address(regT0, JSCell::structureOffset())); … … 990 992 loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, object)), regT1); 991 993 992 emitWriteBarrier(regT1, regT 2, WriteBarrierForVariableAccess);994 emitWriteBarrier(regT1, regT0, regT2, regT3, ShouldFilterImmediates, WriteBarrierForVariableAccess); 993 995 994 996 loadPtr(Address(regT1, JSVariableObject::offsetOfRegisters()), regT1); … … 1010 1012 1011 1013 emitGetVirtualRegister(currentInstruction[2].u.operand, regT0); 1014 1012 1015 move(TrustedImmPtr(globalObject), regT1); 1013 1014 emitWriteBarrier(regT1, regT2, WriteBarrierForVariableAccess);1015 1016 1016 loadPtr(Address(regT1, JSVariableObject::offsetOfRegisters()), regT1); 1017 1017 storePtr(regT0, Address(regT1, currentInstruction[1].u.operand * sizeof(Register))); 1018 } 1019 1020 void JIT::emitWriteBarrier(RegisterID owner, RegisterID scratch, WriteBarrierUseKind useKind) 1018 emitWriteBarrier(globalObject, regT0, regT2, ShouldFilterImmediates, WriteBarrierForVariableAccess); 1019 } 1020 1021 #endif // USE(JSVALUE64) 1022 1023 void JIT::emitWriteBarrier(RegisterID owner, RegisterID value, RegisterID scratch, RegisterID scratch2, WriteBarrierMode mode, WriteBarrierUseKind useKind) 1024 { 1025 UNUSED_PARAM(owner); 1026 UNUSED_PARAM(scratch); 1027 UNUSED_PARAM(scratch2); 1028 UNUSED_PARAM(useKind); 1029 UNUSED_PARAM(value); 1030 UNUSED_PARAM(mode); 1031 ASSERT(owner != scratch); 1032 ASSERT(owner != scratch2); 1033 1034 #if ENABLE(WRITE_BARRIER_PROFILING) 1035 emitCount(WriteBarrierCounters::jitCounterFor(useKind)); 1036 #endif 1037 1038 #if ENABLE(GGC) 1039 Jump filterCells; 1040 if (mode == ShouldFilterImmediates) 1041 filterCells = emitJumpIfNotJSCell(value); 1042 move(owner, scratch); 1043 andPtr(TrustedImm32(static_cast<int32_t>(MarkedBlock::blockMask)), scratch); 1044 move(owner, scratch2); 1045 andPtr(TrustedImm32(static_cast<int32_t>(~MarkedBlock::blockMask)), scratch2); 1046 rshift32(TrustedImm32(MarkedBlock::log2CardSize), scratch2); 1047 store8(TrustedImm32(1), BaseIndex(scratch, scratch2, TimesOne, MarkedBlock::offsetOfCards())); 1048 if (mode == ShouldFilterImmediates) 1049 filterCells.link(this); 1050 #endif 1051 } 1052 1053 void JIT::emitWriteBarrier(JSCell* owner, RegisterID value, RegisterID scratch, WriteBarrierMode mode, WriteBarrierUseKind useKind) 1021 1054 { 1022 1055 UNUSED_PARAM(owner); 1023 1056 UNUSED_PARAM(scratch); 1024 1057 UNUSED_PARAM(useKind); 1025 ASSERT(owner != scratch); 1058 UNUSED_PARAM(value); 1059 UNUSED_PARAM(mode); 1026 1060 1027 1061 #if ENABLE(WRITE_BARRIER_PROFILING) 1028 1062 emitCount(WriteBarrierCounters::jitCounterFor(useKind)); 1029 1063 #endif 1030 } 1031 1032 #endif // USE(JSVALUE64) 1064 1065 #if ENABLE(GGC) 1066 Jump filterCells; 1067 if (mode == ShouldFilterImmediates) 1068 filterCells = emitJumpIfNotJSCell(value); 1069 uint8_t* cardAddress = Heap::addressOfCardFor(owner); 1070 move(TrustedImmPtr(cardAddress), scratch); 1071 store8(TrustedImm32(1), Address(scratch)); 1072 if (mode == ShouldFilterImmediates) 1073 filterCells.link(this); 1074 #endif 1075 } 1033 1076 1034 1077 void JIT::testPrototype(JSValue prototype, JumpList& failureCases) -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
r95455 r95865 259 259 260 260 addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); 261 emitJumpSlowCaseIfNotJSCell(base, regT1);262 emitWriteBarrier(regT0, regT1, WriteBarrierForPropertyAccess);263 261 addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr))); 264 262 addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, JSArray::vectorLengthOffset()))); 265 263 264 emitJumpSlowCaseIfNotJSCell(base, regT1); 265 emitWriteBarrier(regT0, regT1, regT1, regT3, UnconditionalWriteBarrier, WriteBarrierForPropertyAccess); 266 266 267 loadPtr(Address(regT0, JSArray::storageOffset()), regT3); 267 268 … … 397 398 emitJumpSlowCaseIfNotJSCell(base, regT1); 398 399 399 emitWriteBarrier(regT0, regT1, WriteBarrierForPropertyAccess);400 401 400 BEGIN_UNINTERRUPTED_SEQUENCE(sequencePutById); 402 401 … … 411 410 ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetPutByIdStructure); 412 411 413 loadPtr(Address(regT0, JSObject::offsetOfPropertyStorage()), regT 0);414 DataLabel32 displacementLabel1 = storePtrWithAddressOffsetPatch(regT2, Address(regT 0, patchPutByIdDefaultOffset)); // payload415 DataLabel32 displacementLabel2 = storePtrWithAddressOffsetPatch(regT3, Address(regT 0, patchPutByIdDefaultOffset)); // tag412 loadPtr(Address(regT0, JSObject::offsetOfPropertyStorage()), regT1); 413 DataLabel32 displacementLabel1 = storePtrWithAddressOffsetPatch(regT2, Address(regT1, patchPutByIdDefaultOffset)); // payload 414 DataLabel32 displacementLabel2 = storePtrWithAddressOffsetPatch(regT3, Address(regT1, patchPutByIdDefaultOffset)); // tag 416 415 417 416 END_UNINTERRUPTED_SEQUENCE(sequencePutById); 417 418 emitWriteBarrier(regT0, regT2, regT1, regT2, ShouldFilterImmediates, WriteBarrierForPropertyAccess); 418 419 419 420 ASSERT_JIT_OFFSET_UNUSED(displacementLabel1, differenceBetween(hotPathBegin, displacementLabel1), patchOffsetPutByIdPropertyMapOffset1); … … 431 432 432 433 JITStubCall stubCall(this, direct ? cti_op_put_by_id_direct : cti_op_put_by_id); 433 stubCall.addArgument( regT1, regT0);434 stubCall.addArgument(base); 434 435 stubCall.addArgument(TrustedImmPtr(&(m_codeBlock->identifier(ident)))); 435 436 stubCall.addArgument(regT3, regT2); … … 517 518 } 518 519 519 emitWriteBarrier(regT0, regT1, WriteBarrierForPropertyAccess);520 emitWriteBarrier(regT0, regT1, regT1, regT3, UnconditionalWriteBarrier, WriteBarrierForPropertyAccess); 520 521 521 522 storePtr(TrustedImmPtr(newStructure), Address(regT0, JSCell::structureOffset())); … … 1044 1045 loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, object)), regT2); 1045 1046 1046 emitWriteBarrier(regT2, regT3, WriteBarrierForVariableAccess); 1047 1048 loadPtr(Address(regT2, JSVariableObject::offsetOfRegisters()), regT2); 1049 emitStore(index, regT1, regT0, regT2); 1050 map(m_bytecodeOffset + OPCODE_LENGTH(op_put_scoped_var), value, regT1, regT0); 1047 loadPtr(Address(regT2, JSVariableObject::offsetOfRegisters()), regT3); 1048 emitStore(index, regT1, regT0, regT3); 1049 emitWriteBarrier(regT2, regT1, regT0, regT1, ShouldFilterImmediates, WriteBarrierForVariableAccess); 1051 1050 } 1052 1051 … … 1075 1074 move(TrustedImmPtr(globalObject), regT2); 1076 1075 1077 emitWriteBarrier( regT2, regT3, WriteBarrierForVariableAccess);1076 emitWriteBarrier(globalObject, regT1, regT3, ShouldFilterImmediates, WriteBarrierForVariableAccess); 1078 1077 1079 1078 loadPtr(Address(regT2, JSVariableObject::offsetOfRegisters()), regT2); … … 1082 1081 } 1083 1082 1084 void JIT::emitWriteBarrier(RegisterID owner, RegisterID scratch, WriteBarrierUseKind useKind)1085 {1086 UNUSED_PARAM(owner);1087 UNUSED_PARAM(scratch);1088 UNUSED_PARAM(useKind);1089 ASSERT(owner != scratch);1090 1091 #if ENABLE(WRITE_BARRIER_PROFILING)1092 emitCount(WriteBarrierCounters::jitCounterFor(useKind));1093 #endif1094 }1095 1096 1083 } // namespace JSC 1097 1084 -
trunk/Source/WebCore/ChangeLog
r95863 r95865 1 2011-09-23 Oliver Hunt <oliver@apple.com> 2 3 Make write barriers actually do something when enabled 4 https://bugs.webkit.org/show_bug.cgi?id=68717 5 6 Reviewed by Geoffrey Garen. 7 8 Add a forwarding header, and fix an evaluation ordering 9 issue that shows up if you try to use write barriers. 10 11 * ForwardingHeaders/heap/CardSet.h: Added. 12 * bindings/js/JSEventListener.h: 13 (WebCore::JSEventListener::jsFunction): 14 1 15 2011-09-23 James Robinson <jamesr@chromium.org> 2 16 -
trunk/Source/WebCore/bindings/js/JSEventListener.h
r86499 r95865 75 75 inline JSC::JSObject* JSEventListener::jsFunction(ScriptExecutionContext* scriptExecutionContext) const 76 76 { 77 if (!m_jsFunction) 78 m_jsFunction.setMayBeNull(*scriptExecutionContext->globalData(), m_wrapper.get(), initializeJSFunction(scriptExecutionContext)); 77 if (!m_jsFunction) { 78 JSC::JSObject* function = initializeJSFunction(scriptExecutionContext); 79 m_jsFunction.setMayBeNull(*scriptExecutionContext->globalData(), m_wrapper.get(), function); 80 } 79 81 80 82 // Verify that we have a valid wrapper protecting our function from
Note: See TracChangeset
for help on using the changeset viewer.