Changeset 50254 in webkit for trunk/JavaScriptCore


Ignore:
Timestamp:
Oct 28, 2009, 6:25:02 PM (16 years ago)
Author:
[email protected]
Message:

Improve for..in enumeration performance
https://bugs.webkit.org/show_bug.cgi?id=30887

Reviewed by Geoff Garen.

Improve indexing of an object with a for..in iterator by
identifying cases where get_by_val is being used with a iterator
as the subscript and replace it with a new get_by_pname
bytecode. get_by_pname then optimizes lookups that directly access
the base object.

Location:
trunk/JavaScriptCore
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r50248 r50254  
     12009-10-28  Oliver Hunt  <[email protected]>
     2
     3        Reviewed by Geoff Garen.
     4
     5        Improve for..in enumeration performance
     6        https://bugs.webkit.org/show_bug.cgi?id=30887
     7
     8        Improve indexing of an object with a for..in iterator by
     9        identifying cases where get_by_val is being used with a iterator
     10        as the subscript and replace it with a new get_by_pname
     11        bytecode.  get_by_pname then optimizes lookups that directly access
     12        the base object.
     13
     14        * bytecode/CodeBlock.cpp:
     15        (JSC::CodeBlock::dump):
     16        * bytecode/Opcode.h:
     17        * bytecompiler/BytecodeGenerator.cpp:
     18        (JSC::BytecodeGenerator::emitGetByVal):
     19        * bytecompiler/BytecodeGenerator.h:
     20        (JSC::BytecodeGenerator::pushOptimisedForIn):
     21        (JSC::BytecodeGenerator::popOptimisedForIn):
     22        * interpreter/Interpreter.cpp:
     23        (JSC::Interpreter::privateExecute):
     24        * jit/JIT.cpp:
     25        (JSC::JIT::privateCompileMainPass):
     26        (JSC::JIT::privateCompileSlowCases):
     27        * jit/JIT.h:
     28        * jit/JITPropertyAccess.cpp:
     29        (JSC::JIT::compileGetDirectOffset):
     30        (JSC::JIT::emit_op_get_by_pname):
     31        (JSC::JIT::emitSlow_op_get_by_pname):
     32        * parser/Nodes.cpp:
     33        (JSC::ForInNode::emitBytecode):
     34        * runtime/JSObject.h:
     35        * runtime/JSPropertyNameIterator.cpp:
     36        (JSC::JSPropertyNameIterator::create):
     37        * runtime/JSPropertyNameIterator.h:
     38        (JSC::JSPropertyNameIterator::getOffset):
     39        (JSC::JSPropertyNameIterator::JSPropertyNameIterator):
     40        * runtime/JSValue.h:
     41        (JSC::JSValue::):
     42        * runtime/Structure.cpp:
     43        (JSC::Structure::addPropertyTransition):
     44        (JSC::Structure::changePrototypeTransition):
     45        (JSC::Structure::despecifyFunctionTransition):
     46        (JSC::Structure::addAnonymousSlotsTransition):
     47        (JSC::Structure::getterSetterTransition):
     48        (JSC::Structure::toDictionaryTransition):
     49        (JSC::Structure::addPropertyWithoutTransition):
     50          Track the existence (or not) of non-enumerable properties.
     51        * runtime/Structure.h:
     52        (JSC::Structure::propertyStorageCapacity):
     53        (JSC::Structure::propertyStorageSize):
     54        (JSC::Structure::hasNonEnumerableProperties):
     55        (JSC::Structure::hasAnonymousSlots):
     56
    1572009-10-28  Dmitry Titov  <[email protected]>
    258
  • trunk/JavaScriptCore/bytecode/CodeBlock.cpp

    r49734 r50254  
    825825            break;
    826826        }
     827        case op_get_by_pname: {
     828            int r0 = (++it)->u.operand;
     829            int r1 = (++it)->u.operand;
     830            int r2 = (++it)->u.operand;
     831            int r3 = (++it)->u.operand;
     832            int r4 = (++it)->u.operand;
     833            int r5 = (++it)->u.operand;
     834            printf("[%4d] get_by_pname\t %s, %s, %s, %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), registerName(r3).c_str(), registerName(r4).c_str(), registerName(r5).c_str());
     835            break;
     836        }
    827837        case op_put_by_val: {
    828838            int r0 = (++it)->u.operand;
     
    10161026        }
    10171027        case op_get_pnames: {
    1018             int r0 = it[0].u.operand;
    1019             int r1 = it[1].u.operand;
    1020             printf("[%4d] get_pnames\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
     1028            int r0 = it[1].u.operand;
     1029            int r1 = it[2].u.operand;
     1030            int r2 = it[3].u.operand;
     1031            int r3 = it[4].u.operand;
     1032            int offset = it[5].u.operand;
     1033            printf("[%4d] get_pnames\t %s, %s, %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), registerName(r3).c_str(), offset, location + offset);
    10211034            it += OPCODE_LENGTH(op_get_pnames) - 1;
    10221035            break;
    10231036        }
    10241037        case op_next_pname: {
    1025             int dest = it[0].u.operand;
     1038            int dest = it[1].u.operand;
    10261039            int iter = it[4].u.operand;
    10271040            int offset = it[5].u.operand;
  • trunk/JavaScriptCore/bytecode/Opcode.h

    r49734 r50254  
    114114        macro(op_del_by_id, 4) \
    115115        macro(op_get_by_val, 4) \
     116        macro(op_get_by_pname, 7) \
    116117        macro(op_put_by_val, 4) \
    117118        macro(op_del_by_val, 4) \
  • trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r49734 r50254  
    12821282RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
    12831283{
     1284    for (size_t i = m_forInContextStack.size(); i > 0; i--) {
     1285        ForInContext& context = m_forInContextStack[i - 1];
     1286        if (context.propertyRegister == property) {
     1287            emitOpcode(op_get_by_pname);
     1288            instructions().append(dst->index());
     1289            instructions().append(base->index());
     1290            instructions().append(property->index());
     1291            instructions().append(context.expectedSubscriptRegister->index());
     1292            instructions().append(context.iterRegister->index());
     1293            instructions().append(context.indexRegister->index());
     1294            return dst;
     1295        }
     1296    }
    12841297    emitOpcode(op_get_by_val);
    12851298    instructions().append(dst->index());
  • trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r49734 r50254  
    6262    };
    6363
     64    struct ForInContext {
     65        RefPtr<RegisterID> expectedSubscriptRegister;
     66        RefPtr<RegisterID> iterRegister;
     67        RefPtr<RegisterID> indexRegister;
     68        RefPtr<RegisterID> propertyRegister;
     69    };
     70
    6471    class BytecodeGenerator : public FastAllocBase {
    6572    public:
     
    332339        void popFinallyContext();
    333340
     341        void pushOptimisedForIn(RegisterID* expectedBase, RegisterID* iter, RegisterID* index, RegisterID* propertyRegister)
     342        {
     343            ForInContext context = { expectedBase, iter, index, propertyRegister };
     344            m_forInContextStack.append(context);
     345        }
     346
     347        void popOptimisedForIn()
     348        {
     349            m_forInContextStack.removeLast();
     350        }
     351
    334352        LabelScope* breakTarget(const Identifier&);
    335353        LabelScope* continueTarget(const Identifier&);
     
    468486        Vector<ControlFlowContext> m_scopeContextStack;
    469487        Vector<SwitchInfo> m_switchContextStack;
     488        Vector<ForInContext> m_forInContextStack;
    470489
    471490        int m_nextGlobalIndex;
  • trunk/JavaScriptCore/interpreter/Interpreter.cpp

    r49734 r50254  
    24162416        callFrame->r(dst) = result;
    24172417        vPC += OPCODE_LENGTH(op_del_by_id);
     2418        NEXT_INSTRUCTION();
     2419    }
     2420    DEFINE_OPCODE(op_get_by_pname) {
     2421        int dst = vPC[1].u.operand;
     2422        int base = vPC[2].u.operand;
     2423        int property = vPC[3].u.operand;
     2424        int expected = vPC[4].u.operand;
     2425        int iter = vPC[5].u.operand;
     2426        int i = vPC[6].u.operand;
     2427
     2428        JSValue baseValue = callFrame->r(base).jsValue();
     2429        JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator();
     2430        JSValue subscript = callFrame->r(property).jsValue();
     2431        JSValue expectedSubscript = callFrame->r(expected).jsValue();
     2432        int index = callFrame->r(i).i() - 1;
     2433        JSValue result;
     2434        int offset = 0;
     2435        if (subscript == expectedSubscript && baseValue.isCell() && (baseValue.asCell()->structure() == it->cachedStructure()) && it->getOffset(index, offset)) {
     2436            callFrame->r(dst) = asObject(baseValue)->getDirectOffset(offset);
     2437            vPC += OPCODE_LENGTH(op_get_by_pname);
     2438            NEXT_INSTRUCTION();
     2439        }
     2440        Identifier propertyName(callFrame, subscript.toString(callFrame));
     2441        result = baseValue.get(callFrame, propertyName);
     2442        CHECK_FOR_EXCEPTION();
     2443        callFrame->r(dst) = result;
     2444        vPC += OPCODE_LENGTH(op_get_by_pname);
    24182445        NEXT_INSTRUCTION();
    24192446    }
  • trunk/JavaScriptCore/jit/JIT.cpp

    r49734 r50254  
    240240        DEFINE_OP(op_get_by_id)
    241241        DEFINE_OP(op_get_by_val)
     242        DEFINE_OP(op_get_by_pname)
    242243        DEFINE_OP(op_get_global_var)
    243244        DEFINE_OP(op_get_pnames)
     
    386387        DEFINE_SLOWCASE_OP(op_get_by_id)
    387388        DEFINE_SLOWCASE_OP(op_get_by_val)
     389        DEFINE_SLOWCASE_OP(op_get_by_pname)
    388390        DEFINE_SLOWCASE_OP(op_instanceof)
    389391        DEFINE_SLOWCASE_OP(op_jfalse)
  • trunk/JavaScriptCore/jit/JIT.h

    r50211 r50254  
    429429        void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, Structure* structure, size_t cachedOffset);
    430430        void compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset);
     431        void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID structure, RegisterID offset);
    431432        void compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterID valuePayload, Structure* structure, size_t cachedOffset);
    432433
     
    530531        void compileGetDirectOffset(RegisterID base, RegisterID result, Structure* structure, size_t cachedOffset);
    531532        void compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID result, size_t cachedOffset);
     533        void compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID structure, RegisterID offset, RegisterID scratch);
    532534        void compilePutDirectOffset(RegisterID base, RegisterID value, Structure* structure, size_t cachedOffset);
    533535
     
    684686        void emit_op_get_by_id(Instruction*);
    685687        void emit_op_get_by_val(Instruction*);
     688        void emit_op_get_by_pname(Instruction*);
    686689        void emit_op_get_global_var(Instruction*);
    687690        void emit_op_get_scoped_var(Instruction*);
     
    773776        void emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&);
    774777        void emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
     778        void emitSlow_op_get_by_pname(Instruction*, Vector<SlowCaseEntry>::iterator&);
    775779        void emitSlow_op_instanceof(Instruction*, Vector<SlowCaseEntry>::iterator&);
    776780        void emitSlow_op_jfalse(Instruction*, Vector<SlowCaseEntry>::iterator&);
  • trunk/JavaScriptCore/jit/JITPropertyAccess.cpp

    r50201 r50254  
    3434#include "JSArray.h"
    3535#include "JSFunction.h"
     36#include "JSPropertyNameIterator.h"
    3637#include "Interpreter.h"
    3738#include "LinkBuffer.h"
     
    935936#endif // !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
    936937
     938void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID structure, RegisterID offset)
     939{
     940    ASSERT(sizeof(((Structure*)0)->m_propertyStorageCapacity) == sizeof(int32_t));
     941    ASSERT(sizeof(JSObject::inlineStorageCapacity) == sizeof(int32_t));
     942    ASSERT(sizeof(JSValue) == 8);
     943
     944    Jump notUsingInlineStorage = branch32(NotEqual, Address(structure, OBJECT_OFFSETOF(Structure, m_propertyStorageCapacity)), Imm32(JSObject::inlineStorageCapacity));
     945    loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSObject, m_inlineStorage)+OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload);
     946    loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSObject, m_inlineStorage)+OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag);
     947    Jump finishedLoad = jump();
     948    notUsingInlineStorage.link(this);
     949    loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
     950    loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload);
     951    loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag);
     952    finishedLoad.link(this);
     953}
     954
     955void JIT::emit_op_get_by_pname(Instruction* currentInstruction)
     956{
     957    unsigned dst = currentInstruction[1].u.operand;
     958    unsigned base = currentInstruction[2].u.operand;
     959    unsigned property = currentInstruction[3].u.operand;
     960    unsigned expected = currentInstruction[4].u.operand;
     961    unsigned iter = currentInstruction[5].u.operand;
     962    unsigned i = currentInstruction[6].u.operand;
     963
     964    emitLoad2(property, regT1, regT0, base, regT3, regT2);
     965    emitJumpSlowCaseIfNotJSCell(property, regT1);
     966    addSlowCase(branchPtr(NotEqual, regT0, payloadFor(expected)));
     967    // Property registers are now available as the property is known
     968    emitJumpSlowCaseIfNotJSCell(base, regT3);
     969    emitLoadPayload(iter, regT1);
     970   
     971    // Test base's structure
     972    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
     973    addSlowCase(branchPtr(NotEqual, regT0, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure))));
     974    load32(addressFor(i), regT3);
     975    sub32(Imm32(1), regT3);
     976    addSlowCase(branch32(AboveOrEqual, regT3, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_numCacheableSlots))));
     977    compileGetDirectOffset(regT2, regT1, regT0, regT0, regT3);   
     978
     979    emitStore(dst, regT1, regT0);
     980    map(m_bytecodeIndex + OPCODE_LENGTH(op_get_by_pname), dst, regT1, regT0);
     981}
     982
     983void JIT::emitSlow_op_get_by_pname(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     984{
     985    unsigned dst = currentInstruction[1].u.operand;
     986    unsigned base = currentInstruction[2].u.operand;
     987    unsigned property = currentInstruction[3].u.operand;
     988   
     989    linkSlowCaseIfNotJSCell(iter, property);
     990    linkSlowCase(iter);
     991    linkSlowCaseIfNotJSCell(iter, base);
     992    linkSlowCase(iter);
     993    linkSlowCase(iter);
     994   
     995    JITStubCall stubCall(this, cti_op_get_by_val);
     996    stubCall.addArgument(base);
     997    stubCall.addArgument(property);
     998    stubCall.call(dst);
     999}
     1000
    9371001#else // USE(JSVALUE32_64)
    9381002
     
    9681032}
    9691033
     1034void JIT::emit_op_get_by_pname(Instruction* currentInstruction)
     1035{
     1036    unsigned dst = currentInstruction[1].u.operand;
     1037    unsigned base = currentInstruction[2].u.operand;
     1038    unsigned property = currentInstruction[3].u.operand;
     1039    unsigned expected = currentInstruction[4].u.operand;
     1040    unsigned iter = currentInstruction[5].u.operand;
     1041    unsigned i = currentInstruction[6].u.operand;
     1042
     1043    emitGetVirtualRegister(property, regT0);
     1044    addSlowCase(branchPtr(NotEqual, regT0, addressFor(expected)));
     1045    emitGetVirtualRegisters(base, regT0, iter, regT1);
     1046    emitJumpSlowCaseIfNotJSCell(regT0, base);
     1047
     1048    // Test base's structure
     1049    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
     1050    addSlowCase(branchPtr(NotEqual, regT2, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure))));
     1051    load32(addressFor(i), regT3);
     1052    sub32(Imm32(1), regT3);
     1053    addSlowCase(branch32(AboveOrEqual, regT3, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_numCacheableSlots))));
     1054    compileGetDirectOffset(regT0, regT0, regT2, regT3, regT1);
     1055
     1056    emitPutVirtualRegister(dst, regT0);
     1057}
     1058
     1059void JIT::emitSlow_op_get_by_pname(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     1060{
     1061    unsigned dst = currentInstruction[1].u.operand;
     1062    unsigned base = currentInstruction[2].u.operand;
     1063    unsigned property = currentInstruction[3].u.operand;
     1064
     1065    linkSlowCase(iter);
     1066    linkSlowCaseIfNotJSCell(iter, base);
     1067    linkSlowCase(iter);
     1068    linkSlowCase(iter);
     1069
     1070    JITStubCall stubCall(this, cti_op_get_by_val);
     1071    stubCall.addArgument(base, regT2);
     1072    stubCall.addArgument(property, regT2);
     1073    stubCall.call(dst);
     1074}
     1075
    9701076void JIT::emit_op_put_by_val(Instruction* currentInstruction)
    9711077{
     
    13501456        loadPtr(Address(temp, cachedOffset * sizeof(JSValue)), result);
    13511457    }
     1458}
     1459
     1460void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID structure, RegisterID offset, RegisterID scratch)
     1461{
     1462    ASSERT(sizeof(((Structure*)0)->m_propertyStorageCapacity) == sizeof(int32_t));
     1463    ASSERT(sizeof(JSObject::inlineStorageCapacity) == sizeof(int32_t));
     1464
     1465    Jump notUsingInlineStorage = branch32(NotEqual, Address(structure, OBJECT_OFFSETOF(Structure, m_propertyStorageCapacity)), Imm32(JSObject::inlineStorageCapacity));
     1466    loadPtr(BaseIndex(base, offset, ScalePtr, OBJECT_OFFSETOF(JSObject, m_inlineStorage)), result);
     1467    Jump finishedLoad = jump();
     1468    notUsingInlineStorage.link(this);
     1469    loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), scratch);
     1470    loadPtr(BaseIndex(scratch, offset, ScalePtr, 0), result);   
     1471    finishedLoad.link(this);
    13521472}
    13531473
  • trunk/JavaScriptCore/parser/Nodes.cpp

    r49734 r50254  
    14781478    RefPtr<RegisterID> i = generator.newTemporary();
    14791479    RefPtr<RegisterID> size = generator.newTemporary();
     1480    RefPtr<RegisterID> expectedSubscript;
    14801481    RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), base.get(), i.get(), size.get(), scope->breakTarget());
    14811482    generator.emitJump(scope->continueTarget());
     
    14851486
    14861487    RegisterID* propertyName;
     1488    bool optimizedForinAccess = false;
    14871489    if (m_lexpr->isResolveNode()) {
    14881490        const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
     
    14951497            generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    14961498            generator.emitPutById(base, ident, propertyName);
     1499        } else {
     1500            expectedSubscript = generator.emitMove(generator.newTemporary(), propertyName);
     1501            generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), propertyName);
     1502            optimizedForinAccess = true;
    14971503        }
    14981504    } else if (m_lexpr->isDotAccessorNode()) {
     
    15181524
    15191525    generator.emitNode(dst, m_statement);
     1526
     1527    if (optimizedForinAccess)
     1528        generator.popOptimisedForIn();
    15201529
    15211530    generator.emitLabel(scope->continueTarget());
  • trunk/JavaScriptCore/runtime/JSObject.h

    r49721 r50254  
    203203        bool isUsingInlineStorage() const { return m_structure->isUsingInlineStorage(); }
    204204
    205         static const size_t inlineStorageCapacity = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 4 : 3;
    206         static const size_t nonInlineBaseStorageCapacity = 16;
     205        static const unsigned inlineStorageCapacity = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 4 : 3;
     206        static const unsigned nonInlineBaseStorageCapacity = 16;
    207207
    208208        static PassRefPtr<Structure> createStructure(JSValue prototype)
  • trunk/JavaScriptCore/runtime/JSPropertyNameIterator.cpp

    r49734 r50254  
    4444    PropertyNameArray propertyNames(exec);
    4545    o->getPropertyNames(exec, propertyNames);
    46     JSPropertyNameIterator* jsPropertyNameIterator = new (exec) JSPropertyNameIterator(exec, propertyNames.data());
     46    size_t numCacheableSlots = 0;
     47    if (!o->structure()->hasNonEnumerableProperties() && !o->structure()->hasAnonymousSlots() &&
     48        !o->structure()->isUncacheableDictionary() && !o->structure()->typeInfo().overridesGetPropertyNames())
     49        numCacheableSlots = o->structure()->propertyStorageSize();
     50
     51    JSPropertyNameIterator* jsPropertyNameIterator = new (exec) JSPropertyNameIterator(exec, propertyNames.data(), numCacheableSlots);
    4752
    4853    if (o->structure()->isDictionary())
  • trunk/JavaScriptCore/runtime/JSPropertyNameIterator.h

    r49955 r50254  
    5555        virtual void markChildren(MarkStack&);
    5656
     57        bool getOffset(size_t i, int& offset)
     58        {
     59            if (i >= m_numCacheableSlots)
     60                return false;
     61            offset = i;
     62            return true;
     63        }
     64
    5765        JSValue get(ExecState*, JSObject*, size_t i);
    5866        size_t size() { return m_jsStringsSize; }
     
    6573
    6674    private:
    67         JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData);
     75        JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlot);
    6876
    6977        Structure* m_cachedStructure;
    7078        RefPtr<StructureChain> m_cachedPrototypeChain;
    71         size_t m_jsStringsSize;
     79        uint32_t m_numCacheableSlots;
     80        uint32_t m_jsStringsSize;
    7281        OwnArrayPtr<JSValue> m_jsStrings;
    7382    };
    7483
    75 inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData)
     84inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlots)
    7685    : JSCell(exec->globalData().propertyNameIteratorStructure.get())
    7786    , m_cachedStructure(0)
     87    , m_numCacheableSlots(numCacheableSlots)
    7888    , m_jsStringsSize(propertyNameArrayData->propertyNameVector().size())
    7989    , m_jsStrings(new JSValue[m_jsStringsSize])
  • trunk/JavaScriptCore/runtime/Structure.cpp

    r49734 r50254  
    376376    transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
    377377    transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
     378    transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
    378379
    379380    if (structure->m_propertyTable) {
     
    418419    transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
    419420    transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
     421    transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
    420422
    421423    // Don't set m_offset, as one can not transition to this.
     
    434436    transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
    435437    transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
     438    transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
    436439
    437440    // Don't set m_offset, as one can not transition to this.
     
    465468    transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
    466469    transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
     470    transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
    467471
    468472    if (structure->m_propertyTable) {
     
    493497    transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
    494498    transition->m_hasGetterSetterProperties = transition->m_hasGetterSetterProperties;
     499    transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
    495500
    496501    // Don't set m_offset, as one can not transition to this.
     
    511516    transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
    512517    transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
     518    transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
    513519   
    514520    structure->materializePropertyMapIfNecessary();
     
    551557
    552558    m_isPinnedPropertyTable = true;
     559    if (attributes & DontEnum)
     560        m_hasNonEnumerableProperties = true;
     561
    553562    size_t offset = put(propertyName, attributes, specificValue);
    554563    if (propertyStorageSize() > propertyStorageCapacity())
  • trunk/JavaScriptCore/runtime/Structure.h

    r49734 r50254  
    9696
    9797        void growPropertyStorageCapacity();
    98         size_t propertyStorageCapacity() const { return m_propertyStorageCapacity; }
    99         size_t propertyStorageSize() const { return m_propertyTable ? m_propertyTable->keyCount + m_propertyTable->anonymousSlotCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1; }
     98        unsigned propertyStorageCapacity() const { return m_propertyStorageCapacity; }
     99        unsigned propertyStorageSize() const { return m_propertyTable ? m_propertyTable->keyCount + m_propertyTable->anonymousSlotCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1; }
    100100        bool isUsingInlineStorage() const;
    101101
     
    120120        void setHasGetterSetterProperties(bool hasGetterSetterProperties) { m_hasGetterSetterProperties = hasGetterSetterProperties; }
    121121
     122        bool hasNonEnumerableProperties() const { return m_hasNonEnumerableProperties; }
     123
     124        bool hasAnonymousSlots() const { return m_propertyTable && m_propertyTable->anonymousSlotCount; }
     125       
    122126        bool isEmpty() const { return m_propertyTable ? !m_propertyTable->keyCount : m_offset == noOffset; }
    123127
     
    191195        PropertyMapHashTable* m_propertyTable;
    192196
    193         size_t m_propertyStorageCapacity;
     197        uint32_t m_propertyStorageCapacity;
    194198        signed char m_offset;
    195199
     
    197201        bool m_isPinnedPropertyTable : 1;
    198202        bool m_hasGetterSetterProperties : 1;
     203        bool m_hasNonEnumerableProperties : 1;
    199204#if COMPILER(WINSCW)
    200205        // Workaround for Symbian WINSCW compiler that cannot resolve unsigned type of the declared
Note: See TracChangeset for help on using the changeset viewer.