Changeset 62896 in webkit


Ignore:
Timestamp:
Jul 8, 2010 10:47:49 PM (14 years ago)
Author:
oliver@apple.com
Message:

2010-07-08 Oliver Hunt <oliver@apple.com>

Reviewed by Sam Weinig.

Property declarations in an object literal should not consider the prototype chain when being added to the new object
https://bugs.webkit.org/show_bug.cgi?id=41929

To fix this all we need to do is ensure that all new properties are
added with putDirect rather than a fully generic call to put. This
is safe as an object literal is by definition going to produce a
completely normal object.

Rather than duplicating all the put_by_id logic we add an additional
flag to op_put_by_id to indicate it should be using putDirect. In
the interpreter this adds a runtime branch, but in the jit this is
essentially free as the branch is taken at compile time. This does
actually improve object literal creation time even in the interpreter
as we no longer need to walk the prototype chain to verify that the
cached put is safe.

We still emit normal put_by_id code when emitting proto as we want
to get the correct handling for changing the prototype.

Sunspider claims this is a 0.7% speedup which is conceivably real due
to the performance improvement in object literals, but I suspect its
really just the result of code motion.

  • bytecode/Opcode.h:
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitPutById): (JSC::BytecodeGenerator::emitDirectPutById):
  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp: (JSC::PropertyListNode::emitBytecode):
  • interpreter/Interpreter.cpp: (JSC::Interpreter::privateExecute):
  • jit/JIT.h: (JSC::JIT::compilePutByIdTransition):
  • jit/JITPropertyAccess.cpp: (JSC::JIT::emit_op_put_by_id): (JSC::JIT::emitSlow_op_put_by_id): (JSC::JIT::privateCompilePutByIdTransition): (JSC::JIT::patchPutByIdReplace):
  • jit/JITPropertyAccess32_64.cpp: (JSC::JIT::emitSlow_op_put_by_id): (JSC::JIT::privateCompilePutByIdTransition): (JSC::JIT::patchPutByIdReplace):
  • jit/JITStubs.cpp: (JSC::JITThunks::tryCachePutByID): (JSC::DEFINE_STUB_FUNCTION):
  • jit/JITStubs.h: (JSC::):
  • runtime/JSGlobalData.cpp: (JSC::JSGlobalData::JSGlobalData):
  • runtime/JSObject.h: (JSC::JSObject::putDirect): (JSC::JSValue::putDirect):
  • runtime/JSValue.h:

2010-07-08 Oliver Hunt <oliver@apple.com>

Reviewed by Sam Weinig.

Property declarations in an object literal should not consider the prototype chain when being added to the new object
https://bugs.webkit.org/show_bug.cgi?id=41929

Add tests to ensure correct behaviour of object literals when there
are setters on the prototype chain.

  • fast/js/object-literal-direct-put-expected.txt: Added.
  • fast/js/object-literal-direct-put.html: Added.
  • fast/js/script-tests/object-literal-direct-put.js: Added.
  • ietestcenter/Javascript/15.4.4.14-9-b-i-6-expected.txt:
  • ietestcenter/Javascript/15.4.4.15-8-b-i-6-expected.txt:
  • platform/chromium/test_expectations.txt:
Location:
trunk
Files:
3 added
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r62885 r62896  
     12010-07-08  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Sam Weinig.
     4
     5        Property declarations in an object literal should not consider the prototype chain when being added to the new object
     6        https://bugs.webkit.org/show_bug.cgi?id=41929
     7
     8        To fix this all we need to do is ensure that all new properties are
     9        added with putDirect rather than a fully generic call to put.  This
     10        is safe as an object literal is by definition going to produce a
     11        completely normal object.
     12
     13        Rather than duplicating all the put_by_id logic we add an additional
     14        flag to op_put_by_id to indicate it should be using putDirect.  In
     15        the interpreter this adds a runtime branch, but in the jit this is
     16        essentially free as the branch is taken at compile time.  This does
     17        actually improve object literal creation time even in the interpreter
     18        as we no longer need to walk the prototype chain to verify that the
     19        cached put is safe.
     20
     21        We still emit normal put_by_id code when emitting __proto__ as we want
     22        to get the correct handling for changing the prototype.
     23
     24        Sunspider claims this is a 0.7% speedup which is conceivably real due
     25        to the performance improvement in object literals, but I suspect its
     26        really just the result of code motion.
     27
     28        * bytecode/Opcode.h:
     29        * bytecompiler/BytecodeGenerator.cpp:
     30        (JSC::BytecodeGenerator::emitPutById):
     31        (JSC::BytecodeGenerator::emitDirectPutById):
     32        * bytecompiler/BytecodeGenerator.h:
     33        * bytecompiler/NodesCodegen.cpp:
     34        (JSC::PropertyListNode::emitBytecode):
     35        * interpreter/Interpreter.cpp:
     36        (JSC::Interpreter::privateExecute):
     37        * jit/JIT.h:
     38        (JSC::JIT::compilePutByIdTransition):
     39        * jit/JITPropertyAccess.cpp:
     40        (JSC::JIT::emit_op_put_by_id):
     41        (JSC::JIT::emitSlow_op_put_by_id):
     42        (JSC::JIT::privateCompilePutByIdTransition):
     43        (JSC::JIT::patchPutByIdReplace):
     44        * jit/JITPropertyAccess32_64.cpp:
     45        (JSC::JIT::emitSlow_op_put_by_id):
     46        (JSC::JIT::privateCompilePutByIdTransition):
     47        (JSC::JIT::patchPutByIdReplace):
     48        * jit/JITStubs.cpp:
     49        (JSC::JITThunks::tryCachePutByID):
     50        (JSC::DEFINE_STUB_FUNCTION):
     51        * jit/JITStubs.h:
     52        (JSC::):
     53        * runtime/JSGlobalData.cpp:
     54        (JSC::JSGlobalData::JSGlobalData):
     55        * runtime/JSObject.h:
     56        (JSC::JSObject::putDirect):
     57        (JSC::JSValue::putDirect):
     58        * runtime/JSValue.h:
     59
    1602010-07-08  Gavin Barraclough  <barraclough@apple.com>
    261
  • trunk/JavaScriptCore/bytecode/Opcode.h

    r61474 r62896  
    121121        macro(op_get_array_length, 8) \
    122122        macro(op_get_string_length, 8) \
    123         macro(op_put_by_id, 8) \
    124         macro(op_put_by_id_transition, 8) \
    125         macro(op_put_by_id_replace, 8) \
    126         macro(op_put_by_id_generic, 8) \
     123        macro(op_put_by_id, 9) \
     124        macro(op_put_by_id_transition, 9) \
     125        macro(op_put_by_id_replace, 9) \
     126        macro(op_put_by_id_generic, 9) \
    127127        macro(op_del_by_id, 4) \
    128128        macro(op_get_by_val, 4) \
  • trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r61430 r62896  
    12811281    instructions().append(0);
    12821282    instructions().append(0);
     1283    instructions().append(0);
     1284    return value;
     1285}
     1286
     1287RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value)
     1288{
     1289#if ENABLE(JIT)
     1290    m_codeBlock->addStructureStubInfo(StructureStubInfo(access_put_by_id));
     1291#else
     1292    m_codeBlock->addPropertyAccessInstruction(instructions().size());
     1293#endif
     1294   
     1295    emitOpcode(op_put_by_id);
     1296    instructions().append(base->index());
     1297    instructions().append(addConstant(property));
     1298    instructions().append(value->index());
     1299    instructions().append(0);
     1300    instructions().append(0);
     1301    instructions().append(0);
     1302    instructions().append(0);
     1303    instructions().append(property != m_globalData->propertyNames->underscoreProto);
    12831304    return value;
    12841305}
  • trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r61430 r62896  
    329329        RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
    330330        RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value);
     331        RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value);
    331332        RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&);
    332333        RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
  • trunk/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r61623 r62896  
    267267        switch (p->m_node->m_type) {
    268268            case PropertyNode::Constant: {
    269                 generator.emitPutById(newObj.get(), p->m_node->name(), value);
     269                generator.emitDirectPutById(newObj.get(), p->m_node->name(), value);
    270270                break;
    271271            }
  • trunk/JavaScriptCore/interpreter/Interpreter.cpp

    r62766 r62896  
    29032903    }
    29042904    DEFINE_OPCODE(op_put_by_id) {
    2905         /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
     2905        /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n) direct(b)
    29062906
    29072907           Generic property access: Sets the property named by identifier
     
    29102910           Unlike many opcodes, this one does not write any output to
    29112911           the register file.
     2912
     2913           The "direct" flag should only be set this put_by_id is to initialize
     2914           an object literal.
    29122915        */
    29132916
     
    29152918        int property = vPC[2].u.operand;
    29162919        int value = vPC[3].u.operand;
     2920        int direct = vPC[8].u.operand;
    29172921
    29182922        JSValue baseValue = callFrame->r(base).jsValue();
    29192923        Identifier& ident = codeBlock->identifier(property);
    29202924        PutPropertySlot slot;
    2921         baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
     2925        if (direct) {
     2926            baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot);
     2927            ASSERT(slot.base() == baseValue);
     2928        } else
     2929            baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
    29222930        CHECK_FOR_EXCEPTION();
    29232931
     
    29282936    }
    29292937    DEFINE_OPCODE(op_put_by_id_transition) {
    2930         /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n)
     2938        /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n) direct(b)
    29312939         
    29322940           Cached property access: Attempts to set a new property with a cached transition
     
    29492957                ASSERT(baseCell->isObject());
    29502958                JSObject* baseObject = asObject(baseCell);
    2951 
    2952                 RefPtr<Structure>* it = vPC[6].u.structureChain->head();
    2953 
    2954                 JSValue proto = baseObject->structure()->prototypeForLookup(callFrame);
    2955                 while (!proto.isNull()) {
    2956                     if (UNLIKELY(asObject(proto)->structure() != (*it).get())) {
    2957                         uncachePutByID(codeBlock, vPC);
    2958                         NEXT_INSTRUCTION();
     2959                int direct = vPC[8].u.operand;
     2960               
     2961                if (direct) {
     2962                    RefPtr<Structure>* it = vPC[6].u.structureChain->head();
     2963
     2964                    JSValue proto = baseObject->structure()->prototypeForLookup(callFrame);
     2965                    while (!proto.isNull()) {
     2966                        if (UNLIKELY(asObject(proto)->structure() != (*it).get())) {
     2967                            uncachePutByID(codeBlock, vPC);
     2968                            NEXT_INSTRUCTION();
     2969                        }
     2970                        ++it;
     2971                        proto = asObject(proto)->structure()->prototypeForLookup(callFrame);
    29592972                    }
    2960                     ++it;
    2961                     proto = asObject(proto)->structure()->prototypeForLookup(callFrame);
    29622973                }
    2963 
    29642974                baseObject->transitionTo(newStructure);
    29652975
     
    29782988    }
    29792989    DEFINE_OPCODE(op_put_by_id_replace) {
    2980         /* op_put_by_id_replace base(r) property(id) value(r) structure(sID) offset(n) nop(n) nop(n)
     2990        /* op_put_by_id_replace base(r) property(id) value(r) structure(sID) offset(n) nop(n) nop(n) direct(b)
    29812991
    29822992           Cached property access: Attempts to set a pre-existing, cached
     
    30133023    }
    30143024    DEFINE_OPCODE(op_put_by_id_generic) {
    3015         /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
     3025        /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n) direct(b)
    30163026
    30173027           Generic property access: Sets the property named by identifier
     
    30243034        int property = vPC[2].u.operand;
    30253035        int value = vPC[3].u.operand;
     3036        int direct = vPC[8].u.operand;
    30263037
    30273038        JSValue baseValue = callFrame->r(base).jsValue();
    30283039        Identifier& ident = codeBlock->identifier(property);
    30293040        PutPropertySlot slot;
    3030         baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
     3041        if (direct) {
     3042            baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot);
     3043            ASSERT(slot.base() == baseValue);
     3044        } else
     3045            baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
    30313046        CHECK_FOR_EXCEPTION();
    30323047
  • trunk/JavaScriptCore/jit/JIT.h

    r60376 r62896  
    212212        }
    213213       
    214         static void compilePutByIdTransition(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress)
     214        static void compilePutByIdTransition(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress, bool direct)
    215215        {
    216216            JIT jit(globalData, codeBlock);
    217             jit.privateCompilePutByIdTransition(stubInfo, oldStructure, newStructure, cachedOffset, chain, returnAddress);
     217            jit.privateCompilePutByIdTransition(stubInfo, oldStructure, newStructure, cachedOffset, chain, returnAddress, direct);
    218218        }
    219219
     
    231231
    232232        static void patchGetByIdSelf(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress);
    233         static void patchPutByIdReplace(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress);
     233        static void patchPutByIdReplace(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress, bool direct);
    234234        static void patchMethodCallProto(CodeBlock* codeblock, MethodCallLinkInfo&, JSFunction*, Structure*, JSObject*, ReturnAddressPtr);
    235235
     
    267267        void privateCompileGetByIdChainList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, StructureChain* chain, size_t count, const Identifier&, const PropertySlot&, size_t cachedOffset, CallFrame* callFrame);
    268268        void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, const Identifier&, const PropertySlot&, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
    269         void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, ReturnAddressPtr returnAddress);
     269        void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, ReturnAddressPtr returnAddress, bool direct);
    270270
    271271        void privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* data, TrampolineStructure *trampolines);
  • trunk/JavaScriptCore/jit/JITPropertyAccess.cpp

    r59955 r62896  
    308308    Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
    309309    unsigned valueVReg = currentInstruction[3].u.operand;
     310    unsigned direct = currentInstruction[8].u.operand;
    310311
    311312    emitGetVirtualRegisters(baseVReg, regT0, valueVReg, regT1);
    312313
    313     JITStubCall stubCall(this, cti_op_put_by_id_generic);
     314    JITStubCall stubCall(this, direct ? cti_op_put_by_id_direct_generic, cti_op_put_by_id_generic);
    314315    stubCall.addArgument(regT0);
    315316    stubCall.addArgument(ImmPtr(ident));
     
    531532    unsigned baseVReg = currentInstruction[1].u.operand;
    532533    Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
     534    unsigned direct = currentInstruction[8].u.operand;
    533535
    534536    unsigned propertyAccessInstructionIndex = m_propertyAccessInstructionIndex++;
     
    537539    linkSlowCase(iter);
    538540
    539     JITStubCall stubCall(this, cti_op_put_by_id);
     541    JITStubCall stubCall(this, direct ? cti_op_put_by_id_direct : cti_op_put_by_id);
    540542    stubCall.addArgument(regT0);
    541543    stubCall.addArgument(ImmPtr(ident));
     
    591593}
    592594
    593 void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress)
     595void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress, bool direct)
    594596{
    595597    JumpList failureCases;
     
    600602
    601603    // ecx = baseObject->m_structure
    602     for (RefPtr<Structure>* it = chain->head(); *it; ++it)
    603         testPrototype(it->get(), failureCases);
     604    if (!direct) {
     605        for (RefPtr<Structure>* it = chain->head(); *it; ++it)
     606            testPrototype(it->get(), failureCases);
     607    }
    604608
    605609    Call callTarget;
     
    642646    LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
    643647
    644     patchBuffer.link(failureCall, FunctionPtr(cti_op_put_by_id_fail));
     648    patchBuffer.link(failureCall, FunctionPtr(direct ? cti_op_put_by_id_direct_fail : cti_op_put_by_id_fail));
    645649
    646650    if (willNeedStorageRealloc) {
     
    695699}
    696700
    697 void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress)
     701void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress, bool direct)
    698702{
    699703    RepatchBuffer repatchBuffer(codeBlock);
     
    701705    // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
    702706    // Should probably go to cti_op_put_by_id_fail, but that doesn't do anything interesting right now.
    703     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_put_by_id_generic));
     707    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
    704708
    705709    int offset = sizeof(JSValue) * cachedOffset;
  • trunk/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r61830 r62896  
    532532    int base = currentInstruction[1].u.operand;
    533533    int ident = currentInstruction[2].u.operand;
    534    
     534    int direct = currentInstruction[8].u.operand;
     535
    535536    linkSlowCaseIfNotJSCell(iter, base);
    536537    linkSlowCase(iter);
    537538   
    538     JITStubCall stubCall(this, cti_op_put_by_id);
     539    JITStubCall stubCall(this, direct ? cti_op_put_by_id_direct : cti_op_put_by_id);
    539540    stubCall.addArgument(regT1, regT0);
    540541    stubCall.addArgument(ImmPtr(&(m_codeBlock->identifier(ident))));
     
    593594}
    594595
    595 void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress)
     596void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress, bool direct)
    596597{
    597598    // It is assumed that regT0 contains the basePayload and regT1 contains the baseTag.  The value can be found on the stack.
     
    602603    testPrototype(oldStructure, failureCases);
    603604   
    604     // Verify that nothing in the prototype chain has a setter for this property.
    605     for (RefPtr<Structure>* it = chain->head(); *it; ++it)
    606         testPrototype(it->get(), failureCases);
    607    
     605    if (!direct) {
     606        // Verify that nothing in the prototype chain has a setter for this property.
     607        for (RefPtr<Structure>* it = chain->head(); *it; ++it)
     608            testPrototype(it->get(), failureCases);
     609    }
     610
    608611    // Reallocate property storage if needed.
    609612    Call callTarget;
     
    644647    LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
    645648   
    646     patchBuffer.link(failureCall, FunctionPtr(cti_op_put_by_id_fail));
     649    patchBuffer.link(failureCall, FunctionPtr(direct ? cti_op_put_by_id_direct_fail : cti_op_put_by_id_fail));
    647650   
    648651    if (willNeedStorageRealloc) {
     
    698701}
    699702
    700 void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress)
     703void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress, bool direct)
    701704{
    702705    RepatchBuffer repatchBuffer(codeBlock);
     
    704707    // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
    705708    // Should probably go to cti_op_put_by_id_fail, but that doesn't do anything interesting right now.
    706     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_put_by_id_generic));
     709    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
    707710   
    708711    int offset = sizeof(JSValue) * cachedOffset;
  • trunk/JavaScriptCore/jit/JITStubs.cpp

    r62432 r62896  
    845845#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
    846846
    847 NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo)
     847NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo, bool direct)
    848848{
    849849    // The interpreter checks for recursion here; I do not believe this can occur in CTI.
     
    854854    // Uncacheable: give up.
    855855    if (!slot.isCacheable()) {
    856         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
     856        ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
    857857        return;
    858858    }
     
    862862
    863863    if (structure->isUncacheableDictionary()) {
    864         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
     864        ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
    865865        return;
    866866    }
     
    868868    // If baseCell != base, then baseCell must be a proxy for another object.
    869869    if (baseCell != slot.base()) {
    870         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
     870        ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
    871871        return;
    872872    }
     
    877877    if (slot.type() == PutPropertySlot::NewProperty) {
    878878        if (structure->isDictionary()) {
    879             ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
     879            ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
    880880            return;
    881881        }
     
    886886        StructureChain* prototypeChain = structure->prototypeChain(callFrame);
    887887        stubInfo->initPutByIdTransition(structure->previousID(), structure, prototypeChain);
    888         JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress);
     888        JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress, direct);
    889889        return;
    890890    }
     
    892892    stubInfo->initPutByIdReplace(structure);
    893893
    894     JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
     894    JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress, direct);
    895895}
    896896
     
    13451345}
    13461346
     1347DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_generic)
     1348{
     1349    STUB_INIT_STACK_FRAME(stackFrame);
     1350   
     1351    PutPropertySlot slot;
     1352    stackFrame.args[0].jsValue().putDirect(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
     1353    CHECK_FOR_EXCEPTION_AT_END();
     1354}
     1355
    13471356DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_generic)
    13481357{
     
    13671376    CallFrame* callFrame = stackFrame.callFrame;
    13681377    Identifier& ident = stackFrame.args[1].identifier();
    1369 
     1378   
    13701379    PutPropertySlot slot;
    13711380    stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
    1372 
     1381   
    13731382    CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
    13741383    StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
     
    13761385        stubInfo->setSeen();
    13771386    else
    1378         JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo);
    1379 
     1387        JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, false);
     1388   
     1389    CHECK_FOR_EXCEPTION_AT_END();
     1390}
     1391
     1392DEFINE_STUB_FUNCTION(void, op_put_by_id_direct)
     1393{
     1394    STUB_INIT_STACK_FRAME(stackFrame);
     1395    CallFrame* callFrame = stackFrame.callFrame;
     1396    Identifier& ident = stackFrame.args[1].identifier();
     1397   
     1398    PutPropertySlot slot;
     1399    stackFrame.args[0].jsValue().putDirect(callFrame, ident, stackFrame.args[2].jsValue(), slot);
     1400   
     1401    CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
     1402    StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
     1403    if (!stubInfo->seenOnce())
     1404        stubInfo->setSeen();
     1405    else
     1406        JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, true);
     1407   
    13801408    CHECK_FOR_EXCEPTION_AT_END();
    13811409}
     
    13911419    stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
    13921420
     1421    CHECK_FOR_EXCEPTION_AT_END();
     1422}
     1423
     1424DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_fail)
     1425{
     1426    STUB_INIT_STACK_FRAME(stackFrame);
     1427   
     1428    CallFrame* callFrame = stackFrame.callFrame;
     1429    Identifier& ident = stackFrame.args[1].identifier();
     1430   
     1431    PutPropertySlot slot;
     1432    stackFrame.args[0].jsValue().putDirect(callFrame, ident, stackFrame.args[2].jsValue(), slot);
     1433   
    13931434    CHECK_FOR_EXCEPTION_AT_END();
    13941435}
  • trunk/JavaScriptCore/jit/JITStubs.h

    r60631 r62896  
    258258
    259259        static void tryCacheGetByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot&, StructureStubInfo* stubInfo);
    260         static void tryCachePutByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot&, StructureStubInfo* stubInfo);
     260        static void tryCachePutByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot&, StructureStubInfo* stubInfo, bool direct);
    261261
    262262        MacroAssemblerCodePtr ctiStringLengthTrampoline() { return m_trampolineStructure.ctiStringLengthTrampoline; }
     
    379379    void JIT_STUB cti_op_put_by_id_fail(STUB_ARGS_DECLARATION);
    380380    void JIT_STUB cti_op_put_by_id_generic(STUB_ARGS_DECLARATION);
     381    void JIT_STUB cti_op_put_by_id_direct(STUB_ARGS_DECLARATION);
     382    void JIT_STUB cti_op_put_by_id_direct_fail(STUB_ARGS_DECLARATION);
     383    void JIT_STUB cti_op_put_by_id_direct_generic(STUB_ARGS_DECLARATION);
    381384    void JIT_STUB cti_op_put_by_index(STUB_ARGS_DECLARATION);
    382385    void JIT_STUB cti_op_put_by_val(STUB_ARGS_DECLARATION);
  • trunk/JavaScriptCore/runtime/JSObject.h

    r60762 r62896  
    178178        void putDirect(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
    179179        void putDirect(const Identifier& propertyName, JSValue value, unsigned attr = 0);
     180        void putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot&);
    180181
    181182        void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr = 0);
     
    591592}
    592593
     594inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
     595{
     596    putDirectInternal(propertyName, value, 0, false, slot, 0);
     597}
     598
    593599inline void JSObject::putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
    594600{
     
    693699}
    694700
     701inline void JSValue::putDirect(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
     702{
     703    ASSERT(isCell() && isObject());
     704    asObject(asCell())->putDirect(propertyName, value, slot);
     705}
     706
    695707inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value)
    696708{
  • trunk/JavaScriptCore/runtime/JSValue.h

    r60631 r62896  
    182182        JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const;
    183183        void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
     184        void putDirect(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
    184185        void put(ExecState*, unsigned propertyName, JSValue);
    185186
  • trunk/LayoutTests/ChangeLog

    r62894 r62896  
     12010-07-08  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Sam Weinig.
     4
     5        Property declarations in an object literal should not consider the prototype chain when being added to the new object
     6        https://bugs.webkit.org/show_bug.cgi?id=41929
     7
     8        Add tests to ensure correct behaviour of object literals when there
     9        are setters on the prototype chain.
     10
     11        * fast/js/object-literal-direct-put-expected.txt: Added.
     12        * fast/js/object-literal-direct-put.html: Added.
     13        * fast/js/script-tests/object-literal-direct-put.js: Added.
     14        * ietestcenter/Javascript/15.4.4.14-9-b-i-6-expected.txt:
     15        * ietestcenter/Javascript/15.4.4.15-8-b-i-6-expected.txt:
     16        * platform/chromium/test_expectations.txt:
     17
    1182010-07-08  Simon Fraser  <simon.fraser@apple.com>
    219
  • trunk/LayoutTests/ietestcenter/Javascript/15.4.4.14-9-b-i-6-expected.txt

    r62810 r62896  
    55
    66PASS ES5Harness.preconditionPassed is true
    7 FAIL ES5Harness.testPassed should be true. Was false.
     7PASS ES5Harness.testPassed is true
    88PASS successfullyParsed is true
    99
  • trunk/LayoutTests/ietestcenter/Javascript/15.4.4.15-8-b-i-6-expected.txt

    r62810 r62896  
    55
    66PASS ES5Harness.preconditionPassed is true
    7 FAIL ES5Harness.testPassed should be true. Was false.
     7PASS ES5Harness.testPassed is true
    88PASS successfullyParsed is true
    99
  • trunk/LayoutTests/platform/chromium/test_expectations.txt

    r62870 r62896  
    30053005BUGAWONG WIN LINUX MAC : ietestcenter/Javascript/15.4.4.14-4-9.html = TEXT
    30063006BUGAWONG WIN LINUX MAC : ietestcenter/Javascript/15.4.4.14-9-a-12.html = TEXT
     3007BUGAWONG WIN LINUX MAC : ietestcenter/Javascript/15.4.4.14-9-b-i-6.html = TEXT
    30073008BUGAWONG WIN LINUX MAC : ietestcenter/Javascript/15.4.4.15-3-12.html = TEXT
    30083009BUGAWONG WIN LINUX MAC : ietestcenter/Javascript/15.4.4.15-3-13.html = TEXT
     
    30203021BUGAWONG WIN LINUX MAC : ietestcenter/Javascript/15.4.4.15-8-9.html = TEXT
    30213022BUGAWONG WIN LINUX MAC : ietestcenter/Javascript/15.4.4.15-8-a-12.html = TEXT
     3023BUGAWONG WIN LINUX MAC : ietestcenter/Javascript/15.4.4.15-8-b-i-6.html = TEXT
    30223024BUGAWONG WIN LINUX MAC : ietestcenter/Javascript/15.5.4.20-4-10.html = TEXT
    30233025BUGAWONG WIN LINUX MAC : ietestcenter/Javascript/15.5.4.20-4-18.html = TEXT
     
    30463048// Likely from r62862. Probably just needs rebaseline.
    30473049BUGAWONG WIN LINUX MAC : fast/js/no-semi-insertion-at-end-of-script.html = TEXT
     3050BUGAWONG WIN LINUX MAC : fast/js/object-literal-direct-put.html = TEXT
Note: See TracChangeset for help on using the changeset viewer.