Commit 911414cc authored by ggaren's avatar ggaren

JavaScriptCore:

        Reviewed by Darin.

        - JavaScriptCore side of fix for <rdar://problem/4308243> 8F36 
        Regression: crash in malloc_consolidate if you use a .PAC file

        The crash was a result of threaded deallocation of thread-unsafe
        objects. Pure JS objects are thread-safe because all JS execution
        is synchronized through JSLock. However, JS objects that wrap WebCore 
        objects are thread-unsafe because JS and WebCore execution are not 
        synchronized.  That unsafety comes into play when the collector 
        deallocates a JS object that wraps a WebCore object, thus causing the 
        WebCore object to be deallocated.

        The solution here is to have each JSCell know whether it is safe to
        collect on a non-main thread, and to avoid collecting unsafe cells
        when on a non-main thread.

        We don't have a way to test PAC files yet, so there's no test
        attached to this patch.

        * kjs/collector.cpp:
        (KJS::Collector::collect):
        (1) Added the test "currentThreadIsMainThread || 
        imp->m_destructorIsThreadSafe". 

        * kjs/protect.h:
        (KJS::gcProtectNullTolerant):
        (KJS::gcUnprotectNullTolerant):
        * kjs/value.h:
        (KJS::JSCell::JSCell): The bools here must be bitfields, otherwise
        m_destructorIsThreadSafe becomes another whole word, ruining the
        collector optimizations we've made based on the size of a JSObject.
        * kxmlcore/FastMalloc.cpp:
        (KXMLCore::currentThreadIsMainThread):
        (KXMLCore::fastMallocRegisterThread):
        * kxmlcore/FastMalloc.h:

WebCore:

        Reviewed by Hyatt.

        - Fix for http://bugzilla.opendarwin.org/show_bug.cgi?id=6986
        Switch to use new text field implementation for <input type="text">

        * css/html4.css: Added default style info for new text fields.
        * rendering/RenderTextField.cpp:
        (WebCore::RenderTextField::createDivStyle): Added an extra 1px of padding on the left & right to match Win IE & the latest Mozilla.
        (WebCore::RenderTextField::updateFromElement): Removed some outdated comments.  Cleaned up the way we add text nodes to the div.
        (WebCore::RenderTextField::setSelectionStart): Tweaked selection code to better match Mozilla behavior.
        (WebCore::RenderTextField::setSelectionEnd): ditto.
        (WebCore::RenderTextField::select): Cleaned this up by having it call setSelectionRange.
        (WebCore::RenderTextField::setSelectionRange): Calls updateLayout now in case this is called in an onload handler, and no other layout has occurred.
        (WebCore::RenderTextField::calcMinMaxWidth): Use floatWidth to calculate the width of the "0" character.
        * rendering/RenderTheme.cpp: (WebCore::RenderTheme::isControlStyled): If the text field's specified border is different from 
         the default border, then treat the control as styled, so the engine knows to turn off the aqua appearance.
        * rendering/RenderThemeMac.mm:
        (WebCore::RenderThemeMac::paintTextField): return false so the engine knows not to try to draw the border.
        (WebCore::RenderThemeMac::adjustTextFieldStyle): text field style info has been moved to html4.css. 
         We also add intrinsic margins here if the font size is large enough.
        * html/HTMLTextFieldInnerElement.cpp: (WebCore::HTMLTextFieldInnerElement::defaultEventHandler):
         No longer check for appearance. All text fields with m_type == TEXT will use the new implementation.
        * html/HTMLInputElement.cpp:
        (WebCore::HTMLInputElement::isKeyboardFocusable): ditto.
        (WebCore::HTMLInputElement::focus): ditto.
        (WebCore::HTMLInputElement::selectionStart): ditto.
        (WebCore::HTMLInputElement::selectionEnd): ditto.
        (WebCore::HTMLInputElement::setSelectionStart): ditto.
        (WebCore::HTMLInputElement::setSelectionEnd): ditto.
        (WebCore::HTMLInputElement::select): ditto.
        (WebCore::HTMLInputElement::setSelectionRange): ditto.
        (WebCore::HTMLInputElement::createRenderer): ditto.
        (WebCore::HTMLInputElement::defaultEventHandler): ditto.
        (WebCore::HTMLInputElement::isMouseFocusable): Added.  Old text fields relied on the widget to provide a focus policy.  
         A text field that is focusable should be mouse focusable, and shouldn't need to ask the base class.
        * html/HTMLInputElement.h: Added isMouseFocusable.
        * html/HTMLGenericFormElement.cpp: (WebCore::HTMLGenericFormElement::isMouseFocusable):
         Removed specific text field code since that is now done in HTMLInputElement::isMouseFocusable.
        * dom/Document.cpp: (WebCore::Document::clearSelectionIfNeeded): Check that the new selection is does not have a shadowAncestorNode that is focused.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@13568 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent b6a2ac4e
2006-03-29 Geoffrey Garen <ggaren@apple.com>
Reviewed by Darin.
- JavaScriptCore side of fix for <rdar://problem/4308243> 8F36
Regression: crash in malloc_consolidate if you use a .PAC file
The crash was a result of threaded deallocation of thread-unsafe
objects. Pure JS objects are thread-safe because all JS execution
is synchronized through JSLock. However, JS objects that wrap WebCore
objects are thread-unsafe because JS and WebCore execution are not
synchronized. That unsafety comes into play when the collector
deallocates a JS object that wraps a WebCore object, thus causing the
WebCore object to be deallocated.
The solution here is to have each JSCell know whether it is safe to
collect on a non-main thread, and to avoid collecting unsafe cells
when on a non-main thread.
We don't have a way to test PAC files yet, so there's no test
attached to this patch.
* kjs/collector.cpp:
(KJS::Collector::collect):
(1) Added the test "currentThreadIsMainThread ||
imp->m_destructorIsThreadSafe".
* kjs/protect.h:
(KJS::gcProtectNullTolerant):
(KJS::gcUnprotectNullTolerant):
* kjs/value.h:
(KJS::JSCell::JSCell): The bools here must be bitfields, otherwise
m_destructorIsThreadSafe becomes another whole word, ruining the
collector optimizations we've made based on the size of a JSObject.
* kxmlcore/FastMalloc.cpp:
(KXMLCore::currentThreadIsMainThread):
(KXMLCore::fastMallocRegisterThread):
* kxmlcore/FastMalloc.h:
2006-03-28 Darin Adler <darin@apple.com>
Reviewed by Geoff.
......
......@@ -443,7 +443,6 @@ bool Collector::collect()
if (InterpreterImp::s_hook) {
InterpreterImp *scr = InterpreterImp::s_hook;
do {
//fprintf( stderr, "Collector marking interpreter %p\n",(void*)scr);
scr->mark();
scr = scr->next;
} while (scr != InterpreterImp::s_hook);
......@@ -460,6 +459,12 @@ bool Collector::collect()
size_t emptyBlocks = 0;
size_t numLiveObjects = heap.numLiveObjects;
#if USE(MULTIPLE_THREADS)
bool currentThreadIsMainThread = !pthread_is_threaded_np() || pthread_main_np();
#else
bool currentThreadIsMainThread = true;
#endif
for (size_t block = 0; block < heap.usedBlocks; block++) {
CollectorBlock *curBlock = heap.blocks[block];
......@@ -473,7 +478,7 @@ bool Collector::collect()
JSCell *imp = reinterpret_cast<JSCell *>(cell);
if (imp->m_marked) {
imp->m_marked = false;
} else {
} else if (currentThreadIsMainThread || imp->m_destructorIsThreadSafe) {
imp->~JSCell();
--usedCells;
--numLiveObjects;
......@@ -494,7 +499,7 @@ bool Collector::collect()
JSCell *imp = reinterpret_cast<JSCell *>(cell);
if (imp->m_marked) {
imp->m_marked = false;
} else {
} else if (currentThreadIsMainThread || imp->m_destructorIsThreadSafe) {
imp->~JSCell();
--usedCells;
--numLiveObjects;
......
......@@ -117,13 +117,13 @@ namespace KJS {
*
* @param proto The prototype
*/
JSObject(JSObject *proto);
JSObject(JSObject *proto, bool destructorIsThreadSafe = true);
/**
* Creates a new JSObject with a prototype of jsNull()
* (that is, the ECMAScript "null" value, not a null object pointer).
*/
JSObject();
explicit JSObject(bool destructorIsThreadSafe = true);
virtual void mark();
virtual JSType type() const;
......@@ -579,14 +579,18 @@ JSObject *throwError(ExecState *, ErrorType, const UString &message);
JSObject *throwError(ExecState *, ErrorType, const char *message);
JSObject *throwError(ExecState *, ErrorType);
inline JSObject::JSObject(JSObject *proto)
: _proto(proto), _internalValue(0)
inline JSObject::JSObject(JSObject *proto, bool destructorIsThreadSafe)
: JSCell(destructorIsThreadSafe)
, _proto(proto)
, _internalValue(0)
{
assert(proto);
}
inline JSObject::JSObject()
: _proto(jsNull()), _internalValue(0)
inline JSObject::JSObject(bool destructorIsThreadSafe)
: JSCell(destructorIsThreadSafe)
, _proto(jsNull())
, _internalValue(0)
{
}
......
......@@ -43,12 +43,14 @@ namespace KJS {
inline void gcProtectNullTolerant(JSValue *val)
{
if (val) gcProtect(val);
if (val)
gcProtect(val);
}
inline void gcUnprotectNullTolerant(JSValue *val)
{
if (val) gcUnprotect(val);
if (val)
gcUnprotect(val);
}
// FIXME: Share more code with RefPtr template? The only differences are the ref/deref operation
......
......@@ -121,7 +121,7 @@ class JSCell : public JSValue {
friend class JSObject;
friend class GetterSetterImp;
private:
JSCell();
explicit JSCell(bool destructorIsThreadSafe = true);
virtual ~JSCell();
public:
// Querying the type.
......@@ -155,7 +155,8 @@ public:
bool marked() const;
private:
bool m_marked;
bool m_destructorIsThreadSafe : 1;
bool m_marked : 1;
};
JSValue *jsUndefined();
......@@ -208,8 +209,9 @@ inline JSValue::~JSValue()
{
}
inline JSCell::JSCell()
: m_marked(false)
inline JSCell::JSCell(bool destructorIsThreadSafe)
: m_destructorIsThreadSafe(destructorIsThreadSafe)
, m_marked(false)
{
}
......
......@@ -103,7 +103,7 @@ void fastMallocRegisterThread(pthread_t)
}
#endif
} // namespace KJS
} // namespace KXMLCore
#else
......@@ -1395,12 +1395,12 @@ void fastMallocRegisterThread(pthread_t thread)
{
if (thread != mainThreadID) {
// We lock when writing isMultiThreaded but not when reading it.
// It's ok if the main thread temporarily gets it wrong - the global
// variable cache is the same as the thread-specific cache for the main thread.
// It's ok if the main thread gets it wrong - for the main thread, the
// global variable cache is the same as the thread-specific cache.
// And other threads can't get it wrong because they must have gone through
// this function before allocating so they've synchronized.
// Also, mainThreadCache is only set when isMultiThreaded is false,
// to save a branchin some cases.
// to save a branch in some cases.
SpinLockHolder lock(&multiThreadedLock);
isMultiThreaded = true;
mainThreadCache = 0;
......@@ -2315,7 +2315,7 @@ extern "C" {
#endif
#if KXC_CHANGES
} // namespace KJS
} // namespace KXMLCore
#endif
#endif // USE_SYSTEM_MALLOC
......@@ -32,7 +32,7 @@ namespace KXMLCore {
void *fastCalloc(size_t n_elements, size_t element_size);
void fastFree(void* p);
void *fastRealloc(void* p, size_t n);
} // namespace KXMLCore
using KXMLCore::fastMalloc;
......
......@@ -76,6 +76,45 @@
(WebCore::Image::getNSImage): Use KWQRetainNSRelease to properly retain
a reference to an Objective-C object in a C++ class.
2006-03-29 Geoffrey Garen <ggaren@apple.com>
Reviewed by Darin.
- WebCore side of fix for <rdar://problem/4308243> 8F36 Regression:
crash in malloc_consolidate if you use a .PAC file
(1) To ensure thread-safe deallocation, set the "unsafe to destroy on
non-main threads" bit in the DOMObject constructor.
(2) Made all binding objects inherit from DOMObject, because the
WebCore data structures they wrap are not thread-safe. "DOMObject" is
a slightly awkward name for things like the Window object, but the
DOM spec is considering adding a Window object, and creating a whole
new base class for this purpose seemed like overkill.
* khtml/ecma/JSDOMParser.h:
* khtml/ecma/JSXMLHttpRequest.h:
* khtml/ecma/JSXMLSerializer.cpp:
(KJS::XMLSerializerConstructorImp::XMLSerializerConstructorImp):
* khtml/ecma/JSXMLSerializer.h:
* khtml/ecma/JSXSLTProcessor.h:
* khtml/ecma/kjs_binding.h:
(KJS::DOMObject::DOMObject): Unset the "safe to collect on non-main
threads bit" to ensure thread-safe deallocation.
* khtml/ecma/kjs_html.h:
* khtml/ecma/kjs_navigator.cpp:
(KJS::Navigator::Navigator):
(KJS::PluginBase::PluginBase):
* khtml/ecma/kjs_navigator.h:
* khtml/ecma/kjs_proxy.cpp:
* khtml/ecma/kjs_window.cpp:
(KJS::History::History):
(KJS::FrameArray::FrameArray):
(KJS::Screen::Screen):
(KJS::Window::Window):
(KJS::BarInfo::BarInfo):
* khtml/ecma/kjs_window.h:
2006-03-29 Geoffrey Garen <ggaren@apple.com>
Reviewed by Darin.
......@@ -26,7 +26,7 @@
namespace KJS {
class DOMParserConstructorImp : public JSObject {
class DOMParserConstructorImp : public DOMObject {
public:
DOMParserConstructorImp(ExecState*, WebCore::Document*);
virtual bool implementsConstruct() const;
......
......@@ -32,7 +32,7 @@ namespace WebCore {
namespace KJS {
class JSXMLHttpRequestConstructorImp : public JSObject {
class JSXMLHttpRequestConstructorImp : public DOMObject {
public:
JSXMLHttpRequestConstructorImp(ExecState *exec, WebCore::Document *d);
~JSXMLHttpRequestConstructorImp();
......
......@@ -41,7 +41,6 @@ KJS_IMPLEMENT_PROTOFUNC(XMLSerializerProtoFunc)
KJS_IMPLEMENT_PROTOTYPE("XMLSerializer",XMLSerializerProto,XMLSerializerProtoFunc)
XMLSerializerConstructorImp::XMLSerializerConstructorImp(ExecState *exec)
: JSObject()
{
putDirect(prototypePropertyName, XMLSerializerProto::self(exec), DontEnum|DontDelete|ReadOnly);
}
......
......@@ -27,7 +27,7 @@ namespace KJS {
class JSEventListener;
class XMLSerializerConstructorImp : public JSObject {
class XMLSerializerConstructorImp : public DOMObject {
public:
XMLSerializerConstructorImp(ExecState *);
virtual bool implementsConstruct() const;
......
......@@ -57,7 +57,7 @@ private:
RefPtr<WebCore::XSLTProcessor> m_impl;
};
class XSLTProcessorConstructorImp : public JSObject {
class XSLTProcessorConstructorImp : public DOMObject {
public:
XSLTProcessorConstructorImp(ExecState *);
virtual bool implementsConstruct() const { return true; }
......
......@@ -46,9 +46,11 @@ namespace KJS {
*/
class DOMObject : public JSObject {
protected:
DOMObject() : JSObject() {}
// DOMObject Destruction is not thread-safe because JS DOM objects
// wrap unsafe WebCore DOM data structures
DOMObject() : JSObject(false) {}
public:
virtual UString toString(ExecState *exec) const;
virtual UString toString(ExecState *exec) const;
};
class DOMNode;
......
......@@ -339,7 +339,7 @@ namespace KJS {
////////////////////// Option Object ////////////////////////
class OptionConstructorImp : public JSObject {
class OptionConstructorImp : public DOMObject {
public:
OptionConstructorImp(ExecState *exec, WebCore::Document *d);
virtual bool implementsConstruct() const;
......@@ -350,7 +350,7 @@ namespace KJS {
////////////////////// Image Object ////////////////////////
class ImageConstructorImp : public JSObject {
class ImageConstructorImp : public DOMObject {
public:
ImageConstructorImp(ExecState *exec, WebCore::Document *d);
virtual bool implementsConstruct() const;
......
......@@ -36,7 +36,7 @@ using namespace WebCore;
namespace KJS {
class PluginBase : public JSObject {
class PluginBase : public DOMObject {
public:
PluginBase(ExecState *exec);
virtual ~PluginBase();
......@@ -141,8 +141,11 @@ const ClassInfo Navigator::info = { "Navigator", 0, &NavigatorTable, 0 };
*/
KJS_IMPLEMENT_PROTOFUNC(NavigatorFunc)
Navigator::Navigator(ExecState *exec, Frame *p)
: JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()), m_frame(p) { }
Navigator::Navigator(ExecState *exec, Frame *f)
: m_frame(f)
{
setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
}
bool Navigator::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
{
......@@ -224,8 +227,9 @@ void PluginBase::cachePluginDataIfNecessary()
}
PluginBase::PluginBase(ExecState *exec)
: JSObject(exec->lexicalInterpreter()->builtinObjectPrototype() )
{
setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
cachePluginDataIfNecessary();
m_plugInCacheRefCount++;
}
......
......@@ -21,6 +21,7 @@
#ifndef KJS_Navigator_H
#define KJS_Navigator_H
#include "kjs_binding.h"
#include <kjs/object.h>
namespace WebCore {
......@@ -29,7 +30,7 @@ namespace WebCore {
namespace KJS {
class Navigator : public JSObject {
class Navigator : public DOMObject {
public:
Navigator(ExecState *exec, WebCore::Frame *p);
virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
......
......@@ -125,9 +125,8 @@ ScriptInterpreter *KJSProxy::interpreter()
}
// Implementation of the debug() function
class TestFunctionImp : public JSObject {
class TestFunctionImp : public DOMObject {
public:
TestFunctionImp() : JSObject() {}
virtual bool implementsCall() const { return true; }
virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
};
......
......@@ -95,11 +95,14 @@ public:
////////////////////// History Object ////////////////////////
class History : public JSObject {
class History : public DOMObject {
friend class HistoryFunc;
public:
History(ExecState *exec, Frame *p)
: JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()), m_frame(p) { }
History(ExecState *exec, Frame *f)
: m_frame(f)
{
setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
}
virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
JSValue *getValueProperty(ExecState *exec, int token) const;
virtual const ClassInfo* classInfo() const { return &info; }
......@@ -111,10 +114,14 @@ public:
Frame* m_frame;
};
class FrameArray : public JSObject {
class FrameArray : public DOMObject {
public:
FrameArray(ExecState *exec, Frame *p)
: JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()), m_frame(p) { }
FrameArray(ExecState *exec, Frame *f)
: m_frame(f)
{
setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
}
virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
JSValue *getValueProperty(ExecState *exec, int token);
virtual UString toString(ExecState *exec) const;
......@@ -156,8 +163,9 @@ const ClassInfo Screen::info = { "Screen", 0, &ScreenTable, 0 };
// We set the object prototype so that toString is implemented
Screen::Screen(ExecState* exec, Frame* f)
: JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()), m_frame(f)
: m_frame(f)
{
setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
}
bool Screen::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
......@@ -306,9 +314,8 @@ const ClassInfo Window::info = { "Window", 0, &WindowTable, 0 };
*/
KJS_IMPLEMENT_PROTOFUNC(WindowFunc)
Window::Window(Frame *p)
: JSObject(/*no proto*/)
, m_frame(p)
Window::Window(Frame *f)
: m_frame(f)
, screen(0)
, history(0)
, frames(0)
......@@ -2377,11 +2384,11 @@ const ClassInfo BarInfo::info = { "BarInfo", 0, 0, 0 };
visible BarInfo::Visible DontDelete|ReadOnly
@end
*/
BarInfo::BarInfo(ExecState *exec, Frame *p, Type barType)
: JSObject(exec->lexicalInterpreter()->builtinObjectPrototype())
, m_frame(p)
BarInfo::BarInfo(ExecState *exec, Frame *f, Type barType)
: m_frame(f)
, m_type(barType)
{
setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
}
JSValue *BarInfo::getValueProperty(ExecState *exec, int token) const
......
......@@ -67,7 +67,7 @@ namespace KJS {
class DOMWindowTimer;
class Screen : public JSObject {
class Screen : public DOMObject {
public:
enum { Height, Width, ColorDepth, PixelDepth, AvailLeft, AvailTop, AvailHeight, AvailWidth };
virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
......@@ -80,7 +80,7 @@ namespace KJS {
WebCore::Frame* m_frame;
};
class Window : public JSObject {
class Window : public DOMObject {
friend class Location;
friend class WindowFunc;
friend class ScheduledAction;
......@@ -218,7 +218,7 @@ namespace KJS {
DeprecatedString m_code;
};
class Location : public JSObject {
class Location : public DOMObject {
public:
virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
JSValue *getValueProperty(ExecState *exec, int token) const;
......@@ -236,7 +236,7 @@ namespace KJS {
WebCore::Frame* m_frame;
};
class Selection : public JSObject {
class Selection : public DOMObject {
public:
virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
JSValue *getValueProperty(ExecState *exec, int token) const;
......@@ -254,7 +254,7 @@ namespace KJS {
WebCore::Frame* m_frame;
};
class BarInfo : public JSObject {
class BarInfo : public DOMObject {
public:
virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
JSValue *getValueProperty(ExecState *exec, int token) const;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment