Changeset 34355 in webkit for trunk/JavaScriptCore/kjs/object.h


Ignore:
Timestamp:
Jun 3, 2008, 5:40:47 PM (17 years ago)
Author:
Darin Adler
Message:

JavaScriptCore:

2008-06-03 Darin Adler <Darin Adler>

Reviewed by Geoff.

Makes standalone SunSpider 1.025x as fast as before.

The getOwnPropertySlot virtual function now takes care of the toObject call
for get. Similarly, the put function (and later deleteProperty) does the
same for those operations. To do this, the virtual functions were moved from
the JSObject class to the JSCell class. Also, since the caller no longer knows
the identity of the "original object", which is used by JavaScript-function
based getters, changed the PropertySlot class so the original object is
already stored in the slot when getOwnPropertySlot is called, if the caller
intends to call getValue.

This affected the old interpreter code enough that the easiest thing for me
was to just delete it. While I am not certain the mysterious slowdown is not
still occurring, the net change is definitely a significant speedup.

  • VM/Machine.cpp: Moved the UNLIKELY macro into AlwaysInline.h. (KJS::resolve): Set up the originalObject in the PropertySlot before calling getPropertySlot. Also removed the originalObject argument from getValue. (KJS::resolve_skip): Ditto. (KJS::resolveBaseAndProperty): Ditto. (KJS::resolveBaseAndFunc): Ditto. (KJS::Machine::privateExecute): Removed the toObject calls from the get and put functions where possible, instead calling directly with JSValue and letting the JSValue and JSCell calls handle toObject. Same for toThisObject.
  • kjs/ExecState.h: Removed OldInterpreterExecState.
  • API/JSBase.cpp: Updated includes.
  • kjs/LocalStorageEntry.h: Removed contents. Later we can remove the file too.
  • kjs/array_instance.cpp: (KJS::ArrayInstance::lengthGetter): Removed originalObject argumet. (KJS::ArrayInstance::inlineGetOwnPropertySlot): Don't pass a base value to setValueSlot. Also use UNLIKELY around the "getting elements past the end of the array" code path; less common than successfully getting an element.
  • kjs/array_object.cpp: (KJS::getProperty): Initialize the PropertySlot with the original object. Don't pass the original object to the get function. (KJS::arrayProtoFuncFilter): Ditto. (KJS::arrayProtoFuncMap): Ditto. (KJS::arrayProtoFuncEvery): Ditto. (KJS::arrayProtoFuncForEach): Ditto. (KJS::arrayProtoFuncSome): Ditto.
  • kjs/function_object.cpp: (KJS::FunctionObjectImp::construct): Removed an obsolete comment.
  • kjs/grammar.y: Eliminated support for some of the node types that were used to optimize executing from the syntax tree.
  • kjs/internal.cpp: (KJS::StringImp::toThisObject): Added. Same as toObject. (KJS::NumberImp::toThisObject): Ditto. (KJS::GetterSetterImp::getOwnPropertySlot): Added. Not reached. (KJS::GetterSetterImp::put): Ditto. (KJS::GetterSetterImp::toThisObject): Ditto.
  • kjs/internal.h: Added toThisObject to NumberImp for speed.
  • kjs/lexer.cpp: (KJS::Lexer::shift): Changed shift to just do a single character, to unroll the loop and especially to make the one character case faster. (KJS::Lexer::setCode): Call shift multiple times instead of passing a number. (KJS::Lexer::lex): Ditto. (KJS::Lexer::matchPunctuator): Ditto. Also removed unneeded elses after returns. (KJS::Lexer::scanRegExp): Ditto.
  • kjs/lexer.h: Removed the count argument from shift.
  • kjs/math_object.cpp: (KJS::mathProtoFuncPow): Call jsNaN instead of jsNumber(NaN).
  • kjs/nodes.cpp: Removed some of the things needed only for the pre-SquirrelFish execution model. (KJS::ForNode::emitCode): Handle cases where some expressions are missing by not emitting any code at all. The old way was to emit code for "true", but this is an unnecessary remnant of the old way of doing things.
  • kjs/nodes.h: Removed some of the things needed only for the pre-SquirrelFish execution model.
  • kjs/object.cpp: (KJS::JSObject::fillGetterPropertySlot): Changed to only pass in the getter function. The old code passed in a base, but it was never used when actually getting the property; the toThisObject call was pointless. Also changed to not pass a base for setUndefined.
  • kjs/object.h: Added the new JSCell operations to GetterSetterImp. Never called. (KJS::JSObject::get): Initialize the object in the PropertySlot and don't pass it in getValue. (KJS::JSObject::getOwnPropertySlotForWrite): Removed the base argument in calls to setValueSlot. (KJS::JSObject::getOwnPropertySlot): Ditto. (KJS::JSValue::get): Added. Here because it calls through to JSObject. A version of JSObject::get that also handles the other types of JSValue by creating the appropriate wrapper. Saves the virtual call to toObject. (KJS::JSValue::put): Ditto. (KJS::JSValue::deleteProperty): Ditto.
  • kjs/property_slot.cpp: (KJS::PropertySlot::undefinedGetter): Removed the originalObject argument. (KJS::PropertySlot::ungettableGetter): Ditto. (KJS::PropertySlot::functionGetter): Ditto. Use the value in the base as the "this" object, which will be set to the original object by the new PropertySlot initialization code. Also call toThisObject. The old code did not do this, but needed to so we can properly handle the activation object like the other similar code paths.
  • kjs/property_slot.h: (KJS::PropertySlot::PropertySlot): Added a constructor that takes a base object. In debug builds, set the base to 0 if you don't pass one. (KJS::PropertySlot::getValue): Don't take or pass the originalObject. (KJS::PropertySlot::setValueSlot): Don't take a base object, and clear the base object in debug builds. (KJS::PropertySlot::setGetterSlot): Ditto. (KJS::PropertySlot::setUndefined): Ditto. (KJS::PropertySlot::setUngettable): Ditto. (KJS::PropertySlot::slotBase): Assert that a base object is present. This will fire if someone actually calls the get function without having passed in a base object and the getter needs it. (KJS::PropertySlot::setBase): Added. Used by the code that implements toObject so it can supply the original object after the fact. (KJS::PropertySlot::clearBase): Added. Clears the base, but is debug-only code because it's an error to fetch the base if you don't have a guarantee it was set.
  • API/JSCallbackObject.h:
  • API/JSCallbackObjectFunctions.h: (KJS::JSCallbackObject::cachedValueGetter): (KJS::JSCallbackObject::staticValueGetter): (KJS::JSCallbackObject::staticFunctionGetter): (KJS::JSCallbackObject::callbackGetter):
  • kjs/JSActivation.cpp: (KJS::JSActivation::getOwnPropertySlot): (KJS::JSActivation::argumentsGetter):
  • kjs/JSActivation.h:
  • kjs/JSVariableObject.h: (KJS::JSVariableObject::symbolTableGet):
  • kjs/array_instance.h:
  • kjs/function.cpp: (KJS::FunctionImp::argumentsGetter): (KJS::FunctionImp::callerGetter): (KJS::FunctionImp::lengthGetter): (KJS::Arguments::mappedIndexGetter):
  • kjs/function.h:
  • kjs/lookup.h: (KJS::staticFunctionGetter): (KJS::staticValueGetter):
  • kjs/string_object.cpp: (KJS::StringInstance::lengthGetter): (KJS::StringInstance::indexGetter): (KJS::stringInstanceNumericPropertyGetter):
  • kjs/string_object.h: Removed originalObject arguments from getters. Don't pass base values to the various PropertySlot functions that no longer take them.
  • kjs/value.cpp: (KJS::JSCell::getOwnPropertySlot): Added. Calls toObject and then sets the slot. This function has to always return true, because the caller can't walk the prototype chain. Because of that, we do a getPropertySlot, not getOwnPropertySlot, which works for the caller. This is private, only called by getOwnPropertySlotInternal. (KJS::JSCell::put): Added. Calls toObject and then put. (KJS::JSCell::toThisObject): Added. Calls toObject.
  • kjs/value.h: Added get, put, and toThisObject to both JSValue and JSCell. These take care of the toObject operation without an additional virtual function call, and so make the common "already an object" case faster.
  • wtf/AlwaysInline.h: Moved the UNLIKELY macro here for now. Maybe we can find a better place later, or rename this header.

JavaScriptGlue:

2008-06-03 Darin Adler <Darin Adler>

  • UserObjectImp.cpp: (UserObjectImp::userObjectGetter): Removed originalObject argument.
  • UserObjectImp.h: Ditto.

WebCore:

2008-06-03 Justin Garcia <[email protected]>

Reviewed by John.

<rdar://problem/5763082> GMail: Hang when removing indent from nested list
<rdar://problem/5775449> In Gmail and GoogleDocs, a hang occurs when I attempt to apply a list style to a large selection of text
<rdar://problem/5937624> 9D32: Hang in Safari. Using 100% of processor

  • editing/InsertListCommand.cpp: (WebCore::InsertListCommand::modifyRange): doApply() may operate on and remove the last paragraph of the selection from the document if it's in the same list item as startOfCurrentParagraph. Return early to avoid an infinite loop and because there is no more work to be done. Added a FIXME (<rdar://problem/5983974>) about the incorrect endingSelection()s.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/object.h

    r34334 r34355  
    103103     
    104104  private:
     105    // Object operations, with the toObject operation included.
     106    virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
     107    virtual bool getOwnPropertySlot(ExecState*, unsigned index, PropertySlot&);
     108    virtual void put(ExecState*, const Identifier& propertyName, JSValue*);
     109    virtual void put(ExecState*, unsigned propertyName, JSValue*);
     110    virtual JSObject* toThisObject(ExecState*) const;
     111
    105112    JSObject *getter;
    106113    JSObject *setter; 
     
    526533inline JSValue *JSObject::get(ExecState *exec, const Identifier &propertyName) const
    527534{
    528   PropertySlot slot;
     535  PropertySlot slot(const_cast<JSObject *>(this));
    529536
    530537  if (const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot))
    531     return slot.getValue(exec, const_cast<JSObject *>(this), propertyName);
     538    return slot.getValue(exec, propertyName);
    532539   
    533540  return jsUndefined();
     
    536543inline JSValue *JSObject::get(ExecState *exec, unsigned propertyName) const
    537544{
    538   PropertySlot slot;
     545  PropertySlot slot(const_cast<JSObject *>(this));
    539546  if (const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot))
    540     return slot.getValue(exec, const_cast<JSObject *>(this), propertyName);
     547    return slot.getValue(exec, propertyName);
    541548   
    542549  return jsUndefined();
     
    588595            fillGetterPropertySlot(slot, location);
    589596        } else
    590             slot.setValueSlot(this, location);
     597            slot.setValueSlot(location);
    591598        return true;
    592599    }
     
    594601    // non-standard Netscape extension
    595602    if (propertyName == exec->propertyNames().underscoreProto) {
    596         slot.setValueSlot(this, &_proto);
     603        slot.setValueSlot(&_proto);
    597604        slotIsWriteable = false;
    598605        return true;
     
    611618            fillGetterPropertySlot(slot, location);
    612619        else
    613             slot.setValueSlot(this, location);
     620            slot.setValueSlot(location);
    614621        return true;
    615622    }
     
    617624    // non-standard Netscape extension
    618625    if (propertyName == exec->propertyNames().underscoreProto) {
    619         slot.setValueSlot(this, &_proto);
     626        slot.setValueSlot(&_proto);
    620627        return true;
    621628    }
     
    639646}
    640647
     648inline JSValue* JSValue::get(ExecState* exec, const Identifier& propertyName) const
     649{
     650    if (UNLIKELY(JSImmediate::isImmediate(this))) {
     651        JSObject* object = JSImmediate::toObject(this, exec);
     652        PropertySlot slot(object);
     653        if (!object->getPropertySlot(exec, propertyName, slot))
     654            return jsUndefined();
     655        return slot.getValue(exec, propertyName);
     656    }
     657    JSCell* cell = static_cast<JSCell*>(const_cast<JSValue*>(this));
     658    PropertySlot slot(cell);
     659    while (true) {
     660        if (cell->getOwnPropertySlot(exec, propertyName, slot))
     661            return slot.getValue(exec, propertyName);
     662        ASSERT(cell->isObject());
     663        JSValue* proto = static_cast<JSObject*>(cell)->prototype();
     664        if (!proto->isObject())
     665            return jsUndefined();
     666        cell = static_cast<JSCell*>(proto);
     667    }
     668}
     669
     670inline JSValue* JSValue::get(ExecState* exec, unsigned propertyName) const
     671{
     672    if (UNLIKELY(JSImmediate::isImmediate(this))) {
     673        JSObject* object = JSImmediate::toObject(this, exec);
     674        PropertySlot slot(object);
     675        if (!object->getPropertySlot(exec, propertyName, slot))
     676            return jsUndefined();
     677        return slot.getValue(exec, propertyName);
     678    }
     679    JSCell* cell = const_cast<JSCell*>(asCell());
     680    PropertySlot slot(cell);
     681    while (true) {
     682        if (cell->getOwnPropertySlot(exec, propertyName, slot))
     683            return slot.getValue(exec, propertyName);
     684        ASSERT(cell->isObject());
     685        JSValue* proto = static_cast<JSObject*>(cell)->prototype();
     686        if (!proto->isObject())
     687            return jsUndefined();
     688        cell = static_cast<JSCell*>(proto);
     689    }
     690}
     691
     692inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValue* value)
     693{
     694    if (UNLIKELY(JSImmediate::isImmediate(this))) {
     695        JSImmediate::toObject(this, exec)->put(exec, propertyName, value);
     696        return;
     697    }
     698    asCell()->put(exec, propertyName, value);
     699}
     700
     701inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue* value)
     702{
     703    if (UNLIKELY(JSImmediate::isImmediate(this))) {
     704        JSImmediate::toObject(this, exec)->put(exec, propertyName, value);
     705        return;
     706    }
     707    asCell()->put(exec, propertyName, value);
     708}
     709
     710inline JSObject* PropertySlot::slotBase() const
     711{
     712    ASSERT(m_slotBase);
     713    // It's be nice to assert that m_slotBase is an object here, but that's a bit
     714    // too slow, even for debug builds.
     715    return static_cast<JSObject*>(m_slotBase);
     716}
     717
    641718} // namespace
    642719
Note: See TracChangeset for help on using the changeset viewer.