Changeset 20004 in webkit
- Timestamp:
- Mar 6, 2007 8:25:49 PM (17 years ago)
- Location:
- trunk
- Files:
-
- 33 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/API/JSObjectRef.h
r19059 r20004 91 91 /*! 92 92 @typedef JSObjectFinalizeCallback 93 @abstract The callback invoked when an object is finalized (prepared for garbage collection). 93 @abstract The callback invoked when an object is finalized (prepared for garbage collection). An object may be finalized on any thread. 94 94 @param object The JSObject being finalized. 95 95 @discussion If you named your function Finalize, you would declare it like this: -
trunk/JavaScriptCore/ChangeLog
r19994 r20004 1 2007-03-06 Geoffrey Garen <ggaren@apple.com> 2 3 Reviewed by Maciej Stachowiak. 4 5 Fixed all known crashers exposed by run-webkit-tests --threaded. This covers: 6 7 <rdar://problem/4565394> | http://bugs.webkit.org/show_bug.cgi?id=12585 8 PAC file: after closing a window that contains macworld.com, new window 9 crashes (KJS::PropertyMap::mark()) (12585) 10 <rdar://problem/4571215> | http://bugs.webkit.org/show_bug.cgi?id=9211 11 PAC file: Crash occurs when clicking on the navigation tabs at http://www.businessweek.com/ (9211) 12 <rdar://problem/4557926> 13 PAC file: Crash occurs when attempting to view image in slideshow mode 14 at http://d.smugmug.com/gallery/581716 ( KJS::IfNode::execute (KJS:: 15 ExecState*) + 312) if you use a PAC file 16 17 (1) Added some missing JSLocks, along with related ASSERTs. 18 19 (2) Fully implemented support for objects that can only be garbage collected 20 on the main thread. So far, only WebCore uses this. We can add it to API 21 later if we learn that it's needed. 22 23 The implementation uses a "main thread only" flag inside each object. When 24 collecting on a secondary thread, the Collector does an extra pass through 25 the heap to mark all flagged objects before sweeping. This solution makes 26 the common case -- flag lots of objects, but never collect on a secondary 27 thread -- very fast, even though the uncommon case of garbage collecting 28 on a secondary thread isn't as fast as it could be. I left some notes 29 about how to speed it up, if we ever care. 30 31 For posterity, here are some things I learned about GC while investigating: 32 33 * Each collect must either mark or delete every heap object. "Zombie" 34 objects, which are neither marked nor deleted, raise these issues: 35 36 * On the next pass, the conservative marking algorithm might mark a 37 zombie, causing it to mark freed objects. 38 39 * The client might try to use a zombie, which would seem live because 40 its finalizer had not yet run. 41 42 * A collect on the main thread is free to delete any object. Presumably, 43 objects allocated on secondary threads have thread-safe finalizers. 44 45 * A collect on a secondary thread must not delete thread-unsafe objects. 46 47 * The mark function must be thread-safe. 48 49 Line by line comments: 50 51 * API/JSObjectRef.h: Added comment specifying that the finalize callback 52 may run on any thread. 53 54 * JavaScriptCore.exp: Nothing to see here. 55 56 * bindings/npruntime.cpp: 57 (_NPN_GetStringIdentifier): Added JSLock. 58 59 * bindings/objc/objc_instance.h: 60 * bindings/objc/objc_instance.mm: 61 (ObjcInstance::~ObjcInstance): Use an autorelease pool. The other callers 62 to CFRelease needed one, too, but they were dead code, so I removed them 63 instead. (This fixes a leak seen while running run-webkit-tests --threaded, 64 although I don't think it's specifically a threading issue.) 65 66 * kjs/collector.cpp: 67 (KJS::Collector::collectOnMainThreadOnly): New function. Tells the collector 68 to collect a value only if it's collecting on the main thread. 69 (KJS::Collector::markMainThreadOnlyObjects): New function. Scans the heap 70 for "main thread only" objects and marks them. 71 72 * kjs/date_object.cpp: 73 (KJS::DateObjectImp::DateObjectImp): To make the new ASSERTs happy, allocate 74 our globals on the heap, avoiding a seemingly unsafe destructor call at 75 program exit time. 76 * kjs/function_object.cpp: 77 (FunctionPrototype::FunctionPrototype): ditto 78 79 * kjs/interpreter.cpp: 80 (KJS::Interpreter::mark): Removed boolean parameter, which was an incomplete 81 and arguably hackish way to implement markMainThreadOnlyObjects() inside WebCore. 82 * kjs/interpreter.h: 83 84 * kjs/identifier.cpp: 85 (KJS::identifierTable): Added some ASSERTs to check for thread safety 86 problems. 87 88 * kjs/list.cpp: Added some ASSERTs to check for thread safety problems. 89 (KJS::allocateListImp): 90 (KJS::List::release): 91 (KJS::List::append): 92 (KJS::List::empty): Make the new ASSERTs happy. 93 94 * kjs/object.h: 95 (KJS::JSObject::JSObject): "m_destructorIsThreadSafe" => "m_collectOnMainThreadOnly". 96 I removed the constructor parameter because m_collectOnMainThreadOnly, 97 like m_marked, is a Collector bit, so only the Collector should set or get it. 98 99 * kjs/object_object.cpp: 100 (ObjectPrototype::ObjectPrototype): Make the ASSERTs happy. 101 * kjs/regexp_object.cpp: 102 (RegExpPrototype::RegExpPrototype): ditto 103 104 * kjs/ustring.cpp: Added some ASSERTs to check for thread safety problems. 105 (KJS::UCharReference::ref): 106 (KJS::UString::Rep::createCopying): 107 (KJS::UString::Rep::create): 108 (KJS::UString::Rep::destroy): 109 (KJS::UString::null): Make the new ASSERTs happy. 110 * kjs/ustring.h: 111 (KJS::UString::Rep::ref): Added some ASSERTs to check for thread safety problems. 112 (KJS::UString::Rep::deref): 113 114 * kjs/value.h: 115 (KJS::JSCell::JSCell): 116 1 117 2007-03-06 Geoffrey Garen <ggaren@apple.com> 2 118 -
trunk/JavaScriptCore/JavaScriptCore.exp
r19894 r20004 118 118 __ZN3KJS11Interpreter21shouldPrintExceptionsEv 119 119 __ZN3KJS11Interpreter24setShouldPrintExceptionsEb 120 __ZN3KJS11Interpreter4markE b120 __ZN3KJS11Interpreter4markEv 121 121 __ZN3KJS11Interpreter6s_hookE 122 122 __ZN3KJS11Interpreter8evaluateERKNS_7UStringEiPKNS_5UCharEiPNS_7JSValueE … … 167 167 __ZN3KJS6JSLock4lockEv 168 168 __ZN3KJS6JSLock6unlockEv 169 __ZN3KJS6JSLock9lockCountEv 169 170 __ZN3KJS6Lookup9findEntryEPKNS_9HashTableERKNS_10IdentifierE 170 171 __ZN3KJS6Parser11prettyPrintERKNS_7UStringEPiPS1_ … … 215 216 __ZN3KJS9Collector19numProtectedObjectsEv 216 217 __ZN3KJS9Collector20rootObjectTypeCountsEv 218 __ZN3KJS9Collector23collectOnMainThreadOnlyEPNS_7JSValueE 217 219 __ZN3KJS9Collector4sizeEv 218 220 __ZN3KJS9Collector7collectEv … … 274 276 __ZTVN3KJS15JSWrapperObjectE 275 277 __ZTVN3KJS19InternalFunctionImpE 278 __ZTVN3KJS6JSCellE 276 279 __ZTVN3KJS8JSObjectE 277 280 _kJSClassDefinitionEmpty -
trunk/JavaScriptCore/bindings/npruntime.cpp
r18424 r20004 29 29 #include "npruntime_priv.h" 30 30 31 #include "JSLock.h" 31 32 #include "c_utility.h" 32 33 #include "identifier.h" … … 62 63 if (name) { 63 64 PrivateIdentifier* identifier = 0; 65 66 KJS::JSLock lock; 64 67 65 68 identifier = getStringIdentifierMap()->get(identifierFromNPIdentifier(name).ustring().rep()); -
trunk/JavaScriptCore/bindings/objc/objc_instance.h
r15696 r20004 44 44 virtual Class *getClass() const; 45 45 46 ObjcInstance(const ObjcInstance &other);47 48 ObjcInstance &operator=(const ObjcInstance &other);49 50 46 virtual void begin(); 51 47 virtual void end(); … … 73 69 74 70 private: 71 ObjcInstance(const ObjcInstance& other); 72 ObjcInstance& operator=(const ObjcInstance& other); 73 75 74 ObjectStructPtr _instance; 76 75 mutable ObjcClass *_class; -
trunk/JavaScriptCore/bindings/objc/objc_instance.mm
r16310 r20004 53 53 ObjcInstance::~ObjcInstance() 54 54 { 55 begin(); // -finalizeForWebScript and -dealloc/-finalize may require autorelease pools. 55 56 if ([_instance respondsToSelector:@selector(finalizeForWebScript)]) 56 57 [_instance performSelector:@selector(finalizeForWebScript)]; 57 58 if (_instance) 58 59 CFRelease(_instance); 59 } 60 61 ObjcInstance::ObjcInstance(const ObjcInstance &other) : Instance() 62 { 63 _instance = other._instance; 64 if (_instance) 65 CFRetain(_instance); 66 _class = other._class; 67 _pool = 0; 68 _beginCount = 0; 69 } 70 71 ObjcInstance &ObjcInstance::operator=(const ObjcInstance &other) 72 { 73 ObjectStructPtr _oldInstance = _instance; 74 _instance = other._instance; 75 if (_instance) 76 CFRetain(_instance); 77 if (_oldInstance) 78 CFRelease(_oldInstance); 79 // Classes are kept around forever. 80 _class = other._class; 81 return* this; 60 end(); 82 61 } 83 62 -
trunk/JavaScriptCore/kjs/collector.cpp
r19994 r20004 109 109 static CollectorHeap heap = {NULL, 0, 0, 0, NULL, 0, 0, 0, 0}; 110 110 111 size_t Collector::mainThreadOnlyObjectCount = 0; 111 112 bool Collector::memoryFull = false; 112 113 … … 474 475 } 475 476 477 void Collector::collectOnMainThreadOnly(JSValue* value) 478 { 479 ASSERT(value); 480 ASSERT(JSLock::lockCount() > 0); 481 482 if (JSImmediate::isImmediate(value)) 483 return; 484 485 JSCell* cell = value->downcast(); 486 cell->m_collectOnMainThreadOnly = true; 487 ++mainThreadOnlyObjectCount; 488 } 489 476 490 void Collector::markProtectedObjects() 477 491 { … … 485 499 } 486 500 501 void Collector::markMainThreadOnlyObjects() 502 { 503 ASSERT(!pthread_main_np()); 504 505 // Optimization for clients that never register "main thread only" objects. 506 if (!mainThreadOnlyObjectCount) 507 return; 508 509 // FIXME: We can optimize this marking algorithm by keeping an exact set of 510 // "main thread only" objects when the "main thread only" object count is 511 // small. We don't want to keep an exact set all the time, because WebCore 512 // tends to create lots of "main thread only" objects, and all that set 513 // thrashing can be expensive. 514 515 size_t count = 0; 516 517 for (size_t block = 0; block < heap.usedBlocks; block++) { 518 ASSERT(count < mainThreadOnlyObjectCount); 519 520 CollectorBlock* curBlock = heap.blocks[block]; 521 size_t minimumCellsToProcess = curBlock->usedCells; 522 for (size_t i = 0; (i < minimumCellsToProcess) & (i < CELLS_PER_BLOCK); i++) { 523 CollectorCell* cell = curBlock->cells + i; 524 if (cell->u.freeCell.zeroIfFree == 0) 525 ++minimumCellsToProcess; 526 else { 527 JSCell* imp = reinterpret_cast<JSCell*>(cell); 528 if (imp->m_collectOnMainThreadOnly) { 529 if(!imp->marked()) 530 imp->mark(); 531 if (++count == mainThreadOnlyObjectCount) 532 return; 533 } 534 } 535 } 536 } 537 538 for (size_t cell = 0; cell < heap.usedOversizeCells; cell++) { 539 ASSERT(count < mainThreadOnlyObjectCount); 540 541 JSCell* imp = reinterpret_cast<JSCell*>(heap.oversizeCells[cell]); 542 if (imp->m_collectOnMainThreadOnly) { 543 if (!imp->marked()) 544 imp->mark(); 545 if (++count == mainThreadOnlyObjectCount) 546 return; 547 } 548 } 549 } 550 487 551 bool Collector::collect() 488 552 { … … 502 566 Interpreter* scr = Interpreter::s_hook; 503 567 do { 504 scr->mark( currentThreadIsMainThread);568 scr->mark(); 505 569 scr = scr->next; 506 570 } while (scr != Interpreter::s_hook); … … 512 576 markProtectedObjects(); 513 577 List::markProtectedLists(); 578 if (!currentThreadIsMainThread) 579 markMainThreadOnlyObjects(); 514 580 515 581 // SWEEP: delete everything with a zero refcount (garbage) and unmark everything else … … 531 597 if (imp->m_marked) { 532 598 imp->m_marked = false; 533 } else if (currentThreadIsMainThread || imp->m_destructorIsThreadSafe){599 } else { 534 600 // special case for allocated but uninitialized object 535 // (We don't need this check earlier because nothing prior this point assumes the object has a valid vptr.) 601 // (We don't need this check earlier because nothing prior this point 602 // assumes the object has a valid vptr.) 536 603 if (cell->u.freeCell.zeroIfFree == 0) 537 604 continue; 538 605 606 ASSERT(currentThreadIsMainThread || !imp->m_collectOnMainThreadOnly); 607 if (imp->m_collectOnMainThreadOnly) 608 --mainThreadOnlyObjectCount; 539 609 imp->~JSCell(); 540 610 --usedCells; … … 557 627 if (imp->m_marked) { 558 628 imp->m_marked = false; 559 } else if (currentThreadIsMainThread || imp->m_destructorIsThreadSafe) { 629 } else { 630 ASSERT(currentThreadIsMainThread || !imp->m_collectOnMainThreadOnly); 631 if (imp->m_collectOnMainThreadOnly) 632 --mainThreadOnlyObjectCount; 560 633 imp->~JSCell(); 561 634 --usedCells; … … 600 673 JSCell *imp = (JSCell *)heap.oversizeCells[cell]; 601 674 602 if (!imp->m_marked && (currentThreadIsMainThread || imp->m_destructorIsThreadSafe)) { 675 if (imp->m_marked) { 676 imp->m_marked = false; 677 cell++; 678 } else { 679 ASSERT(currentThreadIsMainThread || !imp->m_collectOnMainThreadOnly); 680 if (imp->m_collectOnMainThreadOnly) 681 --mainThreadOnlyObjectCount; 603 682 imp->~JSCell(); 604 683 #if DEBUG_COLLECTOR … … 618 697 heap.oversizeCells = (CollectorCell **)fastRealloc(heap.oversizeCells, heap.numOversizeCells * sizeof(CollectorCell *)); 619 698 } 620 } else {621 imp->m_marked = false;622 cell++;623 699 } 624 700 } -
trunk/JavaScriptCore/kjs/collector.h
r15696 r20004 32 32 namespace KJS { 33 33 34 /**35 * @short Garbage collector.36 */37 34 class Collector { 38 // disallow direct construction/destruction39 Collector();40 35 public: 41 36 static void* allocate(size_t s); … … 54 49 static void protect(JSValue*); 55 50 static void unprotect(JSValue*); 51 52 static void collectOnMainThreadOnly(JSValue*); 56 53 57 54 static size_t numInterpreters(); … … 61 58 class Thread; 62 59 static void registerThread(); 63 60 64 61 private: 62 Collector(); 65 63 66 64 static void markProtectedObjects(); 65 static void markMainThreadOnlyObjects(); 67 66 static void markCurrentThreadConservatively(); 68 67 static void markOtherThreadConservatively(Thread* thread); … … 70 69 static void markStackObjectsConservatively(void* start, void* end); 71 70 71 static size_t mainThreadOnlyObjectCount; 72 72 static bool memoryFull; 73 73 }; -
trunk/JavaScriptCore/kjs/date_object.cpp
r19945 r20004 597 597 : InternalFunctionImp(funcProto) 598 598 { 599 // ECMA 15.9.4.1 Date.prototype 599 static const Identifier* parsePropertyName = new Identifier("parse"); 600 static const Identifier* UTCPropertyName = new Identifier("UTC"); 601 600 602 putDirect(prototypePropertyName, dateProto, DontEnum|DontDelete|ReadOnly); 601 602 static const Identifier parsePropertyName("parse"); 603 putDirectFunction(new DateObjectFuncImp(exec, funcProto, DateObjectFuncImp::Parse, 1, parsePropertyName), DontEnum); 604 static const Identifier UTCPropertyName("UTC"); 605 putDirectFunction(new DateObjectFuncImp(exec, funcProto, DateObjectFuncImp::UTC, 7, UTCPropertyName), DontEnum); 606 607 // no. of arguments for constructor 603 putDirectFunction(new DateObjectFuncImp(exec, funcProto, DateObjectFuncImp::Parse, 1, *parsePropertyName), DontEnum); 604 putDirectFunction(new DateObjectFuncImp(exec, funcProto, DateObjectFuncImp::UTC, 7, *UTCPropertyName), DontEnum); 608 605 putDirect(lengthPropertyName, 7, ReadOnly|DontDelete|DontEnum); 609 606 } -
trunk/JavaScriptCore/kjs/function_object.cpp
r19203 r20004 41 41 FunctionPrototype::FunctionPrototype(ExecState *exec) 42 42 { 43 static const Identifier* applyPropertyName = new Identifier("apply"); 44 static const Identifier* callPropertyName = new Identifier("call"); 45 43 46 putDirect(lengthPropertyName, jsNumber(0), DontDelete|ReadOnly|DontEnum); 44 47 putDirectFunction(new FunctionProtoFunc(exec, this, FunctionProtoFunc::ToString, 0, toStringPropertyName), DontEnum); 45 static const Identifier applyPropertyName("apply"); 46 putDirectFunction(new FunctionProtoFunc(exec, this, FunctionProtoFunc::Apply, 2, applyPropertyName), DontEnum); 47 static const Identifier callPropertyName("call"); 48 putDirectFunction(new FunctionProtoFunc(exec, this, FunctionProtoFunc::Call, 1, callPropertyName), DontEnum); 48 putDirectFunction(new FunctionProtoFunc(exec, this, FunctionProtoFunc::Apply, 2, *applyPropertyName), DontEnum); 49 putDirectFunction(new FunctionProtoFunc(exec, this, FunctionProtoFunc::Call, 1, *callPropertyName), DontEnum); 49 50 } 50 51 -
trunk/JavaScriptCore/kjs/identifier.cpp
r17405 r20004 39 39 #include "identifier.h" 40 40 41 #include "JSLock.h" 42 #include <new> // for placement new 43 #include <string.h> // for strlen 44 #include <wtf/Assertions.h> 41 45 #include <wtf/FastMalloc.h> 42 46 #include <wtf/HashSet.h> 43 #include <string.h> // for strlen44 #include <new> // for placement new45 47 46 48 namespace WTF { … … 67 69 static inline IdentifierTable& identifierTable() 68 70 { 71 ASSERT(JSLock::lockCount() > 0); 72 69 73 if (!table) 70 74 table = new IdentifierTable; -
trunk/JavaScriptCore/kjs/interpreter.cpp
r19901 r20004 538 538 } 539 539 540 void Interpreter::mark( bool)540 void Interpreter::mark() 541 541 { 542 542 if (m_context) -
trunk/JavaScriptCore/kjs/interpreter.h
r19901 r20004 287 287 * implementing custom mark methods must make sure to chain to this one. 288 288 */ 289 virtual void mark( bool currentThreadIsMainThread);289 virtual void mark(); 290 290 291 291 #ifdef KJS_DEBUG_MEM -
trunk/JavaScriptCore/kjs/list.cpp
r15698 r20004 142 142 static inline ListImp *allocateListImp() 143 143 { 144 ASSERT(JSLock::lockCount() > 0); 145 144 146 // Find a free one in the pool. 145 147 if (poolUsed < poolSize) { … … 202 204 203 205 void List::release() 204 { 206 { 207 ASSERT(JSLock::lockCount() > 0); 208 205 209 ListImp *imp = static_cast<ListImp *>(_impBase); 206 210 … … 222 226 poolUsed--; 223 227 } else { 224 assert(imp->state == usedOnHeap);228 ASSERT(imp->state == usedOnHeap); 225 229 HeapListImp *list = static_cast<HeapListImp *>(imp); 226 230 … … 259 263 void List::append(JSValue *v) 260 264 { 265 ASSERT(JSLock::lockCount() > 0); 266 261 267 ListImp *imp = static_cast<ListImp *>(_impBase); 262 268 … … 332 338 } 333 339 334 const List &List::empty()335 { 336 static List emptyList;337 return emptyList;340 const List& List::empty() 341 { 342 static List* staticEmptyList = new List; 343 return *staticEmptyList; 338 344 } 339 345 -
trunk/JavaScriptCore/kjs/object.h
r17372 r20004 107 107 * @param proto The prototype 108 108 */ 109 JSObject(JSValue* proto , bool destructorIsThreadSafe = true);109 JSObject(JSValue* proto); 110 110 111 111 /** … … 113 113 * (that is, the ECMAScript "null" value, not a null object pointer). 114 114 */ 115 explicit JSObject(bool destructorIsThreadSafe = true);115 JSObject(); 116 116 117 117 virtual void mark(); … … 503 503 JSObject *throwError(ExecState *, ErrorType); 504 504 505 inline JSObject::JSObject(JSValue* proto, bool destructorIsThreadSafe) 506 : JSCell(destructorIsThreadSafe) 507 , _proto(proto) 505 inline JSObject::JSObject(JSValue* proto) 506 : _proto(proto) 508 507 { 509 508 assert(proto); 510 509 } 511 510 512 inline JSObject::JSObject(bool destructorIsThreadSafe) 513 : JSCell(destructorIsThreadSafe) 514 , _proto(jsNull()) 511 inline JSObject::JSObject() 512 : _proto(jsNull()) 515 513 { 516 514 } -
trunk/JavaScriptCore/kjs/object_object.cpp
r13833 r20004 34 34 : JSObject() // [[Prototype]] is null 35 35 { 36 static const Identifier* hasOwnPropertyPropertyName = new Identifier("hasOwnProperty"); 37 static const Identifier* propertyIsEnumerablePropertyName = new Identifier("propertyIsEnumerable"); 38 static const Identifier* isPrototypeOfPropertyName = new Identifier("isPrototypeOf"); 39 static const Identifier* defineGetterPropertyName = new Identifier("__defineGetter__"); 40 static const Identifier* defineSetterPropertyName = new Identifier("__defineSetter__"); 41 static const Identifier* lookupGetterPropertyName = new Identifier("__lookupGetter__"); 42 static const Identifier* lookupSetterPropertyName = new Identifier("__lookupSetter__"); 43 36 44 putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::ToString, 0, toStringPropertyName), DontEnum); 37 45 putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::ToLocaleString, 0, toLocaleStringPropertyName), DontEnum); 38 46 putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::ValueOf, 0, valueOfPropertyName), DontEnum); 39 static Identifier hasOwnPropertyPropertyName("hasOwnProperty"); 40 static Identifier propertyIsEnumerablePropertyName("propertyIsEnumerable"); 41 static Identifier isPrototypeOfPropertyName("isPrototypeOf"); 42 putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::HasOwnProperty, 1, hasOwnPropertyPropertyName), DontEnum); 43 putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::PropertyIsEnumerable, 1, propertyIsEnumerablePropertyName), DontEnum); 44 putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::IsPrototypeOf, 1, isPrototypeOfPropertyName), DontEnum); 47 putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::HasOwnProperty, 1, *hasOwnPropertyPropertyName), DontEnum); 48 putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::PropertyIsEnumerable, 1, *propertyIsEnumerablePropertyName), DontEnum); 49 putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::IsPrototypeOf, 1, *isPrototypeOfPropertyName), DontEnum); 45 50 46 51 // Mozilla extensions 47 static const Identifier defineGetterPropertyName("__defineGetter__"); 48 static const Identifier defineSetterPropertyName("__defineSetter__"); 49 static const Identifier lookupGetterPropertyName("__lookupGetter__"); 50 static const Identifier lookupSetterPropertyName("__lookupSetter__"); 51 putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::DefineGetter, 2, defineGetterPropertyName), DontEnum); 52 putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::DefineSetter, 2, defineSetterPropertyName), DontEnum); 53 putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::LookupGetter, 1, lookupGetterPropertyName), DontEnum); 54 putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::LookupSetter, 1, lookupSetterPropertyName), DontEnum); 52 putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::DefineGetter, 2, *defineGetterPropertyName), DontEnum); 53 putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::DefineSetter, 2, *defineSetterPropertyName), DontEnum); 54 putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::LookupGetter, 1, *lookupGetterPropertyName), DontEnum); 55 putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::LookupSetter, 1, *lookupSetterPropertyName), DontEnum); 55 56 } 56 57 -
trunk/JavaScriptCore/kjs/regexp_object.cpp
r18256 r20004 49 49 : JSObject(objProto) 50 50 { 51 // The constructor will be added later in RegExpObject's constructor (?) 52 53 static const Identifier execPropertyName("exec"); 54 static const Identifier testPropertyName("test"); 55 putDirectFunction(new RegExpProtoFunc(exec, funcProto, RegExpProtoFunc::Exec, 0, execPropertyName), DontEnum); 56 putDirectFunction(new RegExpProtoFunc(exec, funcProto, RegExpProtoFunc::Test, 0, testPropertyName), DontEnum); 51 static const Identifier* execPropertyName = new Identifier("exec"); 52 static const Identifier* testPropertyName = new Identifier("test"); 53 54 putDirectFunction(new RegExpProtoFunc(exec, funcProto, RegExpProtoFunc::Exec, 0, *execPropertyName), DontEnum); 55 putDirectFunction(new RegExpProtoFunc(exec, funcProto, RegExpProtoFunc::Test, 0, *testPropertyName), DontEnum); 57 56 putDirectFunction(new RegExpProtoFunc(exec, funcProto, RegExpProtoFunc::ToString, 0, toStringPropertyName), DontEnum); 58 57 } -
trunk/JavaScriptCore/kjs/ustring.cpp
r19679 r20004 25 25 #include "ustring.h" 26 26 27 #include "JSLock.h" 28 #include "dtoa.h" 29 #include "identifier.h" 30 #include "operations.h" 27 31 #include <assert.h> 32 #include <ctype.h> 33 #include <float.h> 34 #include <math.h> 35 #include <stdio.h> 28 36 #include <stdlib.h> 29 #include < stdio.h>30 #include <ctype.h> 37 #include <wtf/Vector.h> 38 31 39 #if HAVE(STRING_H) 32 40 #include <string.h> … … 35 43 #include <strings.h> 36 44 #endif 37 38 #include "dtoa.h"39 #include "identifier.h"40 #include "operations.h"41 #include <float.h>42 #include <math.h>43 #include <wtf/Vector.h>44 45 45 46 using std::max; … … 155 156 UChar& UCharReference::ref() const 156 157 { 158 ASSERT(JSLock::lockCount() > 0); 159 157 160 if (offset < str->rep()->len) 158 161 return *(str->rep()->data() + offset); … … 165 168 PassRefPtr<UString::Rep> UString::Rep::createCopying(const UChar *d, int l) 166 169 { 170 ASSERT(JSLock::lockCount() > 0); 171 167 172 int sizeInBytes = l * sizeof(UChar); 168 173 UChar *copyD = static_cast<UChar *>(fastMalloc(sizeInBytes)); … … 174 179 PassRefPtr<UString::Rep> UString::Rep::create(UChar *d, int l) 175 180 { 181 ASSERT(JSLock::lockCount() > 0); 182 176 183 Rep *r = new Rep; 177 184 r->offset = 0; … … 193 200 PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<Rep> base, int offset, int length) 194 201 { 195 assert(base); 202 ASSERT(JSLock::lockCount() > 0); 203 ASSERT(base); 196 204 197 205 int baseOffset = base->offset; … … 223 231 void UString::Rep::destroy() 224 232 { 233 ASSERT(JSLock::lockCount() > 0); 234 225 235 if (isIdentifier) 226 236 Identifier::remove(this); … … 467 477 } 468 478 469 const UString &UString::null()470 { 471 static UString n;472 return n;479 const UString& UString::null() 480 { 481 static UString* n = new UString; 482 return *n; 473 483 } 474 484 -
trunk/JavaScriptCore/kjs/ustring.h
r19679 r20004 25 25 #define _KJS_USTRING_H_ 26 26 27 #include "JSLock.h" 28 #include <stdint.h> 29 #include <wtf/Assertions.h> 27 30 #include <wtf/FastMalloc.h> 31 #include <wtf/PassRefPtr.h> 28 32 #include <wtf/RefPtr.h> 29 #include <wtf/PassRefPtr.h>30 31 #include <stdint.h>32 33 33 34 /* On ARM some versions of GCC don't pack structures by default so sizeof(UChar) … … 200 201 static unsigned computeHash(const char *); 201 202 202 Rep* ref() { ++rc; return this; }203 void deref() { if (--rc == 0) destroy(); }203 Rep* ref() { ASSERT(JSLock::lockCount() > 0); ++rc; return this; } 204 void deref() { ASSERT(JSLock::lockCount() > 0); if (--rc == 0) destroy(); } 204 205 205 206 // unshared data -
trunk/JavaScriptCore/kjs/value.h
r18715 r20004 123 123 friend class GetterSetterImp; 124 124 private: 125 explicit JSCell(bool destructorIsThreadSafe = true);125 JSCell(); 126 126 virtual ~JSCell(); 127 127 public: … … 157 157 158 158 private: 159 bool m_ destructorIsThreadSafe: 1;159 bool m_collectOnMainThreadOnly : 1; 160 160 bool m_marked : 1; 161 161 }; … … 204 204 } 205 205 206 inline JSCell::JSCell( bool destructorIsThreadSafe)207 : m_ destructorIsThreadSafe(destructorIsThreadSafe)206 inline JSCell::JSCell() 207 : m_collectOnMainThreadOnly(false) 208 208 , m_marked(false) 209 209 { -
trunk/JavaScriptGlue/ChangeLog
r19805 r20004 1 2007-03-06 Geoffrey Garen <ggaren@apple.com> 2 3 Reviewed by Maciej Stachowiak. 4 5 Fixed all known crashers exposed by run-webkit-tests --threaded while using 6 a PAC file (for maximum carnage). See JavaScriptCore ChangeLog for 7 more details. 8 9 * JSBase.cpp: 10 (JSBase::Release): Lock when deleting, because we may be deleting an object 11 (like a JSRun) that holds thread-unsafe data. 12 13 * JSUtils.cpp: 14 (CFStringToUString): Don't lock, because our caller locks. Also, locking 15 inside a function that returns thread-unsafe data by copy will only mask 16 threading problems. 17 18 * JavaScriptGlue.cpp: 19 (JSRunEvaluate): Added missing JSLock. 20 (JSRunCheckSyntax): Converted to JSLock. 21 * JavaScriptGlue.xcodeproj/project.pbxproj: 22 1 23 2007-02-22 Geoffrey Garen <ggaren@apple.com> 2 24 -
trunk/JavaScriptGlue/JSBase.cpp
r13089 r20004 47 47 if (--fRetainCount == 0) 48 48 { 49 JSLock lock; 49 50 delete this; 50 51 } -
trunk/JavaScriptGlue/JSUtils.cpp
r19666 r20004 52 52 UString CFStringToUString(CFStringRef inCFString) 53 53 { 54 JSLock lock;55 56 54 UString result; 57 55 if (inCFString) { -
trunk/JavaScriptGlue/JavaScriptGlue.cpp
r13089 r20004 288 288 if (ptr) 289 289 { 290 JSLock lock; 290 291 Completion completion = ptr->Evaluate(); 291 292 if (completion.isValueCompletion()) … … 321 322 if (ptr) 322 323 { 323 JSLock Interpreter();324 JSLock lock; 324 325 result = ptr->CheckSyntax(); 325 JSUnlockInterpreter();326 326 } 327 327 return result; -
trunk/JavaScriptGlue/JavaScriptGlue.xcodeproj/project.pbxproj
r19725 r20004 271 271 isa = PBXProject; 272 272 buildConfigurationList = 14AC662B08CE7791006915A8 /* Build configuration list for PBXProject "JavaScriptGlue" */; 273 compatibilityVersion = "Xcode 2.4";274 273 hasScannedForEncodings = 1; 275 274 mainGroup = 0867D691FE84028FC02AAC07 /* JavaScriptGlue */; … … 277 276 projectDirPath = ""; 278 277 projectRoot = ""; 279 shouldCheckCompatibility = 1;280 278 targets = ( 281 279 DD66F3B908F73ED700C75FD7 /* JavaScriptGlue */, -
trunk/WebCore/ChangeLog
r20001 r20004 1 2007-03-06 Geoffrey Garen <ggaren@apple.com> 2 3 Reviewed by Maciej Stachowiak. 4 5 Fixed all known crashers exposed by run-webkit-tests --threaded [*]. See 6 JavaScriptCore ChangeLog for more details. 7 8 * bindings/js/kjs_binding.cpp: 9 (KJS::domNodesPerDocument): Added thread safety ASSERT. 10 (KJS::ScriptInterpreter::mark): Removed obsolete logic for marking unsafe 11 objects when collecting on a secondary thread. The Collector takes care 12 of this now. 13 14 * bindings/js/kjs_binding.h: 15 (KJS::DOMObject::DOMObject): Used new API for specifying that WebCore 16 objects should be garbage collected on the main thread only. 17 18 * bindings/js/kjs_window.cpp: 19 (KJS::ScheduledAction::execute): Moved JSLock to cover implementedsCall() call, 20 which, for some subclasses, ends up allocating garbage collected objects. 21 (This fix was speculative. I didn't actually see a crash from this.) 22 (KJS::Window::timerFired): Added JSLock around ScheduleAction destruction, 23 since it destroys a KJS::List. 24 25 * bindings/objc/WebScriptObject.mm: 26 (-[WebScriptObject setException:]): Added JSLock. (This fix was speculative. 27 I didn't actually see a crash from this.) 28 29 * bridge/mac/WebCoreScriptDebugger.mm: 30 (-[WebCoreScriptCallFrame evaluateWebScript:]): Added JSLock. (This fix 31 was speculative. I didn't actually see a crash from this.) 32 33 * dom/Document.cpp: 34 (WebCore::Document::~Document): Added JSLock around modification to 35 domNodesPerDocument(), which can be accessed concurrently during garbage 36 collection. 37 * dom/Node.cpp: 38 (WebCore::Node::setDocument): ditto. 39 40 [*] fast/js/toString-stack-overflow.html is an exception. --threaded mode 41 crashes this test because it causes the garbage collector to run frequently, 42 and this test crashes if you happen to garbage collect while it's running. 43 This is a known issue with stack overflow during the mark phase. It's 44 not related to threading. 45 1 46 2007-03-06 Mark Rowe <mrowe@apple.com> 2 47 -
trunk/WebCore/bindings/js/kjs_binding.cpp
r19855 r20004 120 120 static NodePerDocMap& domNodesPerDocument() 121 121 { 122 // domNodesPerDocument() callers must synchronize using the JSLock because 123 // domNodesPerDocument() is called during garbage collection, which can happen 124 // on a secondary thread. 125 ASSERT(JSLock::lockCount()); 126 122 127 static NodePerDocMap staticDOMNodesPerDocument; 123 128 return staticDOMNodesPerDocument; … … 215 220 } 216 221 } 217 }218 219 void ScriptInterpreter::mark(bool currentThreadIsMainThread)220 {221 if (!currentThreadIsMainThread) {222 // On alternate threads, DOMObjects remain in the cache because they're not collected.223 // So, they need an opportunity to mark their children.224 DOMObjectMap::iterator objectEnd = domObjects().end();225 for (DOMObjectMap::iterator objectIt = domObjects().begin(); objectIt != objectEnd; ++objectIt) {226 DOMObject* object = objectIt->second;227 if (!object->marked())228 object->mark();229 }230 }231 232 Interpreter::mark(currentThreadIsMainThread);233 222 } 234 223 -
trunk/WebCore/bindings/js/kjs_binding.h
r19013 r20004 47 47 class DOMObject : public JSObject { 48 48 protected: 49 // DOMObject Destruction is not thread-safe because JS DOM objects 50 // wrap unsafe WebCore DOM data structures 51 DOMObject() : JSObject(false) {} 49 DOMObject() 50 { 51 // DOMObject destruction is not thread-safe because DOMObjects wrap 52 // unsafe WebCore DOM data structures. 53 Collector::collectOnMainThreadOnly(this); 54 } 52 55 #ifndef NDEBUG 53 56 virtual ~DOMObject(); … … 93 96 bool wasRunByUserGesture() const; 94 97 95 virtual void mark(bool currentThreadIsMainThread);96 98 virtual ExecState* globalExec(); 97 99 -
trunk/WebCore/bindings/js/kjs_window.cpp
r19995 r20004 84 84 DOMWindowTimer(int timeoutId, int nestingLevel, Window* o, ScheduledAction* a) 85 85 : m_timeoutId(timeoutId), m_nestingLevel(nestingLevel), m_object(o), m_action(a) { } 86 virtual ~DOMWindowTimer() { delete m_action; } 86 virtual ~DOMWindowTimer() 87 { 88 JSLock lock; 89 delete m_action; 90 } 87 91 88 92 int timeoutId() const { return m_timeoutId; } … … 1849 1853 1850 1854 if (JSValue* func = m_func.get()) { 1855 JSLock lock; 1851 1856 if (func->isObject() && static_cast<JSObject*>(func)->implementsCall()) { 1852 1857 ExecState* exec = interpreter->globalExec(); 1853 1858 ASSERT(window == interpreter->globalObject()); 1854 JSLock lock;1855 1859 interpreter->startTimeoutCheck(); 1856 1860 static_cast<JSObject*>(func)->call(exec, window, m_args); … … 1991 1995 delete timer; 1992 1996 action->execute(this); 1997 1998 JSLock lock; 1993 1999 delete action; 1994 2000 } -
trunk/WebCore/bindings/objc/WebScriptObject.mm
r19747 r20004 418 418 return; 419 419 420 JSLock lock; 421 420 422 if ([self _rootObject]->interpreter()->context()) { 421 423 ExecState *exec = [self _rootObject]->interpreter()->context()->execState(); -
trunk/WebCore/bridge/mac/WebCoreScriptDebugger.mm
r19747 r20004 337 337 - (id)evaluateWebScript:(NSString *)script 338 338 { 339 JSLock lock; 340 339 341 UString code = String(script); 340 342 … … 360 362 JSValue *result; 361 363 if (eval) { 362 JSLock lock;363 364 List args; 364 365 args.append(jsString(code)); -
trunk/WebCore/dom/Document.cpp
r19952 r20004 393 393 394 394 XMLHttpRequest::detachRequests(this); 395 KJS::ScriptInterpreter::forgetAllDOMNodesForDocument(this); 395 { 396 KJS::JSLock lock; 397 KJS::ScriptInterpreter::forgetAllDOMNodesForDocument(this); 398 } 396 399 397 400 if (m_docChanged && changedDocuments) -
trunk/WebCore/dom/Node.cpp
r19855 r20004 170 170 return; 171 171 172 KJS::ScriptInterpreter::updateDOMNodeDocument(this, m_document.get(), doc); 172 { 173 KJS::JSLock lock; 174 KJS::ScriptInterpreter::updateDOMNodeDocument(this, m_document.get(), doc); 175 } 173 176 m_document = doc; 174 177 }
Note: See TracChangeset
for help on using the changeset viewer.