Changeset 44076 in webkit for trunk/JavaScriptCore/runtime


Ignore:
Timestamp:
May 22, 2009, 6:48:32 PM (16 years ago)
Author:
[email protected]
Message:

2009-05-21 Gavin Barraclough <[email protected]>

Reviewed by Geoff Garen.

op_method_check

Optimize method calls, by caching specific function values within the Structure.
The new opcode is used almost like an x86 opcode prefix byte to optimize op_get_by_id,
where the property access is being used to read a function to be passed to op-call (i.e.
'foo.bar();'). This patch modifies the Structure class such that when a property is
put to an object for the first time we will check if the value is a function. If it is,
we will cache the function value on the Structure. A Structure in such a state guarantees
that not only does a property with the given identifier exist on the object, but also that
its value is unchanged. Upon any further attempt to put a property with the same identifier
(but a different value) to the object, it will transition back to a normal Structure (where
it will guarantee the presence but not the value of the property).

op_method_check makes use of the new information made available by the Structure, by
augmenting the functionality of op_get_by_id. Upon generating a FunctionCallDotNode a
check will be emitted prior to the property access reading the function value, and the JIT
will generate an extra (initially unlinked but patchable) set of checks prior to the regular
JIT code for get_by_id. The new code will do inline structure and prototype structure check
(unlike a regular get_by_id, which can only handle 'self' accesses inline), and then performs
an immediate load of the function value, rather than using memory accesses to load the value
from the obejct's property storage array. If the method check fails it will revert, or if
the access is polymorphic, the op_get_by_id will continue to operate - and optimize itself -
just as any other regular op_get_by_id would.

~2.5% on v8-tests, due to a ~9% progression on richards.

  • API/JSCallbackObjectFunctions.h: (JSC::::put): (JSC::::staticFunctionGetter):
  • API/JSObjectRef.cpp: (JSObjectMakeConstructor):
  • JavaScriptCore.exp:
  • assembler/AbstractMacroAssembler.h: (JSC::AbstractMacroAssembler::differenceBetween):
  • assembler/MacroAssemblerX86.h: (JSC::MacroAssemblerX86::moveWithPatch):
  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::dump):
  • bytecode/CodeBlock.h: (JSC::getMethodCallLinkInfoReturnLocation): (JSC::CodeBlock::getMethodCallLinkInfo): (JSC::CodeBlock::addMethodCallLinkInfos): (JSC::CodeBlock::methodCallLinkInfo):
  • bytecode/Opcode.h:
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitMethodCheck):
  • bytecompiler/BytecodeGenerator.h:
  • interpreter/Interpreter.cpp: (JSC::Interpreter::privateExecute):
  • jit/JIT.cpp: (JSC::JIT::privateCompileMainPass): (JSC::JIT::privateCompileSlowCases): (JSC::JIT::privateCompile):
  • jit/JIT.h: (JSC::MethodCallCompilationInfo::MethodCallCompilationInfo):
  • jit/JITOpcodes.cpp:
  • jit/JITPropertyAccess.cpp: (JSC::JIT::emit_op_method_check): (JSC::JIT::emitSlow_op_method_check): (JSC::JIT::emit_op_get_by_id): (JSC::JIT::emitSlow_op_get_by_id): (JSC::JIT::emit_op_put_by_id): (JSC::JIT::emitSlow_op_put_by_id): (JSC::JIT::compileGetByIdHotPath): (JSC::JIT::compileGetByIdSlowCase): (JSC::JIT::patchMethodCallProto):
  • jit/JITStubs.cpp: (JSC::JITStubs::cti_op_get_by_id_method_check): (JSC::JITStubs::cti_op_get_by_id_method_check_second):
  • jit/JITStubs.h:
  • jsc.cpp: (GlobalObject::GlobalObject):
  • parser/Nodes.cpp: (JSC::FunctionCallDotNode::emitBytecode):
  • runtime/Arguments.cpp: (JSC::Arguments::put):
  • runtime/ArrayConstructor.cpp: (JSC::ArrayConstructor::ArrayConstructor):
  • runtime/BooleanConstructor.cpp: (JSC::BooleanConstructor::BooleanConstructor):
  • runtime/DateConstructor.cpp: (JSC::DateConstructor::DateConstructor):
  • runtime/ErrorConstructor.cpp: (JSC::ErrorConstructor::ErrorConstructor): (JSC::constructError):
  • runtime/ErrorPrototype.cpp: (JSC::ErrorPrototype::ErrorPrototype):
  • runtime/FunctionConstructor.cpp: (JSC::FunctionConstructor::FunctionConstructor):
  • runtime/FunctionPrototype.cpp: (JSC::FunctionPrototype::FunctionPrototype):
  • runtime/InternalFunction.cpp: (JSC::InternalFunction::InternalFunction):
  • runtime/JSActivation.cpp: (JSC::JSActivation::put): (JSC::JSActivation::putWithAttributes):
  • runtime/JSByteArray.cpp: (JSC::JSByteArray::JSByteArray):
  • runtime/JSFunction.cpp: (JSC::JSFunction::JSFunction): (JSC::JSFunction::getOwnPropertySlot):
  • runtime/JSGlobalObject.cpp: (JSC::JSGlobalObject::putWithAttributes): (JSC::JSGlobalObject::reset): (JSC::JSGlobalObject::mark):
  • runtime/JSGlobalObject.h: (JSC::JSGlobalObject::JSGlobalObjectData::JSGlobalObjectData): (JSC::JSGlobalObject::methodCallDummy):
  • runtime/JSObject.cpp: (JSC::JSObject::put): (JSC::JSObject::putWithAttributes): (JSC::JSObject::deleteProperty): (JSC::JSObject::defineGetter): (JSC::JSObject::defineSetter): (JSC::JSObject::getPropertyAttributes): (JSC::JSObject::getPropertySpecificFunction): (JSC::JSObject::putDirectFunction): (JSC::JSObject::putDirectFunctionWithoutTransition):
  • runtime/JSObject.h: (JSC::getJSFunction): (JSC::JSObject::getDirectLocation): (JSC::JSObject::putDirect): (JSC::JSObject::putDirectWithoutTransition):
  • runtime/LiteralParser.cpp: (JSC::LiteralParser::parseObject):
  • runtime/Lookup.cpp: (JSC::setUpStaticFunctionSlot):
  • runtime/Lookup.h: (JSC::lookupPut):
  • runtime/MathObject.cpp: (JSC::MathObject::MathObject):
  • runtime/NativeErrorConstructor.cpp: (JSC::NativeErrorConstructor::NativeErrorConstructor): (JSC::NativeErrorConstructor::construct):
  • runtime/NativeErrorPrototype.cpp: (JSC::NativeErrorPrototype::NativeErrorPrototype):
  • runtime/NumberConstructor.cpp: (JSC::NumberConstructor::NumberConstructor):
  • runtime/ObjectConstructor.cpp: (JSC::ObjectConstructor::ObjectConstructor):
  • runtime/PropertyMapHashTable.h: (JSC::PropertyMapEntry::PropertyMapEntry):
  • runtime/PrototypeFunction.cpp: (JSC::PrototypeFunction::PrototypeFunction):
  • runtime/PutPropertySlot.h: (JSC::PutPropertySlot::): (JSC::PutPropertySlot::PutPropertySlot): (JSC::PutPropertySlot::setNewProperty): (JSC::PutPropertySlot::setDespecifyFunctionProperty): (JSC::PutPropertySlot::isCacheable): (JSC::PutPropertySlot::cachedOffset):
  • runtime/RegExpConstructor.cpp: (JSC::RegExpConstructor::RegExpConstructor):
  • runtime/StringConstructor.cpp: (JSC::StringConstructor::StringConstructor):
  • runtime/StringPrototype.cpp: (JSC::StringPrototype::StringPrototype):
  • runtime/Structure.cpp: (JSC::Structure::Structure): (JSC::Structure::~Structure): (JSC::Structure::materializePropertyMap): (JSC::Structure::addPropertyTransitionToExistingStructure): (JSC::Structure::addPropertyTransition): (JSC::Structure::changeFunctionTransition): (JSC::Structure::addPropertyWithoutTransition): (JSC::Structure::get): (JSC::Structure::despecifyFunction): (JSC::Structure::put): (JSC::Structure::remove):
  • runtime/Structure.h: (JSC::Structure::get): (JSC::Structure::specificFunction):
  • runtime/StructureTransitionTable.h: (JSC::StructureTransitionTableHashTraits::emptyValue):
  • wtf/Platform.h:
Location:
trunk/JavaScriptCore/runtime
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/JSActivation.cpp

    r43603 r44076  
    119119
    120120// FIXME: Make this function honor ReadOnly (const) and DontEnum
    121 void JSActivation::putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes)
     121void JSActivation::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
    122122{
    123123    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
     
    131131    ASSERT(!hasGetterSetterProperties());
    132132    PutPropertySlot slot;
    133     putDirect(propertyName, value, attributes, true, slot);
     133    JSObject::putWithAttributes(exec, propertyName, value, attributes, true, slot);
    134134}
    135135
  • trunk/JavaScriptCore/runtime/JSGlobalObject.cpp

    r43226 r44076  
    171171        JSValue valueAfter = getDirect(propertyName);
    172172        if (valueAfter)
    173             putDirect(propertyName, valueAfter, attributes);
     173            JSObject::putWithAttributes(exec, propertyName, valueAfter, attributes);
    174174    }
    175175}
     
    240240    d()->regExpStructure = RegExpObject::createStructure(d()->regExpPrototype);
    241241
     242    d()->methodCallDummy = constructEmptyObject(exec);
     243
    242244    ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, ErrorPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get());
    243245    d()->errorStructure = ErrorInstance::createStructure(errorPrototype);
     
    254256    // Constructors
    255257
    256     JSValue objectConstructor = new (exec) ObjectConstructor(exec, ObjectConstructor::createStructure(d()->functionPrototype), d()->objectPrototype);
    257     JSValue functionConstructor = new (exec) FunctionConstructor(exec, FunctionConstructor::createStructure(d()->functionPrototype), d()->functionPrototype);
    258     JSValue arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructure(d()->functionPrototype), d()->arrayPrototype);
    259     JSValue stringConstructor = new (exec) StringConstructor(exec, StringConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->stringPrototype);
    260     JSValue booleanConstructor = new (exec) BooleanConstructor(exec, BooleanConstructor::createStructure(d()->functionPrototype), d()->booleanPrototype);
    261     JSValue numberConstructor = new (exec) NumberConstructor(exec, NumberConstructor::createStructure(d()->functionPrototype), d()->numberPrototype);
    262     JSValue dateConstructor = new (exec) DateConstructor(exec, DateConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->datePrototype);
     258    JSCell* objectConstructor = new (exec) ObjectConstructor(exec, ObjectConstructor::createStructure(d()->functionPrototype), d()->objectPrototype);
     259    JSCell* functionConstructor = new (exec) FunctionConstructor(exec, FunctionConstructor::createStructure(d()->functionPrototype), d()->functionPrototype);
     260    JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructure(d()->functionPrototype), d()->arrayPrototype);
     261    JSCell* stringConstructor = new (exec) StringConstructor(exec, StringConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->stringPrototype);
     262    JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, BooleanConstructor::createStructure(d()->functionPrototype), d()->booleanPrototype);
     263    JSCell* numberConstructor = new (exec) NumberConstructor(exec, NumberConstructor::createStructure(d()->functionPrototype), d()->numberPrototype);
     264    JSCell* dateConstructor = new (exec) DateConstructor(exec, DateConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->datePrototype);
    263265
    264266    d()->regExpConstructor = new (exec) RegExpConstructor(exec, RegExpConstructor::createStructure(d()->functionPrototype), d()->regExpPrototype);
     
    275277    d()->URIErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, URIErrorPrototype);
    276278
    277     d()->objectPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, objectConstructor, DontEnum);
    278     d()->functionPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, functionConstructor, DontEnum);
    279     d()->arrayPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, arrayConstructor, DontEnum);
    280     d()->booleanPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, booleanConstructor, DontEnum);
    281     d()->stringPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, stringConstructor, DontEnum);
    282     d()->numberPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, numberConstructor, DontEnum);
    283     d()->datePrototype->putDirectWithoutTransition(exec->propertyNames().constructor, dateConstructor, DontEnum);
    284     d()->regExpPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, d()->regExpConstructor, DontEnum);
    285     errorPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, d()->errorConstructor, DontEnum);
     279    d()->objectPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, objectConstructor, DontEnum);
     280    d()->functionPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, functionConstructor, DontEnum);
     281    d()->arrayPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, arrayConstructor, DontEnum);
     282    d()->booleanPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, booleanConstructor, DontEnum);
     283    d()->stringPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, stringConstructor, DontEnum);
     284    d()->numberPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, numberConstructor, DontEnum);
     285    d()->datePrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, dateConstructor, DontEnum);
     286    d()->regExpPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, d()->regExpConstructor, DontEnum);
     287    errorPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, d()->errorConstructor, DontEnum);
    286288
    287289    evalErrorPrototype->putDirect(exec->propertyNames().constructor, d()->evalErrorConstructor, DontEnum);
     
    296298    // FIXME: These properties could be handled by a static hash table.
    297299
    298     putDirectWithoutTransition(Identifier(exec, "Object"), objectConstructor, DontEnum);
    299     putDirectWithoutTransition(Identifier(exec, "Function"), functionConstructor, DontEnum);
    300     putDirectWithoutTransition(Identifier(exec, "Array"), arrayConstructor, DontEnum);
    301     putDirectWithoutTransition(Identifier(exec, "Boolean"), booleanConstructor, DontEnum);
    302     putDirectWithoutTransition(Identifier(exec, "String"), stringConstructor, DontEnum);
    303     putDirectWithoutTransition(Identifier(exec, "Number"), numberConstructor, DontEnum);
    304     putDirectWithoutTransition(Identifier(exec, "Date"), dateConstructor, DontEnum);
    305     putDirectWithoutTransition(Identifier(exec, "RegExp"), d()->regExpConstructor, DontEnum);
    306     putDirectWithoutTransition(Identifier(exec, "Error"), d()->errorConstructor, DontEnum);
    307     putDirectWithoutTransition(Identifier(exec, "EvalError"), d()->evalErrorConstructor);
    308     putDirectWithoutTransition(Identifier(exec, "RangeError"), d()->rangeErrorConstructor);
    309     putDirectWithoutTransition(Identifier(exec, "ReferenceError"), d()->referenceErrorConstructor);
    310     putDirectWithoutTransition(Identifier(exec, "SyntaxError"), d()->syntaxErrorConstructor);
    311     putDirectWithoutTransition(Identifier(exec, "TypeError"), d()->typeErrorConstructor);
    312     putDirectWithoutTransition(Identifier(exec, "URIError"), d()->URIErrorConstructor);
     300    putDirectFunctionWithoutTransition(Identifier(exec, "Object"), objectConstructor, DontEnum);
     301    putDirectFunctionWithoutTransition(Identifier(exec, "Function"), functionConstructor, DontEnum);
     302    putDirectFunctionWithoutTransition(Identifier(exec, "Array"), arrayConstructor, DontEnum);
     303    putDirectFunctionWithoutTransition(Identifier(exec, "Boolean"), booleanConstructor, DontEnum);
     304    putDirectFunctionWithoutTransition(Identifier(exec, "String"), stringConstructor, DontEnum);
     305    putDirectFunctionWithoutTransition(Identifier(exec, "Number"), numberConstructor, DontEnum);
     306    putDirectFunctionWithoutTransition(Identifier(exec, "Date"), dateConstructor, DontEnum);
     307    putDirectFunctionWithoutTransition(Identifier(exec, "RegExp"), d()->regExpConstructor, DontEnum);
     308    putDirectFunctionWithoutTransition(Identifier(exec, "Error"), d()->errorConstructor, DontEnum);
     309    putDirectFunctionWithoutTransition(Identifier(exec, "EvalError"), d()->evalErrorConstructor);
     310    putDirectFunctionWithoutTransition(Identifier(exec, "RangeError"), d()->rangeErrorConstructor);
     311    putDirectFunctionWithoutTransition(Identifier(exec, "ReferenceError"), d()->referenceErrorConstructor);
     312    putDirectFunctionWithoutTransition(Identifier(exec, "SyntaxError"), d()->syntaxErrorConstructor);
     313    putDirectFunctionWithoutTransition(Identifier(exec, "TypeError"), d()->typeErrorConstructor);
     314    putDirectFunctionWithoutTransition(Identifier(exec, "URIError"), d()->URIErrorConstructor);
    313315
    314316    // Set global values.
     
    388390    markIfNeeded(d()->regExpPrototype);
    389391
     392    markIfNeeded(d()->methodCallDummy);
     393
    390394    markIfNeeded(d()->errorStructure);
    391395
  • trunk/JavaScriptCore/runtime/JSGlobalObject.h

    r43220 r44076  
    8080                , datePrototype(0)
    8181                , regExpPrototype(0)
     82                , methodCallDummy(0)
    8283            {
    8384            }
     
    120121            DatePrototype* datePrototype;
    121122            RegExpPrototype* regExpPrototype;
     123
     124            JSObject* methodCallDummy;
    122125
    123126            RefPtr<Structure> argumentsStructure;
     
    202205        RegExpPrototype* regExpPrototype() const { return d()->regExpPrototype; }
    203206
     207        JSObject* methodCallDummy() const { return d()->methodCallDummy; }
     208
    204209        Structure* argumentsStructure() const { return d()->argumentsStructure.get(); }
    205210        Structure* arrayStructure() const { return d()->arrayStructure.get(); }
  • trunk/JavaScriptCore/runtime/JSObject.cpp

    r43551 r44076  
    130130        prototype = obj->prototype();
    131131        if (prototype.isNull()) {
    132             putDirect(propertyName, value, 0, true, slot);
     132            putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot);
    133133            return;
    134134        }
     
    136136   
    137137    unsigned attributes;
    138     if ((m_structure->get(propertyName, attributes) != WTF::notFound) && attributes & ReadOnly)
     138    JSCell* specificValue;
     139    if ((m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly)
    139140        return;
    140141
     
    166167    }
    167168
    168     putDirect(propertyName, value, 0, true, slot);
     169    putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot);
    169170    return;
    170171}
     
    176177}
    177178
    178 void JSObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes)
    179 {
    180     putDirect(propertyName, value, attributes);
     179void JSObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
     180{
     181    putDirectInternal(exec->globalData(), propertyName, value, attributes, checkReadOnly, slot);
     182}
     183
     184void JSObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
     185{
     186    putDirectInternal(exec->globalData(), propertyName, value, attributes);
    181187}
    182188
     
    202208{
    203209    unsigned attributes;
    204     if (m_structure->get(propertyName, attributes) != WTF::notFound) {
     210    JSCell* specificValue;
     211    if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) {
    205212        if ((attributes & DontDelete))
    206213            return false;
     
    305312    PutPropertySlot slot;
    306313    GetterSetter* getterSetter = new (exec) GetterSetter;
    307     putDirect(propertyName, getterSetter, None, true, slot);
     314    putDirectInternal(exec->globalData(), propertyName, getterSetter, None, true, slot);
    308315
    309316    // putDirect will change our Structure if we add a new property. For
     
    332339    PutPropertySlot slot;
    333340    GetterSetter* getterSetter = new (exec) GetterSetter;
    334     putDirect(propertyName, getterSetter, None, true, slot);
     341    putDirectInternal(exec->globalData(), propertyName, getterSetter, None, true, slot);
    335342
    336343    // putDirect will change our Structure if we add a new property. For
     
    414421bool JSObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
    415422{
    416     if (m_structure->get(propertyName, attributes) != WTF::notFound)
     423    JSCell* specificValue;
     424    if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound)
    417425        return true;
    418426   
     
    427435}
    428436
     437bool JSObject::getPropertySpecificValue(ExecState*, const Identifier& propertyName, JSCell*& specificValue) const
     438{
     439    unsigned attributes;
     440    if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound)
     441        return true;
     442
     443    // This could be a function within the static table? - should probably
     444    // also look in the hash?  This currently should not be a problem, since
     445    // we've currently always call 'get' first, which should have populated
     446    // the normal storage.
     447    return false;
     448}
     449
    429450void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
    430451{
     
    486507void JSObject::putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr)
    487508{
    488     putDirect(Identifier(exec, function->name(&exec->globalData())), function, attr);
     509    putDirectFunction(Identifier(exec, function->name(&exec->globalData())), function, attr);
    489510}
    490511
    491512void JSObject::putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr)
    492513{
    493     putDirectWithoutTransition(Identifier(exec, function->name(&exec->globalData())), function, attr);
     514    putDirectFunctionWithoutTransition(Identifier(exec, function->name(&exec->globalData())), function, attr);
    494515}
    495516
  • trunk/JavaScriptCore/runtime/JSObject.h

    r43692 r44076  
    3333#include "ScopeChain.h"
    3434#include "Structure.h"
     35#include "JSGlobalData.h"
    3536
    3637namespace JSC {
     38
     39    inline JSCell* getJSFunction(JSGlobalData& globalData, JSValue value)
     40    {
     41        if (value.isCell() && (value.asCell()->vptr() == globalData.jsFunctionVPtr))
     42            return value.asCell();
     43        return 0;
     44    }
    3745
    3846    class InternalFunction;
     
    94102        virtual void put(ExecState*, unsigned propertyName, JSValue value);
    95103
     104        virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot);
    96105        virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes);
    97106        virtual void putWithAttributes(ExecState*, unsigned propertyName, JSValue value, unsigned attributes);
     
    123132
    124133        virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const;
     134        bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const;
    125135
    126136        // This get function only looks at the property map.
     
    144154        JSValue* getDirectLocation(const Identifier& propertyName, unsigned& attributes)
    145155        {
    146             size_t offset = m_structure->get(propertyName, attributes);
     156            JSCell* specificFunction;
     157            size_t offset = m_structure->get(propertyName, attributes, specificFunction);
    147158            return offset != WTF::notFound ? locationForOffset(offset) : 0;
    148159        }
     
    169180        bool hasGetterSetterProperties() { return m_structure->hasGetterSetterProperties(); }
    170181
     182        void putDirect(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
    171183        void putDirect(const Identifier& propertyName, JSValue value, unsigned attr = 0);
    172         void putDirect(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
     184
     185        void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr = 0);
     186        void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
    173187        void putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr = 0);
     188
    174189        void putDirectWithoutTransition(const Identifier& propertyName, JSValue value, unsigned attr = 0);
     190        void putDirectFunctionWithoutTransition(const Identifier& propertyName, JSCell* value, unsigned attr = 0);
    175191        void putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr = 0);
    176192
     
    208224
    209225    private:
     226        void putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot, JSCell*);
     227        void putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
     228        void putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr = 0);
     229
    210230        bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
    211231
     
    397417}
    398418
    399 inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attr)
    400 {
    401     PutPropertySlot slot;
    402     putDirect(propertyName, value, attr, false, slot);
    403 }
    404 
    405 inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
     419inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot, JSCell* specificFunction)
    406420{
    407421    ASSERT(value);
     
    410424    if (m_structure->isDictionary()) {
    411425        unsigned currentAttributes;
    412         size_t offset = m_structure->get(propertyName, currentAttributes);
     426        JSCell* currentSpecificFunction;
     427        size_t offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction);
    413428        if (offset != WTF::notFound) {
    414429            if (checkReadOnly && currentAttributes & ReadOnly)
     
    420435
    421436        size_t currentCapacity = m_structure->propertyStorageCapacity();
    422         offset = m_structure->addPropertyWithoutTransition(propertyName, attributes);
     437        offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, specificFunction);
    423438        if (currentCapacity != m_structure->propertyStorageCapacity())
    424439            allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
     
    426441        ASSERT(offset < m_structure->propertyStorageCapacity());
    427442        putDirectOffset(offset, value);
    428         slot.setNewProperty(this, offset);
     443        // See comment on setNewProperty call below.
     444        if (!specificFunction)
     445            slot.setNewProperty(this, offset);
    429446        return;
    430447    }
     
    432449    size_t offset;
    433450    size_t currentCapacity = m_structure->propertyStorageCapacity();
    434     if (RefPtr<Structure> structure = Structure::addPropertyTransitionToExistingStructure(m_structure, propertyName, attributes, offset)) {
     451    if (RefPtr<Structure> structure = Structure::addPropertyTransitionToExistingStructure(m_structure, propertyName, attributes, specificFunction, offset)) {   
    435452        if (currentCapacity != structure->propertyStorageCapacity())
    436453            allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity());
     
    439456        setStructure(structure.release());
    440457        putDirectOffset(offset, value);
    441         slot.setNewProperty(this, offset);
    442         slot.setWasTransition(true);
     458        // See comment on setNewProperty call below.
     459        if (!specificFunction)
     460            slot.setNewProperty(this, offset);
    443461        return;
    444462    }
    445463
    446464    unsigned currentAttributes;
    447     offset = m_structure->get(propertyName, currentAttributes);
     465    JSCell* currentSpecificFunction;
     466    offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction);
    448467    if (offset != WTF::notFound) {
    449468        if (checkReadOnly && currentAttributes & ReadOnly)
    450469            return;
     470
     471        if (currentSpecificFunction && (specificFunction != currentSpecificFunction)) {
     472            setStructure(Structure::changeFunctionTransition(m_structure, propertyName));
     473            putDirectOffset(offset, value);
     474            // Function transitions are not currently cachable, so leave the slot in an uncachable state.
     475            return;
     476        }
    451477        putDirectOffset(offset, value);
    452478        slot.setExistingProperty(this, offset);
     
    454480    }
    455481
    456     RefPtr<Structure> structure = Structure::addPropertyTransition(m_structure, propertyName, attributes, offset);
     482    RefPtr<Structure> structure = Structure::addPropertyTransition(m_structure, propertyName, attributes, specificFunction, offset);
    457483    if (currentCapacity != structure->propertyStorageCapacity())
    458484        allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity());
     
    461487    setStructure(structure.release());
    462488    putDirectOffset(offset, value);
    463     slot.setNewProperty(this, offset);
    464     slot.setWasTransition(true);
     489    // Function transitions are not currently cachable, so leave the slot in an uncachable state.
     490    if (!specificFunction)
     491        slot.setNewProperty(this, offset);
     492}
     493
     494inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
     495{
     496    ASSERT(value);
     497    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
     498
     499    putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, getJSFunction(globalData, value));
     500}
     501
     502inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
     503{
     504    PutPropertySlot slot;
     505    putDirectInternal(propertyName, value, attributes, false, slot, getJSFunction(globalData, value));
     506}
     507
     508inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
     509{
     510    ASSERT(value);
     511    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
     512
     513    putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, 0);
     514}
     515
     516inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes)
     517{
     518    PutPropertySlot slot;
     519    putDirectInternal(propertyName, value, attributes, false, slot, 0);
     520}
     521
     522inline void JSObject::putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
     523{
     524    putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, value);
     525}
     526
     527inline void JSObject::putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr)
     528{
     529    PutPropertySlot slot;
     530    putDirectInternal(propertyName, value, attr, false, slot, value);
    465531}
    466532
     
    468534{
    469535    size_t currentCapacity = m_structure->propertyStorageCapacity();
    470     size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes);
     536    size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, 0);
     537    if (currentCapacity != m_structure->propertyStorageCapacity())
     538        allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
     539    putDirectOffset(offset, value);
     540}
     541
     542inline void JSObject::putDirectFunctionWithoutTransition(const Identifier& propertyName, JSCell* value, unsigned attributes)
     543{
     544    size_t currentCapacity = m_structure->propertyStorageCapacity();
     545    size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, value);
    471546    if (currentCapacity != m_structure->propertyStorageCapacity())
    472547        allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
  • trunk/JavaScriptCore/runtime/Lookup.cpp

    r43225 r44076  
    7272    if (!location) {
    7373        InternalFunction* function = new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), entry->functionLength(), propertyName, entry->function());
    74         thisObj->putDirect(propertyName, function, entry->attributes());
     74
     75        thisObj->putDirectFunction(propertyName, function, entry->attributes());
    7576        location = thisObj->getDirectLocation(propertyName);
    7677    }
  • trunk/JavaScriptCore/runtime/Lookup.h

    r43220 r44076  
    230230            return false;
    231231
    232         if (entry->attributes() & Function) // function: put as override property
    233             thisObj->putDirect(propertyName, value);
    234         else if (!(entry->attributes() & ReadOnly))
     232        if (entry->attributes() & Function) { // function: put as override property
     233            if (LIKELY(value.isCell()))
     234                thisObj->putDirectFunction(propertyName, value.asCell());
     235            else
     236                thisObj->putDirect(propertyName, value);
     237        } else if (!(entry->attributes() & ReadOnly))
    235238            entry->propertyPutter()(exec, thisObj, value);
    236239
  • trunk/JavaScriptCore/runtime/PropertyMapHashTable.h

    r39502 r44076  
    3131        unsigned offset;
    3232        unsigned attributes;
     33        JSCell* specificValue;
    3334        unsigned index;
    3435
    35         PropertyMapEntry(UString::Rep* key, unsigned attributes)
     36        PropertyMapEntry(UString::Rep* key, unsigned attributes, JSCell* specificValue)
    3637            : key(key)
    3738            , offset(0)
    3839            , attributes(attributes)
     40            , specificValue(specificValue)
    3941            , index(0)
    4042        {
    4143        }
    4244
    43         PropertyMapEntry(UString::Rep* key, unsigned offset, unsigned attributes, unsigned index)
     45        PropertyMapEntry(UString::Rep* key, unsigned offset, unsigned attributes, JSCell* specificValue, unsigned index)
    4446            : key(key)
    4547            , offset(offset)
    4648            , attributes(attributes)
     49            , specificValue(specificValue)
    4750            , index(index)
    4851        {
  • trunk/JavaScriptCore/runtime/PutPropertySlot.h

    r37938 r44076  
    3333   
    3434    class JSObject;
     35    class JSFunction;
    3536   
    3637    class PutPropertySlot {
    3738    public:
    38         enum Type { Invalid, ExistingProperty, NewProperty };
     39        enum Type { Uncachable, ExistingProperty, NewProperty };
    3940
    4041        PutPropertySlot()
    41             : m_type(Invalid)
     42            : m_type(Uncachable)
    4243            , m_base(0)
    43             , m_wasTransition(false)
    4444        {
    4545        }
     
    6262        JSObject* base() const { return m_base; }
    6363
    64         bool isCacheable() const { return m_type != Invalid; }
     64        bool isCacheable() const { return m_type != Uncachable; }
    6565        size_t cachedOffset() const {
    6666            ASSERT(isCacheable());
    6767            return m_offset;
    6868        }
    69        
    70         bool wasTransition() const { return m_wasTransition; }
    71         void setWasTransition(bool wasTransition) { m_wasTransition = wasTransition; }
    7269    private:
    7370        Type m_type;
    7471        JSObject* m_base;
    75         bool m_wasTransition;
    7672        size_t m_offset;
    7773    };
  • trunk/JavaScriptCore/runtime/Structure.cpp

    r43122 r44076  
    124124    : m_typeInfo(typeInfo)
    125125    , m_prototype(prototype)
     126    , m_specificValueInPrevious(0)
    126127    , m_propertyTable(0)
    127128    , m_propertyStorageCapacity(JSObject::inlineStorageCapacity)
     
    159160            m_previous->m_transitions.singleTransition = 0;
    160161        } else {
    161             ASSERT(m_previous->m_transitions.table->contains(make_pair(m_nameInPrevious.get(), m_attributesInPrevious)));
    162             m_previous->m_transitions.table->remove(make_pair(m_nameInPrevious.get(), m_attributesInPrevious));
     162            ASSERT(m_previous->m_transitions.table->contains(make_pair(m_nameInPrevious.get(), make_pair(m_attributesInPrevious, m_specificValueInPrevious))));
     163            m_previous->m_transitions.table->remove(make_pair(m_nameInPrevious.get(), make_pair(m_attributesInPrevious, m_specificValueInPrevious)));
    163164        }
    164165    }
     
    280281        structure = structures[i];
    281282        structure->m_nameInPrevious->ref();
    282         PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, ++m_propertyTable->lastIndexUsed);
     283        PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious, ++m_propertyTable->lastIndexUsed);
    283284        insertIntoPropertyMapHashTable(entry);
    284285    }
     
    327328}
    328329
    329 PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, size_t& offset)
     330PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
    330331{
    331332    ASSERT(!structure->m_isDictionary);
     
    334335    if (structure->m_usingSingleTransitionSlot) {
    335336        Structure* existingTransition = structure->m_transitions.singleTransition;
    336         if (existingTransition && existingTransition->m_nameInPrevious.get() == propertyName.ustring().rep() && existingTransition->m_attributesInPrevious == attributes) {
     337        if (existingTransition && existingTransition->m_nameInPrevious.get() == propertyName.ustring().rep()
     338            && existingTransition->m_attributesInPrevious == attributes
     339            && existingTransition->m_specificValueInPrevious == specificValue) {
     340
    337341            ASSERT(structure->m_transitions.singleTransition->m_offset != noOffset);
    338342            offset = structure->m_transitions.singleTransition->m_offset;
     
    340344        }
    341345    } else {
    342         if (Structure* existingTransition = structure->m_transitions.table->get(make_pair(propertyName.ustring().rep(), attributes))) {
     346        if (Structure* existingTransition = structure->m_transitions.table->get(make_pair(propertyName.ustring().rep(), make_pair(attributes, specificValue)))) {
    343347            ASSERT(existingTransition->m_offset != noOffset);
    344348            offset = existingTransition->m_offset;
     
    350354}
    351355
    352 PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, const Identifier& propertyName, unsigned attributes, size_t& offset)
     356PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
    353357{
    354358    ASSERT(!structure->m_isDictionary);
    355359    ASSERT(structure->typeInfo().type() == ObjectType);
    356     ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, offset));
     360    ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, specificValue, offset));
    357361
    358362    if (structure->transitionCount() > s_maxTransitionLength) {
    359363        RefPtr<Structure> transition = toDictionaryTransition(structure);
    360         offset = transition->put(propertyName, attributes);
     364        offset = transition->put(propertyName, attributes, specificValue);
    361365        if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
    362366            transition->growPropertyStorageCapacity();
     
    365369
    366370    RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo());
     371
    367372    transition->m_cachedPrototypeChain = structure->m_cachedPrototypeChain;
    368373    transition->m_previous = structure;
    369374    transition->m_nameInPrevious = propertyName.ustring().rep();
    370375    transition->m_attributesInPrevious = attributes;
     376    transition->m_specificValueInPrevious = specificValue;
    371377    transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
    372378    transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
     
    386392    }
    387393
    388     offset = transition->put(propertyName, attributes);
     394    offset = transition->put(propertyName, attributes, specificValue);
    389395    if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
    390396        transition->growPropertyStorageCapacity();
     
    402408        StructureTransitionTable* transitionTable = new StructureTransitionTable;
    403409        structure->m_transitions.table = transitionTable;
    404         transitionTable->add(make_pair(existingTransition->m_nameInPrevious.get(), existingTransition->m_attributesInPrevious), existingTransition);
    405     }
    406     structure->m_transitions.table->add(make_pair(propertyName.ustring().rep(), attributes), transition.get());
     410        transitionTable->add(make_pair(existingTransition->m_nameInPrevious.get(), make_pair(existingTransition->m_attributesInPrevious, existingTransition->m_specificValueInPrevious)), existingTransition);
     411    }
     412    structure->m_transitions.table->add(make_pair(propertyName.ustring().rep(), make_pair(attributes, specificValue)), transition.get());
    407413    return transition.release();
    408414}
     
    431437    transition->m_propertyTable = structure->copyPropertyTable();
    432438    transition->m_isPinnedPropertyTable = true;
     439
     440    return transition.release();
     441}
     442
     443PassRefPtr<Structure> Structure::changeFunctionTransition(Structure* structure, const Identifier& replaceFunction)
     444{
     445    RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo());
     446
     447    transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
     448    transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
     449
     450    // Don't set m_offset, as one can not transition to this.
     451
     452    structure->materializePropertyMapIfNecessary();
     453    transition->m_propertyTable = structure->copyPropertyTable();
     454    transition->m_isPinnedPropertyTable = true;
     455
     456    bool removed = transition->despecifyFunction(replaceFunction);
     457    ASSERT_UNUSED(removed, removed);
    433458
    434459    return transition.release();
     
    482507}
    483508
    484 size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes)
     509size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
    485510{
    486511    ASSERT(!m_transitions.singleTransition);
     
    489514
    490515    m_isPinnedPropertyTable = true;
    491     size_t offset = put(propertyName, attributes);
     516    size_t offset = put(propertyName, attributes, specificValue);
    492517    if (propertyStorageSize() > propertyStorageCapacity())
    493518        growPropertyStorageCapacity();
     
    565590}
    566591
    567 size_t Structure::get(const Identifier& propertyName, unsigned& attributes)
    568 {
    569     ASSERT(!propertyName.isNull());
    570 
     592size_t Structure::get(const UString::Rep* rep, unsigned& attributes, JSCell*& specificValue)
     593{
    571594    materializePropertyMapIfNecessary();
    572595    if (!m_propertyTable)
    573596        return notFound;
    574597
    575     UString::Rep* rep = propertyName._ustring.rep();
    576 
    577598    unsigned i = rep->computedHash();
    578599
     
    587608    if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
    588609        attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
     610        specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue;
    589611        return m_propertyTable->entries()[entryIndex - 1].offset;
    590612    }
     
    609631        if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
    610632            attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
     633            specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue;
    611634            return m_propertyTable->entries()[entryIndex - 1].offset;
    612635        }
     
    614637}
    615638
    616 size_t Structure::put(const Identifier& propertyName, unsigned attributes)
     639bool Structure::despecifyFunction(const Identifier& propertyName)
     640{
     641    ASSERT(!propertyName.isNull());
     642
     643    materializePropertyMapIfNecessary();
     644    if (!m_propertyTable)
     645        return false;
     646
     647    UString::Rep* rep = propertyName._ustring.rep();
     648
     649    unsigned i = rep->computedHash();
     650
     651#if DUMP_PROPERTYMAP_STATS
     652    ++numProbes;
     653#endif
     654
     655    unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
     656    if (entryIndex == emptyEntryIndex)
     657        return false;
     658
     659    if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
     660        ASSERT(m_propertyTable->entries()[entryIndex - 1].specificValue);
     661        m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
     662        return true;
     663    }
     664
     665#if DUMP_PROPERTYMAP_STATS
     666    ++numCollisions;
     667#endif
     668
     669    unsigned k = 1 | doubleHash(rep->computedHash());
     670
     671    while (1) {
     672        i += k;
     673
     674#if DUMP_PROPERTYMAP_STATS
     675        ++numRehashes;
     676#endif
     677
     678        entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
     679        if (entryIndex == emptyEntryIndex)
     680            return false;
     681
     682        if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
     683            ASSERT(m_propertyTable->entries()[entryIndex - 1].specificValue);
     684            m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
     685            return true;
     686        }
     687    }
     688}
     689
     690size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
    617691{
    618692    ASSERT(!propertyName.isNull());
     
    684758    m_propertyTable->entries()[entryIndex - 1].key = rep;
    685759    m_propertyTable->entries()[entryIndex - 1].attributes = attributes;
     760    m_propertyTable->entries()[entryIndex - 1].specificValue = specificValue;
    686761    m_propertyTable->entries()[entryIndex - 1].index = ++m_propertyTable->lastIndexUsed;
    687762
     
    756831    m_propertyTable->entries()[entryIndex - 1].key = 0;
    757832    m_propertyTable->entries()[entryIndex - 1].attributes = 0;
     833    m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
    758834    m_propertyTable->entries()[entryIndex - 1].offset = 0;
    759835
  • trunk/JavaScriptCore/runtime/Structure.h

    r43432 r44076  
    6262        static void dumpStatistics();
    6363
    64         static PassRefPtr<Structure> addPropertyTransition(Structure*, const Identifier& propertyName, unsigned attributes, size_t& offset);
    65         static PassRefPtr<Structure> addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, size_t& offset);
     64        static PassRefPtr<Structure> addPropertyTransition(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
     65        static PassRefPtr<Structure> addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
    6666        static PassRefPtr<Structure> removePropertyTransition(Structure*, const Identifier& propertyName, size_t& offset);
    6767        static PassRefPtr<Structure> changePrototypeTransition(Structure*, JSValue prototype);
     68        static PassRefPtr<Structure> changeFunctionTransition(Structure*, const Identifier&);       
    6869        static PassRefPtr<Structure> getterSetterTransition(Structure*);
    6970        static PassRefPtr<Structure> toDictionaryTransition(Structure*);
     
    7980
    8081        // These should be used with caution. 
    81         size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes);
     82        size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
    8283        size_t removePropertyWithoutTransition(const Identifier& propertyName);
    8384        void setPrototypeWithoutTransition(JSValue prototype) { m_prototype = prototype; }
     
    99100
    100101        size_t get(const Identifier& propertyName);
    101         size_t get(const Identifier& propertyName, unsigned& attributes);
     102        size_t get(const UString::Rep* rep, unsigned& attributes, JSCell*& specificValue);
     103        size_t get(const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue)
     104        {
     105            ASSERT(!propertyName.isNull());
     106            return get(propertyName._ustring.rep(), attributes, specificValue);
     107        }
     108
    102109        void getEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*);
    103110
     
    107114        bool isEmpty() const { return m_propertyTable ? !m_propertyTable->keyCount : m_offset == noOffset; }
    108115
     116        JSCell* specificValue() { return m_specificValueInPrevious; }
     117
    109118    private:
    110119        Structure(JSValue prototype, const TypeInfo&);
    111120
    112         size_t put(const Identifier& propertyName, unsigned attributes);
     121        size_t put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
    113122        size_t remove(const Identifier& propertyName);
    114123        void getEnumerableNamesFromPropertyTable(PropertyNameArray&);
     
    123132        void checkConsistency();
    124133
     134        bool despecifyFunction(const Identifier&);
     135
    125136        PropertyMapHashTable* copyPropertyTable();
    126137        void materializePropertyMap();
     
    160171            StructureTransitionTable* table;
    161172        } m_transitions;
     173        JSCell* m_specificValueInPrevious;
    162174
    163175        RefPtr<PropertyNameArrayData> m_cachedPropertyNameArrayData;
  • trunk/JavaScriptCore/runtime/StructureTransitionTable.h

    r38440 r44076  
    3838
    3939    struct StructureTransitionTableHash {
    40         typedef std::pair<RefPtr<UString::Rep>, unsigned> Key;
     40        typedef std::pair<RefPtr<UString::Rep>, std::pair<unsigned, JSCell*> > Key;
    4141        static unsigned hash(const Key& p)
    4242        {
     
    5454    struct StructureTransitionTableHashTraits {
    5555        typedef WTF::HashTraits<RefPtr<UString::Rep> > FirstTraits;
    56         typedef WTF::GenericHashTraits<unsigned> SecondTraits;
    57         typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType> TraitType;
     56        typedef WTF::GenericHashTraits<unsigned> SecondFirstTraits;
     57        typedef WTF::GenericHashTraits<JSCell*> SecondSecondTraits;
     58        typedef std::pair<FirstTraits::TraitType, std::pair<SecondFirstTraits::TraitType, SecondSecondTraits::TraitType> > TraitType;
    5859
    59         static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero;
    60         static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); }
     60        static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondFirstTraits::emptyValueIsZero && SecondSecondTraits::emptyValueIsZero;
     61        static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), std::make_pair(SecondFirstTraits::emptyValue(), SecondSecondTraits::emptyValue())); }
    6162
    62         static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction;
     63        static const bool needsDestruction = FirstTraits::needsDestruction || SecondFirstTraits::needsDestruction || SecondSecondTraits::needsDestruction;
    6364
    6465        static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); }
Note: See TracChangeset for help on using the changeset viewer.