Changeset 167641 in webkit
- Timestamp:
- Apr 21, 2014 6:37:34 PM (10 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r167632 r167641 1 2014-04-21 Mark Hahnenberg <mhahnenberg@apple.com> 2 3 Arguments objects shouldn't need a destructor 4 https://bugs.webkit.org/show_bug.cgi?id=131899 5 6 Reviewed by Oliver Hunt. 7 8 This patch rids Arguments objects of their destructors. It does this by 9 switching their backing stores to use CopiedSpace rather than malloc memory. 10 11 * dfg/DFGSpeculativeJIT.cpp: 12 (JSC::DFG::SpeculativeJIT::emitAllocateArguments): Fix the code emitted for inline 13 Arguments allocation so that it only emits an extra write for strict mode code rather 14 than unconditionally. 15 * heap/CopyToken.h: New CopyTokens for the two different types of Arguments backing stores. 16 * runtime/Arguments.cpp: 17 (JSC::Arguments::visitChildren): We need to tell the collector to copy the back stores now. 18 (JSC::Arguments::copyBackingStore): Do the actual copying of the backing stores. 19 (JSC::Arguments::deletePropertyByIndex): Update all the accesses to SlowArgumentData and m_registerArray. 20 (JSC::Arguments::deleteProperty): 21 (JSC::Arguments::defineOwnProperty): 22 (JSC::Arguments::allocateRegisterArray): 23 (JSC::Arguments::tearOff): 24 (JSC::Arguments::destroy): Deleted. We don't need the destructor any more. 25 * runtime/Arguments.h: 26 (JSC::Arguments::registerArraySizeInBytes): 27 (JSC::Arguments::SlowArgumentData::SlowArgumentData): Switch SlowArgumentData to being allocated 28 in CopiedSpace. Now the SlowArgumentData and its backing store are a single contiguous CopiedSpace 29 allocation. 30 (JSC::Arguments::SlowArgumentData::slowArguments): 31 (JSC::Arguments::SlowArgumentData::bytecodeToMachineCaptureOffset): 32 (JSC::Arguments::SlowArgumentData::setBytecodeToMachineCaptureOffset): 33 (JSC::Arguments::SlowArgumentData::sizeForNumArguments): 34 (JSC::Arguments::Arguments): 35 (JSC::Arguments::allocateSlowArguments): 36 (JSC::Arguments::tryDeleteArgument): 37 (JSC::Arguments::isDeletedArgument): 38 (JSC::Arguments::isArgument): 39 (JSC::Arguments::argument): 40 (JSC::Arguments::finishCreation): 41 * runtime/SymbolTable.h: 42 1 43 2014-04-21 Eric Carlson <eric.carlson@apple.com> 2 44 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r167591 r167641 119 119 120 120 m_jit.store32(TrustedImm32(0), MacroAssembler::Address(resultGPR, Arguments::offsetOfOverrodeLength())); 121 m_jit.store8(TrustedImm32(m_jit.isStrictModeFor(m_currentNode->origin.semantic)),122 MacroAssembler::Address(resultGPR, Arguments::offsetOfIsStrictMode()));121 if (m_jit.isStrictModeFor(m_currentNode->origin.semantic)) 122 m_jit.store8(TrustedImm32(1), MacroAssembler::Address(resultGPR, Arguments::offsetOfIsStrictMode())); 123 123 124 124 m_jit.storePtr(GPRInfo::callFrameRegister, MacroAssembler::Address(resultGPR, Arguments::offsetOfRegisters())); -
trunk/Source/JavaScriptCore/heap/CopyToken.h
r154861 r167641 32 32 ButterflyCopyToken, 33 33 TypedArrayVectorCopyToken, 34 MapBackingStoreCopyToken 34 MapBackingStoreCopyToken, 35 ArgumentsRegisterArrayCopyToken, 36 ArgumentsSlowArgumentDataCopyToken 35 37 }; 36 38 -
trunk/Source/JavaScriptCore/runtime/Arguments.cpp
r166493 r167641 26 26 #include "Arguments.h" 27 27 28 #include "CopyVisitorInlines.h" 28 29 #include "JSActivation.h" 29 30 #include "JSArgumentsIterator.h" … … 36 37 namespace JSC { 37 38 39 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(Arguments); 40 38 41 const ClassInfo Arguments::s_info = { "Arguments", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(Arguments) }; 39 42 … … 46 49 JSObject::visitChildren(thisObject, visitor); 47 50 48 if (thisObject->m_registerArray) 51 if (thisObject->m_registerArray) { 52 visitor.copyLater(thisObject, ArgumentsRegisterArrayCopyToken, 53 thisObject->m_registerArray.get(), thisObject->registerArraySizeInBytes()); 49 54 visitor.appendValues(thisObject->m_registerArray.get(), thisObject->m_numArguments); 55 } 56 if (thisObject->m_slowArgumentData) { 57 visitor.copyLater(thisObject, ArgumentsSlowArgumentDataCopyToken, 58 thisObject->m_slowArgumentData.get(), SlowArgumentData::sizeForNumArguments(thisObject->m_numArguments)); 59 } 50 60 visitor.append(&thisObject->m_callee); 51 61 visitor.append(&thisObject->m_activation); 52 62 } 63 64 void Arguments::copyBackingStore(JSCell* cell, CopyVisitor& visitor, CopyToken token) 65 { 66 Arguments* thisObject = jsCast<Arguments*>(cell); 67 ASSERT_GC_OBJECT_INHERITS(thisObject, info()); 68 69 70 switch (token) { 71 case ArgumentsRegisterArrayCopyToken: { 72 WriteBarrier<Unknown>* registerArray = thisObject->m_registerArray.get(); 73 if (!registerArray) 74 return; 75 76 if (visitor.checkIfShouldCopy(registerArray)) { 77 size_t bytes = thisObject->registerArraySizeInBytes(); 78 WriteBarrier<Unknown>* newRegisterArray = static_cast<WriteBarrier<Unknown>*>(visitor.allocateNewSpace(bytes)); 79 memcpy(newRegisterArray, registerArray, bytes); 80 thisObject->m_registerArray.setWithoutWriteBarrier(newRegisterArray); 81 visitor.didCopy(registerArray, bytes); 82 } 83 return; 84 } 85 86 case ArgumentsSlowArgumentDataCopyToken: { 87 SlowArgumentData* slowArgumentData = thisObject->m_slowArgumentData.get(); 88 if (!slowArgumentData) 89 return; 90 91 if (visitor.checkIfShouldCopy(slowArgumentData)) { 92 size_t bytes = SlowArgumentData::sizeForNumArguments(thisObject->m_numArguments); 93 SlowArgumentData* newSlowArgumentData = static_cast<SlowArgumentData*>(visitor.allocateNewSpace(bytes)); 94 memcpy(newSlowArgumentData, slowArgumentData, bytes); 95 thisObject->m_slowArgumentData.setWithoutWriteBarrier(newSlowArgumentData); 96 visitor.didCopy(slowArgumentData, bytes); 97 } 98 return; 99 } 100 101 default: 102 return; 103 } 104 } 53 105 54 106 static EncodedJSValue JSC_HOST_CALL argumentsFuncIterator(ExecState*); 55 56 void Arguments::destroy(JSCell* cell)57 {58 static_cast<Arguments*>(cell)->Arguments::~Arguments();59 }60 107 61 108 void Arguments::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t copyLength, int32_t firstVarArgOffset) … … 227 274 if (!Base::deletePropertyByIndex(cell, exec, i)) 228 275 return false; 229 if (thisObject->tryDeleteArgument( i))276 if (thisObject->tryDeleteArgument(exec->vm(), i)) 230 277 return true; 231 278 } … … 244 291 if (!Base::deleteProperty(cell, exec, propertyName)) 245 292 return false; 246 if (thisObject->tryDeleteArgument( i))293 if (thisObject->tryDeleteArgument(exec->vm(), i)) 247 294 return true; 248 295 } … … 289 336 if (descriptor.isAccessorDescriptor()) { 290 337 // i. Call the [[Delete]] internal method of map passing P, and false as the arguments. 291 thisObject->tryDeleteArgument( i);338 thisObject->tryDeleteArgument(exec->vm(), i); 292 339 } else { // b. Else 293 340 // i. If Desc.[[Value]] is present, then … … 298 345 // 1. Call the [[Delete]] internal method of map passing P and false as arguments. 299 346 if (descriptor.writablePresent() && !descriptor.writable()) 300 thisObject->tryDeleteArgument( i);347 thisObject->tryDeleteArgument(exec->vm(), i); 301 348 } 302 349 } … … 316 363 } 317 364 365 void Arguments::allocateRegisterArray(VM& vm) 366 { 367 ASSERT(!m_registerArray); 368 void* backingStore; 369 if (!vm.heap.tryAllocateStorage(this, registerArraySizeInBytes(), &backingStore)) 370 RELEASE_ASSERT_NOT_REACHED(); 371 m_registerArray.set(vm, this, static_cast<WriteBarrier<Unknown>*>(backingStore)); 372 } 373 318 374 void Arguments::tearOff(CallFrame* callFrame) 319 375 { … … 327 383 ASSERT(bitwise_cast<WriteBarrier<Unknown>*>(callFrame) == m_registers); 328 384 329 m_registerArray = std::make_unique<WriteBarrier<Unknown>[]>(m_numArguments);385 allocateRegisterArray(callFrame->vm()); 330 386 m_registers = m_registerArray.get() - CallFrame::offsetFor(1) - 1; 331 387 … … 335 391 if (m_slowArgumentData && !m_activation) { 336 392 for (size_t i = 0; i < m_numArguments; ++i) { 337 if (m_slowArgumentData->slowArguments [i].status != SlowArgument::Captured)393 if (m_slowArgumentData->slowArguments()[i].status != SlowArgument::Captured) 338 394 continue; 339 m_slowArgumentData->slowArguments [i].status = SlowArgument::Normal;340 m_slowArgumentData->slowArguments [i].index = CallFrame::argumentOffset(i);395 m_slowArgumentData->slowArguments()[i].status = SlowArgument::Normal; 396 m_slowArgumentData->slowArguments()[i].index = CallFrame::argumentOffset(i); 341 397 } 342 398 } … … 367 423 return; 368 424 369 m_registerArray = std::make_unique<WriteBarrier<Unknown>[]>(m_numArguments);425 allocateRegisterArray(callFrame->vm()); 370 426 m_registers = m_registerArray.get() - CallFrame::offsetFor(1) - 1; 371 427 -
trunk/Source/JavaScriptCore/runtime/Arguments.h
r167591 r167641 27 27 #include "CodeOrigin.h" 28 28 #include "JSActivation.h" 29 #include "JSDestructibleObject.h"30 29 #include "JSFunction.h" 31 30 #include "JSGlobalObject.h" … … 37 36 namespace JSC { 38 37 39 class Arguments : public JS DestructibleObject {38 class Arguments : public JSNonFinalObject { 40 39 friend class JIT; 41 40 friend class JSArgumentsIterator; 42 41 public: 43 typedef JS DestructibleObject Base;42 typedef JSNonFinalObject Base; 44 43 45 44 static Arguments* create(VM& vm, CallFrame* callFrame) … … 69 68 70 69 static void visitChildren(JSCell*, SlotVisitor&); 70 static void copyBackingStore(JSCell*, CopyVisitor&, CopyToken); 71 71 72 72 void fillArgList(ExecState*, MarkedArgumentBuffer&); … … 112 112 113 113 private: 114 static void destroy(JSCell*);115 114 static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); 116 115 static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&); … … 124 123 void createStrictModeCalleeIfNecessary(ExecState*); 125 124 125 size_t registerArraySizeInBytes() const { return sizeof(WriteBarrier<Unknown>) * m_numArguments; } 126 void allocateRegisterArray(VM&); 126 127 bool isArgument(size_t); 127 128 bool trySetArgument(VM&, size_t argument, JSValue); 128 129 JSValue tryGetArgument(size_t argument); 129 130 bool isDeletedArgument(size_t); 130 bool tryDeleteArgument( size_t);131 bool tryDeleteArgument(VM&, size_t); 131 132 WriteBarrierBase<Unknown>& argument(size_t); 132 void allocateSlowArguments( );133 void allocateSlowArguments(VM&); 133 134 134 135 void init(CallFrame*); … … 147 148 148 149 WriteBarrierBase<Unknown>* m_registers; 149 std::unique_ptr<WriteBarrier<Unknown>[]> m_registerArray;150 CopyWriteBarrier<WriteBarrier<Unknown>> m_registerArray; 150 151 151 152 public: 152 153 struct SlowArgumentData { 153 WTF_MAKE_FAST_ALLOCATED;154 154 public: 155 156 std::unique_ptr<SlowArgument[]> slowArguments; 157 int bytecodeToMachineCaptureOffset; // Add this if you have a bytecode offset into captured registers and you want the machine offset instead. Subtract if you want to do the opposite. 155 SlowArgumentData() 156 : m_bytecodeToMachineCaptureOffset(0) 157 { 158 } 159 160 SlowArgument* slowArguments() 161 { 162 return reinterpret_cast<SlowArgument*>(WTF::roundUpToMultipleOf<8>(reinterpret_cast<size_t>(this + 1))); 163 } 164 165 int bytecodeToMachineCaptureOffset() const { return m_bytecodeToMachineCaptureOffset; } 166 void setBytecodeToMachineCaptureOffset(int newOffset) { m_bytecodeToMachineCaptureOffset = newOffset; } 167 168 static size_t sizeForNumArguments(unsigned numArguments) 169 { 170 return WTF::roundUpToMultipleOf<8>(sizeof(SlowArgumentData)) + sizeof(SlowArgument) * numArguments; 171 } 172 173 private: 174 int m_bytecodeToMachineCaptureOffset; // Add this if you have a bytecode offset into captured registers and you want the machine offset instead. Subtract if you want to do the opposite. 158 175 }; 159 176 160 177 private: 161 std::unique_ptr<SlowArgumentData> m_slowArgumentData;178 CopyWriteBarrier<SlowArgumentData> m_slowArgumentData; 162 179 163 180 WriteBarrier<JSFunction> m_callee; … … 173 190 174 191 inline Arguments::Arguments(CallFrame* callFrame) 175 : JSDestructibleObject(callFrame->vm(), callFrame->lexicalGlobalObject()->argumentsStructure())192 : Base(callFrame->vm(), callFrame->lexicalGlobalObject()->argumentsStructure()) 176 193 { 177 194 } 178 195 179 196 inline Arguments::Arguments(CallFrame* callFrame, NoParametersType) 180 : JSDestructibleObject(callFrame->vm(), callFrame->lexicalGlobalObject()->argumentsStructure())181 { 182 } 183 184 inline void Arguments::allocateSlowArguments( )185 { 186 if ( m_slowArgumentData)197 : Base(callFrame->vm(), callFrame->lexicalGlobalObject()->argumentsStructure()) 198 { 199 } 200 201 inline void Arguments::allocateSlowArguments(VM& vm) 202 { 203 if (!!m_slowArgumentData) 187 204 return; 188 m_slowArgumentData = std::make_unique<SlowArgumentData>(); 189 m_slowArgumentData->bytecodeToMachineCaptureOffset = 0; 190 m_slowArgumentData->slowArguments = std::make_unique<SlowArgument[]>(m_numArguments); 205 206 void* backingStore; 207 if (!vm.heap.tryAllocateStorage(this, SlowArgumentData::sizeForNumArguments(m_numArguments), &backingStore)) 208 RELEASE_ASSERT_NOT_REACHED(); 209 m_slowArgumentData.set(vm, this, static_cast<SlowArgumentData*>(backingStore)); 210 191 211 for (size_t i = 0; i < m_numArguments; ++i) { 192 ASSERT(m_slowArgumentData->slowArguments [i].status == SlowArgument::Normal);193 m_slowArgumentData->slowArguments [i].index = CallFrame::argumentOffset(i);194 } 195 } 196 197 inline bool Arguments::tryDeleteArgument( size_t argument)212 ASSERT(m_slowArgumentData->slowArguments()[i].status == SlowArgument::Normal); 213 m_slowArgumentData->slowArguments()[i].index = CallFrame::argumentOffset(i); 214 } 215 } 216 217 inline bool Arguments::tryDeleteArgument(VM& vm, size_t argument) 198 218 { 199 219 if (!isArgument(argument)) 200 220 return false; 201 allocateSlowArguments( );202 m_slowArgumentData->slowArguments [argument].status = SlowArgument::Deleted;221 allocateSlowArguments(vm); 222 m_slowArgumentData->slowArguments()[argument].status = SlowArgument::Deleted; 203 223 return true; 204 224 } … … 225 245 if (!m_slowArgumentData) 226 246 return false; 227 if (m_slowArgumentData->slowArguments [argument].status != SlowArgument::Deleted)247 if (m_slowArgumentData->slowArguments()[argument].status != SlowArgument::Deleted) 228 248 return false; 229 249 return true; … … 234 254 if (argument >= m_numArguments) 235 255 return false; 236 if (m_slowArgumentData && m_slowArgumentData->slowArguments [argument].status == SlowArgument::Deleted)256 if (m_slowArgumentData && m_slowArgumentData->slowArguments()[argument].status == SlowArgument::Deleted) 237 257 return false; 238 258 return true; … … 245 265 return m_registers[CallFrame::argumentOffset(argument)]; 246 266 247 int index = m_slowArgumentData->slowArguments [argument].index;248 if (!m_activation || m_slowArgumentData->slowArguments [argument].status != SlowArgument::Captured)267 int index = m_slowArgumentData->slowArguments()[argument].index; 268 if (!m_activation || m_slowArgumentData->slowArguments()[argument].status != SlowArgument::Captured) 249 269 return m_registers[index]; 250 270 251 return m_activation->registerAt(index - m_slowArgumentData->bytecodeToMachineCaptureOffset );271 return m_activation->registerAt(index - m_slowArgumentData->bytecodeToMachineCaptureOffset()); 252 272 } 253 273 … … 270 290 SymbolTable* symbolTable = codeBlock->symbolTable(); 271 291 const SlowArgument* slowArguments = codeBlock->machineSlowArguments(); 272 allocateSlowArguments( );292 allocateSlowArguments(callFrame->vm()); 273 293 size_t count = std::min<unsigned>(m_numArguments, symbolTable->parameterCount()); 274 294 for (size_t i = 0; i < count; ++i) 275 m_slowArgumentData->slowArguments [i] = slowArguments[i];276 m_slowArgumentData-> bytecodeToMachineCaptureOffset =277 codeBlock->framePointerOffsetToGetActivationRegisters() ;295 m_slowArgumentData->slowArguments()[i] = slowArguments[i]; 296 m_slowArgumentData->setBytecodeToMachineCaptureOffset( 297 codeBlock->framePointerOffsetToGetActivationRegisters()); 278 298 } 279 299 -
trunk/Source/JavaScriptCore/runtime/SymbolTable.h
r165676 r167641 40 40 41 41 struct SlowArgument { 42 WTF_MAKE_FAST_ALLOCATED;43 42 public: 44 45 43 enum Status { 46 44 Normal = 0,
Note: See TracChangeset
for help on using the changeset viewer.