Changeset 20351 in webkit for trunk/JavaScriptCore/kjs
- Timestamp:
- Mar 20, 2007, 4:57:01 PM (18 years ago)
- Location:
- trunk/JavaScriptCore/kjs
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/JSLock.cpp
r20115 r20351 25 25 26 26 #include "collector.h" 27 #if USE(MULTIPLE_THREADS) 28 #include <pthread.h> 29 #endif 27 30 28 31 namespace KJS { … … 66 69 pthread_mutex_unlock(&JSMutex); 67 70 } 71 } 72 73 bool JSLock::currentThreadIsHoldingLock() 74 { 75 pthread_once(&createDidLockJSMutexOnce, createDidLockJSMutex); 76 return !!pthread_getspecific(didLockJSMutex); 68 77 } 69 78 -
trunk/JavaScriptCore/kjs/JSLock.h
r20115 r20351 63 63 static void unlock(); 64 64 static int lockCount(); 65 static bool currentThreadIsHoldingLock(); 65 66 66 67 static void registerThread(); -
trunk/JavaScriptCore/kjs/collector.cpp
r20115 r20351 33 33 #include <algorithm> 34 34 35 #if PLATFORM(DARWIN)36 37 35 #include <pthread.h> 36 37 #if PLATFORM(DARWIN) 38 38 39 #include <mach/mach_port.h> 39 40 #include <mach/task.h> … … 45 46 46 47 #elif PLATFORM(UNIX) 47 48 #include <pthread.h>49 48 50 49 #if HAVE(PTHREAD_NP_H) … … 113 112 114 113 #ifndef NDEBUG 114 115 115 class GCLock { 116 116 static bool isLocked; … … 135 135 void* Collector::allocate(size_t s) 136 136 { 137 assert(JSLock::lockCount() > 0); 137 ASSERT(JSLock::lockCount() > 0); 138 ASSERT(JSLock::currentThreadIsHoldingLock()); 138 139 139 140 // collect if needed … … 180 181 targetBlock = heap.blocks[i]; 181 182 targetBlockUsedCells = targetBlock->usedCells; 182 assert(targetBlockUsedCells <= CELLS_PER_BLOCK);183 ASSERT(targetBlockUsedCells <= CELLS_PER_BLOCK); 183 184 while (targetBlockUsedCells == CELLS_PER_BLOCK) { 184 185 if (++i == usedBlocks) … … 186 187 targetBlock = heap.blocks[i]; 187 188 targetBlockUsedCells = targetBlock->usedCells; 188 assert(targetBlockUsedCells <= CELLS_PER_BLOCK);189 ASSERT(targetBlockUsedCells <= CELLS_PER_BLOCK); 189 190 } 190 191 heap.firstBlockWithPossibleSpace = i; … … 220 221 } 221 222 223 static inline void* currentThreadStackBase() 224 { 225 #if PLATFORM(DARWIN) 226 pthread_t thread = pthread_self(); 227 return pthread_get_stackaddr_np(thread); 228 #elif PLATFORM(WIN_OS) && PLATFORM(X86) && COMPILER(MSVC) 229 // offset 0x18 from the FS segment register gives a pointer to 230 // the thread information block for the current thread 231 NT_TIB* pTib; 232 __asm { 233 MOV EAX, FS:[18h] 234 MOV pTib, EAX 235 } 236 return (void*)pTib->StackBase; 237 #elif PLATFORM(UNIX) 238 static void *stackBase = 0; 239 static pthread_t stackThread; 240 pthread_t thread = pthread_self(); 241 if (stackBase == 0 || thread != stackThread) { 242 pthread_attr_t sattr; 243 #if HAVE(PTHREAD_NP_H) 244 // e.g. on FreeBSD 5.4, [email protected] 245 pthread_attr_get_np(thread, &sattr); 246 #else 247 // FIXME: this function is non-portable; other POSIX systems may have different np alternatives 248 pthread_getattr_np(thread, &sattr); 249 #endif 250 size_t stackSize; 251 int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize); 252 (void)rc; // FIXME: deal with error code somehow? seems fatal... 253 ASSERT(stackBase); 254 return (void*)(size_t(stackBase) + stackSize); 255 stackThread = thread; 256 } 257 #else 258 #error Need a way to get the stack base on this platform 259 #endif 260 } 261 262 static pthread_t mainThread; 263 264 void Collector::registerAsMainThread() 265 { 266 mainThread = pthread_self(); 267 } 268 269 static inline bool onMainThread() 270 { 271 #if PLATFORM(DARWIN) 272 return pthread_main_np(); 273 #else 274 return !!pthread_equal(pthread_self(), mainThread); 275 #endif 276 } 277 222 278 #if USE(MULTIPLE_THREADS) 223 279 224 struct Collector::Thread { 225 Thread(pthread_t pthread, mach_port_t mthread) : posixThread(pthread), machThread(mthread) {} 226 Thread *next; 280 #if PLATFORM(DARWIN) 281 typedef mach_port_t PlatformThread; 282 #elif PLATFORM(WIN_OS) 283 struct PlatformThread { 284 PlatformThread(DWORD _id, HANDLE _handle) : id(_id), handle(_handle) {} 285 DWORD id; 286 HANDLE handle; 287 }; 288 #endif 289 290 static inline PlatformThread getCurrentPlatformThread() 291 { 292 #if PLATFORM(DARWIN) 293 return pthread_mach_thread_np(pthread_self()); 294 #elif PLATFORM(WIN_OS) 295 HANDLE threadHandle = pthread_getw32threadhandle_np(pthread_self()); 296 return PlatformThread(GetCurrentThreadId(), threadHandle); 297 #endif 298 } 299 300 class Collector::Thread { 301 public: 302 Thread(pthread_t pthread, const PlatformThread& platThread) : posixThread(pthread), platformThread(platThread) {} 303 Thread* next; 227 304 pthread_t posixThread; 228 mach_port_t machThread;305 PlatformThread platformThread; 229 306 }; 230 307 231 308 pthread_key_t registeredThreadKey; 232 309 pthread_once_t registeredThreadKeyOnce = PTHREAD_ONCE_INIT; 233 Collector::Thread *registeredThreads;234 235 static void destroyRegisteredThread(void *data)236 { 237 Collector::Thread *thread = (Collector::Thread*)data;310 Collector::Thread* registeredThreads; 311 312 static void destroyRegisteredThread(void* data) 313 { 314 Collector::Thread* thread = (Collector::Thread*)data; 238 315 239 316 // Can't use JSLock convenience object here because we don't want to re-register … … 247 324 Collector::Thread *t; 248 325 for (t = registeredThreads->next; t != NULL; t = t->next) { 249 if (t == thread) { 250 last->next = t->next;326 if (t == thread) { 327 last->next = t->next; 251 328 break; 252 329 } … … 269 346 { 270 347 ASSERT(JSLock::lockCount() > 0); 348 ASSERT(JSLock::currentThreadIsHoldingLock()); 271 349 272 350 pthread_once(®isteredThreadKeyOnce, initializeRegisteredThreadKey); 273 351 274 352 if (!pthread_getspecific(registeredThreadKey)) { 275 if (! pthread_main_np())353 if (!onMainThread()) 276 354 WTF::fastMallocSetIsMultiThreaded(); 277 pthread_t pthread = pthread_self();278 Collector::Thread *thread = new Collector::Thread(pthread, pthread_mach_thread_np(pthread)); 355 Collector::Thread *thread = new Collector::Thread(pthread_self(), getCurrentPlatformThread()); 356 279 357 thread->next = registeredThreads; 280 358 registeredThreads = thread; … … 298 376 } 299 377 300 assert(((char *)end - (char *)start) < 0x1000000);301 assert(IS_POINTER_ALIGNED(start));302 assert(IS_POINTER_ALIGNED(end));378 ASSERT(((char *)end - (char *)start) < 0x1000000); 379 ASSERT(IS_POINTER_ALIGNED(start)); 380 ASSERT(IS_POINTER_ALIGNED(end)); 303 381 304 382 char **p = (char **)start; … … 337 415 void Collector::markCurrentThreadConservatively() 338 416 { 417 // setjmp forces volatile registers onto the stack 339 418 jmp_buf registers; 340 419 #if COMPILER(MSVC) … … 347 426 #endif 348 427 349 #if PLATFORM(DARWIN) 350 pthread_t thread = pthread_self(); 351 void *stackBase = pthread_get_stackaddr_np(thread); 352 #elif PLATFORM(WIN_OS) && PLATFORM(X86) && COMPILER(MSVC) 353 NT_TIB *pTib; 354 __asm { 355 MOV EAX, FS:[18h] 356 MOV pTib, EAX 357 } 358 void *stackBase = (void *)pTib->StackBase; 359 #elif PLATFORM(UNIX) 360 static void *stackBase = 0; 361 static pthread_t stackThread; 362 pthread_t thread = pthread_self(); 363 if (stackBase == 0 || thread != stackThread) { 364 pthread_attr_t sattr; 365 #if HAVE(PTHREAD_NP_H) 366 // e.g. on FreeBSD 5.4, [email protected] 367 pthread_attr_get_np(thread, &sattr); 368 #else 369 // FIXME: this function is non-portable; other POSIX systems may have different np alternatives 370 pthread_getattr_np(thread, &sattr); 371 #endif 372 size_t stackSize; 373 int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize); 374 (void)rc; // FIXME: deal with error code somehow? seems fatal... 375 assert(stackBase); 376 stackBase = (void*)(size_t(stackBase) + stackSize); 377 stackThread = thread; 378 } 379 #else 380 #error Need a way to get the stack base on this platform 381 #endif 382 383 void *dummy; 384 void *stackPointer = &dummy; 428 void* dummy; 429 void* stackPointer = &dummy; 430 void* stackBase = currentThreadStackBase(); 385 431 386 432 markStackObjectsConservatively(stackPointer, stackBase); … … 389 435 #if USE(MULTIPLE_THREADS) 390 436 437 static inline void suspendThread(const PlatformThread& platformThread) 438 { 439 #if PLATFORM(DARWIN) 440 thread_suspend(platformThread); 441 #elif PLATFORM(WIN_OS) 442 SuspendThread(platformThread.handle); 443 #else 444 #error Need a way to suspend threads on this platform 445 #endif 446 } 447 448 static inline void resumeThread(const PlatformThread& platformThread) 449 { 450 #if PLATFORM(DARWIN) 451 thread_resume(platformThread); 452 #elif PLATFORM(WIN_OS) 453 ResumeThread(platformThread.handle); 454 #else 455 #error Need a way to resume threads on this platform 456 #endif 457 } 458 391 459 typedef unsigned long usword_t; // word size, assumed to be either 32 or 64 bit 392 460 393 void Collector::markOtherThreadConservatively(Thread *thread) 394 { 395 thread_suspend(thread->machThread); 396 397 #if PLATFORM(X86) 398 i386_thread_state_t regs; 461 #if PLATFORM(DARWIN) 462 463 #if PLATFORM(X86) 464 typedef i386_thread_state_t PlatformThreadRegisters; 465 #elif PLATFORM(X86_64) 466 typedef x86_thread_state64_t PlatformThreadRegisters; 467 #elif PLATFORM(PPC) 468 typedef ppc_thread_state_t PlatformThreadRegisters; 469 #elif PLATFORM(PPC64) 470 typedef ppc_thread_state64_t PlatformThreadRegisters; 471 #else 472 #error Unknown Architecture 473 #endif 474 475 #elif PLATFORM(WIN_OS)&& PLATFORM(X86) 476 typedef CONTEXT PlatformThreadRegisters; 477 #else 478 #error Need a thread register struct for this platform 479 #endif 480 481 size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs) 482 { 483 #if PLATFORM(DARWIN) 484 485 #if PLATFORM(X86) 399 486 unsigned user_count = sizeof(regs)/sizeof(int); 400 487 thread_state_flavor_t flavor = i386_THREAD_STATE; 401 #elif PLATFORM(X86_64) 402 x86_thread_state64_t regs; 488 #elif PLATFORM(X86_64) 403 489 unsigned user_count = x86_THREAD_STATE64_COUNT; 404 490 thread_state_flavor_t flavor = x86_THREAD_STATE64; 405 #elif PLATFORM(PPC) 406 ppc_thread_state_t regs; 491 #elif PLATFORM(PPC) 407 492 unsigned user_count = PPC_THREAD_STATE_COUNT; 408 493 thread_state_flavor_t flavor = PPC_THREAD_STATE; 409 #elif PLATFORM(PPC64) 410 ppc_thread_state64_t regs; 494 #elif PLATFORM(PPC64) 411 495 unsigned user_count = PPC_THREAD_STATE64_COUNT; 412 496 thread_state_flavor_t flavor = PPC_THREAD_STATE64; … … 414 498 #error Unknown Architecture 415 499 #endif 416 // get the thread register state 417 thread_get_state(thread->machThread, flavor, (thread_state_t)®s, &user_count); 418 419 // scan the registers 420 markStackObjectsConservatively((void *)®s, (void *)((char *)®s + (user_count * sizeof(usword_t)))); 421 422 // scan the stack 423 #if PLATFORM(X86) && __DARWIN_UNIX03 424 markStackObjectsConservatively((void *)regs.__esp, pthread_get_stackaddr_np(thread->posixThread)); 425 #elif PLATFORM(X86) 426 markStackObjectsConservatively((void *)regs.esp, pthread_get_stackaddr_np(thread->posixThread)); 427 #elif PLATFORM(X86_64) && __DARWIN_UNIX03 428 markStackObjectsConservatively((void *)regs.__rsp, pthread_get_stackaddr_np(thread->posixThread)); 500 501 thread_get_state(platformThread, flavor, (thread_state_t)®s, &user_count); 502 return user_count * sizeof(usword_t); 503 // end PLATFORM(DARWIN) 504 505 #elif PLATFORM(WIN_OS) && PLATFORM(X86) 506 regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS; 507 GetThreadContext(platformThread.handle, ®s); 508 return sizeof(CONTEXT); 509 #else 510 #error Need a way to get thread registers on this platform 511 #endif 512 } 513 514 static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs) 515 { 516 #if PLATFORM(DARWIN) 517 518 #if __DARWIN_UNIX03 519 520 #if PLATFORM(X86) 521 return (void*)regs.__esp; 429 522 #elif PLATFORM(X86_64) 430 markStackObjectsConservatively((void *)regs.rsp, pthread_get_stackaddr_np(thread->posixThread)); 431 #elif (PLATFORM(PPC) || PLATFORM(PPC64)) && __DARWIN_UNIX03 432 markStackObjectsConservatively((void *)regs.__r1, pthread_get_stackaddr_np(thread->posixThread)); 523 return (void*)regs.__rsp; 433 524 #elif PLATFORM(PPC) || PLATFORM(PPC64) 434 markStackObjectsConservatively((void *)regs.r1, pthread_get_stackaddr_np(thread->posixThread));525 return (void*)regs.__r1; 435 526 #else 436 527 #error Unknown Architecture 437 528 #endif 438 529 439 thread_resume(thread->machThread); 530 #else // !__DARWIN_UNIX03 531 532 #if PLATFORM(X86) 533 return (void*)regs.esp; 534 #elif PLATFORM(X86_64) 535 return (void*)regs.rsp; 536 #elif (PLATFORM(PPC) || PLATFORM(PPC64)) 537 return (void*)regs.r1; 538 #else 539 #error Unknown Architecture 540 #endif 541 542 #endif // __DARWIN_UNIX03 543 544 // end PLATFORM(DARWIN) 545 #elif PLATFORM(X86) && PLATFORM(WIN_OS) 546 return (void*)(uintptr_t)regs.Esp; 547 #else 548 #error Need a way to get the stack pointer for another thread on this platform 549 #endif 550 } 551 552 static inline void* otherThreadStackBase(const PlatformThreadRegisters& regs, Collector::Thread* thread) 553 { 554 #if PLATFORM(DARWIN) 555 (void)regs; 556 return pthrad_get_stackaddr_np(thread->posixThread); 557 // end PLATFORM(DARWIN); 558 #elif PLATFORM(X86) && PLATFORM(WIN_OS) 559 LDT_ENTRY desc; 560 NT_TIB* tib; 561 GetThreadSelectorEntry(thread->platformThread.handle, regs.SegFs, &desc); 562 tib = (NT_TIB*)(uintptr_t)(desc.BaseLow | desc.HighWord.Bytes.BaseMid << 16 | desc.HighWord.Bytes.BaseHi << 24); 563 ASSERT(tib == tib->Self); 564 return tib->StackBase; 565 #else 566 #error Need a way to get the stack pointer for another thread on this platform 567 #endif 568 } 569 570 void Collector::markOtherThreadConservatively(Thread* thread) 571 { 572 suspendThread(thread->platformThread); 573 574 PlatformThreadRegisters regs; 575 size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs); 576 577 // mark the thread's registers 578 markStackObjectsConservatively((void*)®s, (void*)((char*)®s + regSize)); 579 580 void* stackPointer = otherThreadStackPointer(regs); 581 void* stackBase = otherThreadStackBase(regs, thread); 582 markStackObjectsConservatively(stackPointer, stackBase); 583 584 resumeThread(thread->platformThread); 440 585 } 441 586 … … 448 593 #if USE(MULTIPLE_THREADS) 449 594 for (Thread *thread = registeredThreads; thread != NULL; thread = thread->next) { 450 if ( thread->posixThread != pthread_self()) {595 if (!pthread_equal(thread->posixThread, pthread_self())) { 451 596 markOtherThreadConservatively(thread); 452 597 } … … 465 610 void Collector::protect(JSValue *k) 466 611 { 467 assert(k); 468 assert(JSLock::lockCount() > 0); 612 ASSERT(k); 613 ASSERT(JSLock::lockCount() > 0); 614 ASSERT(JSLock::currentThreadIsHoldingLock()); 469 615 470 616 if (JSImmediate::isImmediate(k)) … … 476 622 void Collector::unprotect(JSValue *k) 477 623 { 478 assert(k); 479 assert(JSLock::lockCount() > 0); 624 ASSERT(k); 625 ASSERT(JSLock::lockCount() > 0); 626 ASSERT(JSLock::currentThreadIsHoldingLock()); 480 627 481 628 if (JSImmediate::isImmediate(k)) … … 489 636 ASSERT(value); 490 637 ASSERT(JSLock::lockCount() > 0); 638 ASSERT(JSLock::currentThreadIsHoldingLock()); 491 639 492 640 if (JSImmediate::isImmediate(value)) … … 512 660 { 513 661 #if USE(MULTIPLE_THREADS) 514 ASSERT(! pthread_main_np());662 ASSERT(!onMainThread()); 515 663 #endif 516 664 … … 563 711 bool Collector::collect() 564 712 { 565 assert(JSLock::lockCount() > 0); 713 ASSERT(JSLock::lockCount() > 0); 714 ASSERT(JSLock::currentThreadIsHoldingLock()); 715 566 716 567 717 #ifndef NDEBUG … … 570 720 571 721 #if USE(MULTIPLE_THREADS) 572 bool currentThreadIsMainThread = pthread_main_np();722 bool currentThreadIsMainThread = onMainThread(); 573 723 #else 574 724 bool currentThreadIsMainThread = true; -
trunk/JavaScriptCore/kjs/collector.h
r20004 r20351 59 59 static void registerThread(); 60 60 61 static void registerAsMainThread(); 62 61 63 private: 62 64 Collector();
Note:
See TracChangeset
for help on using the changeset viewer.