Changeset 120172 in webkit
- Timestamp:
- Jun 13, 2012, 1:20:39 AM (13 years ago)
- Location:
- trunk
- Files:
-
- 6 added
- 63 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r120170 r120172 1 2012-06-12 Filip Pizlo <[email protected]> 2 3 DFG should be able to set watchpoints on global variables 4 https://bugs.webkit.org/show_bug.cgi?id=88692 5 6 Rubber stamped by Geoffrey Garen. 7 8 Added a test for watchpoints. Also updated the jsc-test-list to include the latest 9 tests. 10 11 * fast/js/dfg-call-function-hit-watchpoint-expected.txt: Added. 12 * fast/js/dfg-call-function-hit-watchpoint.html: Added. 13 * fast/js/jsc-test-list: 14 * fast/js/script-tests/dfg-call-function-hit-watchpoint.js: Added. 15 (foo): 16 (bar): 17 (.foo): 18 1 19 2012-06-13 Kristóf Kosztyó <[email protected]> 2 20 -
trunk/LayoutTests/fast/js/jsc-test-list
r118323 r120172 65 65 fast/js/delete-getters-setters 66 66 fast/js/delete-then-put 67 fast/js/dfg-add-not-number 68 fast/js/dfg-arguments-alias-escape 69 fast/js/dfg-arguments-alias-one-block-osr-exit 70 fast/js/dfg-arguments-alias-one-block-overwrite-arguments 71 fast/js/dfg-arguments-alias-one-block-overwrite 72 fast/js/dfg-arguments-alias-one-block 73 fast/js/dfg-arguments-alias 74 fast/js/dfg-arguments-cross-code-origin 75 fast/js/dfg-arguments-mixed-alias 67 76 fast/js/dfg-arguments-osr-exit 68 fast/js/dfg-arguments-mixed-alias 69 fast/js/dfg-arguments-cross-code-origin 77 fast/js/dfg-arguments-out-of-bounds 70 78 fast/js/dfg-arguments-unexpected-escape 71 fast/js/dfg-arguments-alias72 fast/js/dfg-arguments-alias-escape73 79 fast/js/dfg-array-length-dead 80 fast/js/dfg-branch-not-fail 81 fast/js/dfg-check-two-structures 82 fast/js/dfg-constant-fold-first-local-read-after-block-merge 74 83 fast/js/dfg-convert-this-dom-window 84 fast/js/dfg-cse-cfa-discrepancy 85 fast/js/dfg-dead-min-one-arg 86 fast/js/dfg-dead-min-two-args 87 fast/js/dfg-dead-speculation 88 fast/js/dfg-dead-variable-on-exit 89 fast/js/dfg-double-use-of-post-simplification-double-prediction 75 90 fast/js/dfg-double-vote-fuzz 76 91 fast/js/dfg-exception 77 92 fast/js/dfg-float32array 78 93 fast/js/dfg-float64array 94 fast/js/dfg-flush-get-local 79 95 fast/js/dfg-get-by-val-clobber 80 96 fast/js/dfg-get-by-val-getter-cse 81 97 fast/js/dfg-getter-throw 82 98 fast/js/dfg-getter 99 fast/js/dfg-inline-arguments-become-double 100 fast/js/dfg-inline-arguments-become-int32 83 101 fast/js/dfg-inline-arguments-int32 102 fast/js/dfg-inline-arguments-osr-exit-and-capture 103 fast/js/dfg-inline-arguments-out-of-bounds 104 fast/js/dfg-inline-arguments-reset-changetype 105 fast/js/dfg-inline-arguments-reset 84 106 fast/js/dfg-inline-arguments-simple 85 107 fast/js/dfg-inline-arguments-use-directly-from-inlined-code … … 97 119 fast/js/dfg-inlining-reg-alloc 98 120 fast/js/dfg-int16array 121 fast/js/dfg-int32-to-double-on-known-number 99 122 fast/js/dfg-int32array-overflow-values 100 123 fast/js/dfg-int32array … … 106 129 fast/js/dfg-min-max 107 130 fast/js/dfg-multiply 131 fast/js/dfg-negative-array-index 132 fast/js/dfg-obvious-constant-cfa 108 133 fast/js/dfg-other-branch 109 134 fast/js/dfg-poison-fuzz 135 fast/js/dfg-proto-access-inline-osr-exit 136 fast/js/dfg-put-by-id-prototype-check 137 fast/js/dfg-putbyval-cfa-clobber 110 138 fast/js/dfg-string-stricteq 139 fast/js/dfg-tear-off-arguments-not-activation 111 140 fast/js/dfg-uint16array 141 fast/js/dfg-uint32-to-number-on-captured-variable 142 fast/js/dfg-uint32-to-number 143 fast/js/dfg-uint32array-overflow-constant 112 144 fast/js/dfg-uint32array-overflow-values 113 fast/js/dfg-uint32-to-number 114 fast/js/dfg-uint32-to-number-on-captured-variable 145 fast/js/dfg-uint32array 115 146 fast/js/dfg-uint8array 116 147 fast/js/dfg-uint8clampedarray 148 fast/js/dfg-weak-js-constant-silent-fill 117 149 fast/js/dictionary-no-cache 118 150 fast/js/dictionary-prototype-caching … … 127 159 fast/js/exception-for-nonobject 128 160 fast/js/exception-linenums 161 fast/js/exception-propagate-from-dfg-to-llint 129 162 fast/js/exception-properties 130 163 fast/js/exception-try-finally-scope-error -
trunk/Source/JavaScriptCore/CMakeLists.txt
r119660 r120172 54 54 bytecode/SamplingTool.cpp 55 55 bytecode/StructureStubInfo.cpp 56 bytecode/Watchpoint.cpp 56 57 57 58 bytecompiler/BytecodeGenerator.cpp … … 232 233 runtime/Structure.cpp 233 234 runtime/StructureChain.cpp 235 runtime/SymbolTable.cpp 234 236 runtime/TimeoutChecker.cpp 235 237 runtime/UString.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r120159 r120172 1 2012-06-12 Filip Pizlo <[email protected]> 2 3 DFG should be able to set watchpoints on global variables 4 https://bugs.webkit.org/show_bug.cgi?id=88692 5 6 Reviewed by Geoffrey Garen. 7 8 This implements global variable constant folding by allowing the optimizing 9 compiler to set a "watchpoint" on globals that it wishes to constant fold. 10 If the watchpoint fires, then an OSR exit is forced by overwriting the 11 machine code that the optimizing compiler generated with a jump. 12 13 As such, this patch is adding quite a bit of stuff: 14 15 - Jump replacement on those hardware targets supported by the optimizing 16 JIT. It is now possible to patch in a jump instruction over any recorded 17 watchpoint label. The jump must be "local" in the sense that it must be 18 within the range of the largest jump distance supported by a one 19 instruction jump. 20 21 - WatchpointSets and Watchpoints. A Watchpoint is a doubly-linked list node 22 that records the location where a jump must be inserted and the 23 destination to which it should jump. Watchpoints can be added to a 24 WatchpointSet. The WatchpointSet can be fired all at once, which plants 25 all jumps. WatchpointSet also remembers if it had ever been invalidated, 26 which allows for monotonicity: we typically don't want to optimize using 27 watchpoints on something for which watchpoints had previously fired. The 28 act of notifying a WatchpointSet has a trivial fast path in case no 29 Watchpoints are registered (one-byte load+branch). 30 31 - SpeculativeJIT::speculationWatchpoint(). It's like speculationCheck(), 32 except that you don't have to emit branches. But, you need to know what 33 WatchpointSet to add the resulting Watchpoint to. Not everything that 34 you could write a speculationCheck() for will have a WatchpointSet that 35 would get notified if the condition you were speculating against became 36 invalid. 37 38 - SymbolTableEntry now has the ability to refer to a WatchpointSet. It can 39 do so without incurring any space overhead for those entries that don't 40 have WatchpointSets. 41 42 - The bytecode generator infers all global function variables to be 43 watchable, and makes all stores perform the WatchpointSet's write check, 44 and marks all loads as being potentially watchable (i.e. you can compile 45 them to a watchpoint and a constant). 46 47 Put together, this allows for fully sleazy inlining of calls to globally 48 declared functions. The inline prologue will no longer contain the load of 49 the function, or any checks of the function you're calling. I.e. it's 50 pretty much like the kind of inlining you would see in Java or C++. 51 Furthermore, the watchpointing functionality is built to be fairly general, 52 and should allow setting watchpoints on all sorts of interesting things 53 in the future. 54 55 The sleazy inlining means that we will now sometimes inline in code paths 56 that have never executed. Previously, to inline we would have either had 57 to have executed the call (to read the call's inline cache) or have 58 executed the method check (to read the method check's inline cache). Now, 59 we might inline when the callee is a watched global variable. This 60 revealed some humorous bugs. First, constant folding disagreed with CFA 61 over what kinds of operations can clobber (example: code path A is dead 62 but stores a String into variable X, all other code paths store 0 into 63 X, and then you do CompareEq(X, 0) - CFA will say that this is a non- 64 clobbering constant, but constant folding thought it was clobbering 65 because it saw the String prediction). Second, inlining would crash if 66 the inline callee had not been compiled. This patch fixes both bugs, 67 since otherwise run-javascriptcore-tests would report regressions. 68 69 * CMakeLists.txt: 70 * GNUmakefile.list.am: 71 * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: 72 * JavaScriptCore.xcodeproj/project.pbxproj: 73 * Target.pri: 74 * assembler/ARMv7Assembler.h: 75 (ARMv7Assembler): 76 (JSC::ARMv7Assembler::ARMv7Assembler): 77 (JSC::ARMv7Assembler::labelForWatchpoint): 78 (JSC::ARMv7Assembler::label): 79 (JSC::ARMv7Assembler::replaceWithJump): 80 (JSC::ARMv7Assembler::maxJumpReplacementSize): 81 * assembler/AbstractMacroAssembler.h: 82 (JSC): 83 (AbstractMacroAssembler): 84 (Label): 85 (JSC::AbstractMacroAssembler::watchpointLabel): 86 * assembler/AssemblerBuffer.h: 87 * assembler/MacroAssemblerARM.h: 88 (JSC::MacroAssemblerARM::replaceWithJump): 89 (MacroAssemblerARM): 90 (JSC::MacroAssemblerARM::maxJumpReplacementSize): 91 * assembler/MacroAssemblerARMv7.h: 92 (MacroAssemblerARMv7): 93 (JSC::MacroAssemblerARMv7::replaceWithJump): 94 (JSC::MacroAssemblerARMv7::maxJumpReplacementSize): 95 (JSC::MacroAssemblerARMv7::branchTest8): 96 (JSC::MacroAssemblerARMv7::jump): 97 (JSC::MacroAssemblerARMv7::makeBranch): 98 * assembler/MacroAssemblerMIPS.h: 99 (JSC::MacroAssemblerMIPS::replaceWithJump): 100 (MacroAssemblerMIPS): 101 (JSC::MacroAssemblerMIPS::maxJumpReplacementSize): 102 * assembler/MacroAssemblerSH4.h: 103 (JSC::MacroAssemblerSH4::replaceWithJump): 104 (MacroAssemblerSH4): 105 (JSC::MacroAssemblerSH4::maxJumpReplacementSize): 106 * assembler/MacroAssemblerX86.h: 107 (MacroAssemblerX86): 108 (JSC::MacroAssemblerX86::branchTest8): 109 * assembler/MacroAssemblerX86Common.h: 110 (JSC::MacroAssemblerX86Common::replaceWithJump): 111 (MacroAssemblerX86Common): 112 (JSC::MacroAssemblerX86Common::maxJumpReplacementSize): 113 * assembler/MacroAssemblerX86_64.h: 114 (MacroAssemblerX86_64): 115 (JSC::MacroAssemblerX86_64::branchTest8): 116 * assembler/X86Assembler.h: 117 (JSC::X86Assembler::X86Assembler): 118 (X86Assembler): 119 (JSC::X86Assembler::cmpb_im): 120 (JSC::X86Assembler::testb_im): 121 (JSC::X86Assembler::labelForWatchpoint): 122 (JSC::X86Assembler::label): 123 (JSC::X86Assembler::replaceWithJump): 124 (JSC::X86Assembler::maxJumpReplacementSize): 125 (JSC::X86Assembler::X86InstructionFormatter::memoryModRM): 126 * bytecode/CodeBlock.cpp: 127 (JSC::CodeBlock::dump): 128 * bytecode/CodeBlock.h: 129 (JSC::CodeBlock::appendOSRExit): 130 (JSC::CodeBlock::appendSpeculationRecovery): 131 (CodeBlock): 132 (JSC::CodeBlock::appendWatchpoint): 133 (JSC::CodeBlock::numberOfWatchpoints): 134 (JSC::CodeBlock::watchpoint): 135 (DFGData): 136 * bytecode/DFGExitProfile.h: 137 (JSC::DFG::exitKindToString): 138 (JSC::DFG::exitKindIsCountable): 139 * bytecode/Instruction.h: 140 (Instruction): 141 (JSC::Instruction::Instruction): 142 * bytecode/Opcode.h: 143 (JSC): 144 (JSC::padOpcodeName): 145 * bytecode/Watchpoint.cpp: Added. 146 (JSC): 147 (JSC::Watchpoint::~Watchpoint): 148 (JSC::Watchpoint::correctLabels): 149 (JSC::Watchpoint::fire): 150 (JSC::WatchpointSet::WatchpointSet): 151 (JSC::WatchpointSet::~WatchpointSet): 152 (JSC::WatchpointSet::add): 153 (JSC::WatchpointSet::notifyWriteSlow): 154 (JSC::WatchpointSet::fireAllWatchpoints): 155 * bytecode/Watchpoint.h: Added. 156 (JSC): 157 (Watchpoint): 158 (JSC::Watchpoint::Watchpoint): 159 (JSC::Watchpoint::setDestination): 160 (WatchpointSet): 161 (JSC::WatchpointSet::isStillValid): 162 (JSC::WatchpointSet::hasBeenInvalidated): 163 (JSC::WatchpointSet::startWatching): 164 (JSC::WatchpointSet::notifyWrite): 165 (JSC::WatchpointSet::addressOfIsWatched): 166 * bytecompiler/BytecodeGenerator.cpp: 167 (JSC::ResolveResult::checkValidity): 168 (JSC::BytecodeGenerator::addGlobalVar): 169 (JSC::BytecodeGenerator::BytecodeGenerator): 170 (JSC::BytecodeGenerator::resolve): 171 (JSC::BytecodeGenerator::emitResolve): 172 (JSC::BytecodeGenerator::emitResolveWithBase): 173 (JSC::BytecodeGenerator::emitResolveWithThis): 174 (JSC::BytecodeGenerator::emitGetStaticVar): 175 (JSC::BytecodeGenerator::emitPutStaticVar): 176 * bytecompiler/BytecodeGenerator.h: 177 (BytecodeGenerator): 178 * bytecompiler/NodesCodegen.cpp: 179 (JSC::FunctionCallResolveNode::emitBytecode): 180 (JSC::PostfixResolveNode::emitBytecode): 181 (JSC::PrefixResolveNode::emitBytecode): 182 (JSC::ReadModifyResolveNode::emitBytecode): 183 (JSC::AssignResolveNode::emitBytecode): 184 (JSC::ConstDeclNode::emitCodeSingle): 185 * dfg/DFGAbstractState.cpp: 186 (JSC::DFG::AbstractState::execute): 187 (JSC::DFG::AbstractState::clobberStructures): 188 * dfg/DFGAbstractState.h: 189 (AbstractState): 190 (JSC::DFG::AbstractState::didClobber): 191 * dfg/DFGByteCodeParser.cpp: 192 (JSC::DFG::ByteCodeParser::handleInlining): 193 (JSC::DFG::ByteCodeParser::parseBlock): 194 * dfg/DFGCCallHelpers.h: 195 (CCallHelpers): 196 (JSC::DFG::CCallHelpers::setupArguments): 197 * dfg/DFGCSEPhase.cpp: 198 (JSC::DFG::CSEPhase::globalVarWatchpointElimination): 199 (CSEPhase): 200 (JSC::DFG::CSEPhase::globalVarStoreElimination): 201 (JSC::DFG::CSEPhase::performNodeCSE): 202 * dfg/DFGCapabilities.h: 203 (JSC::DFG::canCompileOpcode): 204 * dfg/DFGConstantFoldingPhase.cpp: 205 (JSC::DFG::ConstantFoldingPhase::run): 206 * dfg/DFGCorrectableJumpPoint.h: 207 (JSC::DFG::CorrectableJumpPoint::isSet): 208 (CorrectableJumpPoint): 209 * dfg/DFGJITCompiler.cpp: 210 (JSC::DFG::JITCompiler::linkOSRExits): 211 (JSC::DFG::JITCompiler::link): 212 * dfg/DFGNode.h: 213 (JSC::DFG::Node::hasIdentifierNumberForCheck): 214 (Node): 215 (JSC::DFG::Node::identifierNumberForCheck): 216 (JSC::DFG::Node::hasRegisterPointer): 217 * dfg/DFGNodeType.h: 218 (DFG): 219 * dfg/DFGOSRExit.cpp: 220 (JSC::DFG::OSRExit::OSRExit): 221 * dfg/DFGOSRExit.h: 222 (OSRExit): 223 * dfg/DFGOperations.cpp: 224 * dfg/DFGOperations.h: 225 * dfg/DFGPredictionPropagationPhase.cpp: 226 (JSC::DFG::PredictionPropagationPhase::propagate): 227 * dfg/DFGSpeculativeJIT.h: 228 (JSC::DFG::SpeculativeJIT::callOperation): 229 (JSC::DFG::SpeculativeJIT::appendCall): 230 (SpeculativeJIT): 231 (JSC::DFG::SpeculativeJIT::speculationWatchpoint): 232 * dfg/DFGSpeculativeJIT32_64.cpp: 233 (JSC::DFG::SpeculativeJIT::compile): 234 * dfg/DFGSpeculativeJIT64.cpp: 235 (JSC::DFG::SpeculativeJIT::compile): 236 * jit/JIT.cpp: 237 (JSC::JIT::privateCompileMainPass): 238 (JSC::JIT::privateCompileSlowCases): 239 * jit/JIT.h: 240 * jit/JITPropertyAccess.cpp: 241 (JSC::JIT::emit_op_put_global_var_check): 242 (JSC): 243 (JSC::JIT::emitSlow_op_put_global_var_check): 244 * jit/JITPropertyAccess32_64.cpp: 245 (JSC::JIT::emit_op_put_global_var_check): 246 (JSC): 247 (JSC::JIT::emitSlow_op_put_global_var_check): 248 * jit/JITStubs.cpp: 249 (JSC::JITThunks::JITThunks): 250 (JSC::DEFINE_STUB_FUNCTION): 251 (JSC): 252 * jit/JITStubs.h: 253 * llint/LLIntSlowPaths.cpp: 254 (JSC::LLInt::LLINT_SLOW_PATH_DECL): 255 (LLInt): 256 * llint/LLIntSlowPaths.h: 257 (LLInt): 258 * llint/LowLevelInterpreter32_64.asm: 259 * llint/LowLevelInterpreter64.asm: 260 * runtime/JSObject.cpp: 261 (JSC::JSObject::removeDirect): 262 * runtime/JSObject.h: 263 (JSObject): 264 * runtime/JSSymbolTableObject.h: 265 (JSC::symbolTableGet): 266 (JSC::symbolTablePut): 267 (JSC::symbolTablePutWithAttributes): 268 * runtime/SymbolTable.cpp: Added. 269 (JSC): 270 (JSC::SymbolTableEntry::copySlow): 271 (JSC::SymbolTableEntry::freeFatEntrySlow): 272 (JSC::SymbolTableEntry::couldBeWatched): 273 (JSC::SymbolTableEntry::attemptToWatch): 274 (JSC::SymbolTableEntry::addressOfIsWatched): 275 (JSC::SymbolTableEntry::addWatchpoint): 276 (JSC::SymbolTableEntry::notifyWriteSlow): 277 (JSC::SymbolTableEntry::inflateSlow): 278 * runtime/SymbolTable.h: 279 (JSC): 280 (SymbolTableEntry): 281 (Fast): 282 (JSC::SymbolTableEntry::Fast::Fast): 283 (JSC::SymbolTableEntry::Fast::isNull): 284 (JSC::SymbolTableEntry::Fast::getIndex): 285 (JSC::SymbolTableEntry::Fast::isReadOnly): 286 (JSC::SymbolTableEntry::Fast::getAttributes): 287 (JSC::SymbolTableEntry::Fast::isFat): 288 (JSC::SymbolTableEntry::SymbolTableEntry): 289 (JSC::SymbolTableEntry::~SymbolTableEntry): 290 (JSC::SymbolTableEntry::operator=): 291 (JSC::SymbolTableEntry::isNull): 292 (JSC::SymbolTableEntry::getIndex): 293 (JSC::SymbolTableEntry::getFast): 294 (JSC::SymbolTableEntry::getAttributes): 295 (JSC::SymbolTableEntry::isReadOnly): 296 (JSC::SymbolTableEntry::watchpointSet): 297 (JSC::SymbolTableEntry::notifyWrite): 298 (FatEntry): 299 (JSC::SymbolTableEntry::FatEntry::FatEntry): 300 (JSC::SymbolTableEntry::isFat): 301 (JSC::SymbolTableEntry::fatEntry): 302 (JSC::SymbolTableEntry::inflate): 303 (JSC::SymbolTableEntry::bits): 304 (JSC::SymbolTableEntry::freeFatEntry): 305 (JSC::SymbolTableEntry::pack): 306 (JSC::SymbolTableEntry::isValidIndex): 307 1 308 2012-06-12 Filip Pizlo <[email protected]> 2 309 -
trunk/Source/JavaScriptCore/GNUmakefile.list.am
r119981 r120172 134 134 Source/JavaScriptCore/bytecode/ValueRecovery.h \ 135 135 Source/JavaScriptCore/bytecode/VirtualRegister.h \ 136 Source/JavaScriptCore/bytecode/Watchpoint.cpp \ 137 Source/JavaScriptCore/bytecode/Watchpoint.h \ 136 138 Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp \ 137 139 Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h \ … … 604 606 Source/JavaScriptCore/runtime/Structure.h \ 605 607 Source/JavaScriptCore/runtime/StructureTransitionTable.h \ 608 Source/JavaScriptCore/runtime/SymbolTable.cpp \ 606 609 Source/JavaScriptCore/runtime/SymbolTable.h \ 607 610 Source/JavaScriptCore/runtime/Terminator.h \ -
trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
r119844 r120172 247 247 ?neuter@ArrayBufferView@WTF@@MAEXXZ 248 248 ?newUninitialized@CString@WTF@@SA?AV12@IAAPAD@Z 249 ?notifyWriteSlow@SymbolTableEntry@JSC@@AAEXXZ 249 250 ?nullptr@@3Vnullptr_t@std@@A 250 251 ?number@String@WTF@@SA?AV12@NII@Z -
trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
r119660 r120172 1255 1255 </File> 1256 1256 <File 1257 RelativePath="..\..\runtime\SymbolTable.cpp" 1258 > 1259 </File> 1260 <File 1257 1261 RelativePath="..\..\runtime\SymbolTable.h" 1258 1262 > … … 1680 1684 <File 1681 1685 RelativePath="..\..\bytecode\ValueProfile.h" 1686 > 1687 </File> 1688 <File 1689 RelativePath="..\..\bytecode\Watchpoint.cpp" 1690 > 1691 </File> 1692 <File 1693 RelativePath="..\..\bytecode\Watchpoint.h" 1682 1694 > 1683 1695 </File> -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r119660 r120172 140 140 0F919D10157F3329004A4E7D /* JSSegmentedVariableObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F919D0E157F3327004A4E7D /* JSSegmentedVariableObject.cpp */; }; 141 141 0F919D11157F332C004A4E7D /* JSSegmentedVariableObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F919D0F157F3327004A4E7D /* JSSegmentedVariableObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; 142 0F919D2515853CE0004A4E7D /* Watchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F919D2215853CDE004A4E7D /* Watchpoint.cpp */; }; 143 0F919D2615853CE3004A4E7D /* Watchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F919D2315853CDE004A4E7D /* Watchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; }; 144 0F919D2815856773004A4E7D /* SymbolTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F919D2715856770004A4E7D /* SymbolTable.cpp */; }; 142 145 0F93329D14CA7DC30085F3C6 /* CallLinkStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */; }; 143 146 0F93329E14CA7DC50085F3C6 /* CallLinkStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329414CA7DC10085F3C6 /* CallLinkStatus.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 371 374 7EFF00640EC05A9A00AA7C93 /* NodeInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 7EFF00630EC05A9A00AA7C93 /* NodeInfo.h */; }; 372 375 840480131021A1D9008E7F01 /* JSAPIValueWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = BC0894D60FAFBA2D00001865 /* JSAPIValueWrapper.h */; settings = {ATTRIBUTES = (Private, ); }; }; 373 860161E30F3A83C100F84710 /* AbstractMacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161DF0F3A83C100F84710 /* AbstractMacroAssembler.h */; };374 860161E40F3A83C100F84710 /* MacroAssemblerX86.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161E00F3A83C100F84710 /* MacroAssemblerX86.h */; };375 860161E50F3A83C100F84710 /* MacroAssemblerX86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161E10F3A83C100F84710 /* MacroAssemblerX86_64.h */; };376 860161E60F3A83C100F84710 /* MacroAssemblerX86Common.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161E20F3A83C100F84710 /* MacroAssemblerX86Common.h */; };376 860161E30F3A83C100F84710 /* AbstractMacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161DF0F3A83C100F84710 /* AbstractMacroAssembler.h */; settings = {ATTRIBUTES = (Private, ); }; }; 377 860161E40F3A83C100F84710 /* MacroAssemblerX86.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161E00F3A83C100F84710 /* MacroAssemblerX86.h */; settings = {ATTRIBUTES = (Private, ); }; }; 378 860161E50F3A83C100F84710 /* MacroAssemblerX86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161E10F3A83C100F84710 /* MacroAssemblerX86_64.h */; settings = {ATTRIBUTES = (Private, ); }; }; 379 860161E60F3A83C100F84710 /* MacroAssemblerX86Common.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161E20F3A83C100F84710 /* MacroAssemblerX86Common.h */; settings = {ATTRIBUTES = (Private, ); }; }; 377 380 8604F505143CE1C200B295F5 /* JSGlobalThis.h in Headers */ = {isa = PBXBuildFile; fileRef = 8604F503143CE1C100B295F5 /* JSGlobalThis.h */; settings = {ATTRIBUTES = (Private, ); }; }; 378 381 860BD801148EA6F200112B2F /* Intrinsic.h in Headers */ = {isa = PBXBuildFile; fileRef = 86BF642A148DB2B5004DE36A /* Intrinsic.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 402 405 869EBCB70E8C6D4A008722CC /* ResultType.h in Headers */ = {isa = PBXBuildFile; fileRef = 869EBCB60E8C6D4A008722CC /* ResultType.h */; settings = {ATTRIBUTES = (Private, ); }; }; 403 406 86A90ED00EE7D51F00AB350D /* JITArithmetic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */; }; 404 86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */; };405 86ADD1460FDDEA980006EEC2 /* MacroAssemblerARMv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1440FDDEA980006EEC2 /* MacroAssemblerARMv7.h */; };407 86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */; settings = {ATTRIBUTES = (Private, ); }; }; 408 86ADD1460FDDEA980006EEC2 /* MacroAssemblerARMv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1440FDDEA980006EEC2 /* MacroAssemblerARMv7.h */; settings = {ATTRIBUTES = (Private, ); }; }; 406 409 86AE64A8135E5E1C00963012 /* MacroAssemblerSH4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86AE64A5135E5E1C00963012 /* MacroAssemblerSH4.cpp */; }; 407 86AE64A9135E5E1C00963012 /* MacroAssemblerSH4.h in Headers */ = {isa = PBXBuildFile; fileRef = 86AE64A6135E5E1C00963012 /* MacroAssemblerSH4.h */; };408 86AE64AA135E5E1C00963012 /* SH4Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86AE64A7135E5E1C00963012 /* SH4Assembler.h */; };410 86AE64A9135E5E1C00963012 /* MacroAssemblerSH4.h in Headers */ = {isa = PBXBuildFile; fileRef = 86AE64A6135E5E1C00963012 /* MacroAssemblerSH4.h */; settings = {ATTRIBUTES = (Private, ); }; }; 411 86AE64AA135E5E1C00963012 /* SH4Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86AE64A7135E5E1C00963012 /* SH4Assembler.h */; settings = {ATTRIBUTES = (Private, ); }; }; 409 412 86AE6C4D136A11E400963012 /* DFGFPRInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 86AE6C4B136A11E400963012 /* DFGFPRInfo.h */; }; 410 413 86AE6C4E136A11E400963012 /* DFGGPRInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 86AE6C4C136A11E400963012 /* DFGGPRInfo.h */; }; … … 415 418 86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */; settings = {ATTRIBUTES = (Private, ); }; }; 416 419 86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86C568DD11A213EE0007F7F0 /* MacroAssemblerARM.cpp */; }; 417 86C568E111A213EE0007F7F0 /* MacroAssemblerMIPS.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C568DE11A213EE0007F7F0 /* MacroAssemblerMIPS.h */; };418 86C568E211A213EE0007F7F0 /* MIPSAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C568DF11A213EE0007F7F0 /* MIPSAssembler.h */; };420 86C568E111A213EE0007F7F0 /* MacroAssemblerMIPS.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C568DE11A213EE0007F7F0 /* MacroAssemblerMIPS.h */; settings = {ATTRIBUTES = (Private, ); }; }; 421 86C568E211A213EE0007F7F0 /* MIPSAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C568DF11A213EE0007F7F0 /* MIPSAssembler.h */; settings = {ATTRIBUTES = (Private, ); }; }; 419 422 86CA032E1038E8440028A609 /* Executable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86CA032D1038E8440028A609 /* Executable.cpp */; }; 420 423 86CAFEE31035DDE60028A609 /* Executable.h in Headers */ = {isa = PBXBuildFile; fileRef = 86CAFEE21035DDE60028A609 /* Executable.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 424 427 86CCEFDE0F413F8900FD7F9E /* JITCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 86CCEFDD0F413F8900FD7F9E /* JITCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; 425 428 86D3B2C310156BDE002865E7 /* ARMAssembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86D3B2BF10156BDE002865E7 /* ARMAssembler.cpp */; }; 426 86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C010156BDE002865E7 /* ARMAssembler.h */; };427 86D3B2C510156BDE002865E7 /* AssemblerBufferWithConstantPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C110156BDE002865E7 /* AssemblerBufferWithConstantPool.h */; };428 86D3B2C610156BDE002865E7 /* MacroAssemblerARM.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C210156BDE002865E7 /* MacroAssemblerARM.h */; };429 86D3B3C310159D7F002865E7 /* LinkBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B3C110159D7F002865E7 /* LinkBuffer.h */; };430 86D3B3C410159D7F002865E7 /* RepatchBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B3C210159D7F002865E7 /* RepatchBuffer.h */; };429 86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C010156BDE002865E7 /* ARMAssembler.h */; settings = {ATTRIBUTES = (Private, ); }; }; 430 86D3B2C510156BDE002865E7 /* AssemblerBufferWithConstantPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C110156BDE002865E7 /* AssemblerBufferWithConstantPool.h */; settings = {ATTRIBUTES = (Private, ); }; }; 431 86D3B2C610156BDE002865E7 /* MacroAssemblerARM.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C210156BDE002865E7 /* MacroAssemblerARM.h */; settings = {ATTRIBUTES = (Private, ); }; }; 432 86D3B3C310159D7F002865E7 /* LinkBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B3C110159D7F002865E7 /* LinkBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; }; 433 86D3B3C410159D7F002865E7 /* RepatchBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B3C210159D7F002865E7 /* RepatchBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; }; 431 434 86DB64640F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */; }; 432 86E116B10FE75AC800B512BC /* CodeLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E116B00FE75AC800B512BC /* CodeLocation.h */; };435 86E116B10FE75AC800B512BC /* CodeLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E116B00FE75AC800B512BC /* CodeLocation.h */; settings = {ATTRIBUTES = (Private, ); }; }; 433 436 86E85539111B9968001AF51E /* JSStringBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E85538111B9968001AF51E /* JSStringBuilder.h */; }; 434 437 86EBF2FF1560F06A008E9222 /* NameConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EBF2F91560F036008E9222 /* NameConstructor.cpp */; }; … … 476 479 960097A60EBABB58007A7297 /* LabelScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 960097A50EBABB58007A7297 /* LabelScope.h */; }; 477 480 960626960FB8EC02009798AB /* JITStubCall.h in Headers */ = {isa = PBXBuildFile; fileRef = 960626950FB8EC02009798AB /* JITStubCall.h */; }; 478 9688CB150ED12B4E001D649F /* AssemblerBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB130ED12B4E001D649F /* AssemblerBuffer.h */; };479 9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB140ED12B4E001D649F /* X86Assembler.h */; };481 9688CB150ED12B4E001D649F /* AssemblerBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB130ED12B4E001D649F /* AssemblerBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; }; 482 9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB140ED12B4E001D649F /* X86Assembler.h */; settings = {ATTRIBUTES = (Private, ); }; }; 480 483 969A07230ED1CE3300F1F681 /* BytecodeGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07210ED1CE3300F1F681 /* BytecodeGenerator.h */; }; 481 484 969A072A0ED1CE6900F1F681 /* Label.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07270ED1CE6900F1F681 /* Label.h */; }; … … 837 840 0F919D0E157F3327004A4E7D /* JSSegmentedVariableObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSegmentedVariableObject.cpp; sourceTree = "<group>"; }; 838 841 0F919D0F157F3327004A4E7D /* JSSegmentedVariableObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSegmentedVariableObject.h; sourceTree = "<group>"; }; 842 0F919D2215853CDE004A4E7D /* Watchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Watchpoint.cpp; sourceTree = "<group>"; }; 843 0F919D2315853CDE004A4E7D /* Watchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Watchpoint.h; sourceTree = "<group>"; }; 844 0F919D2715856770004A4E7D /* SymbolTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolTable.cpp; sourceTree = "<group>"; }; 839 845 0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallLinkStatus.cpp; sourceTree = "<group>"; }; 840 846 0F93329414CA7DC10085F3C6 /* CallLinkStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallLinkStatus.h; sourceTree = "<group>"; }; … … 2046 2052 7E4EE7080EBB7963005934AA /* StructureChain.h */, 2047 2053 BC9041470EB9250900FE26FA /* StructureTransitionTable.h */, 2054 0F919D2715856770004A4E7D /* SymbolTable.cpp */, 2048 2055 14A396A60CD2933100B5B4FF /* SymbolTable.h */, 2049 2056 97F6903A1169DF7F00A6BB46 /* Terminator.h */, … … 2297 2304 0F426A451460CBAB00131F8F /* ValueRecovery.h */, 2298 2305 0F426A461460CBAB00131F8F /* VirtualRegister.h */, 2306 0F919D2215853CDE004A4E7D /* Watchpoint.cpp */, 2307 0F919D2315853CDE004A4E7D /* Watchpoint.h */, 2299 2308 ); 2300 2309 path = bytecode; … … 2672 2681 0F919D0D157EE0A2004A4E7D /* JSSymbolTableObject.h in Headers */, 2673 2682 0F919D11157F332C004A4E7D /* JSSegmentedVariableObject.h in Headers */, 2683 0F919D2615853CE3004A4E7D /* Watchpoint.h in Headers */, 2674 2684 ); 2675 2685 runOnlyForDeploymentPostprocessing = 0; … … 3246 3256 0F919D0C157EE09F004A4E7D /* JSSymbolTableObject.cpp in Sources */, 3247 3257 0F919D10157F3329004A4E7D /* JSSegmentedVariableObject.cpp in Sources */, 3258 0F919D2515853CE0004A4E7D /* Watchpoint.cpp in Sources */, 3259 0F919D2815856773004A4E7D /* SymbolTable.cpp in Sources */, 3248 3260 ); 3249 3261 runOnlyForDeploymentPostprocessing = 0; -
trunk/Source/JavaScriptCore/Target.pri
r119660 r120172 63 63 bytecode/Opcode.cpp \ 64 64 bytecode/PolymorphicPutByIdList.cpp \ 65 bytecode/SpeculatedType.cpp \66 65 bytecode/PutByIdStatus.cpp \ 67 66 bytecode/SamplingTool.cpp \ 67 bytecode/SpeculatedType.cpp \ 68 68 bytecode/StructureStubInfo.cpp \ 69 bytecode/Watchpoint.cpp \ 69 70 bytecompiler/BytecodeGenerator.cpp \ 70 71 bytecompiler/NodesCodegen.cpp \ … … 237 238 runtime/StructureChain.cpp \ 238 239 runtime/Structure.cpp \ 240 runtime/SymbolTable.cpp \ 239 241 runtime/TimeoutChecker.cpp \ 240 242 runtime/UString.cpp \ -
trunk/Source/JavaScriptCore/assembler/ARMv7Assembler.h
r118413 r120172 484 484 Condition m_condition : 16; 485 485 }; 486 487 ARMv7Assembler() 488 : m_indexOfLastWatchpoint(INT_MIN) 489 , m_indexOfTailOfLastWatchpoint(INT_MIN) 490 { 491 } 486 492 487 493 private: … … 1821 1827 m_formatter.oneWordOp8Imm8(OP_NOP_T1, 0); 1822 1828 } 1829 1830 AssemblerLabel labelForWatchpoint() 1831 { 1832 AssemblerLabel result = m_formatter.label(); 1833 if (static_cast<int>(result.m_offset) != m_indexOfLastWatchpoint) 1834 result = label(); 1835 m_indexOfLastWatchpoint = result.m_offset; 1836 m_indexOfTailOfLastWatchpoint = result.m_offset + maxJumpReplacementSize(); 1837 return result; 1838 } 1823 1839 1824 1840 AssemblerLabel label() 1825 1841 { 1826 return m_formatter.label(); 1842 AssemblerLabel result = m_formatter.label(); 1843 while (UNLIKELY(static_cast<int>(result.m_offset) < m_indexOfTailOfLastWatchpoint)) { 1844 nop(); 1845 result = m_formatter.label(); 1846 } 1847 return result; 1827 1848 } 1828 1849 … … 2068 2089 return reinterpret_cast<void*>(readInt32(where)); 2069 2090 } 2091 2092 static void replaceWithJump(void* instructionStart, void* to) 2093 { 2094 ASSERT(!(bitwise_cast<uintptr_t>(instructionStart) & 1)); 2095 ASSERT(!(bitwise_cast<uintptr_t>(to) & 1)); 2096 uint16_t* ptr = reinterpret_cast<uint16_t*>(instructionStart) + 2; 2097 2098 // Ensure that we're not in one of those errata-triggering thingies. If we are, then 2099 // prepend a nop. 2100 bool spansTwo4K = ((reinterpret_cast<intptr_t>(ptr) & 0xfff) == 0x002); 2101 2102 if (spansTwo4K) { 2103 ptr[-2] = OP_NOP_T1; 2104 ptr++; 2105 } 2106 2107 linkJumpT4(ptr, to); 2108 cacheFlush(ptr - 2, sizeof(uint16_t) * 2); 2109 } 2110 2111 static ptrdiff_t maxJumpReplacementSize() 2112 { 2113 return 6; 2114 } 2070 2115 2071 2116 unsigned debugOffset() { return m_formatter.debugOffset(); } … … 2605 2650 Vector<LinkRecord> m_jumpsToLink; 2606 2651 Vector<int32_t> m_offsets; 2652 int m_indexOfLastWatchpoint; 2653 int m_indexOfTailOfLastWatchpoint; 2607 2654 }; 2608 2655 -
trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
r118413 r120172 1 1 /* 2 * Copyright (C) 2008 Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2012 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 49 49 class LinkBuffer; 50 50 class RepatchBuffer; 51 class Watchpoint; 51 52 namespace DFG { 52 53 class CorrectableJumpPoint; … … 70 71 // The following types are used as operands to MacroAssembler operations, 71 72 // describing immediate and memory operands to the instructions to be planted. 72 73 73 74 74 enum Scale { … … 280 280 friend class MacroAssemblerCodeRef; 281 281 friend class LinkBuffer; 282 friend class Watchpoint; 282 283 283 284 public: … … 560 561 } 561 562 563 Label watchpointLabel() 564 { 565 Label result; 566 result.m_label = m_assembler.labelForWatchpoint(); 567 return result; 568 } 569 562 570 Label align() 563 571 { -
trunk/Source/JavaScriptCore/assembler/AssemblerBuffer.h
r109307 r120172 1 1 /* 2 * Copyright (C) 2008 Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2012 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 29 29 #if ENABLE(ASSEMBLER) 30 30 31 #include "ExecutableAllocator.h" 31 32 #include "JITCompilationEffort.h" 32 33 #include "JSGlobalData.h" 33 34 #include "stdint.h" 34 35 #include <string.h> 35 #include <jit/ExecutableAllocator.h>36 36 #include <wtf/Assertions.h> 37 37 #include <wtf/FastMalloc.h> -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM.h
r116233 r120172 1009 1009 { 1010 1010 return FunctionPtr(reinterpret_cast<void(*)()>(ARMAssembler::readCallTarget(call.dataLocation()))); 1011 } 1012 1013 static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination) 1014 { 1015 ASSERT_NOT_REACHED(); 1016 } 1017 1018 static ptrdiff_t maxJumpReplacementSize() 1019 { 1020 ASSERT_NOT_REACHED(); 1021 return 0; 1011 1022 } 1012 1023 -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h
r116233 r120172 1187 1187 m_assembler.nop(); 1188 1188 } 1189 1190 static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination) 1191 { 1192 ARMv7Assembler::replaceWithJump(instructionStart.dataLocation(), destination.dataLocation()); 1193 } 1194 1195 static ptrdiff_t maxJumpReplacementSize() 1196 { 1197 return ARMv7Assembler::maxJumpReplacementSize(); 1198 } 1189 1199 1190 1200 // Forwards / external control flow operations: … … 1357 1367 } 1358 1368 1369 Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1)) 1370 { 1371 // use addressTempRegister incase the branchTest8 we call uses dataTempRegister. :-/ 1372 move(TrustedImmPtr(address.m_ptr), addressTempRegister); 1373 load8(Address(addressTempRegister), addressTempRegister); 1374 return branchTest32(cond, addressTempRegister, mask); 1375 } 1376 1359 1377 void jump(RegisterID target) 1360 1378 { … … 1680 1698 ALWAYS_INLINE Jump jump() 1681 1699 { 1700 m_assembler.label(); // Force nop-padding if we're in the middle of a watchpoint. 1682 1701 moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister); 1683 1702 return Jump(m_assembler.bx(dataTempRegister), m_makeJumpPatchable ? ARMv7Assembler::JumpNoConditionFixedSize : ARMv7Assembler::JumpNoCondition); … … 1686 1705 ALWAYS_INLINE Jump makeBranch(ARMv7Assembler::Condition cond) 1687 1706 { 1707 m_assembler.label(); // Force nop-padding if we're in the middle of a watchpoint. 1688 1708 m_assembler.it(cond, true, true); 1689 1709 moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister); -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h
r116233 r120172 1869 1869 } 1870 1870 1871 static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination) 1872 { 1873 ASSERT_NOT_REACHED(); 1874 } 1875 1876 static ptrdiff_t maxJumpReplacementSize() 1877 { 1878 ASSERT_NOT_REACHED(); 1879 return 0; 1880 } 1881 1871 1882 private: 1872 1883 // If m_fixedWidth is true, we will generate a fixed number of instructions. -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h
r115144 r120172 1972 1972 } 1973 1973 1974 static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination) 1975 { 1976 ASSERT_NOT_REACHED(); 1977 } 1978 1979 static ptrdiff_t maxJumpReplacementSize() 1980 { 1981 ASSERT_NOT_REACHED(); 1982 return 0; 1983 } 1984 1974 1985 protected: 1975 1986 SH4Assembler::Condition SH4Condition(RelationalCondition cond) -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86.h
r109038 r120172 52 52 using MacroAssemblerX86Common::storeDouble; 53 53 using MacroAssemblerX86Common::convertInt32ToDouble; 54 using MacroAssemblerX86Common::branchTest8; 54 55 55 56 void add32(TrustedImm32 imm, RegisterID src, RegisterID dest) … … 165 166 m_assembler.movl_i32r(initialValue.asIntptr(), dest); 166 167 return DataLabelPtr(this); 168 } 169 170 Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1)) 171 { 172 ASSERT(mask.m_value >= -128 && mask.m_value <= 255); 173 if (mask.m_value == -1) 174 m_assembler.cmpb_im(0, address.m_ptr); 175 else 176 m_assembler.testb_im(mask.m_value, address.m_ptr); 177 return Jump(m_assembler.jCC(x86Condition(cond))); 167 178 } 168 179 -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h
r113930 r120172 1407 1407 { 1408 1408 m_assembler.nop(); 1409 } 1410 1411 static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination) 1412 { 1413 X86Assembler::replaceWithJump(instructionStart.executableAddress(), destination.executableAddress()); 1414 } 1415 1416 static ptrdiff_t maxJumpReplacementSize() 1417 { 1418 return X86Assembler::maxJumpReplacementSize(); 1409 1419 } 1410 1420 -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h
r113930 r120172 1 1 /* 2 * Copyright (C) 2008 Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2012 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 514 514 return MacroAssemblerX86Common::branchTest8(cond, BaseIndex(scratchRegister, address.base, TimesOne), mask); 515 515 } 516 517 Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1)) 518 { 519 MacroAssemblerX86Common::move(TrustedImmPtr(address.m_ptr), scratchRegister); 520 return MacroAssemblerX86Common::branchTest8(cond, Address(scratchRegister), mask); 521 } 516 522 517 523 static bool supportsFloatingPoint() { return true; } -
trunk/Source/JavaScriptCore/assembler/X86Assembler.h
r118413 r120172 1 1 /* 2 * Copyright (C) 2008 Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2012 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 248 248 249 249 X86Assembler() 250 : m_indexOfLastWatchpoint(INT_MIN) 251 , m_indexOfTailOfLastWatchpoint(INT_MIN) 250 252 { 251 253 } … … 799 801 m_formatter.immediate8(imm); 800 802 } 803 804 #if CPU(X86) 805 void cmpb_im(int imm, const void* addr) 806 { 807 m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_CMP, addr); 808 m_formatter.immediate8(imm); 809 } 810 #endif 801 811 802 812 void cmpl_im(int imm, int offset, RegisterID base, RegisterID index, int scale) … … 948 958 m_formatter.immediate8(imm); 949 959 } 960 961 #if CPU(X86) 962 void testb_im(int imm, const void* addr) 963 { 964 m_formatter.oneByteOp(OP_GROUP3_EbIb, GROUP3_OP_TEST, addr); 965 m_formatter.immediate8(imm); 966 } 967 #endif 950 968 951 969 void testl_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale) … … 1703 1721 return m_formatter.codeSize(); 1704 1722 } 1723 1724 AssemblerLabel labelForWatchpoint() 1725 { 1726 AssemblerLabel result = m_formatter.label(); 1727 if (static_cast<int>(result.m_offset) != m_indexOfLastWatchpoint) 1728 result = label(); 1729 m_indexOfLastWatchpoint = result.m_offset; 1730 m_indexOfTailOfLastWatchpoint = result.m_offset + maxJumpReplacementSize(); 1731 return result; 1732 } 1705 1733 1706 1734 AssemblerLabel label() 1707 1735 { 1708 return m_formatter.label(); 1736 AssemblerLabel result = m_formatter.label(); 1737 while (UNLIKELY(static_cast<int>(result.m_offset) < m_indexOfTailOfLastWatchpoint)) { 1738 nop(); 1739 result = m_formatter.label(); 1740 } 1741 return result; 1709 1742 } 1710 1743 … … 1788 1821 } 1789 1822 1823 static void replaceWithJump(void* instructionStart, void* to) 1824 { 1825 uint8_t* ptr = reinterpret_cast<uint8_t*>(instructionStart); 1826 uint8_t* dstPtr = reinterpret_cast<uint8_t*>(to); 1827 intptr_t distance = (intptr_t)(dstPtr - (ptr + 5)); 1828 ptr[0] = static_cast<uint8_t>(OP_JMP_rel32); 1829 *reinterpret_cast<int32_t*>(ptr + 1) = static_cast<int32_t>(distance); 1830 } 1831 1832 static ptrdiff_t maxJumpReplacementSize() 1833 { 1834 return 5; 1835 } 1836 1790 1837 static unsigned getCallReturnOffset(AssemblerLabel call) 1791 1838 { … … 2340 2387 AssemblerBuffer m_buffer; 2341 2388 } m_formatter; 2389 int m_indexOfLastWatchpoint; 2390 int m_indexOfTailOfLastWatchpoint; 2342 2391 }; 2343 2392 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r119660 r120172 929 929 break; 930 930 } 931 case op_get_global_var_watchable: { 932 int r0 = (++it)->u.operand; 933 WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer; 934 dataLog("[%4d] get_global_var_watchable\t %s, g%d(%p)\n", location, registerName(exec, r0).data(), m_globalObject->findRegisterIndex(registerPointer), registerPointer); 935 it++; 936 it++; 937 break; 938 } 931 939 case op_put_global_var: { 932 940 WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer; 933 941 int r0 = (++it)->u.operand; 934 942 dataLog("[%4d] put_global_var\t g%d(%p), %s\n", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data()); 943 break; 944 } 945 case op_put_global_var_check: { 946 WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer; 947 int r0 = (++it)->u.operand; 948 dataLog("[%4d] put_global_var_check\t g%d(%p), %s\n", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data()); 949 it++; 950 it++; 935 951 break; 936 952 } … … 1307 1323 case op_call_put_result: { 1308 1324 int r0 = (++it)->u.operand; 1309 dataLog("[%4d] op_call_put_result\t\t %s\n", location, registerName(exec, r0).data());1325 dataLog("[%4d] call_put_result\t\t %s\n", location, registerName(exec, r0).data()); 1310 1326 it++; 1311 1327 break; -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r119779 r120172 63 63 #include "UnconditionalFinalizer.h" 64 64 #include "ValueProfile.h" 65 #include "Watchpoint.h" 65 66 #include <wtf/RefCountedArray.h> 66 67 #include <wtf/FastAllocBase.h> … … 274 275 } 275 276 276 void appendOSRExit(const DFG::OSRExit& osrExit)277 unsigned appendOSRExit(const DFG::OSRExit& osrExit) 277 278 { 278 279 createDFGDataIfNecessary(); 280 unsigned result = m_dfgData->osrExit.size(); 279 281 m_dfgData->osrExit.append(osrExit); 282 return result; 280 283 } 281 284 … … 285 288 } 286 289 287 void appendSpeculationRecovery(const DFG::SpeculationRecovery& recovery)290 unsigned appendSpeculationRecovery(const DFG::SpeculationRecovery& recovery) 288 291 { 289 292 createDFGDataIfNecessary(); 293 unsigned result = m_dfgData->speculationRecovery.size(); 290 294 m_dfgData->speculationRecovery.append(recovery); 295 return result; 296 } 297 298 unsigned appendWatchpoint(const Watchpoint& watchpoint) 299 { 300 createDFGDataIfNecessary(); 301 unsigned result = m_dfgData->watchpoints.size(); 302 m_dfgData->watchpoints.append(watchpoint); 303 return result; 291 304 } 292 305 … … 305 318 } 306 319 320 unsigned numberOfWatchpoints() 321 { 322 if (!m_dfgData) 323 return 0; 324 return m_dfgData->watchpoints.size(); 325 } 326 307 327 DFG::OSRExit& osrExit(unsigned index) 308 328 { … … 313 333 { 314 334 return m_dfgData->speculationRecovery[index]; 335 } 336 337 Watchpoint& watchpoint(unsigned index) 338 { 339 return m_dfgData->watchpoints[index]; 315 340 } 316 341 … … 1239 1264 SegmentedVector<DFG::OSRExit, 8> osrExit; 1240 1265 Vector<DFG::SpeculationRecovery> speculationRecovery; 1266 SegmentedVector<Watchpoint, 1, 0> watchpoints; 1241 1267 Vector<WeakReferenceTransition> transitions; 1242 1268 Vector<WriteBarrier<JSCell> > weakReferences; -
trunk/Source/JavaScriptCore/bytecode/DFGExitProfile.h
r118278 r120172 42 42 ArgumentsEscaped, // We exited because arguments escaped but we didn't expect them to. 43 43 Uncountable, // We exited for none of the above reasons, and we should not count it. Most uses of this should be viewed as a FIXME. 44 UncountableWatchpoint // We exited because of a watchpoint, which isn't counted because watchpoints do tracking themselves. 44 45 }; 45 46 … … 59 60 case InadequateCoverage: 60 61 return "InadequateCoverage"; 62 case ArgumentsEscaped: 63 return "ArgumentsEscaped"; 64 case Uncountable: 65 return "Uncountable"; 66 case UncountableWatchpoint: 67 return "UncountableWatchpoint"; 61 68 default: 62 69 return "Unknown"; … … 71 78 case BadType: 72 79 case Uncountable: 80 case UncountableWatchpoint: 73 81 return false; 74 82 default: -
trunk/Source/JavaScriptCore/bytecode/Instruction.h
r119655 r120172 194 194 195 195 Instruction(WriteBarrier<Unknown>* registerPointer) { u.registerPointer = registerPointer; } 196 197 Instruction(bool* predicatePointer) { u.predicatePointer = predicatePointer; } 196 198 197 199 union { … … 206 208 ValueProfile* profile; 207 209 void* pointer; 210 bool* predicatePointer; 208 211 } u; 209 212 -
trunk/Source/JavaScriptCore/bytecode/Opcode.h
r118555 r120172 101 101 macro(op_put_scoped_var, 4) \ 102 102 macro(op_get_global_var, 4) /* has value profiling */ \ 103 macro(op_get_global_var_watchable, 5) /* has value profiling */ \ 103 104 macro(op_put_global_var, 3) \ 105 macro(op_put_global_var_check, 5) \ 104 106 macro(op_resolve_base, 5) /* has value profiling */ \ 105 107 macro(op_ensure_property_exists, 3) \ -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r119655 r120172 149 149 case IndexedGlobal: 150 150 case ReadOnlyIndexedGlobal: 151 case WatchedIndexedGlobal: 151 152 case DynamicIndexedGlobal: 152 153 case DynamicReadOnlyIndexedGlobal: … … 217 218 } 218 219 219 int BytecodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant) 220 { 220 int BytecodeGenerator::addGlobalVar( 221 const Identifier& ident, ConstantMode constantMode, FunctionMode functionMode) 222 { 223 UNUSED_PARAM(functionMode); 221 224 int index = symbolTable().size(); 222 SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0); 225 SymbolTableEntry newEntry(index, (constantMode == IsConstant) ? ReadOnly : 0); 226 if (functionMode == IsFunctionToSpecialize) 227 newEntry.attemptToWatch(); 223 228 SymbolTable::AddResult result = symbolTable().add(ident.impl(), newEntry); 224 if (!result.isNewEntry) 229 if (!result.isNewEntry) { 230 result.iterator->second.notifyWrite(); 225 231 index = result.iterator->second.getIndex(); 232 } 226 233 return index; 227 234 } … … 290 297 for (size_t i = 0; i < functionStack.size(); ++i) { 291 298 FunctionBodyNode* function = functionStack[i]; 292 globalObject->removeDirect(*m_globalData, function->ident()); // Newly declared functions overwrite existing properties. 293 299 bool propertyDidExist = 300 globalObject->removeDirect(*m_globalData, function->ident()); // Newly declared functions overwrite existing properties. 301 294 302 JSValue value = JSFunction::create(exec, makeFunction(exec, function), scopeChain); 295 int index = addGlobalVar(function->ident(), false); 303 int index = addGlobalVar( 304 function->ident(), IsVariable, 305 !propertyDidExist ? IsFunctionToSpecialize : NotFunctionOrNotSpecializable); 296 306 globalObject->registerAt(index).set(*m_globalData, globalObject, value); 297 307 } … … 300 310 if (globalObject->hasProperty(exec, *varStack[i].first)) 301 311 continue; 302 addGlobalVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant); 312 addGlobalVar( 313 *varStack[i].first, 314 (varStack[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable, 315 NotFunctionOrNotSpecializable); 303 316 } 304 317 } … … 1203 1216 if (flags & ResolveResult::DynamicFlag) 1204 1217 return ResolveResult::dynamicIndexedGlobalResolve(entry.getIndex(), depth, currentScope, flags); 1205 return ResolveResult::indexedGlobalResolve(entry.getIndex(), currentScope, flags); 1218 return ResolveResult::indexedGlobalResolve( 1219 entry.getIndex(), currentScope, 1220 flags | (entry.couldBeWatched() ? ResolveResult::WatchedFlag : 0)); 1206 1221 } 1207 1222 #if !ASSERT_DISABLED … … 1297 1312 { 1298 1313 if (resolveResult.isStatic()) 1299 return emitGetStaticVar(dst, resolveResult );1314 return emitGetStaticVar(dst, resolveResult, property); 1300 1315 1301 1316 if (resolveResult.isGlobal() && !shouldAvoidResolveGlobal()) { … … 1380 1395 if (resolveResult.isStatic()) { 1381 1396 // Directly index the property lookup across multiple scopes. 1382 emitGetStaticVar(propDst, resolveResult );1397 emitGetStaticVar(propDst, resolveResult, property); 1383 1398 return baseDst; 1384 1399 } … … 1419 1434 if (resolveResult.isStatic()) { 1420 1435 emitLoad(baseDst, jsUndefined()); 1421 emitGetStaticVar(propDst, resolveResult );1436 emitGetStaticVar(propDst, resolveResult, property); 1422 1437 return baseDst; 1423 1438 } … … 1437 1452 } 1438 1453 1439 RegisterID* BytecodeGenerator::emitGetStaticVar(RegisterID* dst, const ResolveResult& resolveResult )1454 RegisterID* BytecodeGenerator::emitGetStaticVar(RegisterID* dst, const ResolveResult& resolveResult, const Identifier& identifier) 1440 1455 { 1441 1456 ValueProfile* profile = 0; … … 1473 1488 return dst; 1474 1489 1490 case ResolveResult::WatchedIndexedGlobal: 1491 // Skip the peephole for now. It's not clear that it's profitable given 1492 // the DFG's capabilities, and the fact that if it's watchable then we 1493 // don't expect to see any put_global_var's anyway. 1494 profile = emitProfiledOpcode(op_get_global_var_watchable); 1495 instructions().append(dst->index()); 1496 instructions().append(resolveResult.registerPointer()); 1497 instructions().append(addConstant(identifier)); // For the benefit of the DFG. 1498 instructions().append(profile); 1499 return dst; 1500 1475 1501 default: 1476 1502 ASSERT_NOT_REACHED(); … … 1479 1505 } 1480 1506 1481 RegisterID* BytecodeGenerator::emitPutStaticVar(const ResolveResult& resolveResult, RegisterID* value)1507 RegisterID* BytecodeGenerator::emitPutStaticVar(const ResolveResult& resolveResult, const Identifier& identifier, RegisterID* value) 1482 1508 { 1483 1509 switch (resolveResult.type()) { … … 1499 1525 instructions().append(resolveResult.registerPointer()); 1500 1526 instructions().append(value->index()); 1527 return value; 1528 1529 case ResolveResult::WatchedIndexedGlobal: 1530 emitOpcode(op_put_global_var_check); 1531 instructions().append(resolveResult.registerPointer()); 1532 instructions().append(value->index()); 1533 instructions().append(jsCast<JSGlobalObject*>(resolveResult.globalObject())->symbolTable().get(identifier.impl()).addressOfIsWatched()); 1534 instructions().append(addConstant(identifier)); 1501 1535 return value; 1502 1536 -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r119655 r120172 112 112 ReadOnlyFlag = 0x20, 113 113 // The base object is the global object. 114 GlobalFlag = 0x40 114 GlobalFlag = 0x40, 115 // The property is being watched, so writes should be special. 116 WatchedFlag = 0x80 115 117 }; 116 118 enum Type { … … 132 134 // just index into the global object. 133 135 IndexedGlobal = IndexedFlag | GlobalFlag | StaticFlag, 136 // Like IndexedGlobal, but the property is being watched. 137 WatchedIndexedGlobal = IndexedFlag | GlobalFlag | StaticFlag | WatchedFlag, 134 138 // Like IndexedGlobal, but the property is also read-only, like NaN, 135 139 // Infinity, or undefined. … … 442 446 RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); } 443 447 444 RegisterID* emitGetStaticVar(RegisterID* dst, const ResolveResult& );445 RegisterID* emitPutStaticVar(const ResolveResult&, RegisterID* value);448 RegisterID* emitGetStaticVar(RegisterID* dst, const ResolveResult&, const Identifier&); 449 RegisterID* emitPutStaticVar(const ResolveResult&, const Identifier&, RegisterID* value); 446 450 447 451 RegisterID* emitResolve(RegisterID* dst, const ResolveResult&, const Identifier& property); … … 575 579 576 580 // Returns the index of the added var. 577 int addGlobalVar(const Identifier&, bool isConstant); 581 enum ConstantMode { IsConstant, IsVariable }; 582 enum FunctionMode { IsFunctionToSpecialize, NotFunctionOrNotSpecializable }; 583 int addGlobalVar(const Identifier&, ConstantMode, FunctionMode); 578 584 579 585 void addParameter(const Identifier&, int parameterIndex); -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r117706 r120172 431 431 RefPtr<RegisterID> func = generator.newTemporary(); 432 432 CallArguments callArguments(generator, m_args); 433 generator.emitGetStaticVar(func.get(), resolveResult );433 generator.emitGetStaticVar(func.get(), resolveResult, m_ident); 434 434 generator.emitLoad(callArguments.thisRegister(), jsUndefined()); 435 435 return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset()); … … 619 619 620 620 if (resolveResult.isStatic() && !resolveResult.isReadOnly()) { 621 RefPtr<RegisterID> value = generator.emitGetStaticVar(generator.newTemporary(), resolveResult );621 RefPtr<RegisterID> value = generator.emitGetStaticVar(generator.newTemporary(), resolveResult, m_ident); 622 622 RegisterID* oldValue; 623 623 if (dst == generator.ignoredResult()) { … … 627 627 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator); 628 628 } 629 generator.emitPutStaticVar(resolveResult, value.get());629 generator.emitPutStaticVar(resolveResult, m_ident, value.get()); 630 630 return oldValue; 631 631 } … … 804 804 805 805 if (resolveResult.isStatic() && !resolveResult.isReadOnly()) { 806 RefPtr<RegisterID> propDst = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult );806 RefPtr<RegisterID> propDst = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult, m_ident); 807 807 emitPreIncOrDec(generator, propDst.get(), m_operator); 808 generator.emitPutStaticVar(resolveResult, propDst.get());808 generator.emitPutStaticVar(resolveResult, m_ident, propDst.get()); 809 809 return generator.moveToDestinationIfNeeded(dst, propDst.get()); 810 810 } … … 1227 1227 1228 1228 if (resolveResult.isStatic() && !resolveResult.isReadOnly()) { 1229 RefPtr<RegisterID> src1 = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult );1229 RefPtr<RegisterID> src1 = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult, m_ident); 1230 1230 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1231 generator.emitPutStaticVar(resolveResult, result);1231 generator.emitPutStaticVar(resolveResult, m_ident, result); 1232 1232 return result; 1233 1233 } … … 1257 1257 dst = 0; 1258 1258 RegisterID* value = generator.emitNode(dst, m_right); 1259 generator.emitPutStaticVar(resolveResult, value);1259 generator.emitPutStaticVar(resolveResult, m_ident, value); 1260 1260 return value; 1261 1261 } … … 1362 1362 1363 1363 if (resolveResult.isStatic()) 1364 return generator.emitPutStaticVar(resolveResult, value.get());1364 return generator.emitPutStaticVar(resolveResult, m_ident, value.get()); 1365 1365 1366 1366 if (generator.codeType() != EvalCode) -
trunk/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
r119660 r120172 220 220 ASSERT(m_block); 221 221 ASSERT(m_isValid); 222 222 223 m_didClobber = false; 224 223 225 NodeIndex nodeIndex = m_block->at(indexInBlock); 224 226 Node& node = m_graph[nodeIndex]; … … 238 240 case GetLocal: { 239 241 VariableAccessData* variableAccessData = node.variableAccessData(); 242 if (variableAccessData->prediction() == SpecNone) { 243 m_isValid = false; 244 node.setCanExit(true); 245 break; 246 } 240 247 bool canExit = false; 241 canExit |= variableAccessData->prediction() == SpecNone;242 248 AbstractValue value = m_variables.operand(variableAccessData->local()); 243 249 if (!variableAccessData->isCaptured()) { … … 1477 1483 // FIXME: Should be able to propagate the fact that we know what the function is. 1478 1484 break; 1479 1485 1480 1486 case PutById: 1481 1487 case PutByIdDirect: … … 1489 1495 forNode(nodeIndex).makeTop(); 1490 1496 break; 1497 1498 case GlobalVarWatchpoint: 1499 node.setCanExit(true); 1500 break; 1491 1501 1492 1502 case PutGlobalVar: 1503 case PutGlobalVarCheck: 1493 1504 node.setCanExit(false); 1494 1505 break; … … 1579 1590 m_variables.local(i).clobberStructures(); 1580 1591 m_haveStructures = false; 1592 m_didClobber = true; 1581 1593 } 1582 1594 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractState.h
r119660 r120172 194 194 bool execute(unsigned); 195 195 196 // Did the last executed node clobber the world? 197 bool didClobber() const { return m_didClobber; } 198 196 199 // Is the execution state still valid? This will be false if execute() has 197 200 // returned false previously. … … 275 278 276 279 bool m_isValid; 280 bool m_didClobber; 277 281 278 282 BranchDirection m_branchDirection; // This is only set for blocks that end in Branch and that execute to completion (i.e. m_isValid == true). -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r120121 r120172 1235 1235 // an inline candidate? 1236 1236 CodeBlock* profiledBlock = executable->profiledCodeBlockFor(kind); 1237 if (!profiledBlock) 1238 return false; 1239 1237 1240 if (!mightInlineFunctionFor(profiledBlock, kind)) 1238 1241 return false; … … 2252 2255 SpeculatedType prediction = getPrediction(); 2253 2256 2257 JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject(); 2258 2254 2259 NodeIndex getGlobalVar = addToGraph( 2255 2260 GetGlobalVar, 2256 OpInfo( m_inlineStackTop->m_codeBlock->globalObject()->assertRegisterIsInThisObject(currentInstruction[2].u.registerPointer)),2261 OpInfo(globalObject->assertRegisterIsInThisObject(currentInstruction[2].u.registerPointer)), 2257 2262 OpInfo(prediction)); 2258 2263 set(currentInstruction[1].u.operand, getGlobalVar); 2259 2264 NEXT_OPCODE(op_get_global_var); 2265 } 2266 2267 case op_get_global_var_watchable: { 2268 SpeculatedType prediction = getPrediction(); 2269 2270 JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject(); 2271 2272 unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[3].u.operand]; 2273 Identifier identifier = m_codeBlock->identifier(identifierNumber); 2274 SymbolTableEntry entry = globalObject->symbolTable().get(identifier.impl()); 2275 if (!entry.couldBeWatched()) { 2276 NodeIndex getGlobalVar = addToGraph( 2277 GetGlobalVar, 2278 OpInfo(globalObject->assertRegisterIsInThisObject(currentInstruction[2].u.registerPointer)), 2279 OpInfo(prediction)); 2280 set(currentInstruction[1].u.operand, getGlobalVar); 2281 NEXT_OPCODE(op_get_global_var_watchable); 2282 } 2283 2284 // The watchpoint is still intact! This means that we will get notified if the 2285 // current value in the global variable changes. So, we can inline that value. 2286 // Moreover, currently we can assume that this value is a JSFunction*, which 2287 // implies that it's a cell. This simplifies things, since in general we'd have 2288 // to use a JSConstant for non-cells and a WeakJSConstant for cells. So instead 2289 // of having both cases we just assert that the value is a cell. 2290 2291 // NB. If it wasn't for CSE, GlobalVarWatchpoint would have no need for the 2292 // register pointer. But CSE tracks effects on global variables by comparing 2293 // register pointers. Because CSE executes multiple times while the backend 2294 // executes once, we use the following performance trade-off: 2295 // - The node refers directly to the register pointer to make CSE super cheap. 2296 // - To perform backend code generation, the node only contains the identifier 2297 // number, from which it is possible to get (via a few average-time O(1) 2298 // lookups) to the WatchpointSet. 2299 2300 addToGraph( 2301 GlobalVarWatchpoint, 2302 OpInfo(globalObject->assertRegisterIsInThisObject(currentInstruction[2].u.registerPointer)), 2303 OpInfo(identifierNumber)); 2304 2305 JSValue specificValue = globalObject->registerAt(entry.getIndex()).get(); 2306 ASSERT(specificValue.isCell()); 2307 set(currentInstruction[1].u.operand, 2308 addToGraph(WeakJSConstant, OpInfo(specificValue.asCell()))); 2309 2310 NEXT_OPCODE(op_get_global_var_watchable); 2260 2311 } 2261 2312 … … 2267 2318 value); 2268 2319 NEXT_OPCODE(op_put_global_var); 2320 } 2321 2322 case op_put_global_var_check: { 2323 NodeIndex value = get(currentInstruction[2].u.operand); 2324 CodeBlock* codeBlock = m_inlineStackTop->m_codeBlock; 2325 JSGlobalObject* globalObject = codeBlock->globalObject(); 2326 unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[4].u.operand]; 2327 Identifier identifier = m_codeBlock->identifier(identifierNumber); 2328 SymbolTableEntry entry = globalObject->symbolTable().get(identifier.impl()); 2329 if (!entry.couldBeWatched()) { 2330 addToGraph( 2331 PutGlobalVar, 2332 OpInfo(globalObject->assertRegisterIsInThisObject(currentInstruction[1].u.registerPointer)), 2333 value); 2334 NEXT_OPCODE(op_put_global_var_check); 2335 } 2336 addToGraph( 2337 PutGlobalVarCheck, 2338 OpInfo(codeBlock->globalObject()->assertRegisterIsInThisObject(currentInstruction[1].u.registerPointer)), 2339 OpInfo(identifierNumber), 2340 value); 2341 NEXT_OPCODE(op_put_global_var_check); 2269 2342 } 2270 2343 -
trunk/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
r119647 r120172 95 95 addCallArgument(arg2); 96 96 } 97 98 ALWAYS_INLINE void setupArguments(TrustedImmPtr arg1) 99 { 100 resetCallArguments(); 101 addCallArgument(arg1); 102 } 97 103 98 104 ALWAYS_INLINE void setupArgumentsExecState() … … 434 440 setupTwoStubArgs<GPRInfo::argumentGPR0, GPRInfo::argumentGPR1>(arg1, arg2); 435 441 } 442 443 ALWAYS_INLINE void setupArguments(TrustedImmPtr arg1) 444 { 445 move(arg1, GPRInfo::argumentGPR0); 446 } 436 447 437 448 ALWAYS_INLINE void setupArgumentsExecState() -
trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
r119660 r120172 218 218 } 219 219 220 bool globalVarWatchpointElimination(WriteBarrier<Unknown>* registerPointer) 221 { 222 for (unsigned i = m_indexInBlock; i--;) { 223 NodeIndex index = m_currentBlock->at(i); 224 Node& node = m_graph[index]; 225 switch (node.op()) { 226 case GlobalVarWatchpoint: 227 if (node.registerPointer() == registerPointer) 228 return true; 229 break; 230 case PutGlobalVar: 231 if (node.registerPointer() == registerPointer) 232 return false; 233 break; 234 default: 235 break; 236 } 237 if (m_graph.clobbersWorld(index)) 238 break; 239 } 240 return false; 241 } 242 220 243 NodeIndex globalVarStoreElimination(WriteBarrier<Unknown>* registerPointer) 221 244 { … … 227 250 switch (node.op()) { 228 251 case PutGlobalVar: 252 case PutGlobalVarCheck: 229 253 if (node.registerPointer() == registerPointer) 230 254 return index; … … 986 1010 break; 987 1011 1012 case GlobalVarWatchpoint: 1013 if (globalVarWatchpointElimination(node.registerPointer())) 1014 eliminate(); 1015 break; 1016 988 1017 case PutGlobalVar: 1018 case PutGlobalVarCheck: 989 1019 if (m_fixpointState == FixpointNotConverged) 990 1020 break; -
trunk/Source/JavaScriptCore/dfg/DFGCapabilities.h
r118310 r120172 124 124 case op_put_by_id_transition_normal: 125 125 case op_get_global_var: 126 case op_get_global_var_watchable: 126 127 case op_put_global_var: 128 case op_put_global_var_check: 127 129 case op_jmp: 128 130 case op_loop: -
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r119660 r120172 57 57 if (!block->cfaFoundConstants) 58 58 continue; 59 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 60 dataLog("Constant folding considering Block #%u.\n", blockIndex); 61 #endif 59 62 state.beginBasicBlock(block); 60 63 for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) { … … 91 94 state.execute(indexInBlock); 92 95 if (!node.shouldGenerate() 93 || m_graph.clobbersWorld(node)96 || state.didClobber() 94 97 || node.hasConstant()) 95 98 continue; -
trunk/Source/JavaScriptCore/dfg/DFGCorrectableJumpPoint.h
r115141 r120172 65 65 m_condition = check.m_condition; 66 66 #endif 67 } 68 69 bool isSet() 70 { 71 return m_codeOffset != std::numeric_limits<uint32_t>::max(); 67 72 } 68 73 -
trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
r117620 r120172 45 45 for (unsigned i = 0; i < codeBlock()->numberOfOSRExits(); ++i) { 46 46 OSRExit& exit = codeBlock()->osrExit(i); 47 exit.m_check.initialJump().link(this); 47 ASSERT(!exit.m_check.isSet() == (exit.m_watchpointIndex != std::numeric_limits<unsigned>::max())); 48 if (exit.m_watchpointIndex == std::numeric_limits<unsigned>::max()) 49 exit.m_check.initialJump().link(this); 50 else 51 codeBlock()->watchpoint(exit.m_watchpointIndex).setDestination(label()); 48 52 jitAssertHasValidCallFrame(); 49 53 store32(TrustedImm32(i), &globalData()->osrExitIndex); … … 191 195 linkBuffer.link(exit.m_check.lateJump(), target); 192 196 exit.m_check.correctLateJump(linkBuffer); 197 if (exit.m_watchpointIndex != std::numeric_limits<unsigned>::max()) 198 codeBlock()->watchpoint(exit.m_watchpointIndex).correctLabels(linkBuffer); 193 199 } 194 200 -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r119660 r120172 431 431 } 432 432 433 bool hasIdentifierNumberForCheck() 434 { 435 return op() == GlobalVarWatchpoint || op() == PutGlobalVarCheck; 436 } 437 438 unsigned identifierNumberForCheck() 439 { 440 ASSERT(hasIdentifierNumberForCheck()); 441 return m_opInfo2; 442 } 443 433 444 bool hasRegisterPointer() 434 445 { 435 return op() == GetGlobalVar || op() == PutGlobalVar ;446 return op() == GetGlobalVar || op() == PutGlobalVar || op() == GlobalVarWatchpoint || op() == PutGlobalVarCheck; 436 447 } 437 448 -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r118579 r120172 142 142 macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \ 143 143 macro(PutGlobalVar, NodeMustGenerate) \ 144 macro(GlobalVarWatchpoint, NodeMustGenerate) \ 145 macro(PutGlobalVarCheck, NodeMustGenerate) \ 144 146 macro(CheckFunction, NodeMustGenerate) \ 145 147 \ -
trunk/Source/JavaScriptCore/dfg/DFGOSRExit.cpp
r118278 r120172 52 52 , m_codeOriginForExitProfile(m_codeOrigin) 53 53 , m_recoveryIndex(recoveryIndex) 54 , m_watchpointIndex(std::numeric_limits<unsigned>::max()) 54 55 , m_kind(kind) 55 56 , m_count(0) -
trunk/Source/JavaScriptCore/dfg/DFGOSRExit.h
r115093 r120172 97 97 98 98 unsigned m_recoveryIndex; 99 unsigned m_watchpointIndex; 99 100 100 101 ExitKind m_kind; -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r119857 r120172 923 923 { 924 924 return virtualFor(execCallee, CodeForConstruct); 925 } 926 927 void DFG_OPERATION operationNotifyGlobalVarWrite(WatchpointSet* watchpointSet) 928 { 929 watchpointSet->notifyWrite(); 925 930 } 926 931 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r119857 r120172 101 101 typedef void DFG_OPERATION (*V_DFGOperation_EJPP)(ExecState*, EncodedJSValue, EncodedJSValue, void*); 102 102 typedef void DFG_OPERATION (*V_DFGOperation_EPZJ)(ExecState*, void*, int32_t, EncodedJSValue); 103 typedef void DFG_OPERATION (*V_DFGOperation_W)(WatchpointSet*); 103 104 typedef void* DFG_OPERATION (*P_DFGOperation_E)(ExecState*); 104 105 … … 117 118 EncodedJSValue DFG_OPERATION operationCallCustomGetter(ExecState*, JSCell*, PropertySlot::GetValueFunc, Identifier*) WTF_INTERNAL; 118 119 EncodedJSValue DFG_OPERATION operationCallGetter(ExecState*, JSCell*, JSCell*) WTF_INTERNAL; 120 void DFG_OPERATION operationNotifyGlobalVarWrite(WatchpointSet* watchpointSet) WTF_INTERNAL; 119 121 EncodedJSValue DFG_OPERATION operationResolve(ExecState*, Identifier*) WTF_INTERNAL; 120 122 EncodedJSValue DFG_OPERATION operationResolveBase(ExecState*, Identifier*) WTF_INTERNAL; -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r119660 r120172 492 492 } 493 493 494 case PutGlobalVar: { 494 case PutGlobalVar: 495 case PutGlobalVarCheck: { 495 496 changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue); 496 497 break; … … 670 671 case CheckNumber: 671 672 case CheckArgumentsNotCreated: 673 case GlobalVarWatchpoint: 672 674 changed |= mergeDefaultFlags(node); 673 675 break; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r119865 r120172 1415 1415 return appendCallWithExceptionCheck(operation); 1416 1416 } 1417 JITCompiler::Call callOperation(V_DFGOperation_W operation, WatchpointSet* watchpointSet) 1418 { 1419 m_jit.setupArguments(TrustedImmPtr(watchpointSet)); 1420 return appendCall(operation); 1421 } 1417 1422 template<typename FunctionType, typename ArgumentType1> 1418 1423 JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1) … … 1673 1678 return appendCallWithExceptionCheck(operation); 1674 1679 } 1680 JITCompiler::Call callOperation(V_DFGOperation_W operation, WatchpointSet* watchpointSet) 1681 { 1682 m_jit.setupArguments(TrustedImmPtr(watchpointSet)); 1683 return appendCall(operation); 1684 } 1675 1685 template<typename FunctionType, typename ArgumentType1> 1676 1686 JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1) … … 1793 1803 m_jit.move(GPRInfo::returnValueGPR, result); 1794 1804 return call; 1805 } 1806 JITCompiler::Call appendCall(const FunctionPtr& function) 1807 { 1808 prepareForExternalCall(); 1809 return m_jit.appendCall(function); 1795 1810 } 1796 1811 JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, GPRReg result1, GPRReg result2) … … 2194 2209 speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail, recovery); 2195 2210 } 2211 // Use this like you would use speculationCheck(), except that you don't pass it a jump 2212 // (because you don't have to execute a branch; that's kind of the whole point), and you 2213 // must register the returned Watchpoint with something relevant. In general, this should 2214 // be used with extreme care. Use speculationCheck() unless you've got an amazing reason 2215 // not to. 2216 Watchpoint* speculationWatchpoint(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex) 2217 { 2218 if (!m_compileOkay) 2219 return 0; 2220 ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); 2221 OSRExit& exit = m_jit.codeBlock()->osrExit( 2222 m_jit.codeBlock()->appendOSRExit( 2223 OSRExit(kind, jsValueSource, 2224 m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), 2225 JITCompiler::Jump(), this))); 2226 exit.m_watchpointIndex = m_jit.codeBlock()->appendWatchpoint( 2227 Watchpoint(m_jit.watchpointLabel())); 2228 return &m_jit.codeBlock()->watchpoint(exit.m_watchpointIndex); 2229 } 2230 // The default for speculation watchpoints is that they're uncounted, because the 2231 // act of firing a watchpoint invalidates it. So, future recompilations will not 2232 // attempt to set this watchpoint again. 2233 Watchpoint* speculationWatchpoint() 2234 { 2235 return speculationWatchpoint(UncountableWatchpoint, JSValueSource(), NoNode); 2236 } 2196 2237 void forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery) 2197 2238 { -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r119660 r120172 3597 3597 } 3598 3598 3599 case PutGlobalVarCheck: { 3600 JSValueOperand value(this, node.child1()); 3601 3602 WatchpointSet* watchpointSet = 3603 m_jit.globalObjectFor(node.codeOrigin)->symbolTable().get( 3604 identifier(node.identifierNumberForCheck())->impl()).watchpointSet(); 3605 addSlowPathGenerator( 3606 slowPathCall( 3607 m_jit.branchTest8( 3608 JITCompiler::NonZero, 3609 JITCompiler::AbsoluteAddress(watchpointSet->addressOfIsWatched())), 3610 this, operationNotifyGlobalVarWrite, NoResult, watchpointSet)); 3611 3612 if (Heap::isWriteBarrierEnabled()) { 3613 GPRTemporary scratch(this); 3614 GPRReg scratchReg = scratch.gpr(); 3615 3616 writeBarrier(m_jit.globalObjectFor(node.codeOrigin), value.tagGPR(), node.child1(), WriteBarrierForVariableAccess, scratchReg); 3617 } 3618 3619 // FIXME: if we happen to have a spare register - and _ONLY_ if we happen to have 3620 // a spare register - a good optimization would be to put the register pointer into 3621 // a register and then do a zero offset store followed by a four-offset store (or 3622 // vice-versa depending on endianness). 3623 m_jit.store32(value.tagGPR(), node.registerPointer()->tagPointer()); 3624 m_jit.store32(value.payloadGPR(), node.registerPointer()->payloadPointer()); 3625 3626 noResult(m_compileIndex); 3627 break; 3628 } 3629 3630 case GlobalVarWatchpoint: { 3631 m_jit.globalObjectFor(node.codeOrigin)->symbolTable().get( 3632 identifier(node.identifierNumberForCheck())->impl()).addWatchpoint( 3633 speculationWatchpoint()); 3634 3635 #if DFG_ENABLE(JIT_ASSERT) 3636 GPRTemporary scratch(this); 3637 GPRReg scratchGPR = scratch.gpr(); 3638 m_jit.load32(node.registerPointer()->tagPointer(), scratchGPR); 3639 JITCompiler::Jump notOK = m_jit.branch32( 3640 JITCompiler::NotEqual, scratchGPR, 3641 TrustedImm32(node.registerPointer()->get().tag())); 3642 m_jit.load32(node.registerPointer()->payloadPointer(), scratchGPR); 3643 JITCompiler::Jump ok = m_jit.branch32( 3644 JITCompiler::Equal, scratchGPR, 3645 TrustedImm32(node.registerPointer()->get().payload())); 3646 notOK.link(&m_jit); 3647 m_jit.breakpoint(); 3648 ok.link(&m_jit); 3649 #endif 3650 3651 noResult(m_compileIndex); 3652 break; 3653 } 3654 3599 3655 case CheckHasInstance: { 3600 3656 SpeculateCellOperand base(this, node.child1()); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r119660 r120172 3616 3616 } 3617 3617 3618 case PutGlobalVarCheck: { 3619 JSValueOperand value(this, node.child1()); 3620 3621 WatchpointSet* watchpointSet = 3622 m_jit.globalObjectFor(node.codeOrigin)->symbolTable().get( 3623 identifier(node.identifierNumberForCheck())->impl()).watchpointSet(); 3624 addSlowPathGenerator( 3625 slowPathCall( 3626 m_jit.branchTest8( 3627 JITCompiler::NonZero, 3628 JITCompiler::AbsoluteAddress(watchpointSet->addressOfIsWatched())), 3629 this, operationNotifyGlobalVarWrite, NoResult, watchpointSet)); 3630 3631 if (Heap::isWriteBarrierEnabled()) { 3632 GPRTemporary scratch(this); 3633 GPRReg scratchReg = scratch.gpr(); 3634 3635 writeBarrier(m_jit.globalObjectFor(node.codeOrigin), value.gpr(), node.child1(), WriteBarrierForVariableAccess, scratchReg); 3636 } 3637 3638 m_jit.storePtr(value.gpr(), node.registerPointer()); 3639 3640 noResult(m_compileIndex); 3641 break; 3642 } 3643 3644 case GlobalVarWatchpoint: { 3645 m_jit.globalObjectFor(node.codeOrigin)->symbolTable().get( 3646 identifier(node.identifierNumberForCheck())->impl()).addWatchpoint( 3647 speculationWatchpoint()); 3648 3649 #if DFG_ENABLE(JIT_ASSERT) 3650 GPRTemporary scratch(this); 3651 GPRReg scratchGPR = scratch.gpr(); 3652 m_jit.loadPtr(node.registerPointer(), scratchGPR); 3653 JITCompiler::Jump ok = m_jit.branchPtr( 3654 JITCompiler::Equal, scratchGPR, 3655 TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(node.registerPointer()->get())))); 3656 m_jit.breakpoint(); 3657 ok.link(&m_jit); 3658 #endif 3659 3660 noResult(m_compileIndex); 3661 break; 3662 } 3663 3618 3664 case CheckHasInstance: { 3619 3665 SpeculateCellOperand base(this, node.child1()); -
trunk/Source/JavaScriptCore/jit/JIT.cpp
r118270 r120172 260 260 DEFINE_OP(op_get_argument_by_val) 261 261 DEFINE_OP(op_get_by_pname) 262 DEFINE_OP(op_get_global_var_watchable) 262 263 DEFINE_OP(op_get_global_var) 263 264 DEFINE_OP(op_get_pnames) … … 325 326 DEFINE_OP(op_put_getter_setter) 326 327 DEFINE_OP(op_put_global_var) 328 DEFINE_OP(op_put_global_var_check) 327 329 DEFINE_OP(op_put_scoped_var) 328 330 DEFINE_OP(op_resolve) … … 482 484 DEFINE_SLOWCASE_OP(op_put_by_id) 483 485 DEFINE_SLOWCASE_OP(op_put_by_val) 486 DEFINE_SLOWCASE_OP(op_put_global_var_check); 484 487 DEFINE_SLOWCASE_OP(op_resolve_global) 485 488 DEFINE_SLOWCASE_OP(op_resolve_global_dynamic) -
trunk/Source/JavaScriptCore/jit/JIT.h
r118270 r120172 464 464 bool getMappedPayload(int virtualRegisterIndex, RegisterID& payload); 465 465 bool getMappedTag(int virtualRegisterIndex, RegisterID& tag); 466 466 467 467 void emitJumpSlowCaseIfNotJSCell(int virtualRegisterIndex); 468 468 void emitJumpSlowCaseIfNotJSCell(int virtualRegisterIndex, RegisterID tag); … … 600 600 void emit_op_get_by_pname(Instruction*); 601 601 void emit_op_get_global_var(Instruction*); 602 void emit_op_get_global_var_watchable(Instruction* instruction) { emit_op_get_global_var(instruction); } 602 603 void emit_op_get_scoped_var(Instruction*); 603 604 void emit_op_init_lazy_reg(Instruction*); … … 663 664 void emit_op_put_getter_setter(Instruction*); 664 665 void emit_op_put_global_var(Instruction*); 666 void emit_op_put_global_var_check(Instruction*); 665 667 void emit_op_put_scoped_var(Instruction*); 666 668 void emit_op_resolve(Instruction*); … … 740 742 void emitSlow_op_put_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&); 741 743 void emitSlow_op_put_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&); 744 void emitSlow_op_put_global_var_check(Instruction*, Vector<SlowCaseEntry>::iterator&); 742 745 void emitSlow_op_resolve_global(Instruction*, Vector<SlowCaseEntry>::iterator&); 743 746 void emitSlow_op_resolve_global_dynamic(Instruction*, Vector<SlowCaseEntry>::iterator&); -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
r119655 r120172 1028 1028 } 1029 1029 1030 void JIT::emit_op_put_global_var_check(Instruction* currentInstruction) 1031 { 1032 emitGetVirtualRegister(currentInstruction[2].u.operand, regT0); 1033 1034 addSlowCase(branchTest8(NonZero, AbsoluteAddress(currentInstruction[3].u.predicatePointer))); 1035 1036 JSGlobalObject* globalObject = m_codeBlock->globalObject(); 1037 1038 storePtr(regT0, currentInstruction[1].u.registerPointer); 1039 if (Heap::isWriteBarrierEnabled()) 1040 emitWriteBarrier(globalObject, regT0, regT2, ShouldFilterImmediates, WriteBarrierForVariableAccess); 1041 } 1042 1043 void JIT::emitSlow_op_put_global_var_check(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 1044 { 1045 linkSlowCase(iter); 1046 1047 JITStubCall stubCall(this, cti_op_put_global_var_check); 1048 stubCall.addArgument(regT0); 1049 stubCall.addArgument(TrustedImm32(currentInstruction[4].u.operand)); 1050 stubCall.call(); 1051 } 1052 1030 1053 void JIT::resetPatchGetById(RepatchBuffer& repatchBuffer, StructureStubInfo* stubInfo) 1031 1054 { -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
r119655 r120172 1091 1091 } 1092 1092 1093 void JIT::emit_op_put_global_var_check(Instruction* currentInstruction) 1094 { 1095 WriteBarrier<Unknown>* registerPointer = currentInstruction[1].u.registerPointer; 1096 int value = currentInstruction[2].u.operand; 1097 1098 JSGlobalObject* globalObject = m_codeBlock->globalObject(); 1099 1100 emitLoad(value, regT1, regT0); 1101 1102 addSlowCase(branchTest8(NonZero, AbsoluteAddress(currentInstruction[3].u.predicatePointer))); 1103 1104 if (Heap::isWriteBarrierEnabled()) { 1105 move(TrustedImmPtr(globalObject), regT2); 1106 emitWriteBarrier(globalObject, regT1, regT3, ShouldFilterImmediates, WriteBarrierForVariableAccess); 1107 } 1108 1109 store32(regT1, registerPointer->tagPointer()); 1110 store32(regT0, registerPointer->payloadPointer()); 1111 unmap(); 1112 } 1113 1114 void JIT::emitSlow_op_put_global_var_check(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 1115 { 1116 linkSlowCase(iter); 1117 1118 JITStubCall stubCall(this, cti_op_put_global_var_check); 1119 stubCall.addArgument(regT1, regT0); 1120 stubCall.addArgument(TrustedImm32(currentInstruction[4].u.operand)); 1121 stubCall.call(); 1122 } 1123 1093 1124 void JIT::resetPatchGetById(RepatchBuffer& repatchBuffer, StructureStubInfo* stubInfo) 1094 1125 { -
trunk/Source/JavaScriptCore/jit/JITStubs.cpp
r120159 r120172 2378 2378 } 2379 2379 2380 DEFINE_STUB_FUNCTION(void, op_put_global_var_check) 2381 { 2382 STUB_INIT_STACK_FRAME(stackFrame); 2383 2384 CallFrame* callFrame = stackFrame.callFrame; 2385 CodeBlock* codeBlock = callFrame->codeBlock(); 2386 symbolTablePut(codeBlock->globalObject(), callFrame, codeBlock->identifier(stackFrame.args[1].int32()), stackFrame.args[0].jsValue(), true); 2387 } 2388 2380 2389 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve) 2381 2390 { -
trunk/Source/JavaScriptCore/jit/JITStubs.h
r119857 r120172 446 446 void JIT_STUB cti_op_put_by_val(STUB_ARGS_DECLARATION) WTF_INTERNAL; 447 447 void JIT_STUB cti_op_put_getter_setter(STUB_ARGS_DECLARATION) WTF_INTERNAL; 448 void JIT_STUB cti_op_put_global_var_check(STUB_ARGS_DECLARATION) WTF_INTERNAL; 448 449 void JIT_STUB cti_op_tear_off_activation(STUB_ARGS_DECLARATION) WTF_INTERNAL; 449 450 void JIT_STUB cti_op_tear_off_arguments(STUB_ARGS_DECLARATION) WTF_INTERNAL; -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
r119602 r120172 854 854 LLINT_OP(2) = result; 855 855 // FIXME: technically should have profiling, but we don't do it because the DFG won't use it. 856 LLINT_END(); 857 } 858 859 LLINT_SLOW_PATH_DECL(slow_path_put_global_var_check) 860 { 861 LLINT_BEGIN(); 862 CodeBlock* codeBlock = exec->codeBlock(); 863 symbolTablePut(codeBlock->globalObject(), exec, codeBlock->identifier(pc[4].u.operand), LLINT_OP_C(2).jsValue(), true); 856 864 LLINT_END(); 857 865 } -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h
r119857 r120172 148 148 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_with_base); 149 149 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_with_this); 150 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_global_var_check); 150 151 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_by_id); 151 152 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_arguments_length); -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
r119655 r120172 1040 1040 1041 1041 1042 _llint_op_get_global_var: 1042 macro getGlobalVar(size) 1043 1043 traceExecution() 1044 1044 loadp 8[PC], t0 … … 1048 1048 storei t2, TagOffset[cfr, t3, 8] 1049 1049 storei t1, PayloadOffset[cfr, t3, 8] 1050 loadi 12[PC], t31050 loadi (size - 1) * 4[PC], t3 1051 1051 valueProfile(t2, t1, t3) 1052 dispatch(4) 1052 dispatch(size) 1053 end 1054 1055 _llint_op_get_global_var: 1056 getGlobalVar(4) 1057 1058 1059 _llint_op_get_global_var_watchable: 1060 getGlobalVar(5) 1053 1061 1054 1062 … … 1062 1070 storei t3, PayloadOffset[t0] 1063 1071 dispatch(3) 1072 1073 1074 _llint_op_put_global_var_check: 1075 traceExecution() 1076 loadp 12[PC], t2 1077 loadi 8[PC], t1 1078 loadi 4[PC], t0 1079 btbnz [t2], .opPutGlobalVarCheckSlow 1080 loadConstantOrVariable(t1, t2, t3) 1081 writeBarrier(t2, t3) 1082 storei t2, TagOffset[t0] 1083 storei t3, PayloadOffset[t0] 1084 dispatch(5) 1085 .opPutGlobalVarCheckSlow: 1086 callSlowPath(_llint_slow_path_put_global_var_check) 1087 dispatch(5) 1064 1088 1065 1089 -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r119655 r120172 894 894 895 895 896 _llint_op_get_global_var: 896 macro getGlobalVar(size) 897 897 traceExecution() 898 898 loadp 16[PB, PC, 8], t0 … … 900 900 loadp [t0], t1 901 901 storep t1, [cfr, t3, 8] 902 loadp 24[PB, PC, 8], t0902 loadp (size - 1) * 8[PB, PC, 8], t0 903 903 valueProfile(t1, t0) 904 dispatch(4) 904 dispatch(size) 905 end 906 907 _llint_op_get_global_var: 908 getGlobalVar(4) 909 910 911 _llint_op_get_global_var_watchable: 912 getGlobalVar(5) 905 913 906 914 … … 913 921 storep t2, [t0] 914 922 dispatch(3) 923 924 925 _llint_op_put_global_var_check: 926 traceExecution() 927 loadp 24[PB, PC, 8], t2 928 loadis 16[PB, PC, 8], t1 929 loadp 8[PB, PC, 8], t0 930 btbnz [t2], .opPutGlobalVarCheckSlow 931 loadConstantOrVariable(t1, t2) 932 writeBarrier(t2) 933 storep t2, [t0] 934 dispatch(5) 935 .opPutGlobalVarCheckSlow: 936 callSlowPath(_llint_slow_path_put_global_var_check) 937 dispatch(5) 915 938 916 939 -
trunk/Source/JavaScriptCore/runtime/JSObject.cpp
r120045 r120172 505 505 } 506 506 507 voidJSObject::removeDirect(JSGlobalData& globalData, PropertyName propertyName)507 bool JSObject::removeDirect(JSGlobalData& globalData, PropertyName propertyName) 508 508 { 509 509 if (structure()->get(globalData, propertyName) == WTF::notFound) 510 return ;510 return false; 511 511 512 512 size_t offset; 513 513 if (structure()->isUncacheableDictionary()) { 514 514 offset = structure()->removePropertyWithoutTransition(globalData, propertyName); 515 if (offset != WTF::notFound) 516 putUndefinedAtDirectOffset(offset); 517 return; 515 if (offset == WTF::notFound) 516 return false; 517 putUndefinedAtDirectOffset(offset); 518 return true; 518 519 } 519 520 520 521 setStructure(globalData, Structure::removePropertyTransition(globalData, structure(), propertyName, offset)); 521 if (offset != WTF::notFound) 522 putUndefinedAtDirectOffset(offset); 522 if (offset == WTF::notFound) 523 return false; 524 putUndefinedAtDirectOffset(offset); 525 return true; 523 526 } 524 527 -
trunk/Source/JavaScriptCore/runtime/JSObject.h
r119865 r120172 177 177 void transitionTo(JSGlobalData&, Structure*); 178 178 179 void removeDirect(JSGlobalData&, PropertyName);179 bool removeDirect(JSGlobalData&, PropertyName); // Return true if anything is removed. 180 180 bool hasCustomProperties() { return structure()->didTransition(); } 181 181 bool hasGetterSetterProperties() { return structure()->hasGetterSetterProperties(); } -
trunk/Source/JavaScriptCore/runtime/JSSymbolTableObject.h
r119655 r120172 73 73 SymbolTableObjectType* object, PropertyName propertyName, PropertySlot& slot) 74 74 { 75 SymbolTableEntry entry = object->symbolTable().inlineGet(propertyName.publicName()); 76 if (entry.isNull()) 75 SymbolTable& symbolTable = object->symbolTable(); 76 SymbolTable::iterator iter = symbolTable.find(propertyName.publicName()); 77 if (iter == symbolTable.end()) 77 78 return false; 79 SymbolTableEntry::Fast entry = iter->second; 80 ASSERT(!entry.isNull()); 78 81 slot.setValue(object->registerAt(entry.getIndex()).get()); 79 82 return true; … … 84 87 SymbolTableObjectType* object, PropertyName propertyName, PropertyDescriptor& descriptor) 85 88 { 86 SymbolTableEntry entry = object->symbolTable().inlineGet(propertyName.publicName()); 87 if (entry.isNull()) 89 SymbolTable& symbolTable = object->symbolTable(); 90 SymbolTable::iterator iter = symbolTable.find(propertyName.publicName()); 91 if (iter == symbolTable.end()) 88 92 return false; 93 SymbolTableEntry::Fast entry = iter->second; 94 ASSERT(!entry.isNull()); 89 95 descriptor.setDescriptor( 90 96 object->registerAt(entry.getIndex()).get(), entry.getAttributes() | DontDelete); … … 97 103 bool& slotIsWriteable) 98 104 { 99 SymbolTableEntry entry = object->symbolTable().inlineGet(propertyName.publicName()); 100 if (entry.isNull()) 105 SymbolTable& symbolTable = object->symbolTable(); 106 SymbolTable::iterator iter = symbolTable.find(propertyName.publicName()); 107 if (iter == symbolTable.end()) 101 108 return false; 109 SymbolTableEntry::Fast entry = iter->second; 110 ASSERT(!entry.isNull()); 102 111 slot.setValue(object->registerAt(entry.getIndex()).get()); 103 112 slotIsWriteable = !entry.isReadOnly(); … … 113 122 ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(object)); 114 123 115 SymbolTableEntry entry = object->symbolTable().inlineGet(propertyName.publicName()); 116 if (entry.isNull()) 124 SymbolTable& symbolTable = object->symbolTable(); 125 SymbolTable::iterator iter = symbolTable.find(propertyName.publicName()); 126 if (iter == symbolTable.end()) 117 127 return false; 118 if (entry.isReadOnly()) { 128 bool wasFat; 129 SymbolTableEntry::Fast fastEntry = iter->second.getFast(wasFat); 130 ASSERT(!fastEntry.isNull()); 131 if (fastEntry.isReadOnly()) { 119 132 if (shouldThrow) 120 133 throwTypeError(exec, StrictModeReadonlyPropertyWriteError); 121 134 return true; 122 135 } 123 object->registerAt(entry.getIndex()).set(globalData, object, value); 136 if (UNLIKELY(wasFat)) 137 iter->second.notifyWrite(); 138 object->registerAt(fastEntry.getIndex()).set(globalData, object, value); 124 139 return true; 125 140 } … … 137 152 SymbolTableEntry& entry = iter->second; 138 153 ASSERT(!entry.isNull()); 154 entry.notifyWrite(); 139 155 entry.setAttributes(attributes); 140 156 object->registerAt(entry.getIndex()).set(globalData, object, value); -
trunk/Source/JavaScriptCore/runtime/SymbolTable.h
r109268 r120172 1 1 /* 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.2 * Copyright (C) 2007, 2008, 2012 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 32 32 #include "JSObject.h" 33 33 #include "UString.h" 34 #include "Watchpoint.h" 34 35 #include <wtf/AlwaysInline.h> 35 36 #include <wtf/HashTraits.h> 36 37 37 38 namespace JSC { 39 40 class Watchpoint; 41 class WatchpointSet; 38 42 39 43 static ALWAYS_INLINE int missingSymbolMarker() { return std::numeric_limits<int>::max(); } … … 43 47 // four bits all set or all unset. 44 48 49 // In addition to implementing semantics-mandated variable attributes and 50 // implementation-mandated variable indexing, this class also implements 51 // watchpoints to be used for JIT optimizations. Because watchpoints are 52 // meant to be relatively rare, this class optimizes heavily for the case 53 // that they are not being used. To that end, this class uses the thin-fat 54 // idiom: either it is thin, in which case it contains an in-place encoded 55 // word that consists of attributes, the index, and a bit saying that it is 56 // thin; or it is fat, in which case it contains a pointer to a malloc'd 57 // data structure and a bit saying that it is fat. The malloc'd data 58 // structure will be malloced a second time upon copy, to preserve the 59 // property that in-place edits to SymbolTableEntry do not manifest in any 60 // copies. However, the malloc'd FatEntry data structure contains a ref- 61 // counted pointer to a shared WatchpointSet. Thus, in-place edits of the 62 // WatchpointSet will manifest in all copies. Here's a picture: 63 // 64 // SymbolTableEntry --> FatEntry --> WatchpointSet 65 // 66 // If you make a copy of a SymbolTableEntry, you will have: 67 // 68 // original: SymbolTableEntry --> FatEntry --> WatchpointSet 69 // copy: SymbolTableEntry --> FatEntry -----^ 70 45 71 struct SymbolTableEntry { 72 // Use the SymbolTableEntry::Fast class, either via implicit cast or by calling 73 // getFast(), when you (1) only care about isNull(), getIndex(), and isReadOnly(), 74 // and (2) you are in a hot path where you need to minimize the number of times 75 // that you branch on isFat() when getting the bits(). 76 class Fast { 77 public: 78 Fast() 79 : m_bits(0) 80 { 81 } 82 83 ALWAYS_INLINE Fast(const SymbolTableEntry& entry) 84 : m_bits(entry.bits()) 85 { 86 } 87 88 bool isNull() const 89 { 90 return !m_bits; 91 } 92 93 int getIndex() const 94 { 95 return static_cast<int>(m_bits >> FlagBits); 96 } 97 98 bool isReadOnly() const 99 { 100 return m_bits & ReadOnlyFlag; 101 } 102 103 unsigned getAttributes() const 104 { 105 unsigned attributes = 0; 106 if (m_bits & ReadOnlyFlag) 107 attributes |= ReadOnly; 108 if (m_bits & DontEnumFlag) 109 attributes |= DontEnum; 110 return attributes; 111 } 112 113 bool isFat() const 114 { 115 return m_bits & FatFlag; 116 } 117 118 private: 119 friend struct SymbolTableEntry; 120 intptr_t m_bits; 121 }; 122 46 123 SymbolTableEntry() 47 124 : m_bits(0) … … 50 127 51 128 SymbolTableEntry(int index) 129 : m_bits(0) 52 130 { 53 131 ASSERT(isValidIndex(index)); … … 56 134 57 135 SymbolTableEntry(int index, unsigned attributes) 136 : m_bits(0) 58 137 { 59 138 ASSERT(isValidIndex(index)); … … 61 140 } 62 141 142 ~SymbolTableEntry() 143 { 144 freeFatEntry(); 145 } 146 147 SymbolTableEntry(const SymbolTableEntry& other) 148 : m_bits(0) 149 { 150 *this = other; 151 } 152 153 SymbolTableEntry& operator=(const SymbolTableEntry& other) 154 { 155 if (UNLIKELY(other.isFat())) 156 return copySlow(other); 157 freeFatEntry(); 158 m_bits = other.m_bits; 159 return *this; 160 } 161 63 162 bool isNull() const 64 163 { 65 return ! m_bits;164 return !bits(); 66 165 } 67 166 68 167 int getIndex() const 69 168 { 70 return m_bits >> FlagBits; 71 } 72 169 return static_cast<int>(bits() >> FlagBits); 170 } 171 172 ALWAYS_INLINE Fast getFast() const 173 { 174 return Fast(*this); 175 } 176 177 ALWAYS_INLINE Fast getFast(bool& wasFat) const 178 { 179 Fast result; 180 wasFat = isFat(); 181 if (wasFat) 182 result.m_bits = fatEntry()->m_bits; 183 else 184 result.m_bits = m_bits; 185 return result; 186 } 187 73 188 unsigned getAttributes() const 74 189 { 75 unsigned attributes = 0; 76 if (m_bits & ReadOnlyFlag) 77 attributes |= ReadOnly; 78 if (m_bits & DontEnumFlag) 79 attributes |= DontEnum; 80 return attributes; 190 return getFast().getAttributes(); 81 191 } 82 192 … … 88 198 bool isReadOnly() const 89 199 { 90 return m_bits & ReadOnlyFlag; 91 } 92 200 return bits() & ReadOnlyFlag; 201 } 202 203 bool couldBeWatched(); 204 205 // Notify an opportunity to create a watchpoint for a variable. This is 206 // idempotent and fail-silent. It is idempotent in the sense that if 207 // a watchpoint set had already been created, then another one will not 208 // be created. Hence two calls to this method have the same effect as 209 // one call. It is also fail-silent, in the sense that if a watchpoint 210 // set had been created and had already been invalidated, then this will 211 // just return. This means that couldBeWatched() may return false even 212 // immediately after a call to attemptToWatch(). 213 void attemptToWatch(); 214 215 bool* addressOfIsWatched(); 216 217 void addWatchpoint(Watchpoint*); 218 219 WatchpointSet* watchpointSet() 220 { 221 return fatEntry()->m_watchpoints.get(); 222 } 223 224 ALWAYS_INLINE void notifyWrite() 225 { 226 if (LIKELY(!isFat())) 227 return; 228 notifyWriteSlow(); 229 } 230 93 231 private: 94 static const unsigned ReadOnlyFlag = 0x1; 95 static const unsigned DontEnumFlag = 0x2; 96 static const unsigned NotNullFlag = 0x4; 97 static const unsigned FlagBits = 3; 232 static const intptr_t FatFlag = 0x1; 233 static const intptr_t ReadOnlyFlag = 0x2; 234 static const intptr_t DontEnumFlag = 0x4; 235 static const intptr_t NotNullFlag = 0x8; 236 static const intptr_t FlagBits = 4; 237 238 class FatEntry { 239 WTF_MAKE_FAST_ALLOCATED; 240 public: 241 FatEntry(intptr_t bits) 242 : m_bits(bits | FatFlag) 243 { 244 } 245 246 intptr_t m_bits; // always has FatFlag set and exactly matches what the bits would have been if this wasn't fat. 247 248 RefPtr<WatchpointSet> m_watchpoints; 249 }; 250 251 SymbolTableEntry& copySlow(const SymbolTableEntry&); 252 JS_EXPORT_PRIVATE void notifyWriteSlow(); 253 254 bool isFat() const 255 { 256 return m_bits & FatFlag; 257 } 258 259 const FatEntry* fatEntry() const 260 { 261 ASSERT(isFat()); 262 return bitwise_cast<const FatEntry*>(m_bits & ~FatFlag); 263 } 264 265 FatEntry* fatEntry() 266 { 267 ASSERT(isFat()); 268 return bitwise_cast<FatEntry*>(m_bits & ~FatFlag); 269 } 270 271 FatEntry* inflate() 272 { 273 if (LIKELY(isFat())) 274 return fatEntry(); 275 return inflateSlow(); 276 } 277 278 FatEntry* inflateSlow(); 279 280 ALWAYS_INLINE intptr_t bits() const 281 { 282 if (isFat()) 283 return fatEntry()->m_bits; 284 return m_bits; 285 } 286 287 ALWAYS_INLINE intptr_t& bits() 288 { 289 if (isFat()) 290 return fatEntry()->m_bits; 291 return m_bits; 292 } 293 294 void freeFatEntry() 295 { 296 if (LIKELY(!isFat())) 297 return; 298 freeFatEntrySlow(); 299 } 300 301 void freeFatEntrySlow(); 98 302 99 303 void pack(int index, bool readOnly, bool dontEnum) 100 304 { 101 m_bits = (index << FlagBits) | NotNullFlag; 305 intptr_t& bitsRef = bits(); 306 bitsRef = (static_cast<intptr_t>(index) << FlagBits) | NotNullFlag; 102 307 if (readOnly) 103 m_bits|= ReadOnlyFlag;308 bitsRef |= ReadOnlyFlag; 104 309 if (dontEnum) 105 m_bits|= DontEnumFlag;310 bitsRef |= DontEnumFlag; 106 311 } 107 312 108 313 bool isValidIndex(int index) 109 314 { 110 return (( index << FlagBits) >> FlagBits) == index;111 } 112 113 int m_bits;315 return ((static_cast<intptr_t>(index) << FlagBits) >> FlagBits) == static_cast<intptr_t>(index); 316 } 317 318 intptr_t m_bits; 114 319 }; 115 320 -
trunk/Source/WTF/ChangeLog
r120153 r120172 1 2012-06-10 Filip Pizlo <[email protected]> 2 3 DFG should be able to set watchpoints on global variables 4 https://bugs.webkit.org/show_bug.cgi?id=88692 5 6 Reviewed by Geoffrey Garen. 7 8 Added ability to set the inline capacity of segmented vectors. 9 10 * wtf/SegmentedVector.h: 11 (WTF): 12 (SegmentedVectorIterator): 13 (WTF::SegmentedVectorIterator::operator=): 14 (WTF::SegmentedVectorIterator::SegmentedVectorIterator): 15 (SegmentedVector): 16 1 17 2012-06-12 Geoffrey Garen <[email protected]> 2 18 -
trunk/Source/WTF/wtf/SegmentedVector.h
r117198 r120172 35 35 36 36 // An iterator for SegmentedVector. It supports only the pre ++ operator 37 template <typename T, size_t SegmentSize > class SegmentedVector;38 template <typename T, size_t SegmentSize > class SegmentedVectorIterator {37 template <typename T, size_t SegmentSize = 8, size_t InlineCapacity = 32> class SegmentedVector; 38 template <typename T, size_t SegmentSize = 8, size_t InlineCapacity = 32> class SegmentedVectorIterator { 39 39 private: 40 friend class SegmentedVector<T, SegmentSize >;40 friend class SegmentedVector<T, SegmentSize, InlineCapacity>; 41 41 public: 42 typedef SegmentedVectorIterator<T, SegmentSize > Iterator;42 typedef SegmentedVectorIterator<T, SegmentSize, InlineCapacity> Iterator; 43 43 44 44 ~SegmentedVectorIterator() { } … … 76 76 } 77 77 78 SegmentedVectorIterator& operator=(const SegmentedVectorIterator<T, SegmentSize >& other)78 SegmentedVectorIterator& operator=(const SegmentedVectorIterator<T, SegmentSize, InlineCapacity>& other) 79 79 { 80 80 m_vector = other.m_vector; … … 85 85 86 86 private: 87 SegmentedVectorIterator(SegmentedVector<T, SegmentSize >& vector, size_t segment, size_t index)87 SegmentedVectorIterator(SegmentedVector<T, SegmentSize, InlineCapacity>& vector, size_t segment, size_t index) 88 88 : m_vector(vector) 89 89 , m_segment(segment) … … 92 92 } 93 93 94 SegmentedVector<T, SegmentSize >& m_vector;94 SegmentedVector<T, SegmentSize, InlineCapacity>& m_vector; 95 95 size_t m_segment; 96 96 size_t m_index; … … 99 99 // SegmentedVector is just like Vector, but it doesn't move the values 100 100 // stored in its buffer when it grows. Therefore, it is safe to keep 101 // pointers into a SegmentedVector. 102 template <typename T, size_t SegmentSize> class SegmentedVector { 103 friend class SegmentedVectorIterator<T, SegmentSize>; 101 // pointers into a SegmentedVector. The default tuning values are 102 // optimized for segmented vectors that get large; you may want to use 103 // SegmentedVector<thingy, 1, 0> if you don't expect a lot of entries. 104 template <typename T, size_t SegmentSize, size_t InlineCapacity> 105 class SegmentedVector { 106 friend class SegmentedVectorIterator<T, SegmentSize, InlineCapacity>; 104 107 public: 105 typedef SegmentedVectorIterator<T, SegmentSize > Iterator;108 typedef SegmentedVectorIterator<T, SegmentSize, InlineCapacity> Iterator; 106 109 107 110 SegmentedVector() … … 251 254 size_t m_size; 252 255 Segment m_inlineSegment; 253 Vector<Segment*, 32> m_segments;256 Vector<Segment*, InlineCapacity> m_segments; 254 257 }; 255 258
Note:
See TracChangeset
for help on using the changeset viewer.