Ignore:
Timestamp:
Jul 8, 2010, 10:47:49 PM (15 years ago)
Author:
[email protected]
Message:

2010-07-08 Oliver Hunt <[email protected]>

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 <[email protected]>

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:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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;
Note: See TracChangeset for help on using the changeset viewer.