Changeset 62896 in webkit for trunk/JavaScriptCore/interpreter


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/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
Note: See TracChangeset for help on using the changeset viewer.