Changeset 91199 in webkit
- Timestamp:
- Jul 18, 2011 11:55:48 AM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r91194 r91199 1 2011-07-18 Filip Pizlo <fpizlo@apple.com> 2 3 JSC JIT does not inline GC allocation fast paths 4 https://bugs.webkit.org/show_bug.cgi?id=64582 5 6 Reviewed by Oliver Hunt. 7 8 This addresses inlining allocation for the easiest-to-allocate cases: 9 op_new_object and op_create_this. Inlining GC allocation fast paths 10 required three changes. First, the JSGlobalData now saves the vtable 11 pointer of JSFinalObject, since that's what op_new_object and 12 op_create_this allocate. Second, the Heap exposes a reference to 13 the appropriate SizeClass, so that the JIT may inline accesses 14 directly to the SizeClass for JSFinalObject allocations. And third, 15 the JIT is extended with code to emit inline fast paths for GC 16 allocation. A stub call is emitted in the case where the inline fast 17 path fails. 18 19 * heap/Heap.h: 20 (JSC::Heap::sizeClassFor): 21 (JSC::Heap::allocate): 22 * jit/JIT.cpp: 23 (JSC::JIT::privateCompileSlowCases): 24 * jit/JIT.h: 25 * jit/JITInlineMethods.h: 26 (JSC::JIT::emitAllocateJSFinalObject): 27 * jit/JITOpcodes.cpp: 28 (JSC::JIT::emit_op_new_object): 29 (JSC::JIT::emitSlow_op_new_object): 30 (JSC::JIT::emit_op_create_this): 31 (JSC::JIT::emitSlow_op_create_this): 32 * jit/JITOpcodes32_64.cpp: 33 (JSC::JIT::emit_op_new_object): 34 (JSC::JIT::emitSlow_op_new_object): 35 (JSC::JIT::emit_op_create_this): 36 (JSC::JIT::emitSlow_op_create_this): 37 * runtime/JSGlobalData.cpp: 38 (JSC::JSGlobalData::storeVPtrs): 39 * runtime/JSGlobalData.h: 40 * runtime/JSObject.h: 41 (JSC::JSFinalObject::JSFinalObject): 42 (JSC::JSObject::offsetOfInheritorID): 43 1 44 2011-07-18 Mark Hahnenberg <mhahnenberg@apple.com> 2 45 -
trunk/Source/JavaScriptCore/heap/Heap.h
r91039 r91199 83 83 84 84 void* allocate(size_t); 85 NewSpace::SizeClass& sizeClassFor(size_t); 85 86 void* allocate(NewSpace::SizeClass&); 86 87 void notifyIsSafeToCollect() { m_isSafeToCollect = true; } … … 290 291 } 291 292 293 inline NewSpace::SizeClass& Heap::sizeClassFor(size_t bytes) 294 { 295 return m_newSpace.sizeClassFor(bytes); 296 } 297 292 298 inline void* Heap::allocate(NewSpace::SizeClass& sizeClass) 293 299 { … … 304 310 { 305 311 ASSERT(isValidAllocation(bytes)); 306 NewSpace::SizeClass& sizeClass = m_newSpace.sizeClassFor(bytes);312 NewSpace::SizeClass& sizeClass = sizeClassFor(bytes); 307 313 return allocate(sizeClass); 308 314 } -
trunk/Source/JavaScriptCore/jit/JIT.cpp
r91095 r91199 402 402 DEFINE_SLOWCASE_OP(op_construct) 403 403 DEFINE_SLOWCASE_OP(op_convert_this) 404 DEFINE_SLOWCASE_OP(op_create_this) 404 405 DEFINE_SLOWCASE_OP(op_div) 405 406 DEFINE_SLOWCASE_OP(op_eq) … … 436 437 #endif 437 438 DEFINE_SLOWCASE_OP(op_neq) 439 DEFINE_SLOWCASE_OP(op_new_object) 438 440 DEFINE_SLOWCASE_OP(op_not) 439 441 DEFINE_SLOWCASE_OP(op_nstricteq) -
trunk/Source/JavaScriptCore/jit/JIT.h
r91095 r91199 300 300 301 301 void emitWriteBarrier(RegisterID owner, RegisterID scratch); 302 303 template<typename T> 304 void emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID scratch); 302 305 303 306 #if USE(JSVALUE32_64) … … 854 857 void emitSlow_op_construct(Instruction*, Vector<SlowCaseEntry>::iterator&); 855 858 void emitSlow_op_convert_this(Instruction*, Vector<SlowCaseEntry>::iterator&); 859 void emitSlow_op_create_this(Instruction*, Vector<SlowCaseEntry>::iterator&); 856 860 void emitSlow_op_div(Instruction*, Vector<SlowCaseEntry>::iterator&); 857 861 void emitSlow_op_eq(Instruction*, Vector<SlowCaseEntry>::iterator&); … … 886 890 void emitSlow_op_negate(Instruction*, Vector<SlowCaseEntry>::iterator&); 887 891 void emitSlow_op_neq(Instruction*, Vector<SlowCaseEntry>::iterator&); 892 void emitSlow_op_new_object(Instruction*, Vector<SlowCaseEntry>::iterator&); 888 893 void emitSlow_op_not(Instruction*, Vector<SlowCaseEntry>::iterator&); 889 894 void emitSlow_op_nstricteq(Instruction*, Vector<SlowCaseEntry>::iterator&); -
trunk/Source/JavaScriptCore/jit/JITInlineMethods.h
r85432 r91199 375 375 } 376 376 377 template<typename T> 378 inline void JIT::emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID scratch) 379 { 380 NewSpace::SizeClass* sizeClass = &m_globalData->heap.sizeClassFor(sizeof(JSFinalObject)); 381 loadPtr(&sizeClass->firstFreeCell, result); 382 addSlowCase(branchTestPtr(Zero, result)); 383 384 // remove the object from the free list 385 loadPtr(Address(result), scratch); 386 storePtr(scratch, &sizeClass->firstFreeCell); 387 388 // initialize the object's vtable 389 storePtr(ImmPtr(m_globalData->jsFinalObjectVPtr), Address(result)); 390 391 // initialize the object's structure 392 storePtr(structure, Address(result, JSCell::structureOffset())); 393 394 // initialize the inheritor ID 395 storePtr(ImmPtr(0), Address(result, JSObject::offsetOfInheritorID())); 396 397 // initialize the object's property storage pointer 398 addPtr(Imm32(sizeof(JSObject)), result, scratch); 399 storePtr(scratch, Address(result, JSObject::offsetOfPropertyStorage())); 400 } 401 377 402 #if USE(JSVALUE32_64) 378 403 -
trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp
r91095 r91199 30 30 31 31 #include "Arguments.h" 32 #include "Heap.h" 32 33 #include "JITInlineMethods.h" 33 34 #include "JITStubCall.h" … … 331 332 void JIT::emit_op_new_object(Instruction* currentInstruction) 332 333 { 334 emitAllocateJSFinalObject(ImmPtr(m_codeBlock->globalObject()->emptyObjectStructure()), regT0, regT1); 335 336 emitPutVirtualRegister(currentInstruction[1].u.operand); 337 } 338 339 void JIT::emitSlow_op_new_object(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 340 { 341 linkSlowCase(iter); 333 342 JITStubCall(this, cti_op_new_object).call(currentInstruction[1].u.operand); 334 343 } … … 1157 1166 void JIT::emit_op_create_this(Instruction* currentInstruction) 1158 1167 { 1168 emitGetVirtualRegister(currentInstruction[2].u.operand, regT2); 1169 emitJumpSlowCaseIfNotJSCell(regT2, currentInstruction[2].u.operand); 1170 loadPtr(Address(regT2, JSCell::structureOffset()), regT1); 1171 addSlowCase(branch8(NotEqual, Address(regT1, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType))); 1172 1173 // now we know that the prototype is an object, but we don't know if it's got an 1174 // inheritor ID 1175 1176 loadPtr(Address(regT2, JSObject::offsetOfInheritorID()), regT2); 1177 addSlowCase(branchTestPtr(Zero, regT2)); 1178 1179 // now regT2 contains the inheritorID, which is the structure that the newly 1180 // allocated object will have. 1181 1182 emitAllocateJSFinalObject(regT2, regT0, regT1); 1183 1184 emitPutVirtualRegister(currentInstruction[1].u.operand); 1185 } 1186 1187 void JIT::emitSlow_op_create_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 1188 { 1189 linkSlowCaseIfNotJSCell(iter, currentInstruction[2].u.operand); // not a cell 1190 linkSlowCase(iter); // not an object 1191 linkSlowCase(iter); // doesn't have an inheritor ID 1192 linkSlowCase(iter); // allocation failed 1159 1193 JITStubCall stubCall(this, cti_op_create_this); 1160 1194 stubCall.addArgument(currentInstruction[2].u.operand, regT1); -
trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
r91095 r91199 486 486 void JIT::emit_op_new_object(Instruction* currentInstruction) 487 487 { 488 emitAllocateJSFinalObject(ImmPtr(m_codeBlock->globalObject()->emptyObjectStructure()), regT0, regT1); 489 490 emitStoreCell(currentInstruction[1].u.operand, regT0); 491 } 492 493 void JIT::emitSlow_op_new_object(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 494 { 495 linkSlowCase(iter); 488 496 JITStubCall(this, cti_op_new_object).call(currentInstruction[1].u.operand); 489 497 } … … 1439 1447 void JIT::emit_op_create_this(Instruction* currentInstruction) 1440 1448 { 1449 emitLoad(currentInstruction[2].u.operand, regT1, regT0); 1450 emitJumpSlowCaseIfNotJSCell(currentInstruction[2].u.operand, regT1); 1451 loadPtr(Address(regT0, JSCell::structureOffset()), regT1); 1452 addSlowCase(branch8(NotEqual, Address(regT1, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType))); 1453 1454 // now we know that the prototype is an object, but we don't know if it's got an 1455 // inheritor ID 1456 1457 loadPtr(Address(regT0, JSObject::offsetOfInheritorID()), regT2); 1458 addSlowCase(branchTestPtr(Zero, regT2)); 1459 1460 // now regT2 contains the inheritorID, which is the structure that the newly 1461 // allocated object will have. 1462 1463 emitAllocateJSFinalObject(regT2, regT0, regT1); 1464 1465 emitStoreCell(currentInstruction[1].u.operand, regT0); 1466 } 1467 1468 void JIT::emitSlow_op_create_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 1469 { 1470 linkSlowCaseIfNotJSCell(iter, currentInstruction[2].u.operand); // not a cell 1471 linkSlowCase(iter); // not an object 1472 linkSlowCase(iter); // doesn't have an inheritor ID 1473 linkSlowCase(iter); // allocation failed 1441 1474 unsigned protoRegister = currentInstruction[2].u.operand; 1442 1475 emitLoad(protoRegister, regT1, regT0); -
trunk/Source/JavaScriptCore/runtime/JSGlobalData.cpp
r90865 r91199 114 114 extern JSC_CONST_HASHTABLE HashTable stringConstructorTable; 115 115 116 void* JSGlobalData::jsFinalObjectVPtr; 116 117 void* JSGlobalData::jsArrayVPtr; 117 118 void* JSGlobalData::jsByteArrayVPtr; … … 133 134 // COMPILE_ASSERTS below check that this is true. 134 135 char storage[64]; 136 137 COMPILE_ASSERT(sizeof(JSFinalObject) <= sizeof(storage), sizeof_JSFinalObject_must_be_less_than_storage); 138 JSCell* jsFinalObject = new (storage) JSFinalObject(JSFinalObject::VPtrStealingHack); 139 CLOBBER_MEMORY(); 140 JSGlobalData::jsFinalObjectVPtr = jsFinalObject->vptr(); 135 141 136 142 COMPILE_ASSERT(sizeof(JSArray) <= sizeof(storage), sizeof_JSArray_must_be_less_than_storage); -
trunk/Source/JavaScriptCore/runtime/JSGlobalData.h
r90423 r91199 183 183 184 184 static void storeVPtrs(); 185 static JS_EXPORTDATA void* jsFinalObjectVPtr; 185 186 static JS_EXPORTDATA void* jsArrayVPtr; 186 187 static JS_EXPORTDATA void* jsByteArrayVPtr; -
trunk/Source/JavaScriptCore/runtime/JSObject.h
r91194 r91199 49 49 class HashEntry; 50 50 class InternalFunction; 51 class MarkedBlock; 51 52 class PropertyDescriptor; 52 53 class PropertyNameArray; … … 76 77 friend class JIT; 77 78 friend class JSCell; 79 friend class MarkedBlock; 78 80 friend void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot); 79 81 … … 251 253 static size_t offsetOfInlineStorage(); 252 254 static size_t offsetOfPropertyStorage(); 255 static size_t offsetOfInheritorID(); 253 256 254 257 static JS_EXPORTDATA const ClassInfo s_info; … … 358 361 359 362 public: 363 explicit JSFinalObject(VPtrStealingHackType) 364 : JSObject(VPtrStealingHack, m_inlineStorage) 365 { 366 } 367 360 368 static JSFinalObject* create(ExecState* exec, Structure* structure) 361 369 { … … 390 398 { 391 399 return OBJECT_OFFSETOF(JSObject, m_propertyStorage); 400 } 401 402 inline size_t JSObject::offsetOfInheritorID() 403 { 404 return OBJECT_OFFSETOF(JSObject, m_inheritorID); 392 405 } 393 406
Note: See TracChangeset
for help on using the changeset viewer.