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.h

    r169668 r169703  
    468468    void putDirectNonIndexAccessor(VM&, PropertyName, JSValue, unsigned attributes);
    469469    void putDirectAccessor(ExecState*, PropertyName, JSValue, unsigned attributes);
     470    JS_EXPORT_PRIVATE void putDirectCustomAccessor(VM&, PropertyName, JSValue, unsigned attributes);
    470471
    471472    JS_EXPORT_PRIVATE bool hasProperty(ExecState*, PropertyName) const;
     
    574575    bool hasCustomProperties() { return structure()->didTransition(); }
    575576    bool hasGetterSetterProperties() { return structure()->hasGetterSetterProperties(); }
     577    bool hasCustomGetterSetterProperties() { return structure()->hasCustomGetterSetterProperties(); }
    576578
    577579    // putOwnDataProperty has 'put' like semantics, however this method:
     
    588590
    589591    JS_EXPORT_PRIVATE void putDirectNativeFunction(VM&, JSGlobalObject*, const PropertyName&, unsigned functionLength, NativeFunction, Intrinsic, unsigned attributes);
    590     JSFunction* putDirectBuiltinFunction(VM&, JSGlobalObject*, const PropertyName&, FunctionExecutable*, unsigned attributes);
     592    JS_EXPORT_PRIVATE JSFunction* putDirectBuiltinFunction(VM&, JSGlobalObject*, const PropertyName&, FunctionExecutable*, unsigned attributes);
    591593    JSFunction* putDirectBuiltinFunctionWithoutTransition(VM&, JSGlobalObject*, const PropertyName&, FunctionExecutable*, unsigned attributes);
    592594    void putDirectNativeFunctionWithoutTransition(VM&, JSGlobalObject*, const PropertyName&, unsigned functionLength, NativeFunction, Intrinsic, unsigned attributes);
     
    623625    void setStructureAndReallocateStorageIfNecessary(VM&, unsigned oldCapacity, Structure*);
    624626    void setStructureAndReallocateStorageIfNecessary(VM&, Structure*);
     627
     628    void convertToDictionary(VM& vm)
     629    {
     630        setStructure(vm, Structure::toCacheableDictionaryTransition(vm, structure(vm)));
     631    }
    625632
    626633    void flattenDictionaryObject(VM& vm)
     
    953960    bool inlineGetOwnPropertySlot(ExecState*, VM&, Structure&, PropertyName, PropertySlot&);
    954961    JS_EXPORT_PRIVATE void fillGetterPropertySlot(PropertySlot&, JSValue, unsigned, PropertyOffset);
     962    JS_EXPORT_PRIVATE void fillCustomGetterPropertySlot(PropertySlot&, JSValue, unsigned);
    955963
    956964    const HashTableValue* findPropertyHashEntry(VM&, PropertyName) const;
     
    965973    unsigned getNewVectorLength(unsigned desiredLength);
    966974
    967     JS_EXPORT_PRIVATE bool getOwnPropertySlotSlow(ExecState*, PropertyName, PropertySlot&);
     975    bool getOwnPropertySlotSlow(ExecState*, PropertyName, PropertySlot&);
    968976       
    969977    ArrayStorage* constructConvertedArrayStorageWithoutCopyingElements(VM&, unsigned neededLength);
     
    12141222        if (structure.hasGetterSetterProperties() && value.isGetterSetter())
    12151223            fillGetterPropertySlot(slot, value, attributes, offset);
     1224        else if (structure.hasCustomGetterSetterProperties() && value.isCustomGetterSetter())
     1225            fillCustomGetterPropertySlot(slot, value, attributes);
    12161226        else
    12171227            slot.setValue(this, attributes, value, offset);
     
    12201230
    12211231    return getOwnPropertySlotSlow(exec, propertyName, slot);
     1232}
     1233
     1234inline bool JSObject::getOwnPropertySlotSlow(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
     1235{
     1236    unsigned i = propertyName.asIndex();
     1237    if (i != PropertyName::NotAnIndex)
     1238        return getOwnPropertySlotByIndex(this, exec, i, slot);
     1239    return false;
    12221240}
    12231241
     
    14411459    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
    14421460    ASSERT(!structure()->hasGetterSetterProperties());
     1461    ASSERT(!structure()->hasCustomGetterSetterProperties());
    14431462
    14441463    return putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot, getCallableObject(value));
     
    14481467{
    14491468    ASSERT(!value.isGetterSetter() && !(attributes & Accessor));
     1469    ASSERT(!value.isCustomGetterSetter());
    14501470    PutPropertySlot slot(this);
    14511471    putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot, getCallableObject(value));
     
    14551475{
    14561476    ASSERT(!value.isGetterSetter());
     1477    ASSERT(!value.isCustomGetterSetter());
    14571478    putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, 0, slot, getCallableObject(value));
    14581479}
     
    14621483    DeferGC deferGC(vm.heap);
    14631484    ASSERT(!value.isGetterSetter() && !(attributes & Accessor));
     1485    ASSERT(!value.isCustomGetterSetter());
    14641486    Butterfly* newButterfly = m_butterfly.get();
    14651487    if (structure()->putWillGrowOutOfLineStorage())
Note: See TracChangeset for help on using the changeset viewer.