Changeset 168443 in webkit
- Timestamp:
- May 7, 2014 3:00:10 PM (10 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 1 added
- 26 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r168406 r168443 1 2014-05-07 Mark Lam <mark.lam@apple.com> 2 3 REGRESSION(r166678): Dromaeo/cssquery-dojo.html crashes regularly. 4 <https://webkit.org/b/131356> 5 6 Reviewed by Geoffrey Garen. 7 8 The issue is that GC needs to be made aware of writes to m_inferredValue 9 in the VariableWatchpointSet, but was not. As a result, if a JSCell* 10 is written to a VariableWatchpointSet m_inferredValue, and that JSCell 11 does not survive an eden GC shortly after, we will end up with a stale 12 JSCell pointer left in the m_inferredValue. 13 14 This issue can be detected more easily by running Dromaeo/cssquery-dojo.html 15 using DumpRenderTree with the VM heap in zombie mode. 16 17 The fix is to change VariableWatchpointSet m_inferredValue to type 18 WriteBarrier<Unknown> and ensure that VariableWatchpointSet::notifyWrite() 19 is executed by all the execution engines so that the WriteBarrier semantics 20 are honored. 21 22 We still check if the value to be written is the same as the one in the 23 inferredValue. We'll by-pass calling the slow path notifyWrite() if the 24 values are the same. 25 26 * JavaScriptCore.xcodeproj/project.pbxproj: 27 * bytecode/CodeBlock.cpp: 28 (JSC::CodeBlock::CodeBlock): 29 - need to pass the symbolTable to prepareToWatch() because it will be needed 30 for instantiating the VariableWatchpointSet in prepareToWatch(). 31 32 * bytecode/VariableWatchpointSet.h: 33 (JSC::VariableWatchpointSet::VariableWatchpointSet): 34 - VariableWatchpointSet now tracks its owner symbol table for its m_inferredValue 35 write barrier, and yes, m_inferredValue is now of type WriteBarrier<Unknown>. 36 (JSC::VariableWatchpointSet::inferredValue): 37 (JSC::VariableWatchpointSet::invalidate): 38 (JSC::VariableWatchpointSet::finalizeUnconditionally): 39 (JSC::VariableWatchpointSet::addressOfInferredValue): 40 (JSC::VariableWatchpointSet::notifyWrite): Deleted. 41 * bytecode/VariableWatchpointSetInlines.h: Added. 42 (JSC::VariableWatchpointSet::notifyWrite): 43 44 * dfg/DFGByteCodeParser.cpp: 45 (JSC::DFG::ByteCodeParser::cellConstant): 46 - Added an assert in case we try to make constants of zombified JSCells again. 47 48 * dfg/DFGOperations.cpp: 49 * dfg/DFGOperations.h: 50 * dfg/DFGSpeculativeJIT.h: 51 (JSC::DFG::SpeculativeJIT::callOperation): 52 * dfg/DFGSpeculativeJIT32_64.cpp: 53 (JSC::DFG::SpeculativeJIT::compile): 54 * dfg/DFGSpeculativeJIT64.cpp: 55 (JSC::DFG::SpeculativeJIT::compile): 56 - We now let the slow path handle the cases when the VariableWatchpointSet is 57 in state ClearWatchpoint and IsWatched, and the slow path will ensure that 58 we handle the needed write barrier semantics correctly. 59 We will by-pass the slow path if the value being written is the same as the 60 inferred value. 61 62 * ftl/FTLIntrinsicRepository.h: 63 * ftl/FTLLowerDFGToLLVM.cpp: 64 (JSC::FTL::LowerDFGToLLVM::compileNotifyWrite): 65 - Let the slow path handle the cases when the VariableWatchpointSet is 66 in state ClearWatchpoint and IsWatched. 67 We will by-pass the slow path if the value being written is the same as the 68 inferred value. 69 70 * heap/Heap.cpp: 71 (JSC::Zombify::operator()): 72 - Use a different value for the zombified bits (to distinguish it from 0xbbadbeef 73 which is used everywhere else). 74 * heap/Heap.h: 75 (JSC::Heap::isZombified): 76 - Provide a convenience test function to check if JSCells are zombified. This is 77 currently only used in an assertion in the DFG bytecode parser, but the intent 78 it that we'll apply this test in other strategic places later to help with early 79 detection of usage of GC'ed objects when we run in zombie mode. 80 81 * jit/JITOpcodes.cpp: 82 (JSC::JIT::emitSlow_op_captured_mov): 83 * jit/JITOperations.h: 84 * jit/JITPropertyAccess.cpp: 85 (JSC::JIT::emitNotifyWrite): 86 * jit/JITPropertyAccess32_64.cpp: 87 (JSC::JIT::emitNotifyWrite): 88 (JSC::JIT::emitSlow_op_put_to_scope): 89 - Let the slow path for notifyWrite handle the cases when the VariableWatchpointSet 90 is in state ClearWatchpoint and IsWatched. 91 We will by-pass the slow path if the value being written is the same as the 92 inferred value. 93 94 * llint/LowLevelInterpreter32_64.asm: 95 * llint/LowLevelInterpreter64.asm: 96 - Let the slow path for notifyWrite handle the cases when the VariableWatchpointSet 97 is in state ClearWatchpoint and IsWatched. 98 We will by-pass the slow path if the value being written is the same as the 99 inferred value. 100 101 * runtime/CommonSlowPaths.cpp: 102 103 * runtime/JSCJSValue.h: Fixed some typos in the comments. 104 * runtime/JSGlobalObject.cpp: 105 (JSC::JSGlobalObject::addGlobalVar): 106 (JSC::JSGlobalObject::addFunction): 107 * runtime/JSSymbolTableObject.h: 108 (JSC::symbolTablePut): 109 (JSC::symbolTablePutWithAttributes): 110 * runtime/SymbolTable.cpp: 111 (JSC::SymbolTableEntry::prepareToWatch): 112 (JSC::SymbolTableEntry::notifyWriteSlow): 113 * runtime/SymbolTable.h: 114 (JSC::SymbolTableEntry::notifyWrite): 115 1 116 2014-05-06 Michael Saboff <msaboff@apple.com> 2 117 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r168178 r168443 1709 1709 FE4A331F15BD2E07006F54F3 /* VMInspector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE4A331D15BD2E07006F54F3 /* VMInspector.cpp */; }; 1710 1710 FE4A332015BD2E07006F54F3 /* VMInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = FE4A331E15BD2E07006F54F3 /* VMInspector.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1711 FE5248F9191442D900B7FDE4 /* VariableWatchpointSetInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FE5248F8191442D900B7FDE4 /* VariableWatchpointSetInlines.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1711 1712 FE5932A7183C5A2600A1ECCC /* VMEntryScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */; }; 1712 1713 FE5932A8183C5A2600A1ECCC /* VMEntryScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 3334 3335 FE4A331D15BD2E07006F54F3 /* VMInspector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VMInspector.cpp; sourceTree = "<group>"; }; 3335 3336 FE4A331E15BD2E07006F54F3 /* VMInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMInspector.h; sourceTree = "<group>"; }; 3337 FE5248F8191442D900B7FDE4 /* VariableWatchpointSetInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VariableWatchpointSetInlines.h; sourceTree = "<group>"; }; 3336 3338 FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VMEntryScope.cpp; sourceTree = "<group>"; }; 3337 3339 FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMEntryScope.h; sourceTree = "<group>"; }; … … 5030 5032 0F426A451460CBAB00131F8F /* ValueRecovery.h */, 5031 5033 0F9181C618415CA50057B669 /* VariableWatchpointSet.h */, 5034 FE5248F8191442D900B7FDE4 /* VariableWatchpointSetInlines.h */, 5032 5035 0F426A461460CBAB00131F8F /* VirtualRegister.h */, 5033 5036 0F919D2215853CDE004A4E7D /* Watchpoint.cpp */, … … 5492 5495 A584032018BFFBE1005A0811 /* InspectorAgent.h in Headers */, 5493 5496 2AABCDE718EF294200002096 /* GCLogging.h in Headers */, 5497 FE5248F9191442D900B7FDE4 /* VariableWatchpointSetInlines.h in Headers */, 5494 5498 C2DA778318E259990066FCB6 /* HeapInlines.h in Headers */, 5495 5499 2AACE63D18CA5A0300ED0191 /* GCActivityCallback.h in Headers */, -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r168189 r168443 1794 1794 SymbolTable::Map::iterator iter = m_symbolTable->find(locker, uid); 1795 1795 ASSERT(iter != m_symbolTable->end(locker)); 1796 iter->value.prepareToWatch( );1796 iter->value.prepareToWatch(symbolTable()); 1797 1797 instructions[i + 3].u.watchpointSet = iter->value.watchpointSet(); 1798 1798 break; -
trunk/Source/JavaScriptCore/bytecode/VariableWatchpointSet.h
r160109 r168443 1 1 /* 2 * Copyright (C) 2012 , 2013Apple Inc. All rights reserved.2 * Copyright (C) 2012-2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 32 32 namespace JSC { 33 33 34 class SymbolTable; 35 34 36 class VariableWatchpointSet : public WatchpointSet { 35 37 friend class LLIntOffsetsExtractor; 36 38 public: 37 VariableWatchpointSet( )39 VariableWatchpointSet(SymbolTable& symbolTable) 38 40 : WatchpointSet(ClearWatchpoint) 41 , m_symbolTable(symbolTable) 39 42 { 40 43 } … … 53 56 // either notice that it's invalidated and not install the watchpoint, or 54 57 // you will have been notified that the watchpoint was fired. 55 JSValue inferredValue() const { return m_inferredValue ; }58 JSValue inferredValue() const { return m_inferredValue.get(); } 56 59 57 void notifyWrite(JSValue value) 58 { 59 ASSERT(!!value); 60 switch (state()) { 61 case ClearWatchpoint: 62 m_inferredValue = value; 63 startWatching(); 64 return; 65 66 case IsWatched: 67 ASSERT(!!m_inferredValue); 68 if (value == m_inferredValue) 69 return; 70 invalidate(); 71 return; 72 73 case IsInvalidated: 74 ASSERT(!m_inferredValue); 75 return; 76 } 77 78 ASSERT_NOT_REACHED(); 79 } 60 inline void notifyWrite(VM&, JSValue); 80 61 81 62 void invalidate() 82 63 { 83 m_inferredValue = JSValue();64 m_inferredValue.clear(); 84 65 WatchpointSet::invalidate(); 85 66 } … … 90 71 if (!m_inferredValue) 91 72 return; 92 if (!m_inferredValue.isCell()) 73 JSValue inferredValue = m_inferredValue.get(); 74 if (!inferredValue.isCell()) 93 75 return; 94 JSCell* cell = m_inferredValue.asCell();76 JSCell* cell = inferredValue.asCell(); 95 77 if (Heap::isMarked(cell)) 96 78 return; 97 79 invalidate(); 98 80 } 81 82 WriteBarrier<Unknown>* addressOfInferredValue() { return &m_inferredValue; } 99 83 100 JSValue* addressOfInferredValue() { return &m_inferredValue; }101 102 84 private: 103 JSValue m_inferredValue; 85 SymbolTable& m_symbolTable; 86 WriteBarrier<Unknown> m_inferredValue; 104 87 }; 105 88 -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r168172 r168443 37 37 #include "DFGJITCode.h" 38 38 #include "GetByIdStatus.h" 39 #include "Heap.h" 39 40 #include "JSActivation.h" 40 41 #include "JSCInlines.h" … … 721 722 { 722 723 HashMap<JSCell*, Node*>::AddResult result = m_cellConstantNodes.add(cell, nullptr); 723 if (result.isNewEntry) 724 if (result.isNewEntry) { 725 ASSERT(!Heap::isZombified(cell)); 724 726 result.iterator->value = addToGraph(WeakJSConstant, OpInfo(cell)); 727 } 725 728 726 729 return result.iterator->value; -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r168335 r168443 1019 1019 } 1020 1020 1021 void JIT_OPERATION operationInvalidate(ExecState* exec, VariableWatchpointSet* set) 1022 { 1023 VM& vm = exec->vm(); 1024 NativeCallFrameTracer tracer(&vm, exec); 1025 1026 set->invalidate(); 1021 void JIT_OPERATION operationNotifyWrite(ExecState* exec, VariableWatchpointSet* set, EncodedJSValue encodedValue) 1022 { 1023 VM& vm = exec->vm(); 1024 NativeCallFrameTracer tracer(&vm, exec); 1025 JSValue value = JSValue::decode(encodedValue); 1026 1027 set->notifyWrite(vm, value); 1027 1028 } 1028 1029 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r163765 r168443 125 125 char* JIT_OPERATION operationFindSwitchImmTargetForDouble(ExecState*, EncodedJSValue, size_t tableIndex); 126 126 char* JIT_OPERATION operationSwitchString(ExecState*, size_t tableIndex, JSString*); 127 void JIT_OPERATION operation Invalidate(ExecState*, VariableWatchpointSet*);127 void JIT_OPERATION operationNotifyWrite(ExecState*, VariableWatchpointSet*, EncodedJSValue); 128 128 129 129 #if ENABLE(FTL_JIT) -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r167591 r168443 1145 1145 } 1146 1146 1147 JITCompiler::Call callOperation(V_JITOperation_EVws operation, VariableWatchpointSet* watchpointSet)1148 {1149 m_jit.setupArgumentsWithExecState(TrustedImmPtr(watchpointSet));1150 return appendCall(operation);1151 }1152 1153 1147 JITCompiler::Call callOperationWithCallFrameRollbackOnException(V_JITOperation_ECb operation, void* pointer) 1154 1148 { … … 1438 1432 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3); 1439 1433 return appendCallWithExceptionCheck(operation); 1434 } 1435 1436 JITCompiler::Call callOperation(V_JITOperation_EVwsJ operation, VariableWatchpointSet* watchpointSet, GPRReg arg) 1437 { 1438 m_jit.setupArgumentsWithExecState(TrustedImmPtr(watchpointSet), arg); 1439 return appendCall(operation); 1440 1440 } 1441 1441 … … 1703 1703 m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG SH4_32BIT_DUMMY_ARG arg3Payload, arg3Tag); 1704 1704 return appendCallWithExceptionCheck(operation); 1705 } 1706 1707 JITCompiler::Call callOperation(V_JITOperation_EVwsJ operation, VariableWatchpointSet* watchpointSet, GPRReg argTag, GPRReg argPayload) 1708 { 1709 m_jit.setupArgumentsWithExecState(TrustedImmPtr(watchpointSet), argPayload, argTag); 1710 return appendCall(operation); 1705 1711 } 1706 1712 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r168051 r168443 3899 3899 m_jit.load8(set->addressOfState(), tempGPR); 3900 3900 3901 JITCompiler::JumpList ready; 3902 3903 ready.append(m_jit.branch32(JITCompiler::Equal, tempGPR, TrustedImm32(IsInvalidated))); 3904 3905 if (set->state() == ClearWatchpoint) { 3906 JITCompiler::Jump isWatched = 3907 m_jit.branch32(JITCompiler::NotEqual, tempGPR, TrustedImm32(ClearWatchpoint)); 3908 3909 m_jit.store32(valueTagGPR, &set->addressOfInferredValue()->u.asBits.tag); 3910 m_jit.store32(valuePayloadGPR, &set->addressOfInferredValue()->u.asBits.payload); 3911 m_jit.store8(TrustedImm32(IsWatched), set->addressOfState()); 3912 ready.append(m_jit.jump()); 3913 3914 isWatched.link(&m_jit); 3915 } 3916 3917 JITCompiler::Jump definitelyNotEqual = m_jit.branch32( 3901 JITCompiler::Jump isDone = m_jit.branch32(JITCompiler::Equal, tempGPR, TrustedImm32(IsInvalidated)); 3902 JITCompiler::JumpList notifySlow; 3903 notifySlow.append(m_jit.branch32( 3918 3904 JITCompiler::NotEqual, 3919 JITCompiler::AbsoluteAddress( &set->addressOfInferredValue()->u.asBits.payload),3920 valuePayloadGPR) ;3921 ready.append(m_jit.branch32(3922 JITCompiler:: Equal,3923 JITCompiler::AbsoluteAddress( &set->addressOfInferredValue()->u.asBits.tag),3905 JITCompiler::AbsoluteAddress(set->addressOfInferredValue()->payloadPointer()), 3906 valuePayloadGPR)); 3907 notifySlow.append(m_jit.branch32( 3908 JITCompiler::NotEqual, 3909 JITCompiler::AbsoluteAddress(set->addressOfInferredValue()->tagPointer()), 3924 3910 valueTagGPR)); 3925 definitelyNotEqual.link(&m_jit);3926 3927 JITCompiler::Jump slowCase = m_jit.branchTest8(3928 JITCompiler::NonZero, JITCompiler::AbsoluteAddress(set->addressOfSetIsNotEmpty()));3929 m_jit.store8(TrustedImm32(IsInvalidated), set->addressOfState());3930 m_jit.store32(3931 TrustedImm32(JSValue::EmptyValueTag),3932 &set->addressOfInferredValue()->u.asBits.tag);3933 m_jit.store32(3934 TrustedImm32(0), &set->addressOfInferredValue()->u.asBits.payload);3935 3936 ready.link(&m_jit);3937 3938 3911 addSlowPathGenerator( 3939 slowPathCall(slowCase, this, operationInvalidate, NoResult, set)); 3912 slowPathCall(notifySlow, this, operationNotifyWrite, NoResult, set, valueTagGPR, valuePayloadGPR)); 3913 isDone.link(&m_jit); 3940 3914 3941 3915 noResult(node); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r168051 r168443 3963 3963 m_jit.load8(set->addressOfState(), tempGPR); 3964 3964 3965 JITCompiler::JumpList ready; 3966 3967 ready.append(m_jit.branch32(JITCompiler::Equal, tempGPR, TrustedImm32(IsInvalidated))); 3968 3969 if (set->state() == ClearWatchpoint) { 3970 JITCompiler::Jump isWatched = 3971 m_jit.branch32(JITCompiler::NotEqual, tempGPR, TrustedImm32(ClearWatchpoint)); 3972 3973 m_jit.store64(valueGPR, set->addressOfInferredValue()); 3974 m_jit.store8(TrustedImm32(IsWatched), set->addressOfState()); 3975 ready.append(m_jit.jump()); 3976 3977 isWatched.link(&m_jit); 3978 } 3979 3980 ready.append(m_jit.branch64( 3981 JITCompiler::Equal, 3982 JITCompiler::AbsoluteAddress(set->addressOfInferredValue()), valueGPR)); 3983 3984 JITCompiler::Jump slowCase = m_jit.branchTest8( 3985 JITCompiler::NonZero, JITCompiler::AbsoluteAddress(set->addressOfSetIsNotEmpty())); 3986 m_jit.store8(TrustedImm32(IsInvalidated), set->addressOfState()); 3987 m_jit.move(TrustedImm64(JSValue::encode(JSValue())), tempGPR); 3988 m_jit.store64(tempGPR, set->addressOfInferredValue()); 3989 3990 ready.link(&m_jit); 3965 JITCompiler::Jump isDone = 3966 m_jit.branch32(JITCompiler::Equal, tempGPR, TrustedImm32(IsInvalidated)); 3967 JITCompiler::Jump slowCase = m_jit.branch64(JITCompiler::NotEqual, 3968 JITCompiler::AbsoluteAddress(set->addressOfInferredValue()), valueGPR); 3969 isDone.link(&m_jit); 3991 3970 3992 3971 addSlowPathGenerator( 3993 slowPathCall(slowCase, this, operation Invalidate, NoResult, set));3994 3972 slowPathCall(slowCase, this, operationNotifyWrite, NoResult, set, valueGPR)); 3973 3995 3974 noResult(node); 3996 3975 break; -
trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h
r167392 r168443 88 88 macro(V_JITOperation_EC, functionType(voidType, intPtr, intPtr)) \ 89 89 macro(V_JITOperation_ECb, functionType(voidType, intPtr, intPtr)) \ 90 macro(V_JITOperation_EVws , functionType(voidType, intPtr, intPtr)) \90 macro(V_JITOperation_EVwsJ, functionType(voidType, intPtr, intPtr, int64)) \ 91 91 macro(Z_JITOperation_D, functionType(int32, doubleType)) 92 92 -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
r167612 r168443 3287 3287 3288 3288 LBasicBlock isNotInvalidated = FTL_NEW_BLOCK(m_out, ("NotifyWrite not invalidated case")); 3289 LBasicBlock isClear = FTL_NEW_BLOCK(m_out, ("NotifyWrite clear case")); 3290 LBasicBlock isWatched = FTL_NEW_BLOCK(m_out, ("NotifyWrite watched case")); 3291 LBasicBlock invalidate = FTL_NEW_BLOCK(m_out, ("NotifyWrite invalidate case")); 3292 LBasicBlock invalidateFast = FTL_NEW_BLOCK(m_out, ("NotifyWrite invalidate fast case")); 3293 LBasicBlock invalidateSlow = FTL_NEW_BLOCK(m_out, ("NotifyWrite invalidate slow case")); 3289 LBasicBlock notifySlow = FTL_NEW_BLOCK(m_out, ("NotifyWrite notify slow case")); 3294 3290 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("NotifyWrite continuation")); 3295 3291 … … 3300 3296 usually(continuation), rarely(isNotInvalidated)); 3301 3297 3302 LBasicBlock lastNext = m_out.appendTo(isNotInvalidated, isClear); 3303 3304 LValue isClearValue; 3305 if (set->state() == ClearWatchpoint) 3306 isClearValue = m_out.equal(state, m_out.constInt8(ClearWatchpoint)); 3307 else 3308 isClearValue = m_out.booleanFalse; 3309 m_out.branch(isClearValue, unsure(isClear), unsure(isWatched)); 3310 3311 m_out.appendTo(isClear, isWatched); 3312 3313 m_out.store64(value, m_out.absolute(set->addressOfInferredValue())); 3314 m_out.store8(m_out.constInt8(IsWatched), m_out.absolute(set->addressOfState())); 3315 m_out.jump(continuation); 3316 3317 m_out.appendTo(isWatched, invalidate); 3318 3298 LBasicBlock lastNext = m_out.appendTo(isNotInvalidated, notifySlow); 3299 3319 3300 m_out.branch( 3320 3301 m_out.equal(value, m_out.load64(m_out.absolute(set->addressOfInferredValue()))), 3321 unsure(continuation), unsure(invalidate)); 3322 3323 m_out.appendTo(invalidate, invalidateFast); 3324 3325 m_out.branch( 3326 m_out.notZero8(m_out.load8(m_out.absolute(set->addressOfSetIsNotEmpty()))), 3327 rarely(invalidateSlow), usually(invalidateFast)); 3328 3329 m_out.appendTo(invalidateFast, invalidateSlow); 3330 3331 m_out.store64( 3332 m_out.constInt64(JSValue::encode(JSValue())), 3333 m_out.absolute(set->addressOfInferredValue())); 3334 m_out.store8(m_out.constInt8(IsInvalidated), m_out.absolute(set->addressOfState())); 3335 m_out.jump(continuation); 3336 3337 m_out.appendTo(invalidateSlow, continuation); 3338 3339 vmCall(m_out.operation(operationInvalidate), m_callFrame, m_out.constIntPtr(set)); 3302 unsure(continuation), unsure(notifySlow)); 3303 3304 m_out.appendTo(notifySlow, continuation); 3305 3306 vmCall(m_out.operation(operationNotifyWrite), m_callFrame, m_out.constIntPtr(set), value); 3340 3307 m_out.jump(continuation); 3341 3308 -
trunk/Source/JavaScriptCore/heap/Heap.cpp
r167948 r168443 1334 1334 void* limit = static_cast<void*>(reinterpret_cast<char*>(cell) + MarkedBlock::blockFor(cell)->cellSize()); 1335 1335 for (; current < limit; current++) 1336 *current = reinterpret_cast<void*>(0xbbadbeef);1336 *current = zombifiedBits; 1337 1337 } 1338 1338 }; -
trunk/Source/JavaScriptCore/heap/Heap.h
r167897 r168443 2 2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) 3 3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 4 * Copyright (C) 2003 , 2004, 2005, 2006, 2007, 2008, 2009, 2013Apple Inc. All rights reserved.4 * Copyright (C) 2003-2009, 2013-2014 Apple Inc. All rights reserved. 5 5 * 6 6 * This library is free software; you can redistribute it and/or … … 74 74 } 75 75 76 static void* const zombifiedBits = reinterpret_cast<void*>(0xdeadbeef); 77 76 78 typedef std::pair<JSValue, WTF::String> ValueStringPair; 77 79 typedef HashCountedSet<JSCell*> ProtectCountSet; … … 219 221 220 222 void removeCodeBlock(CodeBlock* cb) { m_codeBlocks.remove(cb); } 223 224 static bool isZombified(JSCell* cell) { return *(void**)cell == zombifiedBits; } 221 225 222 226 private: -
trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp
r167646 r168443 1203 1203 if (!set || set->state() == IsInvalidated) 1204 1204 return; 1205 #if USE(JSVALUE32_64) 1206 linkSlowCase(iter); 1207 #endif 1205 1208 linkSlowCase(iter); 1206 1209 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_captured_mov); -
trunk/Source/JavaScriptCore/jit/JITOperations.h
r166135 r168443 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013-2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 165 165 typedef void JIT_OPERATION (*V_JITOperation_EPZJ)(ExecState*, void*, int32_t, EncodedJSValue); 166 166 typedef void JIT_OPERATION (*V_JITOperation_ESsiJJI)(ExecState*, StructureStubInfo*, EncodedJSValue, EncodedJSValue, StringImpl*); 167 typedef void JIT_OPERATION (*V_JITOperation_EVws )(ExecState*, VariableWatchpointSet*);167 typedef void JIT_OPERATION (*V_JITOperation_EVwsJ)(ExecState*, VariableWatchpointSet*, EncodedJSValue); 168 168 typedef void JIT_OPERATION (*V_JITOperation_EZ)(ExecState*, int32_t); 169 169 typedef void JIT_OPERATION (*V_JITOperation_EVm)(ExecState*, VM*); -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
r167394 r168443 780 780 781 781 load8(set->addressOfState(), scratch); 782 783 JumpList ready; 784 785 ready.append(branch32(Equal, scratch, TrustedImm32(IsInvalidated))); 786 787 if (set->state() == ClearWatchpoint) { 788 Jump isWatched = branch32(NotEqual, scratch, TrustedImm32(ClearWatchpoint)); 789 790 store64(value, set->addressOfInferredValue()); 791 store8(TrustedImm32(IsWatched), set->addressOfState()); 792 ready.append(jump()); 793 794 isWatched.link(this); 795 } 796 797 ready.append(branch64(Equal, AbsoluteAddress(set->addressOfInferredValue()), value)); 798 addSlowCase(branchTest8(NonZero, AbsoluteAddress(set->addressOfSetIsNotEmpty()))); 799 store8(TrustedImm32(IsInvalidated), set->addressOfState()); 800 move(TrustedImm64(JSValue::encode(JSValue())), scratch); 801 store64(scratch, set->addressOfInferredValue()); 802 803 ready.link(this); 782 Jump isDone = branch32(Equal, scratch, TrustedImm32(IsInvalidated)); 783 addSlowCase(branch64(NotEqual, AbsoluteAddress(set->addressOfInferredValue()), value)); 784 isDone.link(this); 804 785 } 805 786 -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
r167288 r168443 813 813 814 814 load8(set->addressOfState(), scratch); 815 816 JumpList ready; 817 818 ready.append(branch32(Equal, scratch, TrustedImm32(IsInvalidated))); 819 820 if (set->state() == ClearWatchpoint) { 821 Jump isWatched = branch32(NotEqual, scratch, TrustedImm32(ClearWatchpoint)); 822 823 store32(tag, &set->addressOfInferredValue()->u.asBits.tag); 824 store32(payload, &set->addressOfInferredValue()->u.asBits.payload); 825 store8(TrustedImm32(IsWatched), set->addressOfState()); 826 ready.append(jump()); 827 828 isWatched.link(this); 829 } 830 831 Jump definitelyNotEqual = branch32( 832 NotEqual, AbsoluteAddress(&set->addressOfInferredValue()->u.asBits.payload), payload); 833 ready.append(branch32( 834 Equal, AbsoluteAddress(&set->addressOfInferredValue()->u.asBits.tag), tag)); 835 definitelyNotEqual.link(this); 836 addSlowCase(branchTest8(NonZero, AbsoluteAddress(set->addressOfSetIsNotEmpty()))); 837 store8(TrustedImm32(IsInvalidated), set->addressOfState()); 838 store32( 839 TrustedImm32(JSValue::EmptyValueTag), &set->addressOfInferredValue()->u.asBits.tag); 840 store32(TrustedImm32(0), &set->addressOfInferredValue()->u.asBits.payload); 841 842 ready.link(this); 815 Jump isDone = branch32(Equal, scratch, TrustedImm32(IsInvalidated)); 816 817 JumpList notifySlow = branch32( 818 NotEqual, AbsoluteAddress(set->addressOfInferredValue()->payloadPointer()), payload); 819 notifySlow.append(branch32( 820 NotEqual, AbsoluteAddress(set->addressOfInferredValue()->tagPointer()), tag)); 821 addSlowCase(notifySlow); 822 823 isDone.link(this); 843 824 } 844 825 … … 901 882 if ((resolveType == GlobalVar || resolveType == GlobalVarWithVarInjectionChecks) 902 883 && currentInstruction[5].u.watchpointSet->state() != IsInvalidated) 903 linkCount ++;884 linkCount += 2; 904 885 if (!linkCount) 905 886 return; -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
r167127 r168443 797 797 loadb VariableWatchpointSet::m_state[set], scratch 798 798 bieq scratch, IsInvalidated, .done 799 bineq scratch, ClearWatchpoint, .overwrite 800 storei valueTag, VariableWatchpointSet::m_inferredValue + TagOffset[set] 801 storei valuePayload, VariableWatchpointSet::m_inferredValue + PayloadOffset[set] 802 storeb IsWatched, VariableWatchpointSet::m_state[set] 803 jmp .done 804 805 .overwrite: 806 bineq valuePayload, VariableWatchpointSet::m_inferredValue + PayloadOffset[set], .definitelyDifferent 807 bieq valueTag, VariableWatchpointSet::m_inferredValue + TagOffset[set], .done 808 .definitelyDifferent: 809 btbnz VariableWatchpointSet::m_setIsNotEmpty[set], slow 810 storei EmptyValueTag, VariableWatchpointSet::m_inferredValue + TagOffset[set] 811 storei 0, VariableWatchpointSet::m_inferredValue + PayloadOffset[set] 812 storeb IsInvalidated, VariableWatchpointSet::m_state[set] 813 799 bineq valuePayload, VariableWatchpointSet::m_inferredValue + PayloadOffset[set], slow 800 bineq valueTag, VariableWatchpointSet::m_inferredValue + TagOffset[set], slow 814 801 .done: 815 802 end -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r167031 r168443 657 657 loadb VariableWatchpointSet::m_state[set], scratch 658 658 bieq scratch, IsInvalidated, .done 659 bineq scratch, ClearWatchpoint, .overwrite 660 storeq value, VariableWatchpointSet::m_inferredValue[set] 661 storeb IsWatched, VariableWatchpointSet::m_state[set] 662 jmp .done 663 664 .overwrite: 665 bqeq value, VariableWatchpointSet::m_inferredValue[set], .done 666 btbnz VariableWatchpointSet::m_setIsNotEmpty[set], slow 667 storeq 0, VariableWatchpointSet::m_inferredValue[set] 668 storeb IsInvalidated, VariableWatchpointSet::m_state[set] 669 670 .done: 659 bqneq value, VariableWatchpointSet::m_inferredValue[set], slow 660 .done: 671 661 end 672 662 -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
r164764 r168443 54 54 #include "JSCInlines.h" 55 55 #include "StructureRareDataInlines.h" 56 #include "VariableWatchpointSetInlines.h" 56 57 #include <wtf/StringPrintStream.h> 57 58 … … 263 264 JSValue value = OP_C(2).jsValue(); 264 265 if (VariableWatchpointSet* set = pc[3].u.watchpointSet) 265 set->notifyWrite(v alue);266 set->notifyWrite(vm, value); 266 267 RETURN(value); 267 268 } … … 274 275 JSValue value = JSFunction::create(vm, codeBlock->functionDecl(pc[2].u.operand), exec->scope()); 275 276 if (VariableWatchpointSet* set = pc[3].u.watchpointSet) 276 set->notifyWrite(v alue);277 set->notifyWrite(vm, value); 277 278 RETURN(value); 278 279 } -
trunk/Source/JavaScriptCore/runtime/JSCJSValue.h
r167394 r168443 334 334 * This range of NaN space is represented by 64-bit numbers begining with the 16-bit 335 335 * hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no valid double-precision 336 * numbers will beginfall in these ranges.336 * numbers will fall in these ranges. 337 337 * 338 338 * The top 16-bits denote the type of the encoded JSValue: … … 348 348 * no encoded double-precision value will begin with the pattern 0x0000 or 0xFFFF. 349 349 * Values must be decoded by reversing this operation before subsequent floating point 350 * operations m y be peformed.350 * operations may be peformed. 351 351 * 352 352 * 32-bit signed integers are marked with the 16-bit tag 0xFFFF. -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r167313 r168443 1 1 /* 2 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.2 * Copyright (C) 2007, 2008, 2009, 2014 Apple Inc. All rights reserved. 3 3 * Copyright (C) 2008 Cameron Zwarich (cwzwarich@uwaterloo.ca) 4 4 * … … 116 116 #include "StringConstructor.h" 117 117 #include "StringPrototype.h" 118 #include "VariableWatchpointSetInlines.h" 118 119 #include "WeakMapConstructor.h" 119 120 #include "WeakMapPrototype.h" … … 243 244 SymbolTableEntry newEntry(index, (constantMode == IsConstant) ? ReadOnly : 0); 244 245 if (constantMode == IsVariable) 245 newEntry.prepareToWatch( );246 newEntry.prepareToWatch(symbolTable()); 246 247 SymbolTable::Map::AddResult result = symbolTable()->add(locker, ident.impl(), newEntry); 247 248 if (result.isNewEntry) … … 257 258 void JSGlobalObject::addFunction(ExecState* exec, const Identifier& propertyName, JSValue value) 258 259 { 259 removeDirect(exec->vm(), propertyName); // Newly declared functions overwrite existing properties. 260 VM& vm = exec->vm(); 261 removeDirect(vm, propertyName); // Newly declared functions overwrite existing properties. 260 262 NewGlobalVar var = addGlobalVar(propertyName, IsVariable); 261 263 registerAt(var.registerNumber).set(exec->vm(), this, value); 262 264 if (var.set) 263 var.set->notifyWrite(v alue);265 var.set->notifyWrite(vm, value); 264 266 } 265 267 -
trunk/Source/JavaScriptCore/runtime/JSSymbolTableObject.h
r165676 r168443 1 1 /* 2 * Copyright (C) 2012 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 33 33 #include "PropertyDescriptor.h" 34 34 #include "SymbolTable.h" 35 #include "VariableWatchpointSetInlines.h" 35 36 36 37 namespace JSC { … … 139 140 } 140 141 if (VariableWatchpointSet* set = iter->value.watchpointSet()) 141 set->notifyWrite(v alue);142 set->notifyWrite(vm, value); 142 143 reg = &object->registerAt(fastEntry.getIndex()); 143 144 } … … 166 167 ASSERT(!entry.isNull()); 167 168 if (VariableWatchpointSet* set = entry.watchpointSet()) 168 set->notifyWrite(v alue);169 set->notifyWrite(vm, value); 169 170 entry.setAttributes(attributes); 170 171 reg = &object->registerAt(entry.getIndex()); -
trunk/Source/JavaScriptCore/runtime/SymbolTable.cpp
r165676 r168443 1 1 /* 2 * Copyright (C) 2012 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 33 33 #include "JSCInlines.h" 34 34 #include "SlotVisitorInlines.h" 35 #include "VariableWatchpointSetInlines.h" 35 36 36 37 namespace JSC { … … 66 67 } 67 68 68 void SymbolTableEntry::prepareToWatch( )69 void SymbolTableEntry::prepareToWatch(SymbolTable* symbolTable) 69 70 { 70 71 FatEntry* entry = inflate(); 71 72 if (entry->m_watchpoints) 72 73 return; 73 entry->m_watchpoints = adoptRef(new VariableWatchpointSet( ));74 entry->m_watchpoints = adoptRef(new VariableWatchpointSet(*symbolTable)); 74 75 } 75 76 … … 79 80 } 80 81 81 void SymbolTableEntry::notifyWriteSlow( JSValue value)82 void SymbolTableEntry::notifyWriteSlow(VM& vm, JSValue value) 82 83 { 83 84 VariableWatchpointSet* watchpoints = fatEntry()->m_watchpoints.get(); … … 85 86 return; 86 87 87 watchpoints->notifyWrite(v alue);88 watchpoints->notifyWrite(vm, value); 88 89 } 89 90 -
trunk/Source/JavaScriptCore/runtime/SymbolTable.h
r167641 r168443 1 1 /* 2 * Copyright (C) 2007, 2008, 2012 , 2013Apple Inc. All rights reserved.2 * Copyright (C) 2007, 2008, 2012-2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 219 219 JSValue inferredValue(); 220 220 221 void prepareToWatch( );221 void prepareToWatch(SymbolTable*); 222 222 223 223 void addWatchpoint(Watchpoint*); … … 230 230 } 231 231 232 ALWAYS_INLINE void notifyWrite( JSValue value)232 ALWAYS_INLINE void notifyWrite(VM& vm, JSValue value) 233 233 { 234 234 if (LIKELY(!isFat())) 235 235 return; 236 notifyWriteSlow(v alue);236 notifyWriteSlow(vm, value); 237 237 } 238 238 … … 258 258 259 259 SymbolTableEntry& copySlow(const SymbolTableEntry&); 260 JS_EXPORT_PRIVATE void notifyWriteSlow( JSValue);260 JS_EXPORT_PRIVATE void notifyWriteSlow(VM&, JSValue); 261 261 262 262 bool isFat() const
Note: See TracChangeset
for help on using the changeset viewer.