Changeset 49004 in webkit for trunk/JavaScriptCore


Ignore:
Timestamp:
Oct 1, 2009, 4:32:48 PM (16 years ago)
Author:
[email protected]
Message:

Take one branch instead of two to test for JSValue().

Patch by Geoffrey Garen <[email protected]> on 2009-10-01
Reviewed by Sam Weinig.

1.1% SunSpider speedup.

  • jit/JITCall.cpp:

(JSC::JIT::compileOpCall):

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_to_jsnumber):
(JSC::JIT::emit_op_create_arguments):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emitSlow_op_get_by_val):
(JSC::JIT::emit_op_put_by_val): Test for the empty value tag, instead
of testing for the cell tag with a 0 payload.

  • runtime/JSValue.cpp:

(JSC::JSValue::description): Added support for dumping the new empty value,
and deleted values, in debug builds.

  • runtime/JSValue.h:

(JSC::JSValue::JSValue()): Construct JSValue() with the empty value tag.

(JSC::JSValue::JSValue(JSCell*)): Convert null pointer to the empty value
tag, to avoid having two different c++ versions of null / empty.

(JSC::JSValue::operator bool): Test for the empty value tag, instead
of testing for the cell tag with a 0 payload.

Location:
trunk/JavaScriptCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r48988 r49004  
     12009-10-01  Geoffrey Garen  <[email protected]>
     2
     3        Reviewed by Sam Weinig.
     4
     5        Take one branch instead of two to test for JSValue().
     6       
     7        1.1% SunSpider speedup.
     8
     9        * jit/JITCall.cpp:
     10        (JSC::JIT::compileOpCall):
     11        * jit/JITOpcodes.cpp:
     12        (JSC::JIT::emit_op_to_jsnumber):
     13        (JSC::JIT::emit_op_create_arguments):
     14        * jit/JITPropertyAccess.cpp:
     15        (JSC::JIT::emitSlow_op_get_by_val):
     16        (JSC::JIT::emit_op_put_by_val): Test for the empty value tag, instead
     17        of testing for the cell tag with a 0 payload.
     18
     19        * runtime/JSValue.cpp:
     20        (JSC::JSValue::description): Added support for dumping the new empty value,
     21        and deleted values, in debug builds.
     22
     23        * runtime/JSValue.h:
     24        (JSC::JSValue::JSValue()): Construct JSValue() with the empty value tag.
     25
     26        (JSC::JSValue::JSValue(JSCell*)): Convert null pointer to the empty value
     27        tag, to avoid having two different c++ versions of null / empty.
     28
     29        (JSC::JSValue::operator bool): Test for the empty value tag, instead
     30        of testing for the cell tag with a 0 payload.
     31
    1322009-10-01  Yongjun Zhang  <[email protected]>
    233
  • trunk/JavaScriptCore/jit/JITCall.cpp

    r47614 r49004  
    237237    int registerOffset = instruction[4].u.operand;
    238238
    239     Jump wasEval1;
    240     Jump wasEval2;
     239    Jump wasEval;
    241240    if (opcodeID == op_call_eval) {
    242241        JITStubCall stubCall(this, cti_op_call_eval);
     
    245244        stubCall.addArgument(JIT::Imm32(argCount));
    246245        stubCall.call();
    247         wasEval1 = branchTest32(NonZero, regT0);
    248         wasEval2 = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
     246        wasEval = branch32(Equal, regT1, Imm32(JSValue::EmptyValueTag));
    249247    }
    250248
     
    272270    emitNakedCall(m_globalData->jitStubs.ctiVirtualCall());
    273271
    274     if (opcodeID == op_call_eval) {
    275         wasEval1.link(this);
    276         wasEval2.link(this);
    277     }
     272    if (opcodeID == op_call_eval)
     273        wasEval.link(this);
    278274
    279275    emitStore(dst, regT1, regT0);;
     
    307303    int registerOffset = instruction[4].u.operand;
    308304
    309     Jump wasEval1;
    310     Jump wasEval2;
     305    Jump wasEval;
    311306    if (opcodeID == op_call_eval) {
    312307        JITStubCall stubCall(this, cti_op_call_eval);
     
    315310        stubCall.addArgument(JIT::Imm32(argCount));
    316311        stubCall.call();
    317         wasEval1 = branchTest32(NonZero, regT0);
    318         wasEval2 = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
     312        wasEval = branch32(NotEqual, regT1, Imm32(JSValue::EmptyValueTag));
    319313    }
    320314
     
    360354    m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall();
    361355   
    362     if (opcodeID == op_call_eval) {
    363         wasEval1.link(this);
    364         wasEval2.link(this);
    365     }
     356    if (opcodeID == op_call_eval)
     357        wasEval.link(this);
    366358
    367359    // Put the return value in dst. In the interpreter, op_ret does this.
  • trunk/JavaScriptCore/jit/JITOpcodes.cpp

    r48830 r49004  
    249249
    250250    // Check for an exception
    251     // FIXME: Maybe we can optimize this comparison to JSValue().
    252251    move(ImmPtr(&globalData->exception), regT2);
    253     Jump sawException1 = branch32(NotEqual, tagFor(0, regT2), Imm32(JSValue::CellTag));
    254     Jump sawException2 = branch32(NonZero, payloadFor(0, regT2), Imm32(0));
     252    Jump sawException = branch32(NotEqual, tagFor(0, regT2), Imm32(JSValue::EmptyValueTag));
    255253
    256254    // Grab the return address.
     
    265263
    266264    // Handle an exception
    267     sawException1.link(this);
    268     sawException2.link(this);
     265    sawException.link(this);
    269266    // Grab the return address.
    270267    emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
     
    12381235
    12391236    Jump isInt32 = branch32(Equal, regT1, Imm32(JSValue::Int32Tag));
    1240     addSlowCase(branch32(AboveOrEqual, regT1, Imm32(JSValue::DeletedValueTag)));
     1237    addSlowCase(branch32(AboveOrEqual, regT1, Imm32(JSValue::EmptyValueTag)));
    12411238    isInt32.link(this);
    12421239
     
    13821379void JIT::emit_op_create_arguments(Instruction*)
    13831380{
    1384     Jump argsNotCell = branch32(NotEqual, tagFor(RegisterFile::ArgumentsRegister, callFrameRegister), Imm32(JSValue::CellTag));
    1385     Jump argsNotNull = branchTestPtr(NonZero, payloadFor(RegisterFile::ArgumentsRegister, callFrameRegister));
     1381    Jump argsCreated = branch32(NotEqual, tagFor(RegisterFile::ArgumentsRegister, callFrameRegister), Imm32(JSValue::EmptyValueTag));
    13861382
    13871383    // If we get here the arguments pointer is a null cell - i.e. arguments need lazy creation.
     
    13911387        JITStubCall(this, cti_op_create_arguments).call();
    13921388
    1393     argsNotCell.link(this);
    1394     argsNotNull.link(this);
     1389    argsCreated.link(this);
    13951390}
    13961391   
  • trunk/JavaScriptCore/jit/JITPropertyAccess.cpp

    r47614 r49004  
    311311    load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4), regT1); // tag
    312312    load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT0); // payload
    313 
    314     // FIXME: Maybe we can optimize this comparison to JSValue().
    315     Jump skip = branch32(NotEqual, regT0, Imm32(0));
    316     branch32(Equal, regT1, Imm32(JSValue::CellTag), callGetByValJITStub);
    317 
    318     skip.link(this);
     313    branch32(Equal, regT1, Imm32(JSValue::EmptyValueTag)).linkTo(callGetByValJITStub, this);
     314
    319315    emitStore(dst, regT1, regT0);
    320316}
     
    334330
    335331    Jump inFastVector = branch32(Below, regT2, Address(regT0, OBJECT_OFFSETOF(JSArray, m_fastAccessCutoff)));
    336 
     332   
    337333    // Check if the access is within the vector.
    338334    addSlowCase(branch32(AboveOrEqual, regT2, Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_vectorLength))));
     
    340336    // This is a write to the slow part of the vector; first, we have to check if this would be the first write to this location.
    341337    // FIXME: should be able to handle initial write to array; increment the the number of items in the array, and potentially update fast access cutoff.
    342     Jump skip = branch32(NotEqual, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4), Imm32(JSValue::CellTag));
    343     addSlowCase(branch32(Equal, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), Imm32(0)));
    344     skip.link(this);
     338    addSlowCase(branch32(Equal, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4), Imm32(JSValue::EmptyValueTag)));
    345339
    346340    inFastVector.link(this);
  • trunk/JavaScriptCore/runtime/JSValue.cpp

    r46598 r49004  
    123123    else if (isNull())
    124124        snprintf(description, size, "Null");
     125    else if (isUndefined())
     126        snprintf(description, size, "Undefined");
     127    else if (tag() == EmptyValueTag)
     128        snprintf(description, size, "<JSValue()>");
    125129    else {
    126         ASSERT(isUndefined());
    127         snprintf(description, size, "Undefined");
     130        ASSERT(tag() == DeletedValueTag);
     131        snprintf(description, size, "<HashTableDeletedValue>");
    128132    }
    129133
  • trunk/JavaScriptCore/runtime/JSValue.h

    r48068 r49004  
    214214        enum { NullTag =         0xfffffffb };
    215215        enum { UndefinedTag =    0xfffffffa };
    216         enum { DeletedValueTag = 0xfffffff9 };
     216        enum { EmptyValueTag =   0xfffffff9 };
     217        enum { DeletedValueTag = 0xfffffff8 };
    217218
    218219        enum { LowestTag =  DeletedValueTag };
     
    428429    inline JSValue::JSValue()
    429430    {
    430         u.asBits.tag = CellTag;
     431        u.asBits.tag = EmptyValueTag;
    431432        u.asBits.payload = 0;
    432433    }
     
    464465    inline JSValue::JSValue(JSCell* ptr)
    465466    {
    466         u.asBits.tag = CellTag;
     467        if (ptr)
     468            u.asBits.tag = CellTag;
     469        else
     470            u.asBits.tag = EmptyValueTag;
    467471        u.asBits.payload = reinterpret_cast<int32_t>(ptr);
    468472    }
     
    470474    inline JSValue::JSValue(const JSCell* ptr)
    471475    {
    472         u.asBits.tag = CellTag;
     476        if (ptr)
     477            u.asBits.tag = CellTag;
     478        else
     479            u.asBits.tag = EmptyValueTag;
    473480        u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
    474481    }
     
    476483    inline JSValue::operator bool() const
    477484    {
    478         return u.asBits.payload || tag() != CellTag;
     485        ASSERT(tag() != DeletedValueTag);
     486        return tag() != EmptyValueTag;
    479487    }
    480488
Note: See TracChangeset for help on using the changeset viewer.