Fixed <rdar://problem/
3972522> (179-180) 40% slowdown on iBench JavaScript test
I added a member variable to ObjectImp. This changed it's size and consequently
hampered the optimizations built into the garbage collector. Objects no longer
fit within the allocators cell size, and thus allocation fell back to a slower
allocator.
As a result of this fix I also dramatically cleaned up how runtime objects are
accessed. The path mostly *removes* code.
Reviewed by Chris.
* bindings/runtime_method.cpp:
(RuntimeMethodImp::call):
* bindings/runtime_object.cpp:
(RuntimeObjectImp::get):
(RuntimeObjectImp::put):
(RuntimeObjectImp::canPut):
(RuntimeObjectImp::hasProperty):
(RuntimeObjectImp::defaultValue):
* bindings/runtime_object.h:
* kjs/object.cpp:
(KJS::ObjectImp::ObjectImp):
* kjs/object.h:
WebCore:
Fixed <rdar://problem/
3972522> (179-180) 40% slowdown on iBench JavaScript test
I added a member variable to ObjectImp. This changed it's size and consequently
hampered the optimizations built into the garbage collector. Objects no longer
fit within the allocators cell size, and thus allocation fell back to a slower
allocator.
As a result of this fix I also dramatically cleaned up how runtime objects are
accessed. The path mostly *removes* code.
Reviewed by Chris.
* khtml/ecma/kjs_dom.cpp:
(DOMDocumentProtoFunc::tryCall):
(DOMElementProtoFunc::tryCall):
(KJS::getRuntimeObject):
* khtml/ecma/kjs_dom.h:
* khtml/ecma/kjs_html.cpp:
(KJS::HTMLDocument::tryGet):
(KJS::HTMLElement::tryGet):
(KJS::HTMLElement::implementsCall):
(KJS::HTMLElement::call):
(KJS::HTMLElement::tryPut):
(KJS::HTMLCollection::tryGet):
(KJS::HTMLCollection::getNamedItems):
* khtml/ecma/kjs_html.h:
* khtml/ecma/kjs_window.cpp:
(Window::get):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@8453
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2005-01-26 Richard Williamson <rjw@apple.com>
+
+ Fixed <rdar://problem/3972522> (179-180) 40% slowdown on iBench JavaScript test
+
+ I added a member variable to ObjectImp. This changed it's size and consequently
+ hampered the optimizations built into the garbage collector. Objects no longer
+ fit within the allocators cell size, and thus allocation fell back to a slower
+ allocator.
+
+ As a result of this fix I also dramatically cleaned up how runtime objects are
+ accessed. The path mostly *removes* code.
+
+ Reviewed by Chris.
+
+ * bindings/runtime_method.cpp:
+ (RuntimeMethodImp::call):
+ * bindings/runtime_object.cpp:
+ (RuntimeObjectImp::get):
+ (RuntimeObjectImp::put):
+ (RuntimeObjectImp::canPut):
+ (RuntimeObjectImp::hasProperty):
+ (RuntimeObjectImp::defaultValue):
+ * bindings/runtime_object.h:
+ * kjs/object.cpp:
+ (KJS::ObjectImp::ObjectImp):
+ * kjs/object.h:
+
2005-01-20 Darin Adler <darin@apple.com>
Reviewed by me, changes by Han Ming Ong.
Value RuntimeMethodImp::call(ExecState *exec, Object &thisObj, const List &args)
{
if (_methodList.length() > 0) {
- RuntimeObjectImp *imp = static_cast<RuntimeObjectImp*>(thisObj.imp());
+ Value runtimeObject = thisObj.get(exec, "__apple_runtime_object");
+ RuntimeObjectImp *imp = static_cast<RuntimeObjectImp*>(runtimeObject.imp());
if (imp) {
Instance *instance = imp->getInternalInstance();
instance = i;
}
-RuntimeObjectImp::RuntimeObjectImp(Bindings::Instance *i, const Value &fb, bool oi) : ObjectImp ((ObjectImp *)0)
-{
- ownsInstance = oi;
- instance = i;
- fallback = fb;
-}
-
Value RuntimeObjectImp::get(ExecState *exec, const Identifier &propertyName) const
{
Value result = Undefined();
if (methodList.length() > 0) {
result = Object (new RuntimeMethodImp(exec, propertyName, methodList));
}
- else if (!fallback.isNull() && fallback.type() == ObjectType){
- ObjectImp *imp = static_cast<ObjectImp*>(fallback.imp());
- imp->setForwardingScriptMessage(true);
- result = imp->get (exec, propertyName);
- imp->setForwardingScriptMessage(false);
- }
}
if (result.type() == UndefinedType) {
getInternalInstance()->setValueOfField(exec, aField, value);
}
else {
- bool domHasProperty = false;
- if (!fallback.isNull() && fallback.type() == ObjectType){
- ObjectImp *imp = static_cast<ObjectImp*>(fallback.imp());
- imp->setForwardingScriptMessage(true);
- domHasProperty = imp->hasProperty(exec, propertyName);
- imp->setForwardingScriptMessage(false);
- }
-
- // If the DOM has the property, give it a crack first (even if it read-only).
- if (domHasProperty || !getInternalInstance()->supportsSetValueOfUndefinedField()) {
- ObjectImp *imp = static_cast<ObjectImp*>(fallback.imp());
- imp->setForwardingScriptMessage(true);
- imp->put(exec, propertyName, value, attr);
- imp->setForwardingScriptMessage(false);
- }
- // Now let the runtime object attempt to handle the undefined field.
- else if (getInternalInstance()->supportsSetValueOfUndefinedField()){
+ if (getInternalInstance()->supportsSetValueOfUndefinedField()){
getInternalInstance()->setValueOfUndefinedField(exec, propertyName, value);
}
}
if (aField)
return true;
- if (!fallback.isNull() && fallback.type() == ObjectType) {
- ObjectImp *imp = static_cast<ObjectImp*>(fallback.imp());
- imp->setForwardingScriptMessage(true);
- result = imp->canPut (exec, propertyName);
- imp->setForwardingScriptMessage(false);
- }
-
return result;
}
if (methodList.length() > 0)
return true;
- if (!fallback.isNull() && fallback.type() == ObjectType) {
- ObjectImp *imp = static_cast<ObjectImp*>(fallback.imp());
- imp->setForwardingScriptMessage(true);
- result = imp->hasProperty (exec, propertyName);
- imp->setForwardingScriptMessage(false);
- }
-
return result;
}
instance->begin();
- if (!fallback.isNull() && fallback.type() == ObjectType) {
- ObjectImp *imp = static_cast<ObjectImp*>(fallback.imp());
- imp->setForwardingScriptMessage(true);
- result = imp->defaultValue (exec, hint);
- imp->setForwardingScriptMessage(false);
- }
- else {
- result = getInternalInstance()->defaultValue(hint);
- }
+ result = getInternalInstance()->defaultValue(hint);
instance->end();
~RuntimeObjectImp();
RuntimeObjectImp(Bindings::Instance *i, bool ownsInstance = true);
- RuntimeObjectImp(Bindings::Instance *i, const Value &fallback, bool ownsInstance = true);
const ClassInfo *classInfo() const { return &info; }
virtual bool implementsCall() const;
virtual Value call(ExecState *exec, Object &thisObj, const List &args);
-
- Value fallbackObject() { return fallback; }
static const ClassInfo info;
private:
- ProtectedValue fallback;
Bindings::Instance *instance;
bool ownsInstance;
};
// ------------------------------ ObjectImp ------------------------------------
ObjectImp::ObjectImp(const Object &proto)
- : _proto(static_cast<ObjectImp*>(proto.imp())), _internalValue(0L), _forwardingScriptMessage(false)
+ : _proto(static_cast<ObjectImp*>(proto.imp())), _internalValue(0L)
{
//fprintf(stderr,"ObjectImp::ObjectImp %p\n",(void*)this);
}
ObjectImp::ObjectImp(ObjectImp *proto)
- : _proto(proto), _internalValue(0L), _forwardingScriptMessage(false)
+ : _proto(proto), _internalValue(0L)
{
//fprintf(stderr,"ObjectImp::ObjectImp %p\n",(void*)this);
}
//fprintf(stderr,"ObjectImp::ObjectImp %p\n",(void*)this);
_proto = NullImp::staticNull;
_internalValue = 0L;
- _forwardingScriptMessage = false;
}
ObjectImp::~ObjectImp()
void saveProperties(SavedProperties &p) const { _prop.save(p); }
void restoreProperties(const SavedProperties &p) { _prop.restore(p); }
-#if APPLE_CHANGES
- bool forwardingScriptMessage() const { return _forwardingScriptMessage; }
- void setForwardingScriptMessage(bool f) { _forwardingScriptMessage = f; }
-#endif
-
protected:
PropertyMap _prop;
private:
ValueImp *_proto;
ValueImp *_internalValue;
ScopeChain _scope;
-
-#if APPLE_CHANGES
- bool _forwardingScriptMessage;
-#endif
};
/**
+2005-01-26 Richard Williamson <rjw@apple.com>
+
+ Fixed <rdar://problem/3972522> (179-180) 40% slowdown on iBench JavaScript test
+
+ I added a member variable to ObjectImp. This changed it's size and consequently
+ hampered the optimizations built into the garbage collector. Objects no longer
+ fit within the allocators cell size, and thus allocation fell back to a slower
+ allocator.
+
+ As a result of this fix I also dramatically cleaned up how runtime objects are
+ accessed. The path mostly *removes* code.
+
+ Reviewed by Chris.
+
+ * khtml/ecma/kjs_dom.cpp:
+ (DOMDocumentProtoFunc::tryCall):
+ (DOMElementProtoFunc::tryCall):
+ (KJS::getRuntimeObject):
+ * khtml/ecma/kjs_dom.h:
+ * khtml/ecma/kjs_html.cpp:
+ (KJS::HTMLDocument::tryGet):
+ (KJS::HTMLElement::tryGet):
+ (KJS::HTMLElement::implementsCall):
+ (KJS::HTMLElement::call):
+ (KJS::HTMLElement::tryPut):
+ (KJS::HTMLCollection::tryGet):
+ (KJS::HTMLCollection::getNamedItems):
+ * khtml/ecma/kjs_html.h:
+ * khtml/ecma/kjs_window.cpp:
+ (Window::get):
+
2005-01-26 Richard Williamson <rjw@apple.com>
Fixed <rdar://problem/3757712> REGRESSION (Mail): WebCore does not allow Devanagari ligature input
return getDOMNodeList(exec,doc.getElementsByTagNameNS(args[0].toString(exec).string(),
args[1].toString(exec).string()));
case DOMDocument::GetElementById:
-#if APPLE_CHANGES
- {
- DOM::Element node = doc.getElementById(args[0].toString(exec).string());
- if (!node.isNull()) {
- Value domValue = getDOMNode(exec, node);
- ObjectImp *imp = static_cast<ObjectImp *>(domValue.imp());
- if (!imp->forwardingScriptMessage() && (node.handle()->id() == ID_APPLET || node.handle()->id() == ID_EMBED || node.handle()->id() == ID_OBJECT)) {
- Value v = getRuntimeObject(exec,node,domValue);
- if (!v.isNull())
- return v;
- }
- return domValue;
- }
- return getDOMNode(exec,node);
- }
-#else
return getDOMNode(exec,doc.getElementById(args[0].toString(exec).string()));
-#endif
case DOMDocument::CreateRange:
return getDOMRange(exec,doc.createRange());
case DOMDocument::CreateNodeIterator: {
return Undefined();
}
-Value DOMElementProtoFunc::tryCall(ExecState *exec, Object &to, const List &args)
+Value DOMElementProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
{
- Object thisObj;
-
- if (to.classInfo() == &KJS::RuntimeObjectImp::info) {
- KJS::RuntimeObjectImp *imp = static_cast<KJS::RuntimeObjectImp *>(to.imp());
- thisObj = imp->fallbackObject().toObject(exec);
- }
- else {
- thisObj = to;
- }
-
if (!thisObj.inherits(&KJS::DOMNode::info)) { // node should be enough here, given the cast
Object err = Error::create(exec,TypeError);
exec->setException(err);
return Value(cacheDOMObject<DOM::NamedNodeMap, KJS::DOMNamedNodeMap>(exec, m));
}
-Value KJS::getRuntimeObject(ExecState *exec, const DOM::Node &node, const Value &fallback)
+Value KJS::getRuntimeObject(ExecState *exec, const DOM::Node &node)
{
DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
if (appletElement->getAppletInstance()) {
// The instance is owned by the applet element.
- RuntimeObjectImp *appletImp = new RuntimeObjectImp(appletElement->getAppletInstance(), fallback, false);
+ RuntimeObjectImp *appletImp = new RuntimeObjectImp(appletElement->getAppletInstance(), false);
return Value(appletImp);
}
}
DOM::HTMLEmbedElementImpl *embedElement = static_cast<DOM::HTMLEmbedElementImpl *>(element.handle());
if (embedElement->getEmbedInstance()) {
- RuntimeObjectImp *runtimeImp = new RuntimeObjectImp(embedElement->getEmbedInstance(), fallback, false);
+ RuntimeObjectImp *runtimeImp = new RuntimeObjectImp(embedElement->getEmbedInstance(), false);
return Value(runtimeImp);
}
}
DOM::HTMLObjectElementImpl *objectElement = static_cast<DOM::HTMLObjectElementImpl *>(element.handle());
if (objectElement->getObjectInstance()) {
- RuntimeObjectImp *runtimeImp = new RuntimeObjectImp(objectElement->getObjectInstance(), fallback, false);
+ RuntimeObjectImp *runtimeImp = new RuntimeObjectImp(objectElement->getObjectInstance(), false);
return Value(runtimeImp);
}
}
Value getDOMDocumentNode(ExecState *exec, const DOM::Document &n);
bool checkNodeSecurity(ExecState *exec, const DOM::Node& n);
#if APPLE_CHANGES
- Value getRuntimeObject(ExecState *exec, const DOM::Node &n, const Value &fallback);
+ Value getRuntimeObject(ExecState *exec, const DOM::Node &n);
#endif
Value getDOMNode(ExecState *exec, const DOM::Node &n);
Value getDOMNamedNodeMap(ExecState *exec, const DOM::NamedNodeMap &m);
#include "ecma/kjs_window.h"
#include "ecma/kjs_html.lut.h"
#include "kjs_events.h"
+#include "kjs_proxy.h"
#include "misc/htmltags.h"
DOM::HTMLCollection applets = doc.applets();
DOM::HTMLElement anApplet = applets.namedItem (propertyName.string());
if (!anApplet.isNull()) {
- Value domValue = getDOMNode(exec,anApplet);
- ObjectImp *imp = static_cast<ObjectImp *>(domValue.imp());
- if (!imp->forwardingScriptMessage()) {
- Value v = getRuntimeObject(exec,anApplet,getDOMNode(exec,anApplet));
- if (!v.isNull())
- return v;
- }
+ return getDOMNode(exec,anApplet);
}
DOM::HTMLCollection embeds = doc.embeds();
DOM::HTMLElement anEmbed = embeds.namedItem (propertyName.string());
if (!anEmbed.isNull()) {
- Value domValue = getDOMNode(exec,anEmbed);
- ObjectImp *imp = static_cast<ObjectImp *>(domValue.imp());
- if (!imp->forwardingScriptMessage()) {
- Value v = getRuntimeObject(exec,anEmbed,getDOMNode(exec,anEmbed));
- if (!v.isNull())
- return v;
- }
+ return getDOMNode(exec,anApplet);
}
DOM::HTMLCollection objects = doc.objects();
DOM::HTMLElement anObject = objects.namedItem (propertyName.string());
if (!anObject.isNull()) {
- Value domValue = getDOMNode(exec,anObject);
- ObjectImp *imp = static_cast<ObjectImp *>(domValue.imp());
- if (!imp->forwardingScriptMessage()) {
- Value v = getRuntimeObject(exec,anObject,getDOMNode(exec,anObject));
- if (!v.isNull())
- return v;
- }
+ return getDOMNode(exec,anApplet);
}
#endif
case ID_EMBED:
case ID_OBJECT:
case ID_APPLET: {
+ if (propertyName == "__apple_runtime_object") {
+ return getRuntimeObject(exec,element);
+ }
+
Value domValue = getDOMNode(exec,element);
- ObjectImp *imp = static_cast<ObjectImp *>(domValue.imp());
- if (!imp->forwardingScriptMessage()) {
- Value v = getRuntimeObject(exec,element,getDOMNode(exec,element));
- if (!v.isNull())
- return v;
+ Value runtimeObject = getRuntimeObject(exec,element);
+ if (!runtimeObject.isNull()) {
+ ObjectImp *imp = static_cast<ObjectImp *>(runtimeObject.imp());
+ if (imp->hasProperty(exec, propertyName)) {
+ return imp->get (exec, propertyName);
+ }
}
}
break;
return DOMObjectLookupGet<KJS::HTMLElementFunction, KJS::HTMLElement, DOMElement>(exec, propertyName, &KJS::HTMLElementTable, this);
}
+#if APPLE_CHANGES
+bool KJS::HTMLElement::implementsCall() const
+{
+ DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
+ switch (element.elementId()) {
+ case ID_EMBED:
+ case ID_OBJECT:
+ case ID_APPLET: {
+ DOM::DocumentImpl* doc = element.handle()->getDocument();
+ KJSProxy *proxy = KJSProxy::proxy(doc->part());
+ ExecState *exec = proxy->interpreter()->globalExec();
+ Value domValue = getDOMNode(exec,element);
+ Value runtimeObject = getRuntimeObject(exec,element);
+ if (!runtimeObject.isNull()) {
+ ObjectImp *imp = static_cast<ObjectImp *>(runtimeObject.imp());
+ return imp->implementsCall ();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+Value KJS::HTMLElement::call(ExecState *exec, Object &thisObj, const List&args)
+{
+ DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
+ switch (element.elementId()) {
+ case ID_EMBED:
+ case ID_OBJECT:
+ case ID_APPLET: {
+ Value domValue = getDOMNode(exec,element);
+ Value runtimeObject = getRuntimeObject(exec,element);
+ if (!runtimeObject.isNull()) {
+ ObjectImp *imp = static_cast<ObjectImp *>(runtimeObject.imp());
+ return imp->call (exec, thisObj, args);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return Undefined();
+}
+#endif
+
Value KJS::HTMLElement::getValueProperty(ExecState *exec, int token) const
{
DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
return;
}
}
+#if APPLE_CHANGES
+ case ID_EMBED:
+ case ID_OBJECT:
+ case ID_APPLET: {
+ Value domValue = getDOMNode(exec,element);
+ Value runtimeObject = getRuntimeObject(exec,element);
+ if (!runtimeObject.isNull()) {
+ ObjectImp *imp = static_cast<ObjectImp *>(runtimeObject.imp());
+ if (imp->canPut(exec, propertyName)) {
+ return imp->put (exec, propertyName, value);
+ }
+ }
+ }
+ break;
+#endif
break;
default:
break;
if (ok) {
DOM::Node node = collection.item(u);
-#if APPLE_CHANGES
- if (!node.isNull()) {
- Value domValue = getDOMNode(exec,node);
- ObjectImp *imp = static_cast<ObjectImp *>(domValue.imp());
- if (!imp->forwardingScriptMessage() &&
- (node.handle()->id() == ID_APPLET || node.handle()->id() == ID_EMBED || node.handle()->id() == ID_OBJECT)) {
- Value v = getRuntimeObject(exec, node, domValue);
- if (!v.isNull())
- return v;
- }
- return domValue;
- }
-#else
return getDOMNode(exec,node);
-#endif
}
else
return getNamedItems(exec,propertyName);
if (namedItems.count() == 1) {
DOM::Node node = namedItems[0];
-#if APPLE_CHANGES
- if (!node.isNull()) {
- Value domValue = getDOMNode(exec,node);
- ObjectImp *imp = static_cast<ObjectImp *>(domValue.imp());
- if (!imp->forwardingScriptMessage() &&
- (node.handle()->id() == ID_APPLET || node.handle()->id() == ID_EMBED || node.handle()->id() == ID_OBJECT)) {
- Value v = getRuntimeObject(exec, node, domValue);
- if (!v.isNull())
- return v;
- }
- return domValue;
- }
-#else
return getDOMNode(exec,node);
-#endif
}
return Value(new DOMNamedNodesCollection(exec,namedItems));
virtual const ClassInfo* classInfo() const;
static const ClassInfo info;
+#if APPLE_CHANGES
+ virtual Value call(ExecState *exec, Object &thisObj, const List&args);
+ virtual bool implementsCall() const;
+#endif
+
static const ClassInfo html_info, head_info, link_info, title_info,
meta_info, base_info, isIndex_info, style_info, body_info, form_info,
select_info, optGroup_info, option_info, input_info, textArea_info,
DOM::HTMLCollection coll = m_part->htmlDocument().all();
DOM::HTMLElement element = coll.namedItem(p.string());
if (!element.isNull()) {
-#if APPLE_CHANGES
- Value domValue = getDOMNode(exec,element);
- ObjectImp *imp = static_cast<ObjectImp *>(domValue.imp());
- if (!imp->forwardingScriptMessage() &&
- (element.handle()->id() == ID_APPLET || element.handle()->id() == ID_EMBED || element.handle()->id() == ID_OBJECT)) {
- Value v = getRuntimeObject(exec,element,domValue);
- if (!v.isNull())
- return v;
- }
- return domValue;
-#else
return getDOMNode(exec,element);
-#endif
}
}