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:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@36417
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
virtual bool deleteProperty(ExecState*, unsigned);
virtual bool implementsHasInstance() const;
- virtual bool hasInstance(ExecState *exec, JSValue *value);
+ virtual bool hasInstance(ExecState* exec, JSValue* value, JSValue* proto);
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
}
template <class Base>
-bool JSCallbackObject<Base>::hasInstance(ExecState *exec, JSValue *value)
+bool JSCallbackObject<Base>::hasInstance(ExecState* exec, JSValue* value, JSValue*)
{
JSContextRef execRef = toRef(exec);
JSObjectRef thisRef = toRef(this);
JSObject* jsConstructor = toJS(constructor);
if (!jsConstructor->implementsHasInstance())
return false;
- bool result = jsConstructor->hasInstance(exec, jsValue); // false if an exception is thrown
+ bool result = jsConstructor->hasInstance(exec, jsValue, jsConstructor->get(exec, exec->propertyNames().prototype)); // false if an exception is thrown
if (exec->hadException()) {
if (exception)
*exception = toRef(exec->exception());
+2008-09-14 Maciej Stachowiak <mjs@apple.com>
+
+ 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:
+
2008-09-14 Gavin Barraclough <barraclough@apple.com>
Reviewed by Sam Weinig.
__ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE
__ZN3JSC8DebuggerC2Ev
__ZN3JSC8DebuggerD2Ev
-__ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateEPNS_7JSValueE
+__ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateEPNS_7JSValueES4_
__ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
__ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
__ZN3JSC8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE
case op_instanceof: {
emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
+ emitGetPutArg(instruction[i + 4].u.operand, 8, X86::ecx);
emitCall(i, Machine::cti_op_instanceof);
emitPutResult(instruction[i + 1].u.operand);
- i += 4;
+ i += 5;
break;
}
case op_del_by_id: {
break;
}
case op_instanceof: {
- printBinaryOp(location, it, "instanceof");
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int r2 = (++it)->u.operand;
+ int r3 = (++it)->u.operand;
+ 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());
break;
}
case op_typeof: {
return true;
}
+RegisterID* CodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype)
+{
+ emitOpcode(op_instanceof);
+ instructions().append(dst->index());
+ instructions().append(value->index());
+ instructions().append(base->index());
+ instructions().append(basePrototype->index());
+ return dst;
+}
+
RegisterID* CodeGenerator::emitResolve(RegisterID* dst, const Identifier& property)
{
size_t depth = 0;
RegisterID* emitPostInc(RegisterID* dst, RegisterID* srcDst);
RegisterID* emitPostDec(RegisterID* dst, RegisterID* srcDst);
- RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base) { return emitBinaryOp(op_instanceof, dst, value, base); }
+ RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype);
RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); }
RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base); }
NEXT_OPCODE;
}
BEGIN_OPCODE(op_instanceof) {
- /* instanceof dst(r) value(r) constructor(r)
+ /* instanceof dst(r) value(r) constructor(r) constructorProto(r)
Tests whether register value is an instance of register
- constructor, and puts the boolean result in register dst.
+ constructor, and puts the boolean result in register
+ dst. Register constructorProto must contain the "prototype"
+ property (not the actual prototype) of the object in
+ register constructor. This lookup is separated so that
+ polymorphic inline caching can apply.
Raises an exception if register constructor is not an
object.
int dst = (++vPC)->u.operand;
int value = (++vPC)->u.operand;
int base = (++vPC)->u.operand;
+ int baseProto = (++vPC)->u.operand;
JSValue* baseVal = r[base].jsValue(exec);
goto vm_throw;
JSObject* baseObj = static_cast<JSObject*>(baseVal);
- r[dst] = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec, r[value].jsValue(exec)) : false);
+ r[dst] = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec, r[value].jsValue(exec), r[baseProto].jsValue(exec)) : false);
++vPC;
NEXT_OPCODE;
}
JSObject* baseObj = static_cast<JSObject*>(baseVal);
- JSValue* result = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec, ARG_src1) : false);
+ JSValue* basePrototype = ARG_src3;
+ JSValue* result = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec, ARG_src1, basePrototype) : false);
VM_CHECK_EXCEPTION_AT_END();
return result;
}
return false;
}
-bool JSObject::hasInstance(ExecState* exec, JSValue* value)
+bool JSObject::hasInstance(ExecState* exec, JSValue* value, JSValue* proto)
{
- JSValue* proto = get(exec, exec->propertyNames().prototype);
if (!proto->isObject()) {
throwError(exec, TypeError, "instanceof called on an object with an invalid prototype property.");
return false;
virtual JSValue* defaultValue(ExecState*, PreferredPrimitiveType) const;
virtual bool implementsHasInstance() const;
- virtual bool hasInstance(ExecState*, JSValue*);
+ virtual bool hasInstance(ExecState*, JSValue*, JSValue* prototypeProperty);
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src1.get(), src2);
}
+RegisterID* InstanceOfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
+ RefPtr<RegisterID> src2 = generator.emitNode(m_expr2.get());
+ RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalExec()->propertyNames().prototype);
+ generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
+ return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype);
+}
+
// ------------------------------ Binary Logical Nodes ----------------------------
RegisterID* LogicalOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_instanceof; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecRelational; }
+
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
};
class InNode : public ThrowableBinaryOpNode {