Ignore:
Timestamp:
Jan 24, 2014, 12:03:34 PM (12 years ago)
Author:
[email protected]
Message:

Generic JSObject::put should handle static properties in the classinfo hierarchy
https://bugs.webkit.org/show_bug.cgi?id=127523

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

This patch makes JSObject::put correctly call static setters
defined by the ClassInfo.

To make this not clobber performance, the ClassInfo HashTable
now includes a flag to indicate that it contains setters. This
required updating the lut generator so that it tracked (and emitted)
this.

The rest of the change was making a number of the methods take
a VM rather than an ExecState*, so that Structure could set the
getter/setter flags during construction (if necessary).

This also means most objects do not need to perform a lookupPut
manually anymore, so most custom ::put's are no longer needed.
DOMWindow is the only exception as it has interesting security
related semantics.

  • create_hash_table:
  • interpreter/CallFrame.h:

(JSC::ExecState::arrayConstructorTable):
(JSC::ExecState::arrayPrototypeTable):
(JSC::ExecState::booleanPrototypeTable):
(JSC::ExecState::dataViewTable):
(JSC::ExecState::dateTable):
(JSC::ExecState::dateConstructorTable):
(JSC::ExecState::errorPrototypeTable):
(JSC::ExecState::globalObjectTable):
(JSC::ExecState::jsonTable):
(JSC::ExecState::numberConstructorTable):
(JSC::ExecState::numberPrototypeTable):
(JSC::ExecState::objectConstructorTable):
(JSC::ExecState::privateNamePrototypeTable):
(JSC::ExecState::regExpTable):
(JSC::ExecState::regExpConstructorTable):
(JSC::ExecState::regExpPrototypeTable):
(JSC::ExecState::stringConstructorTable):
(JSC::ExecState::promisePrototypeTable):
(JSC::ExecState::promiseConstructorTable):

  • runtime/ArrayConstructor.cpp:

(JSC::ArrayConstructor::getOwnPropertySlot):

  • runtime/ArrayPrototype.cpp:

(JSC::ArrayPrototype::getOwnPropertySlot):

  • runtime/BooleanPrototype.cpp:

(JSC::BooleanPrototype::getOwnPropertySlot):

  • runtime/ClassInfo.h:

(JSC::ClassInfo::propHashTable):

  • runtime/DateConstructor.cpp:

(JSC::DateConstructor::getOwnPropertySlot):

  • runtime/DatePrototype.cpp:

(JSC::DatePrototype::getOwnPropertySlot):

  • runtime/ErrorPrototype.cpp:

(JSC::ErrorPrototype::getOwnPropertySlot):

  • runtime/JSDataViewPrototype.cpp:

(JSC::JSDataViewPrototype::getOwnPropertySlot):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::getOwnPropertySlot):

  • runtime/JSONObject.cpp:

(JSC::JSONObject::getOwnPropertySlot):

  • runtime/JSObject.cpp:

(JSC::JSObject::put):
(JSC::JSObject::deleteProperty):

  • runtime/JSPromiseConstructor.cpp:

(JSC::JSPromiseConstructor::getOwnPropertySlot):

  • runtime/JSPromisePrototype.cpp:

(JSC::JSPromisePrototype::getOwnPropertySlot):

  • runtime/Lookup.h:

(JSC::HashTable::copy):
(JSC::putEntry):
(JSC::lookupPut):

  • runtime/NamePrototype.cpp:

(JSC::NamePrototype::getOwnPropertySlot):

  • runtime/NumberConstructor.cpp:

(JSC::NumberConstructor::getOwnPropertySlot):

  • runtime/NumberConstructor.h:
  • runtime/NumberPrototype.cpp:

(JSC::NumberPrototype::getOwnPropertySlot):

  • runtime/ObjectConstructor.cpp:

(JSC::ObjectConstructor::getOwnPropertySlot):

  • runtime/RegExpConstructor.cpp:

(JSC::RegExpConstructor::getOwnPropertySlot):

  • runtime/RegExpConstructor.h:
  • runtime/RegExpObject.cpp:

(JSC::RegExpObject::getOwnPropertySlot):
(JSC::RegExpObject::put):

  • runtime/RegExpPrototype.cpp:

(JSC::RegExpPrototype::getOwnPropertySlot):

  • runtime/StringConstructor.cpp:

(JSC::StringConstructor::getOwnPropertySlot):

  • runtime/Structure.cpp:

(JSC::Structure::Structure):
(JSC::Structure::freezeTransition):
(JSC::ClassInfo::hasStaticSetterOrReadonlyProperties):

Source/WebCore:

Update the bindings generator to emit the flag indicating the presence
of setters, and remove the many (now unnecessary) put overrides.
Tested with run-jsc-benchmarks and shows neutral performance. A few of the
micro benchmarks actually get a significant performance increase which
is nice.

  • bindings/js/JSDOMWindowCustom.cpp:

(WebCore::JSDOMWindow::put):

We still need a custom call to lookupPut here in order
to get the magic security semantics of the window object.

  • bindings/scripts/CodeGeneratorJS.pm:

(hashTableAccessor):
(prototypeHashTableAccessor):
(constructorHashTableAccessor):
(GenerateImplementation):
(GenerateHashTable):
(GenerateConstructorHelperMethods):

  • bindings/js/JSDOMWindowCustom.cpp:

(WebCore::JSDOMWindow::put):

  • bindings/scripts/CodeGeneratorJS.pm:

(hashTableAccessor):
(prototypeHashTableAccessor):
(constructorHashTableAccessor):
(InstanceOverridesPutImplementation):
(InstanceOverridesPutDeclaration):
(GenerateHeader):
(GenerateImplementation):
(GenerateHashTable):
(GenerateConstructorHelperMethods):

  • bindings/scripts/test/JS/JSTestActiveDOMObject.cpp:
  • bindings/scripts/test/JS/JSTestCustomNamedGetter.cpp:
  • bindings/scripts/test/JS/JSTestEventConstructor.cpp:
  • bindings/scripts/test/JS/JSTestEventTarget.cpp:
  • bindings/scripts/test/JS/JSTestException.cpp:
  • bindings/scripts/test/JS/JSTestGenerateIsReachable.cpp:
  • bindings/scripts/test/JS/JSTestInterface.cpp:

(WebCore::JSTestInterface::put):

  • bindings/scripts/test/JS/JSTestMediaQueryListListener.cpp:
  • bindings/scripts/test/JS/JSTestNamedConstructor.cpp:
  • bindings/scripts/test/JS/JSTestNode.cpp:
  • bindings/scripts/test/JS/JSTestObj.cpp:
  • bindings/scripts/test/JS/JSTestObj.h:
  • bindings/scripts/test/JS/JSTestOverloadedConstructors.cpp:
  • bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp:
  • bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.h:
  • bindings/scripts/test/JS/JSTestTypedefs.cpp:
  • bindings/scripts/test/JS/JSTestTypedefs.h:
  • bindings/scripts/test/JS/JSattribute.cpp:
  • bindings/scripts/test/JS/JSreadonly.cpp:
  • html/canvas/WebGLRenderingContext.idl: Remove bogus attribute, as it has never been in the spec and should not have been added.

LayoutTests:

Yay tests!

  • fast/canvas/webgl/constants.html: Remove incorrect constant
  • js/script-tests/static-put-in-prototype-chain.js: Added.
  • js/static-put-in-prototype-chain-expected.txt: Added.
  • js/static-put-in-prototype-chain.html: Added.
File:
1 edited

Legend:

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

    r161309 r162713  
    166166    , m_dictionaryKind(NoneDictionaryKind)
    167167    , m_isPinnedPropertyTable(false)
    168     , m_hasGetterSetterProperties(false)
    169     , m_hasReadOnlyOrGetterSetterPropertiesExcludingProto(false)
     168    , m_hasGetterSetterProperties(classInfo->hasStaticSetterOrReadonlyProperties(vm))
     169    , m_hasReadOnlyOrGetterSetterPropertiesExcludingProto(classInfo->hasStaticSetterOrReadonlyProperties(vm))
    170170    , m_hasNonEnumerableProperties(false)
    171171    , m_attributesInPrevious(0)
     
    178178    ASSERT(static_cast<PropertyOffset>(inlineCapacity) < firstOutOfLineOffset);
    179179    ASSERT(!typeInfo.structureHasRareData());
     180    ASSERT(hasReadOnlyOrGetterSetterPropertiesExcludingProto() || !m_classInfo->hasStaticSetterOrReadonlyProperties(vm));
     181    ASSERT(hasGetterSetterProperties() || !m_classInfo->hasStaticSetterOrReadonlyProperties(vm));
    180182}
    181183
     
    193195    , m_dictionaryKind(NoneDictionaryKind)
    194196    , m_isPinnedPropertyTable(false)
    195     , m_hasGetterSetterProperties(false)
    196     , m_hasReadOnlyOrGetterSetterPropertiesExcludingProto(false)
     197    , m_hasGetterSetterProperties(m_classInfo->hasStaticSetterOrReadonlyProperties(vm))
     198    , m_hasReadOnlyOrGetterSetterPropertiesExcludingProto(m_classInfo->hasStaticSetterOrReadonlyProperties(vm))
    197199    , m_hasNonEnumerableProperties(false)
    198200    , m_attributesInPrevious(0)
     
    202204    , m_staticFunctionReified(false)
    203205{
     206    ASSERT(hasReadOnlyOrGetterSetterPropertiesExcludingProto() || !m_classInfo->hasStaticSetterOrReadonlyProperties(vm));
     207    ASSERT(hasGetterSetterProperties() || !m_classInfo->hasStaticSetterOrReadonlyProperties(vm));
    204208}
    205209
     
    232236    if (previous->m_globalObject)
    233237        m_globalObject.set(vm, this, previous->m_globalObject.get());
     238    ASSERT(hasReadOnlyOrGetterSetterPropertiesExcludingProto() || !m_classInfo->hasStaticSetterOrReadonlyProperties(vm));
     239    ASSERT(hasGetterSetterProperties() || !m_classInfo->hasStaticSetterOrReadonlyProperties(vm));
    234240}
    235241
     
    566572    }
    567573
     574    ASSERT(transition->hasReadOnlyOrGetterSetterPropertiesExcludingProto() || !transition->classInfo()->hasStaticSetterOrReadonlyProperties(vm));
     575    ASSERT(transition->hasGetterSetterProperties() || !transition->classInfo()->hasStaticSetterOrReadonlyProperties(vm));
    568576    transition->checkOffsetConsistency();
    569577    return transition;
     
    11571165#endif // DO_PROPERTYMAP_CONSTENCY_CHECK
    11581166
     1167bool ClassInfo::hasStaticSetterOrReadonlyProperties(VM& vm) const
     1168{
     1169    for (const ClassInfo* ci = this; ci; ci = ci->parentClass) {
     1170        if (const HashTable* table = ci->propHashTable(vm)) {
     1171            if (table->hasSetterOrReadonlyProperties)
     1172                return true;
     1173        }
     1174    }
     1175    return false;
     1176}
     1177
    11591178} // namespace JSC
Note: See TracChangeset for help on using the changeset viewer.