Changeset 108291 in webkit
- Timestamp:
- Feb 20, 2012 7:20:37 PM (12 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r108282 r108291 1 2012-02-20 Mark Hahnenberg <mhahnenberg@apple.com> 2 3 Implement fast path for op_new_array in the baseline JIT 4 https://bugs.webkit.org/show_bug.cgi?id=78612 5 6 Reviewed by Filip Pizlo. 7 8 * heap/CopiedAllocator.h: 9 (CopiedAllocator): Friended the JIT to allow access to m_currentOffset. 10 * heap/CopiedSpace.h: 11 (CopiedSpace): Friended the JIT to allow access to 12 (JSC::CopiedSpace::allocator): 13 * heap/Heap.h: 14 (JSC::Heap::storageAllocator): Added a getter for the CopiedAllocator class so the JIT 15 can use it for simple allocation i.e. when we can just bump the offset without having to 16 do anything else. 17 * jit/JIT.cpp: 18 (JSC::JIT::privateCompileSlowCases): Added new slow case for op_new_array for when 19 we have to bail out because the fast allocation path fails for whatever reason. 20 * jit/JIT.h: 21 (JIT): 22 * jit/JITInlineMethods.h: 23 (JSC::JIT::emitAllocateBasicStorage): Added utility function that allows objects to 24 allocate generic backing stores. This function is used by emitAllocateJSArray. 25 (JSC): 26 (JSC::JIT::emitAllocateJSArray): Added utility function that allows the client to 27 more easily allocate JSArrays. This function is used by emit_op_new_array and I expect 28 it will also be used for emit_op_new_array_buffer. 29 * jit/JITOpcodes.cpp: 30 (JSC::JIT::emit_op_new_array): Changed to do inline allocation of JSArrays. Still does 31 a stub call for oversize arrays. 32 (JSC): 33 (JSC::JIT::emitSlow_op_new_array): Just bails out to a stub call if we fail in any way on 34 the fast path. 35 * runtime/JSArray.cpp: 36 (JSC): 37 * runtime/JSArray.h: Added lots of offset functions for all the fields that we need to 38 initialize in the JIT. 39 (ArrayStorage): 40 (JSC::ArrayStorage::lengthOffset): 41 (JSC::ArrayStorage::numValuesInVectorOffset): 42 (JSC::ArrayStorage::allocBaseOffset): 43 (JSC::ArrayStorage::vectorOffset): 44 (JSArray): 45 (JSC::JSArray::sparseValueMapOffset): 46 (JSC::JSArray::subclassDataOffset): 47 (JSC::JSArray::indexBiasOffset): 48 (JSC): 49 (JSC::JSArray::storageSize): Moved this function from being a static function in the cpp file 50 to being a static function in the JSArray class. This move allows the JIT to call it to 51 see what size it should allocate. 52 1 53 2012-02-20 Gavin Barraclough <barraclough@apple.com> 2 54 -
trunk/Source/JavaScriptCore/heap/CopiedAllocator.h
r108267 r108291 32 32 33 33 class CopiedAllocator { 34 friend class JIT; 34 35 public: 35 36 CopiedAllocator(); -
trunk/Source/JavaScriptCore/heap/CopiedSpace.h
r108267 r108291 47 47 class CopiedSpace { 48 48 friend class SlotVisitor; 49 friend class JIT; 49 50 public: 50 51 CopiedSpace(Heap*); … … 54 55 CheckedBoolean tryReallocate(void**, size_t, size_t); 55 56 57 CopiedAllocator& allocator() { return m_allocator; } 58 56 59 void startedCopying(); 57 60 void doneCopying(); -
trunk/Source/JavaScriptCore/heap/Heap.h
r108119 r108291 98 98 MarkedAllocator& allocatorForObjectWithoutDestructor(size_t bytes) { return m_objectSpace.allocatorFor(bytes); } 99 99 MarkedAllocator& allocatorForObjectWithDestructor(size_t bytes) { return m_objectSpace.destructorAllocatorFor(bytes); } 100 CopiedAllocator& storageAllocator() { return m_storageSpace.allocator(); } 100 101 CheckedBoolean tryAllocateStorage(size_t, void**); 101 102 CheckedBoolean tryReallocateStorage(void**, size_t, size_t); -
trunk/Source/JavaScriptCore/jit/JIT.cpp
r107499 r108291 478 478 #endif 479 479 DEFINE_SLOWCASE_OP(op_neq) 480 DEFINE_SLOWCASE_OP(op_new_array) 480 481 DEFINE_SLOWCASE_OP(op_new_object) 481 482 DEFINE_SLOWCASE_OP(op_new_func) -
trunk/Source/JavaScriptCore/jit/JIT.h
r107594 r108291 337 337 338 338 template<typename ClassType, bool destructor, typename StructureType> void emitAllocateBasicJSObject(StructureType, RegisterID result, RegisterID storagePtr); 339 void emitAllocateBasicStorage(size_t, RegisterID result, RegisterID storagePtr); 339 340 template<typename T> void emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID storagePtr); 340 341 void emitAllocateJSFunction(FunctionExecutable*, RegisterID scopeChain, RegisterID result, RegisterID storagePtr); 342 void emitAllocateJSArray(unsigned valuesRegister, unsigned length, RegisterID cellResult, RegisterID storageResult, RegisterID storagePtr); 341 343 342 344 #if ENABLE(VALUE_PROFILER) … … 958 960 void emitSlow_op_new_func(Instruction*, Vector<SlowCaseEntry>::iterator&); 959 961 void emitSlow_op_new_func_exp(Instruction*, Vector<SlowCaseEntry>::iterator&); 960 962 void emitSlow_op_new_array(Instruction*, Vector<SlowCaseEntry>::iterator&); 961 963 962 964 void emitRightShift(Instruction*, bool isUnsigned); -
trunk/Source/JavaScriptCore/jit/JITInlineMethods.h
r107494 r108291 455 455 } 456 456 457 inline void JIT::emitAllocateBasicStorage(size_t size, RegisterID result, RegisterID storagePtr) 458 { 459 CopiedAllocator* allocator = &m_globalData->heap.storageAllocator(); 460 461 // FIXME: We need to check for wrap-around. 462 // Check to make sure that the allocation will fit in the current block. 463 loadPtr(&allocator->m_currentOffset, result); 464 addPtr(TrustedImm32(size), result); 465 loadPtr(&allocator->m_currentBlock, storagePtr); 466 addPtr(TrustedImm32(HeapBlock::s_blockSize), storagePtr); 467 addSlowCase(branchPtr(AboveOrEqual, result, storagePtr)); 468 469 // Load the original offset. 470 loadPtr(&allocator->m_currentOffset, result); 471 472 // Bump the pointer forward. 473 move(result, storagePtr); 474 addPtr(TrustedImm32(size), storagePtr); 475 storePtr(storagePtr, &allocator->m_currentOffset); 476 } 477 478 inline void JIT::emitAllocateJSArray(unsigned valuesRegister, unsigned length, RegisterID cellResult, RegisterID storageResult, RegisterID storagePtr) 479 { 480 unsigned initialLength = std::max(length, 4U); 481 size_t initialStorage = JSArray::storageSize(initialLength); 482 483 // Allocate the cell for the array. 484 emitAllocateBasicJSObject<JSArray, false>(TrustedImmPtr(m_codeBlock->globalObject()->arrayStructure()), cellResult, storagePtr); 485 486 // Allocate the backing store for the array. 487 emitAllocateBasicStorage(initialStorage, storageResult, storagePtr); 488 489 // Store all the necessary info in the ArrayStorage. 490 storePtr(storageResult, Address(storageResult, ArrayStorage::allocBaseOffset())); 491 store32(Imm32(length), Address(storageResult, ArrayStorage::lengthOffset())); 492 store32(Imm32(length), Address(storageResult, ArrayStorage::numValuesInVectorOffset())); 493 494 // Store the newly allocated ArrayStorage. 495 storePtr(storageResult, Address(cellResult, JSArray::storageOffset())); 496 497 // Store the vector length and index bias. 498 store32(Imm32(initialLength), Address(cellResult, JSArray::vectorLengthOffset())); 499 store32(TrustedImm32(0), Address(cellResult, JSArray::indexBiasOffset())); 500 501 // Initialize the subclass data and the sparse value map. 502 storePtr(TrustedImmPtr(0), Address(cellResult, JSArray::subclassDataOffset())); 503 storePtr(TrustedImmPtr(0), Address(cellResult, JSArray::sparseValueMapOffset())); 504 505 // Store the values we have. 506 for (unsigned i = 0; i < length; i++) { 507 loadPtr(Address(callFrameRegister, (valuesRegister + i) * sizeof(Register)), storagePtr); 508 storePtr(storagePtr, Address(storageResult, ArrayStorage::vectorOffset() + sizeof(WriteBarrier<Unknown>) * i)); 509 } 510 511 // Zero out the remaining slots. 512 for (unsigned i = length; i < initialLength; i++) 513 storePtr(TrustedImmPtr(0), Address(storageResult, ArrayStorage::vectorOffset() + sizeof(WriteBarrier<Unknown>) * i)); 514 } 515 457 516 #if ENABLE(VALUE_PROFILER) 458 517 inline void JIT::emitValueProfilingSite(ValueProfile* valueProfile) -
trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp
r108112 r108291 30 30 31 31 #include "Arguments.h" 32 #include "CopiedSpaceInlineMethods.h" 32 33 #include "Heap.h" 33 34 #include "JITInlineMethods.h" … … 1646 1647 void JIT::emit_op_new_array(Instruction* currentInstruction) 1647 1648 { 1649 int length = currentInstruction[3].u.operand; 1650 // FIXME: Add support for non-empty arrays. This involves copying the values over. 1651 if (CopiedSpace::isOversize(JSArray::storageSize(length))) { 1652 JITStubCall stubCall(this, cti_op_new_array); 1653 stubCall.addArgument(Imm32(currentInstruction[2].u.operand)); 1654 stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); 1655 stubCall.call(currentInstruction[1].u.operand); 1656 return; 1657 } 1658 int dst = currentInstruction[1].u.operand; 1659 int values = currentInstruction[2].u.operand; 1660 1661 emitAllocateJSArray(values, length, regT0, regT1, regT2); 1662 emitStoreCell(dst, regT0); 1663 } 1664 1665 void JIT::emitSlow_op_new_array(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 1666 { 1667 int length = currentInstruction[3].u.operand; 1668 if (CopiedSpace::isOversize(JSArray::storageSize(length))) 1669 return; 1670 linkSlowCase(iter); // Not enough space in MarkedSpace for cell. 1671 linkSlowCase(iter); // Not enough space in CopiedSpace for storage. 1648 1672 JITStubCall stubCall(this, cti_op_new_array); 1649 1673 stubCall.addArgument(Imm32(currentInstruction[2].u.operand)); -
trunk/Source/JavaScriptCore/runtime/JSArray.cpp
r108107 r108291 104 104 // This value is capped by the constant FIRST_VECTOR_GROW defined above. 105 105 static unsigned lastArraySize = 0; 106 107 static inline size_t storageSize(unsigned vectorLength)108 {109 ASSERT(vectorLength <= MAX_STORAGE_VECTOR_LENGTH);110 111 // MAX_STORAGE_VECTOR_LENGTH is defined such that provided (vectorLength <= MAX_STORAGE_VECTOR_LENGTH)112 // - as asserted above - the following calculation cannot overflow.113 size_t size = (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>)) + (vectorLength * sizeof(WriteBarrier<Unknown>));114 // Assertion to detect integer overflow in previous calculation (should not be possible, provided that115 // MAX_STORAGE_VECTOR_LENGTH is correctly defined).116 ASSERT(((size - (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>))) / sizeof(WriteBarrier<Unknown>) == vectorLength) && (size >= (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>))));117 118 return size;119 }120 106 121 107 static inline bool isDenseEnoughForVector(unsigned length, unsigned numValues) -
trunk/Source/JavaScriptCore/runtime/JSArray.h
r107956 r108291 120 120 #endif 121 121 WriteBarrier<Unknown> m_vector[1]; 122 123 static ptrdiff_t lengthOffset() { return OBJECT_OFFSETOF(ArrayStorage, m_length); } 124 static ptrdiff_t numValuesInVectorOffset() { return OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector); } 125 static ptrdiff_t allocBaseOffset() { return OBJECT_OFFSETOF(ArrayStorage, m_allocBase); } 126 static ptrdiff_t vectorOffset() { return OBJECT_OFFSETOF(ArrayStorage, m_vector); } 122 127 }; 123 128 124 129 class JSArray : public JSNonFinalObject { 125 130 friend class Walker; 131 friend class JIT; 126 132 127 133 protected: … … 259 265 260 266 private: 267 static size_t storageSize(unsigned vectorLength); 261 268 bool isLengthWritable() 262 269 { … … 290 297 SparseArrayValueMap* m_sparseValueMap; 291 298 void* m_subclassData; // A JSArray subclass can use this to fill the vector lazily. 299 300 static ptrdiff_t sparseValueMapOffset() { return OBJECT_OFFSETOF(JSArray, m_sparseValueMap); } 301 static ptrdiff_t subclassDataOffset() { return OBJECT_OFFSETOF(JSArray, m_subclassData); } 302 static ptrdiff_t indexBiasOffset() { return OBJECT_OFFSETOF(JSArray, m_indexBias); } 292 303 }; 293 304 … … 331 342 } 332 343 333 } // namespace JSC 344 // The definition of MAX_STORAGE_VECTOR_LENGTH is dependant on the definition storageSize 345 // function below - the MAX_STORAGE_VECTOR_LENGTH limit is defined such that the storage 346 // size calculation cannot overflow. (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>)) + 347 // (vectorLength * sizeof(WriteBarrier<Unknown>)) must be <= 0xFFFFFFFFU (which is maximum value of size_t). 348 #define MAX_STORAGE_VECTOR_LENGTH static_cast<unsigned>((0xFFFFFFFFU - (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>))) / sizeof(WriteBarrier<Unknown>)) 349 350 // These values have to be macros to be used in max() and min() without introducing 351 // a PIC branch in Mach-O binaries, see <rdar://problem/5971391>. 352 #define MIN_SPARSE_ARRAY_INDEX 10000U 353 #define MAX_STORAGE_VECTOR_INDEX (MAX_STORAGE_VECTOR_LENGTH - 1) 354 inline size_t JSArray::storageSize(unsigned vectorLength) 355 { 356 ASSERT(vectorLength <= MAX_STORAGE_VECTOR_LENGTH); 357 358 // MAX_STORAGE_VECTOR_LENGTH is defined such that provided (vectorLength <= MAX_STORAGE_VECTOR_LENGTH) 359 // - as asserted above - the following calculation cannot overflow. 360 size_t size = (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>)) + (vectorLength * sizeof(WriteBarrier<Unknown>)); 361 // Assertion to detect integer overflow in previous calculation (should not be possible, provided that 362 // MAX_STORAGE_VECTOR_LENGTH is correctly defined). 363 ASSERT(((size - (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>))) / sizeof(WriteBarrier<Unknown>) == vectorLength) && (size >= (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>)))); 364 365 return size; 366 } 367 368 } // namespace JSC 334 369 335 370 #endif // JSArray_h
Note: See TracChangeset
for help on using the changeset viewer.