Changeset 159798 in webkit
- Timestamp:
- Nov 26, 2013 6:47:43 PM (10 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 1 added
- 37 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r159795 r159798 1 2013-11-26 Filip Pizlo <fpizlo@apple.com> 2 3 Restructure global variable constant inference so that it could work for any kind of symbol table variable 4 https://bugs.webkit.org/show_bug.cgi?id=124760 5 6 Reviewed by Oliver Hunt. 7 8 This changes the way global variable constant inference works so that it can be reused 9 for closure variable constant inference. Some of the premises that originally motivated 10 this patch are somewhat wrong, but it led to some simplifications anyway and I suspect 11 that we'll be able to fix those premises in the future. The main point of this patch is 12 to make it easy to reuse global variable constant inference for closure variable 13 constant inference, and this will be possible provided we can also either (a) infer 14 one-shot closures (easy) or (b) infer closure variables that are always assigned prior 15 to first use. 16 17 One of the things that this patch is meant to enable is constant inference for closure 18 variables that may be part of a multi-shot closure. Closure variables may be 19 instantiated multiple times, like: 20 21 function foo() { 22 var WIDTH = 45; 23 function bar() { 24 ... use WIDTH ... 25 } 26 ... 27 } 28 29 Even if foo() is called many times and WIDTH is assigned to multiple times, that 30 doesn't change the fact that it's a constant. The goal of closure variable constant 31 inference is to catch any case where a closure variable has been assigned at least once 32 and its value has never changed. This patch doesn't implement that, but it does change 33 global variable constant inference to have most of the powers needed to do that. Note 34 that most likely we will use this functionality only to implement constant inference 35 for one-shot closures, but the resulting machinery is still simpler than what we had 36 before. 37 38 This involves three changes: 39 40 - The watchpoint object now contains the inferred value. This involves creating a 41 new kind of watchpoint set, the VariableWatchpointSet. We will reuse this object 42 for closure variables. 43 44 - Writing to a variable that is watchpointed still involves these three states that 45 we proceed through monotonically (Uninitialized->Initialized->Invalidated) but 46 now, the Initialized->Invalidated state transition only happens if we change the 47 variable's value, rather than store to the variable. Repeatedly storing the same 48 value won't change the variable's state. 49 50 - On 64-bit systems (the only systems on which we do concurrent JIT), you no longer 51 need fancy fencing to get a consistent view of the watchpoint in the JIT. The 52 state of the VariableWatchpointSet for the purposes of constant folding is 53 entirely encapsulated in the VariableWatchpointSet::m_inferredValue. If that is 54 JSValue() then you cannot fold (either because the set is uninitialized or 55 because it's invalidated - doesn't matter which); on the other hand if the value 56 is anything other than JSValue() then you can fold, and that's the value you fold 57 to. Simple! 58 59 This also changes the way that DFG IR deals with variable watchpoints. It's now 60 oblivious to global variables. You install a watchpoint using VariableWatchpoint and 61 you notify write using NotifyWrite. Easy! 62 63 Note that this will requires some more tweaks because of the fact that op_enter will 64 store Undefined into every captured variable. Hence it won't even work for one-shot 65 closures. One-shot closures are easily fixed by introducing another state (so we'll 66 have Uninitialized->Undefined->Initialized->Invalidated). Multi-shot closures will 67 require static analysis. One-shot closures are clearly a higher priority. 68 69 * GNUmakefile.list.am: 70 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj: 71 * JavaScriptCore.xcodeproj/project.pbxproj: 72 * bytecode/Instruction.h: 73 * bytecode/VariableWatchpointSet.h: Added. 74 (JSC::VariableWatchpointSet::VariableWatchpointSet): 75 (JSC::VariableWatchpointSet::~VariableWatchpointSet): 76 (JSC::VariableWatchpointSet::inferredValue): 77 (JSC::VariableWatchpointSet::notifyWrite): 78 (JSC::VariableWatchpointSet::invalidate): 79 (JSC::VariableWatchpointSet::finalizeUnconditionally): 80 (JSC::VariableWatchpointSet::addressOfInferredValue): 81 * bytecode/Watchpoint.h: 82 * dfg/DFGAbstractInterpreterInlines.h: 83 (JSC::DFG::::executeEffects): 84 * dfg/DFGByteCodeParser.cpp: 85 (JSC::DFG::ByteCodeParser::parseBlock): 86 * dfg/DFGCSEPhase.cpp: 87 (JSC::DFG::CSEPhase::performNodeCSE): 88 * dfg/DFGClobberize.h: 89 (JSC::DFG::clobberize): 90 * dfg/DFGFixupPhase.cpp: 91 (JSC::DFG::FixupPhase::fixupNode): 92 * dfg/DFGNode.h: 93 (JSC::DFG::Node::hasRegisterPointer): 94 (JSC::DFG::Node::hasVariableWatchpointSet): 95 (JSC::DFG::Node::variableWatchpointSet): 96 * dfg/DFGNodeType.h: 97 * dfg/DFGOperations.cpp: 98 * dfg/DFGOperations.h: 99 * dfg/DFGPredictionPropagationPhase.cpp: 100 (JSC::DFG::PredictionPropagationPhase::propagate): 101 * dfg/DFGSafeToExecute.h: 102 (JSC::DFG::safeToExecute): 103 * dfg/DFGSpeculativeJIT.cpp: 104 (JSC::DFG::SpeculativeJIT::compileArithMod): 105 * dfg/DFGSpeculativeJIT.h: 106 (JSC::DFG::SpeculativeJIT::callOperation): 107 * dfg/DFGSpeculativeJIT32_64.cpp: 108 (JSC::DFG::SpeculativeJIT::compile): 109 * dfg/DFGSpeculativeJIT64.cpp: 110 (JSC::DFG::SpeculativeJIT::compile): 111 * dfg/DFGWatchpointCollectionPhase.cpp: 112 (JSC::DFG::WatchpointCollectionPhase::handle): 113 * ftl/FTLCapabilities.cpp: 114 (JSC::FTL::canCompile): 115 * ftl/FTLLowerDFGToLLVM.cpp: 116 (JSC::FTL::LowerDFGToLLVM::compileNode): 117 (JSC::FTL::LowerDFGToLLVM::compileNotifyWrite): 118 * jit/JIT.h: 119 * jit/JITOperations.h: 120 * jit/JITPropertyAccess.cpp: 121 (JSC::JIT::emitNotifyWrite): 122 (JSC::JIT::emitPutGlobalVar): 123 * jit/JITPropertyAccess32_64.cpp: 124 (JSC::JIT::emitNotifyWrite): 125 (JSC::JIT::emitPutGlobalVar): 126 * llint/LowLevelInterpreter32_64.asm: 127 * llint/LowLevelInterpreter64.asm: 128 * runtime/JSGlobalObject.cpp: 129 (JSC::JSGlobalObject::addGlobalVar): 130 (JSC::JSGlobalObject::addFunction): 131 * runtime/JSGlobalObject.h: 132 * runtime/JSScope.h: 133 (JSC::ResolveOp::ResolveOp): 134 * runtime/JSSymbolTableObject.h: 135 (JSC::symbolTablePut): 136 (JSC::symbolTablePutWithAttributes): 137 * runtime/SymbolTable.cpp: 138 (JSC::SymbolTableEntry::inferredValue): 139 (JSC::SymbolTableEntry::prepareToWatch): 140 (JSC::SymbolTableEntry::addWatchpoint): 141 (JSC::SymbolTableEntry::notifyWriteSlow): 142 (JSC::SymbolTable::visitChildren): 143 (JSC::SymbolTable::WatchpointCleanup::WatchpointCleanup): 144 (JSC::SymbolTable::WatchpointCleanup::~WatchpointCleanup): 145 (JSC::SymbolTable::WatchpointCleanup::finalizeUnconditionally): 146 * runtime/SymbolTable.h: 147 (JSC::SymbolTableEntry::watchpointSet): 148 (JSC::SymbolTableEntry::notifyWrite): 149 1 150 2013-11-24 Filip Pizlo <fpizlo@apple.com> 2 151 -
trunk/Source/JavaScriptCore/GNUmakefile.list.am
r159642 r159798 182 182 Source/JavaScriptCore/bytecode/ValueRecovery.cpp \ 183 183 Source/JavaScriptCore/bytecode/ValueRecovery.h \ 184 Source/JavaScriptCore/bytecode/VariableWatchpointSet.h \ 184 185 Source/JavaScriptCore/bytecode/VirtualRegister.h \ 185 186 Source/JavaScriptCore/bytecode/Watchpoint.cpp \ -
trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
r159642 r159798 796 796 <ClInclude Include="..\bytecode\ValueProfile.h" /> 797 797 <ClInclude Include="..\bytecode\ValueRecovery.h" /> 798 <ClInclude Include="..\bytecode\VariableWatchpointSet.h" /> 798 799 <ClInclude Include="..\bytecode\VirtualRegister.h" /> 799 800 <ClInclude Include="..\bytecode\Watchpoint.h" /> -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r159642 r159798 301 301 0F8F94441667635400D61971 /* JITCode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8F94431667635200D61971 /* JITCode.cpp */; }; 302 302 0F8F9446166764F100D61971 /* CodeOrigin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8F9445166764EE00D61971 /* CodeOrigin.cpp */; }; 303 0F9181C718415CA50057B669 /* VariableWatchpointSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9181C618415CA50057B669 /* VariableWatchpointSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; 303 304 0F919D0C157EE09F004A4E7D /* JSSymbolTableObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F919D09157EE09D004A4E7D /* JSSymbolTableObject.cpp */; }; 304 305 0F919D0D157EE0A2004A4E7D /* JSSymbolTableObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F919D0A157EE09D004A4E7D /* JSSymbolTableObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 1594 1595 0F8F94431667635200D61971 /* JITCode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITCode.cpp; sourceTree = "<group>"; }; 1595 1596 0F8F9445166764EE00D61971 /* CodeOrigin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeOrigin.cpp; sourceTree = "<group>"; }; 1597 0F9181C618415CA50057B669 /* VariableWatchpointSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VariableWatchpointSet.h; sourceTree = "<group>"; }; 1596 1598 0F919D09157EE09D004A4E7D /* JSSymbolTableObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSymbolTableObject.cpp; sourceTree = "<group>"; }; 1597 1599 0F919D0A157EE09D004A4E7D /* JSSymbolTableObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSymbolTableObject.h; sourceTree = "<group>"; }; … … 4133 4135 0F24E55717F74EDB00ABB217 /* ValueRecovery.cpp */, 4134 4136 0F426A451460CBAB00131F8F /* ValueRecovery.h */, 4137 0F9181C618415CA50057B669 /* VariableWatchpointSet.h */, 4135 4138 0F426A461460CBAB00131F8F /* VirtualRegister.h */, 4136 4139 0F919D2215853CDE004A4E7D /* Watchpoint.cpp */, … … 4376 4379 0FD8A32817D51F5700CA2C40 /* DFGTierUpCheckInjectionPhase.h in Headers */, 4377 4380 0FD8A32A17D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.h in Headers */, 4381 0F9181C718415CA50057B669 /* VariableWatchpointSet.h in Headers */, 4378 4382 0FD8A32C17D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.h in Headers */, 4379 4383 0F63943F15C75F19006A597C /* DFGTypeCheckHoistingPhase.h in Headers */, -
trunk/Source/JavaScriptCore/bytecode/Instruction.h
r159462 r159798 44 44 class ArrayProfile; 45 45 class ObjectAllocationProfile; 46 class VariableWatchpointSet; 46 47 struct LLIntCallLinkInfo; 47 48 struct ValueProfile; … … 116 117 ArrayAllocationProfile* arrayAllocationProfile; 117 118 ObjectAllocationProfile* objectAllocationProfile; 118 WatchpointSet* watchpointSet;119 VariableWatchpointSet* watchpointSet; 119 120 void* pointer; 120 121 bool* predicatePointer; -
trunk/Source/JavaScriptCore/bytecode/Watchpoint.h
r159545 r159798 109 109 } 110 110 111 void notifyWrite()112 {113 if (state() == ClearWatchpoint)114 startWatching();115 else116 fireAll();117 }118 119 111 int8_t* addressOfState() { return &m_state; } 120 112 int8_t* addressOfSetIsNotEmpty() { return &m_setIsNotEmpty; } -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r159545 r159798 1506 1506 break; 1507 1507 1508 case GlobalVarWatchpoint:1508 case VariableWatchpoint: 1509 1509 case VarInjectionWatchpoint: 1510 1510 node->setCanExit(true); … … 1512 1512 1513 1513 case PutGlobalVar: 1514 case Notify PutGlobalVar:1514 case NotifyWrite: 1515 1515 break; 1516 1516 -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r159545 r159798 3095 3095 addToGraph(Phantom, get(VirtualRegister(scope))); 3096 3096 SymbolTableEntry entry = globalObject->symbolTable()->get(uid); 3097 if (!entry.couldBeWatched() || !m_graph.watchpoints().isStillValid(entry.watchpointSet())) { 3097 VariableWatchpointSet* watchpointSet = entry.watchpointSet(); 3098 JSValue specificValue = 3099 watchpointSet ? watchpointSet->inferredValue() : JSValue(); 3100 if (!specificValue) { 3098 3101 set(VirtualRegister(dst), addToGraph(GetGlobalVar, OpInfo(operand), OpInfo(prediction))); 3099 3102 break; 3100 3103 } 3101 3104 3102 addToGraph(GlobalVarWatchpoint, OpInfo(operand), OpInfo(identifierNumber)); 3103 JSValue specificValue = globalObject->registerAt(entry.getIndex()).get(); 3105 addToGraph(VariableWatchpoint, OpInfo(watchpointSet)); 3104 3106 if (specificValue.isCell()) 3105 3107 set(VirtualRegister(dst), cellConstant(specificValue.asCell())); … … 3129 3131 3130 3132 Structure* structure = 0; 3131 WatchpointSet* watchpoints = 0;3133 VariableWatchpointSet* watchpoints = 0; 3132 3134 uintptr_t operand; 3133 3135 { … … 3161 3163 SymbolTableEntry entry = globalObject->symbolTable()->get(uid); 3162 3164 ASSERT(watchpoints == entry.watchpointSet()); 3163 addToGraph(PutGlobalVar, OpInfo(operand), get(VirtualRegister(value))); 3165 Node* valueNode = get(VirtualRegister(value)); 3166 addToGraph(PutGlobalVar, OpInfo(operand), valueNode); 3164 3167 if (watchpoints->state() != IsInvalidated) 3165 addToGraph(Notify PutGlobalVar, OpInfo(operand), OpInfo(identifierNumber));3168 addToGraph(NotifyWrite, OpInfo(watchpoints), valueNode); 3166 3169 // Keep scope alive until after put. 3167 3170 addToGraph(Phantom, get(VirtualRegister(scope))); -
trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
r158384 r159798 261 261 } 262 262 263 bool globalVarWatchpointElimination(WriteBarrier<Unknown>* registerPointer)264 {265 for (unsigned i = m_indexInBlock; i--;) {266 Node* node = m_currentBlock->at(i);267 switch (node->op()) {268 case GlobalVarWatchpoint:269 if (node->registerPointer() == registerPointer)270 return true;271 break;272 case PutGlobalVar:273 if (node->registerPointer() == registerPointer)274 return false;275 break;276 default:277 break;278 }279 if (m_graph.clobbersWorld(node))280 break;281 }282 return false;283 }284 285 263 bool varInjectionWatchpointElimination() 286 264 { … … 1230 1208 } 1231 1209 1232 case GlobalVarWatchpoint:1233 if (cseMode == StoreElimination)1234 break;1235 if (globalVarWatchpointElimination(node->registerPointer()))1236 eliminate();1237 break;1238 1239 1210 case VarInjectionWatchpoint: 1240 1211 if (cseMode == StoreElimination) -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r159545 r159798 144 144 return; 145 145 146 case NotifyPutGlobalVar: 146 case VariableWatchpoint: 147 read(Watchpoint_fire); 148 return; 149 150 case NotifyWrite: 147 151 write(Watchpoint_fire); 152 write(SideState); 148 153 return; 149 154 … … 521 526 522 527 case GetGlobalVar: 523 case GlobalVarWatchpoint:524 528 read(AbstractHeap(Absolute, node->registerPointer())); 525 529 return; -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r159783 r159798 919 919 case GetGlobalVar: 920 920 case PutGlobalVar: 921 case Notify PutGlobalVar:922 case GlobalVarWatchpoint:921 case NotifyWrite: 922 case VariableWatchpoint: 923 923 case VarInjectionWatchpoint: 924 924 case AllocationProfileWatchpoint: -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r159545 r159798 749 749 } 750 750 751 bool hasIdentifierNumberForCheck()752 {753 return op() == GlobalVarWatchpoint || op() == NotifyPutGlobalVar;754 }755 756 unsigned identifierNumberForCheck()757 {758 ASSERT(hasIdentifierNumberForCheck());759 return m_opInfo2;760 }761 762 751 bool hasRegisterPointer() 763 752 { 764 return op() == GetGlobalVar || op() == PutGlobalVar || op() == GlobalVarWatchpoint || op() == NotifyPutGlobalVar;753 return op() == GetGlobalVar || op() == PutGlobalVar; 765 754 } 766 755 … … 974 963 return jsCast<ExecutableBase*>(reinterpret_cast<JSCell*>(m_opInfo)); 975 964 } 965 966 bool hasVariableWatchpointSet() 967 { 968 return op() == NotifyWrite || op() == VariableWatchpoint; 969 } 970 971 VariableWatchpointSet* variableWatchpointSet() 972 { 973 return reinterpret_cast<VariableWatchpointSet*>(m_opInfo); 974 } 976 975 977 976 bool hasStructureTransitionData() -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r159545 r159798 185 185 macro(GetGlobalVar, NodeResultJS) \ 186 186 macro(PutGlobalVar, NodeMustGenerate) \ 187 macro(Notify PutGlobalVar, NodeMustGenerate) \188 macro( GlobalVarWatchpoint, NodeMustGenerate) \187 macro(NotifyWrite, NodeMustGenerate) \ 188 macro(VariableWatchpoint, NodeMustGenerate) \ 189 189 macro(VarInjectionWatchpoint, NodeMustGenerate) \ 190 190 macro(CheckFunction, NodeMustGenerate) \ -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r159545 r159798 999 999 } 1000 1000 1001 void JIT_OPERATION operation NotifyWrite(ExecState* exec,WatchpointSet* set)1002 { 1003 VM& vm = exec->vm(); 1004 NativeCallFrameTracer tracer(&vm, exec); 1005 1006 set-> notifyWrite();1001 void JIT_OPERATION operationInvalidate(ExecState* exec, VariableWatchpointSet* set) 1002 { 1003 VM& vm = exec->vm(); 1004 NativeCallFrameTracer tracer(&vm, exec); 1005 1006 set->invalidate(); 1007 1007 } 1008 1008 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r159545 r159798 126 126 char* JIT_OPERATION operationFindSwitchImmTargetForDouble(ExecState*, EncodedJSValue, size_t tableIndex); 127 127 char* JIT_OPERATION operationSwitchString(ExecState*, size_t tableIndex, JSString*); 128 void JIT_OPERATION operation NotifyWrite(ExecState*,WatchpointSet*);128 void JIT_OPERATION operationInvalidate(ExecState*, VariableWatchpointSet*); 129 129 130 130 #if ENABLE(FTL_JIT) -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r159545 r159798 575 575 case TearOffArguments: 576 576 case CheckArgumentsNotCreated: 577 case GlobalVarWatchpoint:577 case VariableWatchpoint: 578 578 case VarInjectionWatchpoint: 579 579 case AllocationProfileWatchpoint: … … 583 583 case Unreachable: 584 584 case LoopHint: 585 case Notify PutGlobalVar:585 case NotifyWrite: 586 586 break; 587 587 -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r159545 r159798 173 173 case GetGlobalVar: 174 174 case PutGlobalVar: 175 case GlobalVarWatchpoint:175 case VariableWatchpoint: 176 176 case VarInjectionWatchpoint: 177 177 case CheckFunction: … … 243 243 case Int52ToValue: 244 244 case InvalidationPoint: 245 case Notify PutGlobalVar:245 case NotifyWrite: 246 246 return true; 247 247 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r159736 r159798 5601 5601 } 5602 5602 5603 void SpeculativeJIT::compileNotifyPutGlobalVar(Node* node)5604 {5605 WatchpointSet* set = m_jit.globalObjectFor(node->codeOrigin)->symbolTable()->get(5606 m_jit.graph().identifiers()[node->identifierNumberForCheck()]).watchpointSet();5607 5608 GPRTemporary temp(this);5609 GPRReg tempGPR = temp.gpr();5610 5611 m_jit.load8(set->addressOfState(), tempGPR);5612 5613 JITCompiler::JumpList ready;5614 5615 ready.append(m_jit.branch32(JITCompiler::Equal, tempGPR, TrustedImm32(IsInvalidated)));5616 5617 m_jit.memoryFence();5618 5619 if (set->state() == ClearWatchpoint) {5620 JITCompiler::Jump isWatched =5621 m_jit.branch32(JITCompiler::NotEqual, tempGPR, TrustedImm32(ClearWatchpoint));5622 5623 m_jit.store8(TrustedImm32(IsWatched), set->addressOfState());5624 ready.append(m_jit.jump());5625 5626 isWatched.link(&m_jit);5627 }5628 5629 JITCompiler::Jump slowCase = m_jit.branchTest8(5630 JITCompiler::NonZero, JITCompiler::AbsoluteAddress(set->addressOfSetIsNotEmpty()));5631 m_jit.store8(TrustedImm32(IsInvalidated), set->addressOfState());5632 5633 ready.link(&m_jit);5634 5635 addSlowPathGenerator(5636 slowPathCall(slowCase, this, operationNotifyWrite, NoResult, set));5637 5638 noResult(node);5639 }5640 5641 5603 void SpeculativeJIT::addBranch(const MacroAssembler::JumpList& jump, BasicBlock* destination) 5642 5604 { -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r159545 r159798 1085 1085 } 1086 1086 1087 JITCompiler::Call callOperation(V_JITOperation_E W operation,WatchpointSet* watchpointSet)1087 JITCompiler::Call callOperation(V_JITOperation_EVws operation, VariableWatchpointSet* watchpointSet) 1088 1088 { 1089 1089 m_jit.setupArgumentsWithExecState(TrustedImmPtr(watchpointSet)); … … 2045 2045 void compileNewFunctionExpression(Node*); 2046 2046 bool compileRegExpExec(Node*); 2047 2048 void compileNotifyPutGlobalVar(Node*);2049 2047 2050 2048 // size can be an immediate or a register, and must be in bytes. If size is a register, -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r159713 r159798 4072 4072 } 4073 4073 4074 case GlobalVarWatchpoint: { 4075 #if DFG_ENABLE(JIT_ASSERT) 4076 GPRTemporary scratch(this); 4077 GPRReg scratchGPR = scratch.gpr(); 4078 m_jit.load32(node->registerPointer()->tagPointer(), scratchGPR); 4079 JITCompiler::Jump notOK = m_jit.branch32( 4080 JITCompiler::NotEqual, scratchGPR, 4081 TrustedImm32(node->registerPointer()->get().tag())); 4082 m_jit.load32(node->registerPointer()->payloadPointer(), scratchGPR); 4083 JITCompiler::Jump ok = m_jit.branch32( 4084 JITCompiler::Equal, scratchGPR, 4085 TrustedImm32(node->registerPointer()->get().payload())); 4086 notOK.link(&m_jit); 4087 m_jit.breakpoint(); 4088 ok.link(&m_jit); 4089 #endif 4090 4074 case NotifyWrite: { 4075 VariableWatchpointSet* set = node->variableWatchpointSet(); 4076 4077 JSValueOperand value(this, node->child1()); 4078 GPRReg valueTagGPR = value.tagGPR(); 4079 GPRReg valuePayloadGPR = value.payloadGPR(); 4080 4081 GPRTemporary temp(this); 4082 GPRReg tempGPR = temp.gpr(); 4083 4084 m_jit.load8(set->addressOfState(), tempGPR); 4085 4086 JITCompiler::JumpList ready; 4087 4088 ready.append(m_jit.branch32(JITCompiler::Equal, tempGPR, TrustedImm32(IsInvalidated))); 4089 4090 if (set->state() == ClearWatchpoint) { 4091 JITCompiler::Jump isWatched = 4092 m_jit.branch32(JITCompiler::NotEqual, tempGPR, TrustedImm32(ClearWatchpoint)); 4093 4094 m_jit.store32(valueTagGPR, &set->addressOfInferredValue()->u.asBits.tag); 4095 m_jit.store32(valuePayloadGPR, &set->addressOfInferredValue()->u.asBits.payload); 4096 m_jit.store8(TrustedImm32(IsWatched), set->addressOfState()); 4097 ready.append(m_jit.jump()); 4098 4099 isWatched.link(&m_jit); 4100 } 4101 4102 JITCompiler::Jump definitelyNotEqual = m_jit.branch32( 4103 JITCompiler::NotEqual, 4104 JITCompiler::AbsoluteAddress(&set->addressOfInferredValue()->u.asBits.payload), 4105 valuePayloadGPR); 4106 ready.append(m_jit.branch32( 4107 JITCompiler::Equal, 4108 JITCompiler::AbsoluteAddress(&set->addressOfInferredValue()->u.asBits.tag), 4109 valueTagGPR)); 4110 definitelyNotEqual.link(&m_jit); 4111 4112 JITCompiler::Jump slowCase = m_jit.branchTest8( 4113 JITCompiler::NonZero, JITCompiler::AbsoluteAddress(set->addressOfSetIsNotEmpty())); 4114 m_jit.store8(TrustedImm32(IsInvalidated), set->addressOfState()); 4115 m_jit.store32( 4116 TrustedImm32(JSValue::EmptyValueTag), 4117 &set->addressOfInferredValue()->u.asBits.tag); 4118 m_jit.store32( 4119 TrustedImm32(0), &set->addressOfInferredValue()->u.asBits.payload); 4120 4121 ready.link(&m_jit); 4122 4123 addSlowPathGenerator( 4124 slowPathCall(slowCase, this, operationInvalidate, NoResult, set)); 4125 4091 4126 noResult(node); 4092 4127 break; 4093 4128 } 4094 4129 4095 case NotifyPutGlobalVar: { 4096 compileNotifyPutGlobalVar(node); 4097 break; 4098 } 4099 4100 case VarInjectionWatchpoint: { 4130 case VarInjectionWatchpoint: 4131 case VariableWatchpoint: { 4101 4132 noResult(node); 4102 4133 break; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r159713 r159798 4354 4354 } 4355 4355 4356 case GlobalVarWatchpoint: { 4357 #if DFG_ENABLE(JIT_ASSERT) 4358 GPRTemporary scratch(this); 4359 GPRReg scratchGPR = scratch.gpr(); 4360 m_jit.load64(node->registerPointer(), scratchGPR); 4361 JITCompiler::Jump ok = m_jit.branch64( 4362 JITCompiler::Equal, scratchGPR, 4363 TrustedImm64(JSValue::encode(node->registerPointer()->get()))); 4364 m_jit.breakpoint(); 4365 ok.link(&m_jit); 4366 #endif 4367 4356 case NotifyWrite: { 4357 VariableWatchpointSet* set = node->variableWatchpointSet(); 4358 4359 JSValueOperand value(this, node->child1()); 4360 GPRReg valueGPR = value.gpr(); 4361 4362 GPRTemporary temp(this); 4363 GPRReg tempGPR = temp.gpr(); 4364 4365 m_jit.load8(set->addressOfState(), tempGPR); 4366 4367 JITCompiler::JumpList ready; 4368 4369 ready.append(m_jit.branch32(JITCompiler::Equal, tempGPR, TrustedImm32(IsInvalidated))); 4370 4371 if (set->state() == ClearWatchpoint) { 4372 JITCompiler::Jump isWatched = 4373 m_jit.branch32(JITCompiler::NotEqual, tempGPR, TrustedImm32(ClearWatchpoint)); 4374 4375 m_jit.store64(valueGPR, set->addressOfInferredValue()); 4376 m_jit.store8(TrustedImm32(IsWatched), set->addressOfState()); 4377 ready.append(m_jit.jump()); 4378 4379 isWatched.link(&m_jit); 4380 } 4381 4382 ready.append(m_jit.branch64( 4383 JITCompiler::Equal, 4384 JITCompiler::AbsoluteAddress(set->addressOfInferredValue()), valueGPR)); 4385 4386 JITCompiler::Jump slowCase = m_jit.branchTest8( 4387 JITCompiler::NonZero, JITCompiler::AbsoluteAddress(set->addressOfSetIsNotEmpty())); 4388 m_jit.store8(TrustedImm32(IsInvalidated), set->addressOfState()); 4389 m_jit.move(TrustedImm64(JSValue::encode(JSValue())), tempGPR); 4390 m_jit.store64(tempGPR, set->addressOfInferredValue()); 4391 4392 ready.link(&m_jit); 4393 4394 addSlowPathGenerator( 4395 slowPathCall(slowCase, this, operationInvalidate, NoResult, set)); 4396 4368 4397 noResult(node); 4369 4398 break; 4370 4399 } 4371 4372 case NotifyPutGlobalVar: { 4373 compileNotifyPutGlobalVar(node); 4374 break; 4375 } 4376 4377 case VarInjectionWatchpoint: { 4400 4401 case VarInjectionWatchpoint: 4402 case VariableWatchpoint: { 4378 4403 noResult(node); 4379 4404 break; -
trunk/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp
r158304 r159798 119 119 break; 120 120 121 case GlobalVarWatchpoint: 122 addLazily( 123 globalObject()->symbolTable()->get( 124 m_graph.identifiers()[m_node->identifierNumberForCheck()]).watchpointSet()); 121 case VariableWatchpoint: 122 addLazily(m_node->variableWatchpointSet()); 125 123 break; 126 124 -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r159545 r159798 70 70 case GetGlobalVar: 71 71 case PutGlobalVar: 72 case NotifyPutGlobalVar:73 72 case ValueAdd: 74 73 case ArithAdd: … … 93 92 case Call: 94 93 case Construct: 95 case GlobalVarWatchpoint:96 94 case GetMyScope: 97 95 case SkipScope: … … 105 103 case StringCharCodeAt: 106 104 case AllocatePropertyStorage: 105 case VariableWatchpoint: 106 case NotifyWrite: 107 107 // These are OK. 108 108 break; -
trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h
r159545 r159798 66 66 macro(V_JITOperation_EOZD, functionType(voidType, intPtr, intPtr, int32, doubleType)) \ 67 67 macro(V_JITOperation_EOZJ, functionType(voidType, intPtr, intPtr, int32, int64)) \ 68 macro(V_JITOperation_E W, functionType(voidType, intPtr, intPtr)) \68 macro(V_JITOperation_EVws, functionType(voidType, intPtr, intPtr)) \ 69 69 macro(Z_JITOperation_D, functionType(int32, doubleType)) 70 70 -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
r159721 r159798 395 395 compilePutGlobalVar(); 396 396 break; 397 case NotifyPutGlobalVar: 398 compileNotifyPutGlobalVar(); 399 break; 400 case GlobalVarWatchpoint: 401 compileGlobalVarWatchpoint(); 397 case NotifyWrite: 398 compileNotifyWrite(); 399 break; 400 case VariableWatchpoint: 402 401 break; 403 402 case GetMyScope: … … 2118 2117 } 2119 2118 2120 void compileNotifyPutGlobalVar() 2121 { 2122 WatchpointSet* set = m_graph.globalObjectFor(m_node->codeOrigin)->symbolTable()->get( 2123 m_graph.identifiers()[m_node->identifierNumberForCheck()]).watchpointSet(); 2124 2125 LBasicBlock isNotInvalidated = FTL_NEW_BLOCK(m_out, ("NotifyPutGlobalVar not invalidated case")); 2126 LBasicBlock isClear = FTL_NEW_BLOCK(m_out, ("NotifyPutGlobalVar clear case")); 2127 LBasicBlock isWatched = FTL_NEW_BLOCK(m_out, ("NotifyPutGlobalVar watched case")); 2128 LBasicBlock isWatchedFast = FTL_NEW_BLOCK(m_out, ("NotifyPutGlobalVar watched fast case")); 2129 LBasicBlock isWatchedSlow = FTL_NEW_BLOCK(m_out, ("NotifyPutGlobalVar watched slow case")); 2130 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("NotifyPutGlobalVar continuation")); 2119 void compileNotifyWrite() 2120 { 2121 VariableWatchpointSet* set = m_node->variableWatchpointSet(); 2122 2123 LValue value = lowJSValue(m_node->child1()); 2124 2125 LBasicBlock isNotInvalidated = FTL_NEW_BLOCK(m_out, ("NotifyWrite not invalidated case")); 2126 LBasicBlock isClear = FTL_NEW_BLOCK(m_out, ("NotifyWrite clear case")); 2127 LBasicBlock isWatched = FTL_NEW_BLOCK(m_out, ("NotifyWrite watched case")); 2128 LBasicBlock invalidate = FTL_NEW_BLOCK(m_out, ("NotifyWrite invalidate case")); 2129 LBasicBlock invalidateFast = FTL_NEW_BLOCK(m_out, ("NotifyWrite invalidate fast case")); 2130 LBasicBlock invalidateSlow = FTL_NEW_BLOCK(m_out, ("NotifyWrite invalidate slow case")); 2131 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("NotifyWrite continuation")); 2131 2132 2132 2133 LValue state = m_out.load8(m_out.absolute(set->addressOfState())); … … 2138 2139 LBasicBlock lastNext = m_out.appendTo(isNotInvalidated, isClear); 2139 2140 2140 m_out.fenceAcqRel();2141 2142 2141 LValue isClearValue; 2143 2142 if (set->state() == ClearWatchpoint) … … 2149 2148 m_out.appendTo(isClear, isWatched); 2150 2149 2150 m_out.store64(value, m_out.absolute(set->addressOfInferredValue())); 2151 2151 m_out.store8(m_out.constInt8(IsWatched), m_out.absolute(set->addressOfState())); 2152 2152 m_out.jump(continuation); 2153 2153 2154 m_out.appendTo(isWatched, isWatchedFast); 2154 m_out.appendTo(isWatched, invalidate); 2155 2156 m_out.branch( 2157 m_out.equal(value, m_out.load64(m_out.absolute(set->addressOfInferredValue()))), 2158 continuation, invalidate); 2159 2160 m_out.appendTo(invalidate, invalidateFast); 2155 2161 2156 2162 m_out.branch( 2157 2163 m_out.notZero8(m_out.load8(m_out.absolute(set->addressOfSetIsNotEmpty()))), 2158 isWatchedSlow, isWatchedFast); 2159 2160 m_out.appendTo(isWatchedFast, isWatchedSlow); 2161 2164 invalidateSlow, invalidateFast); 2165 2166 m_out.appendTo(invalidateFast, invalidateSlow); 2167 2168 m_out.store64( 2169 m_out.constInt64(JSValue::encode(JSValue())), 2170 m_out.absolute(set->addressOfInferredValue())); 2162 2171 m_out.store8(m_out.constInt8(IsInvalidated), m_out.absolute(set->addressOfState())); 2163 2172 m_out.jump(continuation); 2164 2173 2165 m_out.appendTo(i sWatchedSlow, continuation);2166 2167 vmCall(m_out.operation(operation NotifyWrite), m_callFrame, m_out.constIntPtr(set));2174 m_out.appendTo(invalidateSlow, continuation); 2175 2176 vmCall(m_out.operation(operationInvalidate), m_callFrame, m_out.constIntPtr(set)); 2168 2177 m_out.jump(continuation); 2169 2178 2170 2179 m_out.appendTo(continuation, lastNext); 2171 }2172 2173 void compileGlobalVarWatchpoint()2174 {2175 // FIXME: In debug mode we could emit some assertion code here.2176 // https://bugs.webkit.org/show_bug.cgi?id=1234712177 2180 } 2178 2181 -
trunk/Source/JavaScriptCore/jit/JIT.h
r159721 r159798 619 619 void emitGetClosureVar(int scope, uintptr_t operand); 620 620 void emitPutGlobalProperty(uintptr_t* operandSlot, int value); 621 void emitPutGlobalVar(uintptr_t operand, int value, WatchpointSet*); 621 #if USE(JSVALUE64) 622 void emitNotifyWrite(RegisterID value, RegisterID scratch, VariableWatchpointSet*); 623 #else 624 void emitNotifyWrite(RegisterID tag, RegisterID payload, RegisterID scratch, VariableWatchpointSet*); 625 #endif 626 void emitPutGlobalVar(uintptr_t operand, int value, VariableWatchpointSet*); 622 627 void emitPutClosureVar(int scope, uintptr_t operand, int value); 623 628 -
trunk/Source/JavaScriptCore/jit/JITOperations.h
r159545 r159798 36 36 #include "PutKind.h" 37 37 #include "StructureStubInfo.h" 38 #include " Watchpoint.h"38 #include "VariableWatchpointSet.h" 39 39 40 40 namespace JSC { … … 77 77 V: void 78 78 Vm: VM* 79 W:WatchpointSet*79 Vws: VariableWatchpointSet* 80 80 Z: int32_t 81 81 */ … … 155 155 typedef void JIT_OPERATION (*V_JITOperation_EPZJ)(ExecState*, void*, int32_t, EncodedJSValue); 156 156 typedef void JIT_OPERATION (*V_JITOperation_ESsiJJI)(ExecState*, StructureStubInfo*, EncodedJSValue, EncodedJSValue, StringImpl*); 157 typedef void JIT_OPERATION (*V_JITOperation_E W)(ExecState*,WatchpointSet*);157 typedef void JIT_OPERATION (*V_JITOperation_EVws)(ExecState*, VariableWatchpointSet*); 158 158 typedef void JIT_OPERATION (*V_JITOperation_EZ)(ExecState*, int32_t); 159 159 typedef void JIT_OPERATION (*V_JITOperation_EVm)(ExecState*, VM*); -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
r159545 r159798 772 772 } 773 773 774 void JIT::emitPutGlobalVar(uintptr_t operand, int value, WatchpointSet* set) 775 { 776 if (set && set->state() != IsInvalidated) { 777 load8(set->addressOfState(), regT1); 774 void JIT::emitNotifyWrite(RegisterID value, RegisterID scratch, VariableWatchpointSet* set) 775 { 776 if (!set || set->state() == IsInvalidated) 777 return; 778 779 load8(set->addressOfState(), scratch); 780 781 JumpList ready; 782 783 ready.append(branch32(Equal, scratch, TrustedImm32(IsInvalidated))); 784 785 if (set->state() == ClearWatchpoint) { 786 Jump isWatched = branch32(NotEqual, scratch, TrustedImm32(ClearWatchpoint)); 778 787 779 JumpList ready; 788 store64(value, set->addressOfInferredValue()); 789 store8(TrustedImm32(IsWatched), set->addressOfState()); 790 ready.append(jump()); 780 791 781 ready.append(branch32(Equal, regT1, TrustedImm32(IsInvalidated))); 782 783 if (set->state() == ClearWatchpoint) { 784 Jump isWatched = branch32(NotEqual, regT1, TrustedImm32(ClearWatchpoint)); 785 786 move(TrustedImm32(IsWatched), regT1); 787 ready.append(jump()); 788 789 isWatched.link(this); 790 } 791 792 addSlowCase(branchTest8(NonZero, AbsoluteAddress(set->addressOfSetIsNotEmpty()))); 793 move(TrustedImm32(IsInvalidated), regT1); 794 ready.link(this); 795 } 796 792 isWatched.link(this); 793 } 794 795 ready.append(branch64(Equal, AbsoluteAddress(set->addressOfInferredValue()), value)); 796 addSlowCase(branchTest8(NonZero, AbsoluteAddress(set->addressOfSetIsNotEmpty()))); 797 store8(TrustedImm32(IsInvalidated), set->addressOfState()); 798 move(TrustedImm64(JSValue::encode(JSValue())), scratch); 799 store64(scratch, set->addressOfInferredValue()); 800 801 ready.link(this); 802 } 803 804 void JIT::emitPutGlobalVar(uintptr_t operand, int value, VariableWatchpointSet* set) 805 { 797 806 emitGetVirtualRegister(value, regT0); 807 emitNotifyWrite(regT0, regT1, set); 798 808 storePtr(regT0, reinterpret_cast<void*>(operand)); 799 800 if (set && set->state() != IsInvalidated) {801 memoryFence();802 store8(regT1, set->addressOfState());803 }804 809 } 805 810 -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
r159545 r159798 808 808 } 809 809 810 void JIT::emitPutGlobalVar(uintptr_t operand, int value, WatchpointSet* set) 811 { 812 if (set && set->state() != IsInvalidated) { 813 load8(set->addressOfState(), regT2); 810 void JIT::emitNotifyWrite(RegisterID tag, RegisterID payload, RegisterID scratch, VariableWatchpointSet* set) 811 { 812 if (!set || set->state() == IsInvalidated) 813 return; 814 815 load8(set->addressOfState(), scratch); 816 817 JumpList ready; 818 819 ready.append(branch32(Equal, scratch, TrustedImm32(IsInvalidated))); 820 821 if (set->state() == ClearWatchpoint) { 822 Jump isWatched = branch32(NotEqual, scratch, TrustedImm32(ClearWatchpoint)); 814 823 815 JumpList ready; 824 store32(tag, &set->addressOfInferredValue()->u.asBits.tag); 825 store32(payload, &set->addressOfInferredValue()->u.asBits.payload); 826 store8(TrustedImm32(IsWatched), set->addressOfState()); 827 ready.append(jump()); 816 828 817 ready.append(branch32(Equal, regT2, TrustedImm32(IsInvalidated))); 818 819 if (set->state() == ClearWatchpoint) { 820 Jump isWatched = branch32(NotEqual, regT2, TrustedImm32(ClearWatchpoint)); 821 822 move(TrustedImm32(IsWatched), regT2); 823 ready.append(jump()); 824 825 isWatched.link(this); 826 } 827 828 addSlowCase(branchTest8(NonZero, AbsoluteAddress(set->addressOfSetIsNotEmpty()))); 829 move(TrustedImm32(IsInvalidated), regT2); 830 ready.link(this); 831 } 832 829 isWatched.link(this); 830 } 831 832 Jump definitelyNotEqual = branch32( 833 NotEqual, AbsoluteAddress(&set->addressOfInferredValue()->u.asBits.payload), payload); 834 ready.append(branch32( 835 Equal, AbsoluteAddress(&set->addressOfInferredValue()->u.asBits.tag), tag)); 836 definitelyNotEqual.link(this); 837 addSlowCase(branchTest8(NonZero, AbsoluteAddress(set->addressOfSetIsNotEmpty()))); 838 store8(TrustedImm32(IsInvalidated), set->addressOfState()); 839 store32( 840 TrustedImm32(JSValue::EmptyValueTag), &set->addressOfInferredValue()->u.asBits.tag); 841 store32(TrustedImm32(0), &set->addressOfInferredValue()->u.asBits.payload); 842 843 ready.link(this); 844 } 845 846 void JIT::emitPutGlobalVar(uintptr_t operand, int value, VariableWatchpointSet* set) 847 { 833 848 emitLoad(value, regT1, regT0); 849 emitNotifyWrite(regT1, regT0, regT2, set); 834 850 store32(regT1, reinterpret_cast<char*>(operand) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)); 835 851 store32(regT0, reinterpret_cast<char*>(operand) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)); 836 837 if (set && set->state() != IsInvalidated) {838 memoryFence();839 store8(regT1, set->addressOfState());840 }841 852 } 842 853 -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
r159545 r159798 2133 2133 end 2134 2134 2135 macro notifyWrite(set, valueTag, valuePayload, scratch, slow) 2136 loadb VariableWatchpointSet::m_state[set], scratch 2137 bieq scratch, IsInvalidated, .done 2138 bineq scratch, ClearWatchpoint, .overwrite 2139 storei valueTag, VariableWatchpointSet::m_inferredValue + TagOffset[set] 2140 storei valuePayload, VariableWatchpointSet::m_inferredValue + PayloadOffset[set] 2141 storeb IsWatched, VariableWatchpointSet::m_state[set] 2142 jmp .done 2143 2144 .overwrite: 2145 bineq valuePayload, VariableWatchpointSet::m_inferredValue + PayloadOffset[set], .definitelyDifferent 2146 bieq valueTag, VariableWatchpointSet::m_inferredValue + TagOffset[set], .done 2147 .definitelyDifferent: 2148 btbnz VariableWatchpointSet::m_setIsNotEmpty[set], slow 2149 storei EmptyValueTag, VariableWatchpointSet::m_inferredValue + TagOffset[set] 2150 storei 0, VariableWatchpointSet::m_inferredValue + PayloadOffset[set] 2151 storeb IsInvalidated, VariableWatchpointSet::m_state[set] 2152 2153 .done: 2154 end 2155 2135 2156 macro putGlobalVar() 2136 loadpFromInstruction(5, t2)2137 loadb WatchpointSet::m_state[t2], t32138 bieq t3, IsInvalidated, .ready2139 bineq t3, ClearWatchpoint, .needToInvalidate2140 move IsWatched, t32141 jmp .ready2142 .needToInvalidate:2143 btbnz WatchpointSet::m_setIsNotEmpty[t2], .pDynamic2144 move IsInvalidated, t32145 .ready:2146 2157 loadisFromInstruction(3, t0) 2147 2158 loadConstantOrVariable(t0, t1, t2) 2159 loadpFromInstruction(5, t3) 2160 notifyWrite(t3, t1, t2, t0, .pDynamic) 2148 2161 loadpFromInstruction(6, t0) 2149 2162 storei t1, TagOffset[t0] 2150 2163 storei t2, PayloadOffset[t0] 2151 memfence2152 loadpFromInstruction(5, t2)2153 storeb t3, WatchpointSet::m_state[t2]2154 2164 end 2155 2165 -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r159655 r159798 1953 1953 end 1954 1954 1955 macro notifyWrite(set, value, scratch, slow) 1956 loadb VariableWatchpointSet::m_state[set], scratch 1957 bieq scratch, IsInvalidated, .done 1958 bineq scratch, ClearWatchpoint, .overwrite 1959 storeq value, VariableWatchpointSet::m_inferredValue[set] 1960 storeb IsWatched, VariableWatchpointSet::m_state[set] 1961 jmp .done 1962 1963 .overwrite: 1964 bqeq value, VariableWatchpointSet::m_inferredValue[set], .done 1965 btbnz VariableWatchpointSet::m_setIsNotEmpty[set], slow 1966 storeq 0, VariableWatchpointSet::m_inferredValue[set] 1967 storeb IsInvalidated, VariableWatchpointSet::m_state[set] 1968 1969 .done: 1970 end 1971 1955 1972 macro putGlobalVar() 1956 loadpFromInstruction(5, t2)1957 loadb WatchpointSet::m_state[t2], t31958 bieq t3, IsInvalidated, .ready1959 bineq t3, ClearWatchpoint, .needToInvalidate1960 move IsWatched, t31961 jmp .ready1962 .needToInvalidate:1963 btbnz WatchpointSet::m_setIsNotEmpty[t2], .pDynamic1964 move IsInvalidated, t31965 .ready:1966 1973 loadisFromInstruction(3, t0) 1967 1974 loadConstantOrVariable(t0, t1) 1975 loadpFromInstruction(5, t2) 1976 notifyWrite(t2, t1, t0, .pDynamic) 1968 1977 loadpFromInstruction(6, t0) 1969 1978 storeq t1, [t0] 1970 memfence1971 storeb t3, WatchpointSet::m_state[t2]1972 1979 end 1973 1980 -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r159605 r159798 217 217 SymbolTableEntry newEntry(index, (constantMode == IsConstant) ? ReadOnly : 0); 218 218 if (constantMode == IsVariable) 219 newEntry.prepareToWatch( SymbolTableEntry::NotInitialized);219 newEntry.prepareToWatch(); 220 220 SymbolTable::Map::AddResult result = symbolTable()->add(locker, ident.impl(), newEntry); 221 221 if (result.isNewEntry) … … 235 235 registerAt(var.registerNumber).set(exec->vm(), this, value); 236 236 if (var.set) 237 var.set->notifyWrite( );237 var.set->notifyWrite(value); 238 238 } 239 239 -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h
r159605 r159798 292 292 struct NewGlobalVar { 293 293 int registerNumber; 294 WatchpointSet* set;294 VariableWatchpointSet* set; 295 295 }; 296 296 NewGlobalVar addGlobalVar(const Identifier&, ConstantMode); -
trunk/Source/JavaScriptCore/runtime/JSScope.h
r159462 r159798 32 32 33 33 class ScopeChainIterator; 34 class WatchpointSet;34 class VariableWatchpointSet; 35 35 36 36 enum ResolveMode { … … 97 97 98 98 struct ResolveOp { 99 ResolveOp(ResolveType type, size_t depth, Structure* structure, WatchpointSet* watchpointSet, uintptr_t operand)99 ResolveOp(ResolveType type, size_t depth, Structure* structure, VariableWatchpointSet* watchpointSet, uintptr_t operand) 100 100 : type(type) 101 101 , depth(depth) … … 109 109 size_t depth; 110 110 Structure* structure; 111 WatchpointSet* watchpointSet;111 VariableWatchpointSet* watchpointSet; 112 112 uintptr_t operand; 113 113 }; -
trunk/Source/JavaScriptCore/runtime/JSSymbolTableObject.h
r159713 r159798 124 124 125 125 WriteBarrierBase<Unknown>* reg; 126 WatchpointSet* set = 0;127 126 { 128 127 SymbolTable& symbolTable = *object->symbolTable(); … … 139 138 return true; 140 139 } 141 set = iter->value.watchpointSet(); 140 if (VariableWatchpointSet* set = iter->value.watchpointSet()) 141 set->notifyWrite(value); 142 142 reg = &object->registerAt(fastEntry.getIndex()); 143 143 } … … 146 146 // locks while GC'ing. 147 147 reg->set(vm, object, value); 148 if (set)149 set->notifyWrite();150 148 return true; 151 149 } … … 159 157 160 158 WriteBarrierBase<Unknown>* reg; 161 WatchpointSet* set = 0;162 159 { 163 160 SymbolTable& symbolTable = *object->symbolTable(); … … 168 165 SymbolTableEntry& entry = iter->value; 169 166 ASSERT(!entry.isNull()); 170 set = entry.watchpointSet(); 167 if (VariableWatchpointSet* set = entry.watchpointSet()) 168 set->notifyWrite(value); 171 169 entry.setAttributes(attributes); 172 170 reg = &object->registerAt(entry.getIndex()); 173 171 } 174 172 reg->set(vm, object, value); 175 if (set)176 set->notifyWrite();177 173 return true; 178 174 } -
trunk/Source/JavaScriptCore/runtime/SymbolTable.cpp
r159795 r159798 59 59 } 60 60 61 bool SymbolTableEntry::couldBeWatched()61 JSValue SymbolTableEntry::inferredValue() 62 62 { 63 63 if (!isFat()) 64 return false; 65 WatchpointSet* watchpoints = fatEntry()->m_watchpoints.get(); 66 if (!watchpoints) 67 return false; 68 return watchpoints->state() == IsWatched; 64 return JSValue(); 65 return fatEntry()->m_watchpoints->inferredValue(); 69 66 } 70 67 71 void SymbolTableEntry::prepareToWatch( WatchState state)68 void SymbolTableEntry::prepareToWatch() 72 69 { 73 70 FatEntry* entry = inflate(); 74 71 ASSERT(!entry->m_watchpoints); 75 entry->m_watchpoints = adoptRef( 76 new WatchpointSet(state == AlreadyInitialized ? IsWatched : ClearWatchpoint)); 72 entry->m_watchpoints = adoptRef(new VariableWatchpointSet()); 77 73 } 78 74 79 75 void SymbolTableEntry::addWatchpoint(Watchpoint* watchpoint) 80 76 { 81 ASSERT(couldBeWatched());82 77 fatEntry()->m_watchpoints->add(watchpoint); 83 78 } 84 79 85 void SymbolTableEntry::notifyWriteSlow( )80 void SymbolTableEntry::notifyWriteSlow(JSValue value) 86 81 { 87 WatchpointSet* watchpoints = fatEntry()->m_watchpoints.get();82 VariableWatchpointSet* watchpoints = fatEntry()->m_watchpoints.get(); 88 83 if (!watchpoints) 89 84 return; 90 85 91 watchpoints->notifyWrite( );86 watchpoints->notifyWrite(value); 92 87 } 93 88 … … 109 104 110 105 SymbolTable::~SymbolTable() { } 106 107 void SymbolTable::visitChildren(JSCell* thisCell, SlotVisitor& visitor) 108 { 109 SymbolTable* thisSymbolTable = jsCast<SymbolTable*>(thisCell); 110 if (!thisSymbolTable->m_watchpointCleanup) { 111 thisSymbolTable->m_watchpointCleanup = 112 std::make_unique<WatchpointCleanup>(thisSymbolTable); 113 } 114 115 visitor.addUnconditionalFinalizer(thisSymbolTable->m_watchpointCleanup.get()); 116 } 117 118 SymbolTable::WatchpointCleanup::WatchpointCleanup(SymbolTable* symbolTable) 119 : m_symbolTable(symbolTable) 120 { 121 } 122 123 SymbolTable::WatchpointCleanup::~WatchpointCleanup() { } 124 125 void SymbolTable::WatchpointCleanup::finalizeUnconditionally() 126 { 127 Map::iterator iter = m_symbolTable->m_map.begin(); 128 Map::iterator end = m_symbolTable->m_map.end(); 129 for (; iter != end; ++iter) { 130 if (VariableWatchpointSet* set = iter->value.watchpointSet()) 131 set->finalizeUnconditionally(); 132 } 133 } 111 134 112 135 SymbolTable* SymbolTable::clone(VM& vm) -
trunk/Source/JavaScriptCore/runtime/SymbolTable.h
r159795 r159798 32 32 #include "ConcurrentJITLock.h" 33 33 #include "JSObject.h" 34 #include " Watchpoint.h"34 #include "VariableWatchpointSet.h" 35 35 #include <memory> 36 36 #include <wtf/HashTraits.h> … … 38 38 39 39 namespace JSC { 40 41 class Watchpoint;42 class WatchpointSet;43 40 44 41 struct SlowArgument { … … 80 77 // WatchpointSet will manifest in all copies. Here's a picture: 81 78 // 82 // SymbolTableEntry --> FatEntry --> WatchpointSet79 // SymbolTableEntry --> FatEntry --> VariableWatchpointSet 83 80 // 84 81 // If you make a copy of a SymbolTableEntry, you will have: 85 82 // 86 // original: SymbolTableEntry --> FatEntry --> WatchpointSet83 // original: SymbolTableEntry --> FatEntry --> VariableWatchpointSet 87 84 // copy: SymbolTableEntry --> FatEntry -----^ 88 85 … … 219 216 } 220 217 221 bool couldBeWatched(); 222 223 enum WatchState { NotInitialized, AlreadyInitialized }; 224 void prepareToWatch(WatchState); 218 JSValue inferredValue(); 219 220 void prepareToWatch(); 225 221 226 222 void addWatchpoint(Watchpoint*); 227 223 228 WatchpointSet* watchpointSet()224 VariableWatchpointSet* watchpointSet() 229 225 { 230 226 if (!isFat()) … … 233 229 } 234 230 235 ALWAYS_INLINE void notifyWrite( )231 ALWAYS_INLINE void notifyWrite(JSValue value) 236 232 { 237 233 if (LIKELY(!isFat())) 238 234 return; 239 notifyWriteSlow( );235 notifyWriteSlow(value); 240 236 } 241 237 … … 257 253 intptr_t m_bits; // always has FatFlag set and exactly matches what the bits would have been if this wasn't fat. 258 254 259 RefPtr< WatchpointSet> m_watchpoints;255 RefPtr<VariableWatchpointSet> m_watchpoints; 260 256 }; 261 257 262 258 SymbolTableEntry& copySlow(const SymbolTableEntry&); 263 JS_EXPORT_PRIVATE void notifyWriteSlow( );259 JS_EXPORT_PRIVATE void notifyWriteSlow(JSValue); 264 260 265 261 bool isFat() const … … 469 465 SymbolTable* clone(VM&); 470 466 467 static void visitChildren(JSCell*, SlotVisitor&); 468 471 469 DECLARE_EXPORT_INFO; 472 470 473 471 private: 472 class WatchpointCleanup : public UnconditionalFinalizer { 473 public: 474 WatchpointCleanup(SymbolTable*); 475 virtual ~WatchpointCleanup(); 476 477 protected: 478 virtual void finalizeUnconditionally() OVERRIDE; 479 480 private: 481 SymbolTable* m_symbolTable; 482 }; 483 474 484 JS_EXPORT_PRIVATE SymbolTable(VM&); 475 485 ~SymbolTable(); … … 484 494 485 495 std::unique_ptr<SlowArgument[]> m_slowArguments; 496 497 std::unique_ptr<WatchpointCleanup> m_watchpointCleanup; 486 498 487 499 public:
Note: See TracChangeset
for help on using the changeset viewer.