Ignore:
Timestamp:
Jun 9, 2014, 11:53:32 AM (11 years ago)
Author:
[email protected]
Message:

Eagerly reify DOM prototype attributes
https://bugs.webkit.org/show_bug.cgi?id=133558

Reviewed by Oliver Hunt.

Source/JavaScriptCore:
This allows us to get rid of a lot of the additional overhead of pushing DOM attributes up into the prototype.
By eagerly reifying the custom getters and setters into the actual JSObject we avoid having to override
getOwnPropertySlot for all of the DOM prototypes, which is a lot of the overhead of doing property lookups on
DOM wrappers.

(JSC::LLInt::Data::performAssertions):

  • llint/LowLevelInterpreter.asm:
  • runtime/BatchedTransitionOptimizer.h:

(JSC::BatchedTransitionOptimizer::BatchedTransitionOptimizer):

  • runtime/CustomGetterSetter.cpp: Added.

(JSC::callCustomSetter):

  • runtime/CustomGetterSetter.h: Added.

(JSC::CustomGetterSetter::create):
(JSC::CustomGetterSetter::getter):
(JSC::CustomGetterSetter::setter):
(JSC::CustomGetterSetter::createStructure):
(JSC::CustomGetterSetter::CustomGetterSetter):

  • runtime/JSCJSValue.cpp:

(JSC::JSValue::putToPrimitive):

  • runtime/JSCJSValue.h:
  • runtime/JSCJSValueInlines.h:

(JSC::JSValue::isCustomGetterSetter):

  • runtime/JSCell.h:
  • runtime/JSCellInlines.h:

(JSC::JSCell::isCustomGetterSetter):
(JSC::JSCell::canUseFastGetOwnProperty):

  • runtime/JSFunction.cpp:

(JSC::JSFunction::isHostOrBuiltinFunction): Deleted.
(JSC::JSFunction::isBuiltinFunction): Deleted.

  • runtime/JSFunction.h:
  • runtime/JSFunctionInlines.h: Inlined some random functions that appeared hot during profiling.

(JSC::JSFunction::isBuiltinFunction):
(JSC::JSFunction::isHostOrBuiltinFunction):

  • runtime/JSObject.cpp:

(JSC::JSObject::put):
(JSC::JSObject::putDirectCustomAccessor):
(JSC::JSObject::fillGetterPropertySlot):
(JSC::JSObject::fillCustomGetterPropertySlot):
(JSC::JSObject::getOwnPropertySlotSlow): Deleted.

  • runtime/JSObject.h:

(JSC::JSObject::hasCustomGetterSetterProperties):
(JSC::JSObject::convertToDictionary):
(JSC::JSObject::inlineGetOwnPropertySlot):
(JSC::JSObject::getOwnPropertySlotSlow): Inlined because it looked hot during profiling.
(JSC::JSObject::putOwnDataProperty):
(JSC::JSObject::putDirect):
(JSC::JSObject::putDirectWithoutTransition):

  • runtime/JSType.h:
  • runtime/Lookup.h:

(JSC::reifyStaticProperties):

  • runtime/PropertyDescriptor.h:

(JSC::PropertyDescriptor::PropertyDescriptor):

  • runtime/Structure.cpp:

(JSC::Structure::Structure):
(JSC::nextOutOfLineStorageCapacity): Deleted.
(JSC::Structure::suggestedNewOutOfLineStorageCapacity): Deleted.
(JSC::Structure::get): Deleted.

  • runtime/Structure.h:

(JSC::Structure::hasCustomGetterSetterProperties):
(JSC::Structure::setHasCustomGetterSetterProperties):

  • runtime/StructureInlines.h:

(JSC::Structure::get): Inlined due to hotness.
(JSC::nextOutOfLineStorageCapacity): Inlined due to hotness.
(JSC::Structure::suggestedNewOutOfLineStorageCapacity): Inlined due to hotness.

  • runtime/VM.cpp:

(JSC::VM::VM):

  • runtime/VM.h:
  • runtime/WriteBarrier.h:

(JSC::WriteBarrierBase<Unknown>::isCustomGetterSetter):

Source/WebCore:
No new tests.

This allows us to get rid of a lot of the additional overhead of pushing DOM attributes up into the prototype.
By eagerly reifying the custom getters and setters into the actual JSObject we avoid having to override
getOwnPropertySlot for all of the DOM prototypes, which is a lot of the overhead of doing property lookups on
DOM wrappers.

  • bindings/scripts/CodeGeneratorJS.pm:

(prototypeHashTableAccessor): Changed to pass along the VM.
(AttributeShouldBeOnInstanceForCompatibility): We were being overly conservative in regard to touch events.
This caused us to store the touch event handler getters and setters on the JSElement instance, which caused
us to override getOwnPropertySlot for every JSElement subclass.
(InstanceOverridesGetOwnPropertySlot): This was being overly paranoid about generate a getOwnPropertySlot if
there was going to be a "constructor" property, even though we handled this in another place already.
(GenerateHeader): Generate a finishCreation for prototypes unless it's the JSDOMWindow. We can't correctly
handle the DOMWindow in this version of the patch because reifying the static properties requires a global object,
which hasn't been created yet when the prototype for the window object is being created.
(GenerateImplementation): Generate the finishCreation calls to reifyStaticProperties.

LayoutTests:
Updating a test expectation after this fix.

  • js/dom/constructor-attributes-expected.txt:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/JSObject.cpp

    r168631 r169703  
    2929#include "CopyVisitor.h"
    3030#include "CopyVisitorInlines.h"
     31#include "CustomGetterSetter.h"
    3132#include "DatePrototype.h"
    3233#include "ErrorConstructor.h"
     
    388389                    slot.setCacheableSetter(obj, offset);
    389390                return;
    390             } else
    391                 ASSERT(!(attributes & Accessor));
     391            }
     392            if (gs.isCustomGetterSetter()) {
     393                callCustomSetter(exec, gs, obj, slot.thisValue(), value);
     394                slot.setCustomProperty(obj, jsCast<CustomGetterSetter*>(gs.asCell())->setter());
     395                return;
     396            }
     397            ASSERT(!(attributes & Accessor));
    392398
    393399            // If there's an existing property on the object or one of its
     
    12231229
    12241230    putDirectNonIndexAccessor(exec->vm(), propertyName, value, attributes);
     1231}
     1232
     1233void JSObject::putDirectCustomAccessor(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes)
     1234{
     1235    ASSERT(propertyName.asIndex() == PropertyName::NotAnIndex);
     1236
     1237    PutPropertySlot slot(this);
     1238    putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot, getCallableObject(value));
     1239
     1240    ASSERT(slot.type() == PutPropertySlot::NewProperty);
     1241
     1242    Structure* structure = this->structure(vm);
     1243    if (attributes & ReadOnly)
     1244        structure->setContainsReadOnlyProperties();
     1245    structure->setHasCustomGetterSetterProperties();
    12251246}
    12261247
     
    16671688        return;
    16681689    }
    1669 
    16701690    slot.setCacheableGetterSlot(this, attributes, jsCast<GetterSetter*>(getterSetter), offset);
     1691}
     1692
     1693NEVER_INLINE void JSObject::fillCustomGetterPropertySlot(PropertySlot& slot, JSValue customGetterSetter, unsigned attributes)
     1694{
     1695    if (structure()->isDictionary()) {
     1696        slot.setCustom(this, attributes, jsCast<CustomGetterSetter*>(customGetterSetter)->getter());
     1697        return;
     1698    }
     1699    slot.setCacheableCustom(this, attributes, jsCast<CustomGetterSetter*>(customGetterSetter)->getter());
    16711700}
    16721701
     
    26612690}
    26622691
    2663 bool JSObject::getOwnPropertySlotSlow(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
    2664 {
    2665     unsigned i = propertyName.asIndex();
    2666     if (i != PropertyName::NotAnIndex)
    2667         return getOwnPropertySlotByIndex(this, exec, i, slot);
    2668     return false;
    2669 }
    2670 
    26712692JSObject* throwTypeError(ExecState* exec, const String& message)
    26722693{
Note: See TracChangeset for help on using the changeset viewer.