Changeset 36417 in webkit for trunk/JavaScriptCore


Ignore:
Timestamp:
Sep 14, 2008, 7:13:10 PM (17 years ago)
Author:
[email protected]
Message:

2008-09-14 Maciej Stachowiak <[email protected]>

Reviewed by Cameron Zwarich.


  • split the "prototype" lookup for hasInstance into opcode stream so it can be cached


~5% speedup on v8 earley-boyer test

  • API/JSCallbackObject.h: Add a parameter for the pre-looked-up prototype.
  • API/JSCallbackObjectFunctions.h: (JSC::::hasInstance): Ditto.
  • API/JSValueRef.cpp: (JSValueIsInstanceOfConstructor): Look up and pass in prototype.
  • JavaScriptCore.exp:
  • VM/CTI.cpp: (JSC::CTI::privateCompileMainPass): Pass along prototype.
  • VM/CodeBlock.cpp: (JSC::CodeBlock::dump): Print third arg.
  • VM/CodeGenerator.cpp: (JSC::CodeGenerator::emitInstanceOf): Implement this, now that there is a third argument.
  • VM/CodeGenerator.h:
  • VM/Machine.cpp: (JSC::Machine::privateExecute): Pass along the prototype. (JSC::Machine::cti_op_instanceof): ditto
  • kjs/JSObject.cpp: (JSC::JSObject::hasInstance): Expect to get a pre-looked-up prototype.
  • kjs/JSObject.h:
  • kjs/nodes.cpp: (JSC::InstanceOfNode::emitCode): Emit a get_by_id of the prototype property and pass that register to instanceof.
  • kjs/nodes.h:
Location:
trunk/JavaScriptCore
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/API/JSCallbackObject.h

    r36263 r36417  
    6161
    6262    virtual bool implementsHasInstance() const;
    63     virtual bool hasInstance(ExecState *exec, JSValue *value);
     63    virtual bool hasInstance(ExecState* exec, JSValue* value, JSValue* proto);
    6464
    6565    virtual void getPropertyNames(ExecState*, PropertyNameArray&);
  • trunk/JavaScriptCore/API/JSCallbackObjectFunctions.h

    r36263 r36417  
    284284
    285285template <class Base>
    286 bool JSCallbackObject<Base>::hasInstance(ExecState *exec, JSValue *value)
     286bool JSCallbackObject<Base>::hasInstance(ExecState* exec, JSValue* value, JSValue*)
    287287{
    288288    JSContextRef execRef = toRef(exec);
  • trunk/JavaScriptCore/API/JSValueRef.cpp

    r36263 r36417  
    147147    if (!jsConstructor->implementsHasInstance())
    148148        return false;
    149     bool result = jsConstructor->hasInstance(exec, jsValue); // false if an exception is thrown
     149    bool result = jsConstructor->hasInstance(exec, jsValue, jsConstructor->get(exec, exec->propertyNames().prototype)); // false if an exception is thrown
    150150    if (exec->hadException()) {
    151151        if (exception)
  • trunk/JavaScriptCore/ChangeLog

    r36413 r36417  
     12008-09-14  Maciej Stachowiak  <[email protected]>
     2
     3        Reviewed by Cameron Zwarich.
     4       
     5        - split the "prototype" lookup for hasInstance into opcode stream so it can be cached
     6       
     7        ~5% speedup on v8 earley-boyer test
     8
     9        * API/JSCallbackObject.h: Add a parameter for the pre-looked-up prototype.
     10        * API/JSCallbackObjectFunctions.h:
     11        (JSC::::hasInstance): Ditto.
     12        * API/JSValueRef.cpp:
     13        (JSValueIsInstanceOfConstructor): Look up and pass in prototype.
     14        * JavaScriptCore.exp:
     15        * VM/CTI.cpp:
     16        (JSC::CTI::privateCompileMainPass): Pass along prototype.
     17        * VM/CodeBlock.cpp:
     18        (JSC::CodeBlock::dump): Print third arg.
     19        * VM/CodeGenerator.cpp:
     20        (JSC::CodeGenerator::emitInstanceOf): Implement this, now that there
     21        is a third argument.
     22        * VM/CodeGenerator.h:
     23        * VM/Machine.cpp:
     24        (JSC::Machine::privateExecute): Pass along the prototype.
     25        (JSC::Machine::cti_op_instanceof): ditto
     26        * kjs/JSObject.cpp:
     27        (JSC::JSObject::hasInstance): Expect to get a pre-looked-up prototype.
     28        * kjs/JSObject.h:
     29        * kjs/nodes.cpp:
     30        (JSC::InstanceOfNode::emitCode): Emit a get_by_id of the prototype
     31        property and pass that register to instanceof.
     32        * kjs/nodes.h:
     33
    1342008-09-14  Gavin Barraclough  <[email protected]>
    235
  • trunk/JavaScriptCore/JavaScriptCore.exp

    r36368 r36417  
    217217__ZN3JSC8DebuggerC2Ev
    218218__ZN3JSC8DebuggerD2Ev
    219 __ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateEPNS_7JSValueE
     219__ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateEPNS_7JSValueES4_
    220220__ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
    221221__ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
  • trunk/JavaScriptCore/VM/CTI.cpp

    r36412 r36417  
    631631            emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
    632632            emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
     633            emitGetPutArg(instruction[i + 4].u.operand, 8, X86::ecx);
    633634            emitCall(i, Machine::cti_op_instanceof);
    634635            emitPutResult(instruction[i + 1].u.operand);
    635             i += 4;
     636            i += 5;
    636637            break;
    637638        }
  • trunk/JavaScriptCore/VM/CodeBlock.cpp

    r36412 r36417  
    489489        }
    490490        case op_instanceof: {
    491             printBinaryOp(location, it, "instanceof");
     491            int r0 = (++it)->u.operand;
     492            int r1 = (++it)->u.operand;
     493            int r2 = (++it)->u.operand;
     494            int r3 = (++it)->u.operand;
     495            printf("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), registerName(r3).c_str());
    492496            break;
    493497        }
  • trunk/JavaScriptCore/VM/CodeGenerator.cpp

    r36412 r36417  
    806806}
    807807
     808RegisterID* CodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype)
     809{
     810    emitOpcode(op_instanceof);
     811    instructions().append(dst->index());
     812    instructions().append(value->index());
     813    instructions().append(base->index());
     814    instructions().append(basePrototype->index());
     815    return dst;
     816}
     817
    808818RegisterID* CodeGenerator::emitResolve(RegisterID* dst, const Identifier& property)
    809819{
  • trunk/JavaScriptCore/VM/CodeGenerator.h

    r36412 r36417  
    253253        RegisterID* emitPostDec(RegisterID* dst, RegisterID* srcDst);
    254254
    255         RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base) { return emitBinaryOp(op_instanceof, dst, value, base); }
     255        RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype);
    256256        RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); }
    257257        RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base); }
  • trunk/JavaScriptCore/VM/Machine.cpp

    r36413 r36417  
    20382038    }
    20392039    BEGIN_OPCODE(op_instanceof) {
    2040         /* instanceof dst(r) value(r) constructor(r)
     2040        /* instanceof dst(r) value(r) constructor(r) constructorProto(r)
    20412041
    20422042           Tests whether register value is an instance of register
    2043            constructor, and puts the boolean result in register dst.
     2043           constructor, and puts the boolean result in register
     2044           dst. Register constructorProto must contain the "prototype"
     2045           property (not the actual prototype) of the object in
     2046           register constructor. This lookup is separated so that
     2047           polymorphic inline caching can apply.
    20442048
    20452049           Raises an exception if register constructor is not an
     
    20492053        int value = (++vPC)->u.operand;
    20502054        int base = (++vPC)->u.operand;
     2055        int baseProto = (++vPC)->u.operand;
    20512056
    20522057        JSValue* baseVal = r[base].jsValue(exec);
     
    20562061
    20572062        JSObject* baseObj = static_cast<JSObject*>(baseVal);
    2058         r[dst] = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec, r[value].jsValue(exec)) : false);
     2063        r[dst] = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec, r[value].jsValue(exec), r[baseProto].jsValue(exec)) : false);
    20592064
    20602065        ++vPC;
     
    41774182
    41784183    JSObject* baseObj = static_cast<JSObject*>(baseVal);
    4179     JSValue* result = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec,  ARG_src1) : false);
     4184    JSValue* basePrototype = ARG_src3;
     4185    JSValue* result = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec,  ARG_src1, basePrototype) : false);
    41804186    VM_CHECK_EXCEPTION_AT_END();
    41814187    return result;
  • trunk/JavaScriptCore/kjs/JSObject.cpp

    r36368 r36417  
    390390}
    391391
    392 bool JSObject::hasInstance(ExecState* exec, JSValue* value)
    393 {
    394     JSValue* proto = get(exec, exec->propertyNames().prototype);
     392bool JSObject::hasInstance(ExecState* exec, JSValue* value, JSValue* proto)
     393{
    395394    if (!proto->isObject()) {
    396395        throwError(exec, TypeError, "instanceof called on an object with an invalid prototype property.");
  • trunk/JavaScriptCore/kjs/JSObject.h

    r36401 r36417  
    106106
    107107        virtual bool implementsHasInstance() const;
    108         virtual bool hasInstance(ExecState*, JSValue*);
     108        virtual bool hasInstance(ExecState*, JSValue*, JSValue* prototypeProperty);
    109109
    110110        virtual void getPropertyNames(ExecState*, PropertyNameArray&);
  • trunk/JavaScriptCore/kjs/nodes.cpp

    r36412 r36417  
    793793    generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
    794794    return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src1.get(), src2);
     795}
     796
     797RegisterID* InstanceOfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
     798{
     799    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
     800    RefPtr<RegisterID> src2 = generator.emitNode(m_expr2.get());
     801    RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalExec()->propertyNames().prototype);
     802    generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
     803    return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype);
    795804}
    796805
  • trunk/JavaScriptCore/kjs/nodes.h

    r36412 r36417  
    14281428        virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
    14291429        virtual Precedence precedence() const { return PrecRelational; }
     1430
     1431        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
    14301432    };
    14311433
Note: See TracChangeset for help on using the changeset viewer.