<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; }
#msg ul, pre { overflow: auto; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<title>[20004] trunk</title>
</head>
<body>
<div id="msg">
<dl>
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/20004">20004</a></dd>
<dt>Author</dt> <dd>ggaren</dd>
<dt>Date</dt> <dd>2007-03-06 20:25:49 -0800 (Tue, 06 Mar 2007)</dd>
</dl>
<h3>Log Message</h3>
<pre>JavaScriptCore:
Reviewed by Maciej Stachowiak.
Fixed all known crashers exposed by run-webkit-tests --threaded. This covers:
<rdar://problem/4565394> | http://bugs.webkit.org/show_bug.cgi?id=12585
PAC file: after closing a window that contains macworld.com, new window
crashes (KJS::PropertyMap::mark()) (12585)
<rdar://problem/4571215> | http://bugs.webkit.org/show_bug.cgi?id=9211
PAC file: Crash occurs when clicking on the navigation tabs at http://www.businessweek.com/ (9211)
<rdar://problem/4557926>
PAC file: Crash occurs when attempting to view image in slideshow mode
at http://d.smugmug.com/gallery/581716 ( KJS::IfNode::execute (KJS::
ExecState*) + 312) if you use a PAC file
(1) Added some missing JSLocks, along with related ASSERTs.
(2) Fully implemented support for objects that can only be garbage collected
on the main thread. So far, only WebCore uses this. We can add it to API
later if we learn that it's needed.
The implementation uses a "main thread only" flag inside each object. When
collecting on a secondary thread, the Collector does an extra pass through
the heap to mark all flagged objects before sweeping. This solution makes
the common case -- flag lots of objects, but never collect on a secondary
thread -- very fast, even though the uncommon case of garbage collecting
on a secondary thread isn't as fast as it could be. I left some notes
about how to speed it up, if we ever care.
For posterity, here are some things I learned about GC while investigating:
* Each collect must either mark or delete every heap object. "Zombie"
objects, which are neither marked nor deleted, raise these issues:
* On the next pass, the conservative marking algorithm might mark a
zombie, causing it to mark freed objects.
* The client might try to use a zombie, which would seem live because
its finalizer had not yet run.
* A collect on the main thread is free to delete any object. Presumably,
objects allocated on secondary threads have thread-safe finalizers.
* A collect on a secondary thread must not delete thread-unsafe objects.
* The mark function must be thread-safe.
Line by line comments:
* API/JSObjectRef.h: Added comment specifying that the finalize callback
may run on any thread.
* JavaScriptCore.exp: Nothing to see here.
* bindings/npruntime.cpp:
(_NPN_GetStringIdentifier): Added JSLock.
* bindings/objc/objc_instance.h:
* bindings/objc/objc_instance.mm:
(ObjcInstance::~ObjcInstance): Use an autorelease pool. The other callers
to CFRelease needed one, too, but they were dead code, so I removed them
instead. (This fixes a leak seen while running run-webkit-tests --threaded,
although I don't think it's specifically a threading issue.)
* kjs/collector.cpp:
(KJS::Collector::collectOnMainThreadOnly): New function. Tells the collector
to collect a value only if it's collecting on the main thread.
(KJS::Collector::markMainThreadOnlyObjects): New function. Scans the heap
for "main thread only" objects and marks them.
* kjs/date_object.cpp:
(KJS::DateObjectImp::DateObjectImp): To make the new ASSERTs happy, allocate
our globals on the heap, avoiding a seemingly unsafe destructor call at
program exit time.
* kjs/function_object.cpp:
(FunctionPrototype::FunctionPrototype): ditto
* kjs/interpreter.cpp:
(KJS::Interpreter::mark): Removed boolean parameter, which was an incomplete
and arguably hackish way to implement markMainThreadOnlyObjects() inside WebCore.
* kjs/interpreter.h:
* kjs/identifier.cpp:
(KJS::identifierTable): Added some ASSERTs to check for thread safety
problems.
* kjs/list.cpp: Added some ASSERTs to check for thread safety problems.
(KJS::allocateListImp):
(KJS::List::release):
(KJS::List::append):
(KJS::List::empty): Make the new ASSERTs happy.
* kjs/object.h:
(KJS::JSObject::JSObject): "m_destructorIsThreadSafe" => "m_collectOnMainThreadOnly".
I removed the constructor parameter because m_collectOnMainThreadOnly,
like m_marked, is a Collector bit, so only the Collector should set or get it.
* kjs/object_object.cpp:
(ObjectPrototype::ObjectPrototype): Make the ASSERTs happy.
* kjs/regexp_object.cpp:
(RegExpPrototype::RegExpPrototype): ditto
* kjs/ustring.cpp: Added some ASSERTs to check for thread safety problems.
(KJS::UCharReference::ref):
(KJS::UString::Rep::createCopying):
(KJS::UString::Rep::create):
(KJS::UString::Rep::destroy):
(KJS::UString::null): Make the new ASSERTs happy.
* kjs/ustring.h:
(KJS::UString::Rep::ref): Added some ASSERTs to check for thread safety problems.
(KJS::UString::Rep::deref):
* kjs/value.h:
(KJS::JSCell::JSCell):
JavaScriptGlue:
Reviewed by Maciej Stachowiak.
Fixed all known crashers exposed by run-webkit-tests --threaded while using
a PAC file (for maximum carnage). See JavaScriptCore ChangeLog for
more details.
* JSBase.cpp:
(JSBase::Release): Lock when deleting, because we may be deleting an object
(like a JSRun) that holds thread-unsafe data.
* JSUtils.cpp:
(CFStringToUString): Don't lock, because our caller locks. Also, locking
inside a function that returns thread-unsafe data by copy will only mask
threading problems.
* JavaScriptGlue.cpp:
(JSRunEvaluate): Added missing JSLock.
(JSRunCheckSyntax): Converted to JSLock.
* JavaScriptGlue.xcodeproj/project.pbxproj:
WebCore:
Reviewed by Maciej Stachowiak.
Fixed all known crashers exposed by run-webkit-tests --threaded [*]. See
JavaScriptCore ChangeLog for more details.
* bindings/js/kjs_binding.cpp:
(KJS::domNodesPerDocument): Added thread safety ASSERT.
(KJS::ScriptInterpreter::mark): Removed obsolete logic for marking unsafe
objects when collecting on a secondary thread. The Collector takes care
of this now.
* bindings/js/kjs_binding.h:
(KJS::DOMObject::DOMObject): Used new API for specifying that WebCore
objects should be garbage collected on the main thread only.
* bindings/js/kjs_window.cpp:
(KJS::ScheduledAction::execute): Moved JSLock to cover implementedsCall() call,
which, for some subclasses, ends up allocating garbage collected objects.
(This fix was speculative. I didn't actually see a crash from this.)
(KJS::Window::timerFired): Added JSLock around ScheduleAction destruction,
since it destroys a KJS::List.
* bindings/objc/WebScriptObject.mm:
(-[WebScriptObject setException:]): Added JSLock. (This fix was speculative.
I didn't actually see a crash from this.)
* bridge/mac/WebCoreScriptDebugger.mm:
(-[WebCoreScriptCallFrame evaluateWebScript:]): Added JSLock. (This fix
was speculative. I didn't actually see a crash from this.)
* dom/Document.cpp:
(WebCore::Document::~Document): Added JSLock around modification to
domNodesPerDocument(), which can be accessed concurrently during garbage
collection.
* dom/Node.cpp:
(WebCore::Node::setDocument): ditto.
[*] fast/js/toString-stack-overflow.html is an exception. --threaded mode
crashes this test because it causes the garbage collector to run frequently,
and this test crashes if you happen to garbage collect while it's running.
This is a known issue with stack overflow during the mark phase. It's
not related to threading.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJavaScriptCoreAPIJSObjectRefh">trunk/JavaScriptCore/API/JSObjectRef.h</a></li>
<li><a href="#trunkJavaScriptCoreChangeLog">trunk/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkJavaScriptCoreJavaScriptCoreexp">trunk/JavaScriptCore/JavaScriptCore.exp</a></li>
<li><a href="#trunkJavaScriptCorebindingsnpruntimecpp">trunk/JavaScriptCore/bindings/npruntime.cpp</a></li>
<li><a href="#trunkJavaScriptCorebindingsobjcobjc_instanceh">trunk/JavaScriptCore/bindings/objc/objc_instance.h</a></li>
<li><a href="#trunkJavaScriptCorebindingsobjcobjc_instancemm">trunk/JavaScriptCore/bindings/objc/objc_instance.mm</a></li>
<li><a href="#trunkJavaScriptCorekjscollectorcpp">trunk/JavaScriptCore/kjs/collector.cpp</a></li>
<li><a href="#trunkJavaScriptCorekjscollectorh">trunk/JavaScriptCore/kjs/collector.h</a></li>
<li><a href="#trunkJavaScriptCorekjsdate_objectcpp">trunk/JavaScriptCore/kjs/date_object.cpp</a></li>
<li><a href="#trunkJavaScriptCorekjsfunction_objectcpp">trunk/JavaScriptCore/kjs/function_object.cpp</a></li>
<li><a href="#trunkJavaScriptCorekjsidentifiercpp">trunk/JavaScriptCore/kjs/identifier.cpp</a></li>
<li><a href="#trunkJavaScriptCorekjsinterpretercpp">trunk/JavaScriptCore/kjs/interpreter.cpp</a></li>
<li><a href="#trunkJavaScriptCorekjsinterpreterh">trunk/JavaScriptCore/kjs/interpreter.h</a></li>
<li><a href="#trunkJavaScriptCorekjslistcpp">trunk/JavaScriptCore/kjs/list.cpp</a></li>
<li><a href="#trunkJavaScriptCorekjsobjecth">trunk/JavaScriptCore/kjs/object.h</a></li>
<li><a href="#trunkJavaScriptCorekjsobject_objectcpp">trunk/JavaScriptCore/kjs/object_object.cpp</a></li>
<li><a href="#trunkJavaScriptCorekjsregexp_objectcpp">trunk/JavaScriptCore/kjs/regexp_object.cpp</a></li>
<li><a href="#trunkJavaScriptCorekjsustringcpp">trunk/JavaScriptCore/kjs/ustring.cpp</a></li>
<li><a href="#trunkJavaScriptCorekjsustringh">trunk/JavaScriptCore/kjs/ustring.h</a></li>
<li><a href="#trunkJavaScriptCorekjsvalueh">trunk/JavaScriptCore/kjs/value.h</a></li>
<li><a href="#trunkJavaScriptGlueChangeLog">trunk/JavaScriptGlue/ChangeLog</a></li>
<li><a href="#trunkJavaScriptGlueJSBasecpp">trunk/JavaScriptGlue/JSBase.cpp</a></li>
<li><a href="#trunkJavaScriptGlueJSUtilscpp">trunk/JavaScriptGlue/JSUtils.cpp</a></li>
<li><a href="#trunkJavaScriptGlueJavaScriptGluecpp">trunk/JavaScriptGlue/JavaScriptGlue.cpp</a></li>
<li><a href="#trunkJavaScriptGlueJavaScriptGluexcodeprojprojectpbxproj">trunk/JavaScriptGlue/JavaScriptGlue.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkWebCoreChangeLog">trunk/WebCore/ChangeLog</a></li>
<li><a href="#trunkWebCorebindingsjskjs_bindingcpp">trunk/WebCore/bindings/js/kjs_binding.cpp</a></li>
<li><a href="#trunkWebCorebindingsjskjs_bindingh">trunk/WebCore/bindings/js/kjs_binding.h</a></li>
<li><a href="#trunkWebCorebindingsjskjs_windowcpp">trunk/WebCore/bindings/js/kjs_window.cpp</a></li>
<li><a href="#trunkWebCorebindingsobjcWebScriptObjectmm">trunk/WebCore/bindings/objc/WebScriptObject.mm</a></li>
<li><a href="#trunkWebCorebridgemacWebCoreScriptDebuggermm">trunk/WebCore/bridge/mac/WebCoreScriptDebugger.mm</a></li>
<li><a href="#trunkWebCoredomDocumentcpp">trunk/WebCore/dom/Document.cpp</a></li>
<li><a href="#trunkWebCoredomNodecpp">trunk/WebCore/dom/Node.cpp</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJavaScriptCoreAPIJSObjectRefh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/API/JSObjectRef.h (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/API/JSObjectRef.h        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/API/JSObjectRef.h        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -90,7 +90,7 @@
</span><span class="cx">
</span><span class="cx"> /*!
</span><span class="cx"> @typedef JSObjectFinalizeCallback
</span><del>-@abstract The callback invoked when an object is finalized (prepared for garbage collection).
</del><ins>+@abstract The callback invoked when an object is finalized (prepared for garbage collection). An object may be finalized on any thread.
</ins><span class="cx"> @param object The JSObject being finalized.
</span><span class="cx"> @discussion If you named your function Finalize, you would declare it like this:
</span><span class="cx">
</span></span></pre></div>
<a id="trunkJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/ChangeLog (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/ChangeLog        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/ChangeLog        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -2,6 +2,122 @@
</span><span class="cx">
</span><span class="cx"> Reviewed by Maciej Stachowiak.
</span><span class="cx">
</span><ins>+ Fixed all known crashers exposed by run-webkit-tests --threaded. This covers:
+
+ <rdar://problem/4565394> | http://bugs.webkit.org/show_bug.cgi?id=12585
+ PAC file: after closing a window that contains macworld.com, new window
+ crashes (KJS::PropertyMap::mark()) (12585)
+ <rdar://problem/4571215> | http://bugs.webkit.org/show_bug.cgi?id=9211
+ PAC file: Crash occurs when clicking on the navigation tabs at http://www.businessweek.com/ (9211)
+ <rdar://problem/4557926>
+ PAC file: Crash occurs when attempting to view image in slideshow mode
+ at http://d.smugmug.com/gallery/581716 ( KJS::IfNode::execute (KJS::
+ ExecState*) + 312) if you use a PAC file
+
+ (1) Added some missing JSLocks, along with related ASSERTs.
+
+ (2) Fully implemented support for objects that can only be garbage collected
+ on the main thread. So far, only WebCore uses this. We can add it to API
+ later if we learn that it's needed.
+
+ The implementation uses a "main thread only" flag inside each object. When
+ collecting on a secondary thread, the Collector does an extra pass through
+ the heap to mark all flagged objects before sweeping. This solution makes
+ the common case -- flag lots of objects, but never collect on a secondary
+ thread -- very fast, even though the uncommon case of garbage collecting
+ on a secondary thread isn't as fast as it could be. I left some notes
+ about how to speed it up, if we ever care.
+
+ For posterity, here are some things I learned about GC while investigating:
+
+ * Each collect must either mark or delete every heap object. "Zombie"
+ objects, which are neither marked nor deleted, raise these issues:
+
+ * On the next pass, the conservative marking algorithm might mark a
+ zombie, causing it to mark freed objects.
+
+ * The client might try to use a zombie, which would seem live because
+ its finalizer had not yet run.
+
+ * A collect on the main thread is free to delete any object. Presumably,
+ objects allocated on secondary threads have thread-safe finalizers.
+
+ * A collect on a secondary thread must not delete thread-unsafe objects.
+
+ * The mark function must be thread-safe.
+
+ Line by line comments:
+
+ * API/JSObjectRef.h: Added comment specifying that the finalize callback
+ may run on any thread.
+
+ * JavaScriptCore.exp: Nothing to see here.
+
+ * bindings/npruntime.cpp:
+ (_NPN_GetStringIdentifier): Added JSLock.
+
+ * bindings/objc/objc_instance.h:
+ * bindings/objc/objc_instance.mm:
+ (ObjcInstance::~ObjcInstance): Use an autorelease pool. The other callers
+ to CFRelease needed one, too, but they were dead code, so I removed them
+ instead. (This fixes a leak seen while running run-webkit-tests --threaded,
+ although I don't think it's specifically a threading issue.)
+
+ * kjs/collector.cpp:
+ (KJS::Collector::collectOnMainThreadOnly): New function. Tells the collector
+ to collect a value only if it's collecting on the main thread.
+ (KJS::Collector::markMainThreadOnlyObjects): New function. Scans the heap
+ for "main thread only" objects and marks them.
+
+ * kjs/date_object.cpp:
+ (KJS::DateObjectImp::DateObjectImp): To make the new ASSERTs happy, allocate
+ our globals on the heap, avoiding a seemingly unsafe destructor call at
+ program exit time.
+ * kjs/function_object.cpp:
+ (FunctionPrototype::FunctionPrototype): ditto
+
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::mark): Removed boolean parameter, which was an incomplete
+ and arguably hackish way to implement markMainThreadOnlyObjects() inside WebCore.
+ * kjs/interpreter.h:
+
+ * kjs/identifier.cpp:
+ (KJS::identifierTable): Added some ASSERTs to check for thread safety
+ problems.
+
+ * kjs/list.cpp: Added some ASSERTs to check for thread safety problems.
+ (KJS::allocateListImp):
+ (KJS::List::release):
+ (KJS::List::append):
+ (KJS::List::empty): Make the new ASSERTs happy.
+
+ * kjs/object.h:
+ (KJS::JSObject::JSObject): "m_destructorIsThreadSafe" => "m_collectOnMainThreadOnly".
+ I removed the constructor parameter because m_collectOnMainThreadOnly,
+ like m_marked, is a Collector bit, so only the Collector should set or get it.
+
+ * kjs/object_object.cpp:
+ (ObjectPrototype::ObjectPrototype): Make the ASSERTs happy.
+ * kjs/regexp_object.cpp:
+ (RegExpPrototype::RegExpPrototype): ditto
+
+ * kjs/ustring.cpp: Added some ASSERTs to check for thread safety problems.
+ (KJS::UCharReference::ref):
+ (KJS::UString::Rep::createCopying):
+ (KJS::UString::Rep::create):
+ (KJS::UString::Rep::destroy):
+ (KJS::UString::null): Make the new ASSERTs happy.
+ * kjs/ustring.h:
+ (KJS::UString::Rep::ref): Added some ASSERTs to check for thread safety problems.
+ (KJS::UString::Rep::deref):
+
+ * kjs/value.h:
+ (KJS::JSCell::JSCell):
+
+2007-03-06 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
</ins><span class="cx"> 2% speedup on super accurate JS iBench.
</span><span class="cx">
</span><span class="cx"> (KJS::Collector::collect): Removed anti-optimization to call
</span></span></pre></div>
<a id="trunkJavaScriptCoreJavaScriptCoreexp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/JavaScriptCore.exp (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/JavaScriptCore.exp        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/JavaScriptCore.exp        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -117,7 +117,7 @@
</span><span class="cx"> __ZN3KJS11Interpreter17startTimeoutCheckEv
</span><span class="cx"> __ZN3KJS11Interpreter21shouldPrintExceptionsEv
</span><span class="cx"> __ZN3KJS11Interpreter24setShouldPrintExceptionsEb
</span><del>-__ZN3KJS11Interpreter4markEb
</del><ins>+__ZN3KJS11Interpreter4markEv
</ins><span class="cx"> __ZN3KJS11Interpreter6s_hookE
</span><span class="cx"> __ZN3KJS11Interpreter8evaluateERKNS_7UStringEiPKNS_5UCharEiPNS_7JSValueE
</span><span class="cx"> __ZN3KJS11Interpreter8evaluateERKNS_7UStringEiS3_PNS_7JSValueE
</span><span class="lines">@@ -166,6 +166,7 @@
</span><span class="cx"> __ZN3KJS6JSLock12DropAllLocksD1Ev
</span><span class="cx"> __ZN3KJS6JSLock4lockEv
</span><span class="cx"> __ZN3KJS6JSLock6unlockEv
</span><ins>+__ZN3KJS6JSLock9lockCountEv
</ins><span class="cx"> __ZN3KJS6Lookup9findEntryEPKNS_9HashTableERKNS_10IdentifierE
</span><span class="cx"> __ZN3KJS6Parser11prettyPrintERKNS_7UStringEPiPS1_
</span><span class="cx"> __ZN3KJS7CStringD1Ev
</span><span class="lines">@@ -214,6 +215,7 @@
</span><span class="cx"> __ZN3KJS9Collector15numInterpretersEv
</span><span class="cx"> __ZN3KJS9Collector19numProtectedObjectsEv
</span><span class="cx"> __ZN3KJS9Collector20rootObjectTypeCountsEv
</span><ins>+__ZN3KJS9Collector23collectOnMainThreadOnlyEPNS_7JSValueE
</ins><span class="cx"> __ZN3KJS9Collector4sizeEv
</span><span class="cx"> __ZN3KJS9Collector7collectEv
</span><span class="cx"> __ZN3KJS9Collector7protectEPNS_7JSValueE
</span><span class="lines">@@ -273,6 +275,7 @@
</span><span class="cx"> __ZTVN3KJS14StringInstanceE
</span><span class="cx"> __ZTVN3KJS15JSWrapperObjectE
</span><span class="cx"> __ZTVN3KJS19InternalFunctionImpE
</span><ins>+__ZTVN3KJS6JSCellE
</ins><span class="cx"> __ZTVN3KJS8JSObjectE
</span><span class="cx"> _kJSClassDefinitionEmpty
</span><span class="cx"> _kjs_pcre_compile
</span></span></pre></div>
<a id="trunkJavaScriptCorebindingsnpruntimecpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/bindings/npruntime.cpp (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/bindings/npruntime.cpp        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/bindings/npruntime.cpp        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #include "npruntime_impl.h"
</span><span class="cx"> #include "npruntime_priv.h"
</span><span class="cx">
</span><ins>+#include "JSLock.h"
</ins><span class="cx"> #include "c_utility.h"
</span><span class="cx"> #include "identifier.h"
</span><span class="cx"> #include <wtf/Assertions.h>
</span><span class="lines">@@ -62,6 +63,8 @@
</span><span class="cx"> if (name) {
</span><span class="cx"> PrivateIdentifier* identifier = 0;
</span><span class="cx">
</span><ins>+ KJS::JSLock lock;
+
</ins><span class="cx"> identifier = getStringIdentifierMap()->get(identifierFromNPIdentifier(name).ustring().rep());
</span><span class="cx"> if (identifier == 0) {
</span><span class="cx"> identifier = (PrivateIdentifier*)malloc(sizeof(PrivateIdentifier));
</span></span></pre></div>
<a id="trunkJavaScriptCorebindingsobjcobjc_instanceh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/bindings/objc/objc_instance.h (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/bindings/objc/objc_instance.h        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/bindings/objc/objc_instance.h        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -43,10 +43,6 @@
</span><span class="cx">
</span><span class="cx"> virtual Class *getClass() const;
</span><span class="cx">
</span><del>- ObjcInstance(const ObjcInstance &other);
-
- ObjcInstance &operator=(const ObjcInstance &other);
-
</del><span class="cx"> virtual void begin();
</span><span class="cx"> virtual void end();
</span><span class="cx">
</span><span class="lines">@@ -72,6 +68,9 @@
</span><span class="cx"> JSValue *booleanValue() const;
</span><span class="cx">
</span><span class="cx"> private:
</span><ins>+ ObjcInstance(const ObjcInstance& other);
+ ObjcInstance& operator=(const ObjcInstance& other);
+
</ins><span class="cx"> ObjectStructPtr _instance;
</span><span class="cx"> mutable ObjcClass *_class;
</span><span class="cx"> ObjectStructPtr _pool;
</span></span></pre></div>
<a id="trunkJavaScriptCorebindingsobjcobjc_instancemm"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/bindings/objc/objc_instance.mm (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/bindings/objc/objc_instance.mm        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/bindings/objc/objc_instance.mm        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -52,35 +52,14 @@
</span><span class="cx">
</span><span class="cx"> ObjcInstance::~ObjcInstance()
</span><span class="cx"> {
</span><ins>+ begin(); // -finalizeForWebScript and -dealloc/-finalize may require autorelease pools.
</ins><span class="cx"> if ([_instance respondsToSelector:@selector(finalizeForWebScript)])
</span><span class="cx"> [_instance performSelector:@selector(finalizeForWebScript)];
</span><span class="cx"> if (_instance)
</span><span class="cx"> CFRelease(_instance);
</span><ins>+ end();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-ObjcInstance::ObjcInstance(const ObjcInstance &other) : Instance()
-{
- _instance = other._instance;
- if (_instance)
- CFRetain(_instance);
- _class = other._class;
- _pool = 0;
- _beginCount = 0;
-}
-
-ObjcInstance &ObjcInstance::operator=(const ObjcInstance &other)
-{
- ObjectStructPtr _oldInstance = _instance;
- _instance = other._instance;
- if (_instance)
- CFRetain(_instance);
- if (_oldInstance)
- CFRelease(_oldInstance);
- // Classes are kept around forever.
- _class = other._class;
- return* this;
-}
-
</del><span class="cx"> void ObjcInstance::begin()
</span><span class="cx"> {
</span><span class="cx"> if (!_pool)
</span></span></pre></div>
<a id="trunkJavaScriptCorekjscollectorcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/collector.cpp (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/collector.cpp        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/kjs/collector.cpp        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -108,6 +108,7 @@
</span><span class="cx">
</span><span class="cx"> static CollectorHeap heap = {NULL, 0, 0, 0, NULL, 0, 0, 0, 0};
</span><span class="cx">
</span><ins>+size_t Collector::mainThreadOnlyObjectCount = 0;
</ins><span class="cx"> bool Collector::memoryFull = false;
</span><span class="cx">
</span><span class="cx"> #ifndef NDEBUG
</span><span class="lines">@@ -473,6 +474,19 @@
</span><span class="cx"> protectedValues().remove(k->downcast());
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void Collector::collectOnMainThreadOnly(JSValue* value)
+{
+ ASSERT(value);
+ ASSERT(JSLock::lockCount() > 0);
+
+ if (JSImmediate::isImmediate(value))
+ return;
+
+ JSCell* cell = value->downcast();
+ cell->m_collectOnMainThreadOnly = true;
+ ++mainThreadOnlyObjectCount;
+}
+
</ins><span class="cx"> void Collector::markProtectedObjects()
</span><span class="cx"> {
</span><span class="cx"> ProtectCountSet& protectedValues = KJS::protectedValues();
</span><span class="lines">@@ -484,6 +498,56 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void Collector::markMainThreadOnlyObjects()
+{
+ ASSERT(!pthread_main_np());
+
+ // Optimization for clients that never register "main thread only" objects.
+ if (!mainThreadOnlyObjectCount)
+ return;
+
+ // FIXME: We can optimize this marking algorithm by keeping an exact set of
+ // "main thread only" objects when the "main thread only" object count is
+ // small. We don't want to keep an exact set all the time, because WebCore
+ // tends to create lots of "main thread only" objects, and all that set
+ // thrashing can be expensive.
+
+ size_t count = 0;
+
+ for (size_t block = 0; block < heap.usedBlocks; block++) {
+ ASSERT(count < mainThreadOnlyObjectCount);
+
+ CollectorBlock* curBlock = heap.blocks[block];
+ size_t minimumCellsToProcess = curBlock->usedCells;
+ for (size_t i = 0; (i < minimumCellsToProcess) & (i < CELLS_PER_BLOCK); i++) {
+ CollectorCell* cell = curBlock->cells + i;
+ if (cell->u.freeCell.zeroIfFree == 0)
+ ++minimumCellsToProcess;
+ else {
+ JSCell* imp = reinterpret_cast<JSCell*>(cell);
+ if (imp->m_collectOnMainThreadOnly) {
+ if(!imp->marked())
+ imp->mark();
+ if (++count == mainThreadOnlyObjectCount)
+ return;
+ }
+ }
+ }
+ }
+
+ for (size_t cell = 0; cell < heap.usedOversizeCells; cell++) {
+ ASSERT(count < mainThreadOnlyObjectCount);
+
+ JSCell* imp = reinterpret_cast<JSCell*>(heap.oversizeCells[cell]);
+ if (imp->m_collectOnMainThreadOnly) {
+ if (!imp->marked())
+ imp->mark();
+ if (++count == mainThreadOnlyObjectCount)
+ return;
+ }
+ }
+}
+
</ins><span class="cx"> bool Collector::collect()
</span><span class="cx"> {
</span><span class="cx"> assert(JSLock::lockCount() > 0);
</span><span class="lines">@@ -501,7 +565,7 @@
</span><span class="cx"> if (Interpreter::s_hook) {
</span><span class="cx"> Interpreter* scr = Interpreter::s_hook;
</span><span class="cx"> do {
</span><del>- scr->mark(currentThreadIsMainThread);
</del><ins>+ scr->mark();
</ins><span class="cx"> scr = scr->next;
</span><span class="cx"> } while (scr != Interpreter::s_hook);
</span><span class="cx"> }
</span><span class="lines">@@ -511,6 +575,8 @@
</span><span class="cx"> markStackObjectsConservatively();
</span><span class="cx"> markProtectedObjects();
</span><span class="cx"> List::markProtectedLists();
</span><ins>+ if (!currentThreadIsMainThread)
+ markMainThreadOnlyObjects();
</ins><span class="cx">
</span><span class="cx"> // SWEEP: delete everything with a zero refcount (garbage) and unmark everything else
</span><span class="cx">
</span><span class="lines">@@ -530,12 +596,16 @@
</span><span class="cx"> JSCell *imp = reinterpret_cast<JSCell *>(cell);
</span><span class="cx"> if (imp->m_marked) {
</span><span class="cx"> imp->m_marked = false;
</span><del>- } else if (currentThreadIsMainThread || imp->m_destructorIsThreadSafe) {
</del><ins>+ } else {
</ins><span class="cx"> // special case for allocated but uninitialized object
</span><del>- // (We don't need this check earlier because nothing prior this point assumes the object has a valid vptr.)
</del><ins>+ // (We don't need this check earlier because nothing prior this point
+ // assumes the object has a valid vptr.)
</ins><span class="cx"> if (cell->u.freeCell.zeroIfFree == 0)
</span><span class="cx"> continue;
</span><span class="cx">
</span><ins>+ ASSERT(currentThreadIsMainThread || !imp->m_collectOnMainThreadOnly);
+ if (imp->m_collectOnMainThreadOnly)
+ --mainThreadOnlyObjectCount;
</ins><span class="cx"> imp->~JSCell();
</span><span class="cx"> --usedCells;
</span><span class="cx"> --numLiveObjects;
</span><span class="lines">@@ -556,7 +626,10 @@
</span><span class="cx"> JSCell *imp = reinterpret_cast<JSCell *>(cell);
</span><span class="cx"> if (imp->m_marked) {
</span><span class="cx"> imp->m_marked = false;
</span><del>- } else if (currentThreadIsMainThread || imp->m_destructorIsThreadSafe) {
</del><ins>+ } else {
+ ASSERT(currentThreadIsMainThread || !imp->m_collectOnMainThreadOnly);
+ if (imp->m_collectOnMainThreadOnly)
+ --mainThreadOnlyObjectCount;
</ins><span class="cx"> imp->~JSCell();
</span><span class="cx"> --usedCells;
</span><span class="cx"> --numLiveObjects;
</span><span class="lines">@@ -599,7 +672,13 @@
</span><span class="cx"> while (cell < heap.usedOversizeCells) {
</span><span class="cx"> JSCell *imp = (JSCell *)heap.oversizeCells[cell];
</span><span class="cx">
</span><del>- if (!imp->m_marked && (currentThreadIsMainThread || imp->m_destructorIsThreadSafe)) {
</del><ins>+ if (imp->m_marked) {
+ imp->m_marked = false;
+ cell++;
+ } else {
+ ASSERT(currentThreadIsMainThread || !imp->m_collectOnMainThreadOnly);
+ if (imp->m_collectOnMainThreadOnly)
+ --mainThreadOnlyObjectCount;
</ins><span class="cx"> imp->~JSCell();
</span><span class="cx"> #if DEBUG_COLLECTOR
</span><span class="cx"> heap.oversizeCells[cell]->u.freeCell.zeroIfFree = 0;
</span><span class="lines">@@ -617,9 +696,6 @@
</span><span class="cx"> heap.numOversizeCells = heap.numOversizeCells / GROWTH_FACTOR;
</span><span class="cx"> heap.oversizeCells = (CollectorCell **)fastRealloc(heap.oversizeCells, heap.numOversizeCells * sizeof(CollectorCell *));
</span><span class="cx"> }
</span><del>- } else {
- imp->m_marked = false;
- cell++;
</del><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkJavaScriptCorekjscollectorh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/collector.h (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/collector.h        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/kjs/collector.h        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -31,12 +31,7 @@
</span><span class="cx">
</span><span class="cx"> namespace KJS {
</span><span class="cx">
</span><del>- /**
- * @short Garbage collector.
- */
</del><span class="cx"> class Collector {
</span><del>- // disallow direct construction/destruction
- Collector();
</del><span class="cx"> public:
</span><span class="cx"> static void* allocate(size_t s);
</span><span class="cx"> static bool collect();
</span><span class="lines">@@ -53,6 +48,8 @@
</span><span class="cx">
</span><span class="cx"> static void protect(JSValue*);
</span><span class="cx"> static void unprotect(JSValue*);
</span><ins>+
+ static void collectOnMainThreadOnly(JSValue*);
</ins><span class="cx">
</span><span class="cx"> static size_t numInterpreters();
</span><span class="cx"> static size_t numProtectedObjects();
</span><span class="lines">@@ -60,15 +57,18 @@
</span><span class="cx">
</span><span class="cx"> class Thread;
</span><span class="cx"> static void registerThread();
</span><del>-
</del><ins>+
</ins><span class="cx"> private:
</span><ins>+ Collector();
</ins><span class="cx">
</span><span class="cx"> static void markProtectedObjects();
</span><ins>+ static void markMainThreadOnlyObjects();
</ins><span class="cx"> static void markCurrentThreadConservatively();
</span><span class="cx"> static void markOtherThreadConservatively(Thread* thread);
</span><span class="cx"> static void markStackObjectsConservatively();
</span><span class="cx"> static void markStackObjectsConservatively(void* start, void* end);
</span><span class="cx">
</span><ins>+ static size_t mainThreadOnlyObjectCount;
</ins><span class="cx"> static bool memoryFull;
</span><span class="cx"> };
</span><span class="cx">
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsdate_objectcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/date_object.cpp (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/date_object.cpp        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/kjs/date_object.cpp        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -596,15 +596,12 @@
</span><span class="cx"> DatePrototype *dateProto)
</span><span class="cx"> : InternalFunctionImp(funcProto)
</span><span class="cx"> {
</span><del>- // ECMA 15.9.4.1 Date.prototype
- putDirect(prototypePropertyName, dateProto, DontEnum|DontDelete|ReadOnly);
</del><ins>+ static const Identifier* parsePropertyName = new Identifier("parse");
+ static const Identifier* UTCPropertyName = new Identifier("UTC");
</ins><span class="cx">
</span><del>- static const Identifier parsePropertyName("parse");
- putDirectFunction(new DateObjectFuncImp(exec, funcProto, DateObjectFuncImp::Parse, 1, parsePropertyName), DontEnum);
- static const Identifier UTCPropertyName("UTC");
- putDirectFunction(new DateObjectFuncImp(exec, funcProto, DateObjectFuncImp::UTC, 7, UTCPropertyName), DontEnum);
-
- // no. of arguments for constructor
</del><ins>+ putDirect(prototypePropertyName, dateProto, DontEnum|DontDelete|ReadOnly);
+ putDirectFunction(new DateObjectFuncImp(exec, funcProto, DateObjectFuncImp::Parse, 1, *parsePropertyName), DontEnum);
+ putDirectFunction(new DateObjectFuncImp(exec, funcProto, DateObjectFuncImp::UTC, 7, *UTCPropertyName), DontEnum);
</ins><span class="cx"> putDirect(lengthPropertyName, 7, ReadOnly|DontDelete|DontEnum);
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsfunction_objectcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/function_object.cpp (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/function_object.cpp        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/kjs/function_object.cpp        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -40,12 +40,13 @@
</span><span class="cx">
</span><span class="cx"> FunctionPrototype::FunctionPrototype(ExecState *exec)
</span><span class="cx"> {
</span><ins>+ static const Identifier* applyPropertyName = new Identifier("apply");
+ static const Identifier* callPropertyName = new Identifier("call");
+
</ins><span class="cx"> putDirect(lengthPropertyName, jsNumber(0), DontDelete|ReadOnly|DontEnum);
</span><span class="cx"> putDirectFunction(new FunctionProtoFunc(exec, this, FunctionProtoFunc::ToString, 0, toStringPropertyName), DontEnum);
</span><del>- static const Identifier applyPropertyName("apply");
- putDirectFunction(new FunctionProtoFunc(exec, this, FunctionProtoFunc::Apply, 2, applyPropertyName), DontEnum);
- static const Identifier callPropertyName("call");
- putDirectFunction(new FunctionProtoFunc(exec, this, FunctionProtoFunc::Call, 1, callPropertyName), DontEnum);
</del><ins>+ putDirectFunction(new FunctionProtoFunc(exec, this, FunctionProtoFunc::Apply, 2, *applyPropertyName), DontEnum);
+ putDirectFunction(new FunctionProtoFunc(exec, this, FunctionProtoFunc::Call, 1, *callPropertyName), DontEnum);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> FunctionPrototype::~FunctionPrototype()
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsidentifiercpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/identifier.cpp (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/identifier.cpp        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/kjs/identifier.cpp        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -38,10 +38,12 @@
</span><span class="cx">
</span><span class="cx"> #include "identifier.h"
</span><span class="cx">
</span><ins>+#include "JSLock.h"
+#include <new> // for placement new
+#include <string.h> // for strlen
+#include <wtf/Assertions.h>
</ins><span class="cx"> #include <wtf/FastMalloc.h>
</span><span class="cx"> #include <wtf/HashSet.h>
</span><del>-#include <string.h> // for strlen
-#include <new> // for placement new
</del><span class="cx">
</span><span class="cx"> namespace WTF {
</span><span class="cx">
</span><span class="lines">@@ -66,6 +68,8 @@
</span><span class="cx">
</span><span class="cx"> static inline IdentifierTable& identifierTable()
</span><span class="cx"> {
</span><ins>+ ASSERT(JSLock::lockCount() > 0);
+
</ins><span class="cx"> if (!table)
</span><span class="cx"> table = new IdentifierTable;
</span><span class="cx"> return *table;
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsinterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/interpreter.cpp (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/interpreter.cpp        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/kjs/interpreter.cpp        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -537,7 +537,7 @@
</span><span class="cx"> return m_UriErrorPrototype;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void Interpreter::mark(bool)
</del><ins>+void Interpreter::mark()
</ins><span class="cx"> {
</span><span class="cx"> if (m_context)
</span><span class="cx"> m_context->mark();
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsinterpreterh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/interpreter.h (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/interpreter.h        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/kjs/interpreter.h        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -286,7 +286,7 @@
</span><span class="cx"> * Called during the mark phase of the garbage collector. Subclasses
</span><span class="cx"> * implementing custom mark methods must make sure to chain to this one.
</span><span class="cx"> */
</span><del>- virtual void mark(bool currentThreadIsMainThread);
</del><ins>+ virtual void mark();
</ins><span class="cx">
</span><span class="cx"> #ifdef KJS_DEBUG_MEM
</span><span class="cx"> /**
</span></span></pre></div>
<a id="trunkJavaScriptCorekjslistcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/list.cpp (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/list.cpp        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/kjs/list.cpp        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -141,6 +141,8 @@
</span><span class="cx">
</span><span class="cx"> static inline ListImp *allocateListImp()
</span><span class="cx"> {
</span><ins>+ ASSERT(JSLock::lockCount() > 0);
+
</ins><span class="cx"> // Find a free one in the pool.
</span><span class="cx"> if (poolUsed < poolSize) {
</span><span class="cx"> ListImp *imp = poolFreeList ? poolFreeList : &pool[0];
</span><span class="lines">@@ -201,7 +203,9 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void List::release()
</span><del>-{
</del><ins>+{
+ ASSERT(JSLock::lockCount() > 0);
+
</ins><span class="cx"> ListImp *imp = static_cast<ListImp *>(_impBase);
</span><span class="cx">
</span><span class="cx"> #if DUMP_STATISTICS
</span><span class="lines">@@ -221,7 +225,7 @@
</span><span class="cx"> poolFreeList = imp;
</span><span class="cx"> poolUsed--;
</span><span class="cx"> } else {
</span><del>- assert(imp->state == usedOnHeap);
</del><ins>+ ASSERT(imp->state == usedOnHeap);
</ins><span class="cx"> HeapListImp *list = static_cast<HeapListImp *>(imp);
</span><span class="cx">
</span><span class="cx"> // unlink from heap list
</span><span class="lines">@@ -258,6 +262,8 @@
</span><span class="cx">
</span><span class="cx"> void List::append(JSValue *v)
</span><span class="cx"> {
</span><ins>+ ASSERT(JSLock::lockCount() > 0);
+
</ins><span class="cx"> ListImp *imp = static_cast<ListImp *>(_impBase);
</span><span class="cx">
</span><span class="cx"> int i = imp->size++;
</span><span class="lines">@@ -331,10 +337,10 @@
</span><span class="cx"> return copy;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-const List &List::empty()
</del><ins>+const List& List::empty()
</ins><span class="cx"> {
</span><del>- static List emptyList;
- return emptyList;
</del><ins>+ static List* staticEmptyList = new List;
+ return *staticEmptyList;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> List &List::operator=(const List &b)
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsobjecth"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/object.h (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/object.h        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/kjs/object.h        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -106,13 +106,13 @@
</span><span class="cx"> *
</span><span class="cx"> * @param proto The prototype
</span><span class="cx"> */
</span><del>- JSObject(JSValue* proto, bool destructorIsThreadSafe = true);
</del><ins>+ JSObject(JSValue* proto);
</ins><span class="cx">
</span><span class="cx"> /**
</span><span class="cx"> * Creates a new JSObject with a prototype of jsNull()
</span><span class="cx"> * (that is, the ECMAScript "null" value, not a null object pointer).
</span><span class="cx"> */
</span><del>- explicit JSObject(bool destructorIsThreadSafe = true);
</del><ins>+ JSObject();
</ins><span class="cx">
</span><span class="cx"> virtual void mark();
</span><span class="cx"> virtual JSType type() const;
</span><span class="lines">@@ -502,16 +502,14 @@
</span><span class="cx"> JSObject *throwError(ExecState *, ErrorType, const char *message);
</span><span class="cx"> JSObject *throwError(ExecState *, ErrorType);
</span><span class="cx">
</span><del>-inline JSObject::JSObject(JSValue* proto, bool destructorIsThreadSafe)
- : JSCell(destructorIsThreadSafe)
- , _proto(proto)
</del><ins>+inline JSObject::JSObject(JSValue* proto)
+ : _proto(proto)
</ins><span class="cx"> {
</span><span class="cx"> assert(proto);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-inline JSObject::JSObject(bool destructorIsThreadSafe)
- : JSCell(destructorIsThreadSafe)
- , _proto(jsNull())
</del><ins>+inline JSObject::JSObject()
+ : _proto(jsNull())
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsobject_objectcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/object_object.cpp (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/object_object.cpp        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/kjs/object_object.cpp        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -33,25 +33,26 @@
</span><span class="cx"> ObjectPrototype::ObjectPrototype(ExecState* exec, FunctionPrototype* funcProto)
</span><span class="cx"> : JSObject() // [[Prototype]] is null
</span><span class="cx"> {
</span><ins>+ static const Identifier* hasOwnPropertyPropertyName = new Identifier("hasOwnProperty");
+ static const Identifier* propertyIsEnumerablePropertyName = new Identifier("propertyIsEnumerable");
+ static const Identifier* isPrototypeOfPropertyName = new Identifier("isPrototypeOf");
+ static const Identifier* defineGetterPropertyName = new Identifier("__defineGetter__");
+ static const Identifier* defineSetterPropertyName = new Identifier("__defineSetter__");
+ static const Identifier* lookupGetterPropertyName = new Identifier("__lookupGetter__");
+ static const Identifier* lookupSetterPropertyName = new Identifier("__lookupSetter__");
+
</ins><span class="cx"> putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::ToString, 0, toStringPropertyName), DontEnum);
</span><span class="cx"> putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::ToLocaleString, 0, toLocaleStringPropertyName), DontEnum);
</span><span class="cx"> putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::ValueOf, 0, valueOfPropertyName), DontEnum);
</span><del>- static Identifier hasOwnPropertyPropertyName("hasOwnProperty");
- static Identifier propertyIsEnumerablePropertyName("propertyIsEnumerable");
- static Identifier isPrototypeOfPropertyName("isPrototypeOf");
- putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::HasOwnProperty, 1, hasOwnPropertyPropertyName), DontEnum);
- putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::PropertyIsEnumerable, 1, propertyIsEnumerablePropertyName), DontEnum);
- putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::IsPrototypeOf, 1, isPrototypeOfPropertyName), DontEnum);
</del><ins>+ putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::HasOwnProperty, 1, *hasOwnPropertyPropertyName), DontEnum);
+ putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::PropertyIsEnumerable, 1, *propertyIsEnumerablePropertyName), DontEnum);
+ putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::IsPrototypeOf, 1, *isPrototypeOfPropertyName), DontEnum);
</ins><span class="cx">
</span><span class="cx"> // Mozilla extensions
</span><del>- static const Identifier defineGetterPropertyName("__defineGetter__");
- static const Identifier defineSetterPropertyName("__defineSetter__");
- static const Identifier lookupGetterPropertyName("__lookupGetter__");
- static const Identifier lookupSetterPropertyName("__lookupSetter__");
- putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::DefineGetter, 2, defineGetterPropertyName), DontEnum);
- putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::DefineSetter, 2, defineSetterPropertyName), DontEnum);
- putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::LookupGetter, 1, lookupGetterPropertyName), DontEnum);
- putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::LookupSetter, 1, lookupSetterPropertyName), DontEnum);
</del><ins>+ putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::DefineGetter, 2, *defineGetterPropertyName), DontEnum);
+ putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::DefineSetter, 2, *defineSetterPropertyName), DontEnum);
+ putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::LookupGetter, 1, *lookupGetterPropertyName), DontEnum);
+ putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::LookupSetter, 1, *lookupSetterPropertyName), DontEnum);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx">
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsregexp_objectcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/regexp_object.cpp (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/regexp_object.cpp        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/kjs/regexp_object.cpp        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -48,12 +48,11 @@
</span><span class="cx"> FunctionPrototype *funcProto)
</span><span class="cx"> : JSObject(objProto)
</span><span class="cx"> {
</span><del>- // The constructor will be added later in RegExpObject's constructor (?)
</del><ins>+ static const Identifier* execPropertyName = new Identifier("exec");
+ static const Identifier* testPropertyName = new Identifier("test");
</ins><span class="cx">
</span><del>- static const Identifier execPropertyName("exec");
- static const Identifier testPropertyName("test");
- putDirectFunction(new RegExpProtoFunc(exec, funcProto, RegExpProtoFunc::Exec, 0, execPropertyName), DontEnum);
- putDirectFunction(new RegExpProtoFunc(exec, funcProto, RegExpProtoFunc::Test, 0, testPropertyName), DontEnum);
</del><ins>+ putDirectFunction(new RegExpProtoFunc(exec, funcProto, RegExpProtoFunc::Exec, 0, *execPropertyName), DontEnum);
+ putDirectFunction(new RegExpProtoFunc(exec, funcProto, RegExpProtoFunc::Test, 0, *testPropertyName), DontEnum);
</ins><span class="cx"> putDirectFunction(new RegExpProtoFunc(exec, funcProto, RegExpProtoFunc::ToString, 0, toStringPropertyName), DontEnum);
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsustringcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/ustring.cpp (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/ustring.cpp        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/kjs/ustring.cpp        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -24,10 +24,18 @@
</span><span class="cx"> #include "config.h"
</span><span class="cx"> #include "ustring.h"
</span><span class="cx">
</span><ins>+#include "JSLock.h"
+#include "dtoa.h"
+#include "identifier.h"
+#include "operations.h"
</ins><span class="cx"> #include <assert.h>
</span><ins>+#include <ctype.h>
+#include <float.h>
+#include <math.h>
+#include <stdio.h>
</ins><span class="cx"> #include <stdlib.h>
</span><del>-#include <stdio.h>
-#include <ctype.h>
</del><ins>+#include <wtf/Vector.h>
+
</ins><span class="cx"> #if HAVE(STRING_H)
</span><span class="cx"> #include <string.h>
</span><span class="cx"> #endif
</span><span class="lines">@@ -35,13 +43,6 @@
</span><span class="cx"> #include <strings.h>
</span><span class="cx"> #endif
</span><span class="cx">
</span><del>-#include "dtoa.h"
-#include "identifier.h"
-#include "operations.h"
-#include <float.h>
-#include <math.h>
-#include <wtf/Vector.h>
-
</del><span class="cx"> using std::max;
</span><span class="cx"> using std::min;
</span><span class="cx">
</span><span class="lines">@@ -154,6 +155,8 @@
</span><span class="cx">
</span><span class="cx"> UChar& UCharReference::ref() const
</span><span class="cx"> {
</span><ins>+ ASSERT(JSLock::lockCount() > 0);
+
</ins><span class="cx"> if (offset < str->rep()->len)
</span><span class="cx"> return *(str->rep()->data() + offset);
</span><span class="cx"> else {
</span><span class="lines">@@ -164,6 +167,8 @@
</span><span class="cx">
</span><span class="cx"> PassRefPtr<UString::Rep> UString::Rep::createCopying(const UChar *d, int l)
</span><span class="cx"> {
</span><ins>+ ASSERT(JSLock::lockCount() > 0);
+
</ins><span class="cx"> int sizeInBytes = l * sizeof(UChar);
</span><span class="cx"> UChar *copyD = static_cast<UChar *>(fastMalloc(sizeInBytes));
</span><span class="cx"> memcpy(copyD, d, sizeInBytes);
</span><span class="lines">@@ -173,6 +178,8 @@
</span><span class="cx">
</span><span class="cx"> PassRefPtr<UString::Rep> UString::Rep::create(UChar *d, int l)
</span><span class="cx"> {
</span><ins>+ ASSERT(JSLock::lockCount() > 0);
+
</ins><span class="cx"> Rep *r = new Rep;
</span><span class="cx"> r->offset = 0;
</span><span class="cx"> r->len = l;
</span><span class="lines">@@ -192,7 +199,8 @@
</span><span class="cx">
</span><span class="cx"> PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<Rep> base, int offset, int length)
</span><span class="cx"> {
</span><del>- assert(base);
</del><ins>+ ASSERT(JSLock::lockCount() > 0);
+ ASSERT(base);
</ins><span class="cx">
</span><span class="cx"> int baseOffset = base->offset;
</span><span class="cx">
</span><span class="lines">@@ -222,6 +230,8 @@
</span><span class="cx">
</span><span class="cx"> void UString::Rep::destroy()
</span><span class="cx"> {
</span><ins>+ ASSERT(JSLock::lockCount() > 0);
+
</ins><span class="cx"> if (isIdentifier)
</span><span class="cx"> Identifier::remove(this);
</span><span class="cx"> if (baseString) {
</span><span class="lines">@@ -466,10 +476,10 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-const UString &UString::null()
</del><ins>+const UString& UString::null()
</ins><span class="cx"> {
</span><del>- static UString n;
- return n;
</del><ins>+ static UString* n = new UString;
+ return *n;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> UString UString::from(int i)
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsustringh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/ustring.h (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/ustring.h        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/kjs/ustring.h        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -24,12 +24,13 @@
</span><span class="cx"> #ifndef _KJS_USTRING_H_
</span><span class="cx"> #define _KJS_USTRING_H_
</span><span class="cx">
</span><ins>+#include "JSLock.h"
+#include <stdint.h>
+#include <wtf/Assertions.h>
</ins><span class="cx"> #include <wtf/FastMalloc.h>
</span><ins>+#include <wtf/PassRefPtr.h>
</ins><span class="cx"> #include <wtf/RefPtr.h>
</span><del>-#include <wtf/PassRefPtr.h>
</del><span class="cx">
</span><del>-#include <stdint.h>
-
</del><span class="cx"> /* On ARM some versions of GCC don't pack structures by default so sizeof(UChar)
</span><span class="cx"> will end up being != 2 which causes crashes since the code depends on that. */
</span><span class="cx"> #if COMPILER(GCC) && PLATFORM(ARM)
</span><span class="lines">@@ -199,8 +200,8 @@
</span><span class="cx"> static unsigned computeHash(const UChar *, int length);
</span><span class="cx"> static unsigned computeHash(const char *);
</span><span class="cx">
</span><del>- Rep* ref() { ++rc; return this; }
- void deref() { if (--rc == 0) destroy(); }
</del><ins>+ Rep* ref() { ASSERT(JSLock::lockCount() > 0); ++rc; return this; }
+ void deref() { ASSERT(JSLock::lockCount() > 0); if (--rc == 0) destroy(); }
</ins><span class="cx">
</span><span class="cx"> // unshared data
</span><span class="cx"> int offset;
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsvalueh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/value.h (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/value.h        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptCore/kjs/value.h        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -122,7 +122,7 @@
</span><span class="cx"> friend class JSObject;
</span><span class="cx"> friend class GetterSetterImp;
</span><span class="cx"> private:
</span><del>- explicit JSCell(bool destructorIsThreadSafe = true);
</del><ins>+ JSCell();
</ins><span class="cx"> virtual ~JSCell();
</span><span class="cx"> public:
</span><span class="cx"> // Querying the type.
</span><span class="lines">@@ -156,7 +156,7 @@
</span><span class="cx"> bool marked() const;
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- bool m_destructorIsThreadSafe : 1;
</del><ins>+ bool m_collectOnMainThreadOnly : 1;
</ins><span class="cx"> bool m_marked : 1;
</span><span class="cx"> };
</span><span class="cx">
</span><span class="lines">@@ -203,8 +203,8 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><del>-inline JSCell::JSCell(bool destructorIsThreadSafe)
- : m_destructorIsThreadSafe(destructorIsThreadSafe)
</del><ins>+inline JSCell::JSCell()
+ : m_collectOnMainThreadOnly(false)
</ins><span class="cx"> , m_marked(false)
</span><span class="cx"> {
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkJavaScriptGlueChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptGlue/ChangeLog (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptGlue/ChangeLog        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptGlue/ChangeLog        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -1,3 +1,25 @@
</span><ins>+2007-03-06 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Fixed all known crashers exposed by run-webkit-tests --threaded while using
+ a PAC file (for maximum carnage). See JavaScriptCore ChangeLog for
+ more details.
+
+ * JSBase.cpp:
+ (JSBase::Release): Lock when deleting, because we may be deleting an object
+ (like a JSRun) that holds thread-unsafe data.
+
+ * JSUtils.cpp:
+ (CFStringToUString): Don't lock, because our caller locks. Also, locking
+ inside a function that returns thread-unsafe data by copy will only mask
+ threading problems.
+
+ * JavaScriptGlue.cpp:
+ (JSRunEvaluate): Added missing JSLock.
+ (JSRunCheckSyntax): Converted to JSLock.
+ * JavaScriptGlue.xcodeproj/project.pbxproj:
+
</ins><span class="cx"> 2007-02-22 Geoffrey Garen <ggaren@apple.com>
</span><span class="cx">
</span><span class="cx"> Reviewed by Darin Adler.
</span></span></pre></div>
<a id="trunkJavaScriptGlueJSBasecpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptGlue/JSBase.cpp (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptGlue/JSBase.cpp        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptGlue/JSBase.cpp        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -46,6 +46,7 @@
</span><span class="cx"> {
</span><span class="cx"> if (--fRetainCount == 0)
</span><span class="cx"> {
</span><ins>+ JSLock lock;
</ins><span class="cx"> delete this;
</span><span class="cx"> }
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkJavaScriptGlueJSUtilscpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptGlue/JSUtils.cpp (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptGlue/JSUtils.cpp        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptGlue/JSUtils.cpp        2007-03-07 04:25:49 UTC (rev 20004)
</span><span class="lines">@@ -51,8 +51,6 @@
</span><span class="cx">
</span><span class="cx"> UString CFStringToUString(CFStringRef inCFString)
</span><span class="cx"> {
</span><del>- JSLock lock;
-
</del><span class="cx"> UString result;
</span><span class="cx"> if (inCFString) {
</span><span class="cx"> CFIndex len = CFStringGetLength(inCFString);
</span></span></pre></div>
<a id="trunkJavaScriptGlueJavaScriptGluecpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptGlue/JavaScriptGlue.cpp (20003 => 20004)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptGlue/JavaScriptGlue.cpp        2007-03-07 04:18:16 UTC (rev 20003)
+++ trunk/JavaScriptGlue/JavaScriptGlue.cpp        2007-03-07 04:25:49 UTC (rev 20004)