JavaScriptCore: https://bugs.webkit.org/show_bug.cgi?id=49606
Reviewed by Oliver Hunt.
The bug here is that we read the prototype from the RHS argument using a regular
op_get_by_id before op_instanceof has checked that this is an object implementing
HasInstance. This incorrect behaviour gives rise to further unnecessary complexity
in the code base, since we have additional logic (implemented using the
GetByIdExceptionInfo data structures on CodeBlock) to convert not an object errors
from the get_by_id into invalid parameter errors. Having fixed this bug this code
is all redundant, since in these cases the get_by_id will never have been reached.
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dump):
(JSC::CodeBlock::shrinkToFit):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::addExpressionInfo):
* bytecode/Opcode.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitCheckHasInstance):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::InstanceOfNode::emitBytecode):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::throwException):
(JSC::Interpreter::privateExecute):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_check_has_instance):
(JSC::JIT::emit_op_instanceof):
(JSC::JIT::emitSlow_op_check_has_instance):
(JSC::JIT::emitSlow_op_instanceof):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_check_has_instance):
(JSC::JIT::emit_op_instanceof):
(JSC::JIT::emitSlow_op_check_has_instance):
(JSC::JIT::emitSlow_op_instanceof):
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
* jit/JITStubs.h:
* runtime/ExceptionHelpers.cpp:
(JSC::createInterruptedExecutionException):
(JSC::createTerminatedExecutionException):
(JSC::createUndefinedVariableError):
(JSC::createNotAFunctionError):
(JSC::createNotAnObjectError):
* runtime/ExceptionHelpers.h:
* runtime/JSGlobalData.cpp:
(JSC::JSGlobalData::JSGlobalData):
* runtime/JSGlobalData.h:
* runtime/JSNotAnObject.cpp:
(JSC::JSNotAnObject::toPrimitive):
(JSC::JSNotAnObject::getPrimitiveNumber):
(JSC::JSNotAnObject::toBoolean):
(JSC::JSNotAnObject::toNumber):
(JSC::JSNotAnObject::toString):
(JSC::JSNotAnObject::toObject):
(JSC::JSNotAnObject::getOwnPropertySlot):
(JSC::JSNotAnObject::getOwnPropertyDescriptor):
(JSC::JSNotAnObject::put):
(JSC::JSNotAnObject::deleteProperty):
(JSC::JSNotAnObject::getOwnPropertyNames):
* runtime/JSNotAnObject.h:
(JSC::JSNotAnObject::JSNotAnObject):
* runtime/JSObject.h:
(JSC::JSObject::isActivationObject):
* runtime/JSValue.cpp:
(JSC::JSValue::toObjectSlowCase):
(JSC::JSValue::synthesizeObject):
(JSC::JSValue::synthesizePrototype):
LayoutTests: Bug 49606 - instanceof should only get the prototype property if the RHS operand implements HasInstance
Reviewed by Oliver Hunt.
* fast/js/instanceof-XMLHttpRequest-expected.txt: Copied from LayoutTests/fast/js/instanceof-operator-expected.txt.
* fast/js/instanceof-XMLHttpRequest.html: Copied from LayoutTests/fast/js/instanceof-operator.html.
* fast/js/script-tests/instanceof-XMLHttpRequest.js: Copied from LayoutTests/fast/js/script-tests/instanceof-operator.js.
- renamed existing testcase; these really test XMLHttpRequest objects, rather than the instanceof operator.
* fast/js/instanceof-operator-expected.txt:
* fast/js/script-tests/instanceof-operator.js:
- added test case for: javascript: ({} instanceof { get prototype(){ alert("Error!"); } })
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@72127 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index 203a2e8..1fa5aa4 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -443,7 +443,6 @@
emitOpcode(op_get_callee);
instructions().append(func->index());
// Load prototype.
- emitGetByIdExceptionInfo(op_create_this);
emitGetById(funcProto.get(), func.get(), globalData()->propertyNames->prototype);
emitOpcode(op_create_this);
@@ -1158,6 +1157,12 @@
return true;
}
+void BytecodeGenerator::emitCheckHasInstance(RegisterID* base)
+{
+ emitOpcode(op_check_has_instance);
+ instructions().append(base->index());
+}
+
RegisterID* BytecodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype)
{
emitOpcode(op_instanceof);
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index c00c156..499d232 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -268,17 +268,6 @@
m_codeBlock->addExpressionInfo(info);
}
- void emitGetByIdExceptionInfo(OpcodeID opcodeID)
- {
- // Only op_construct and op_instanceof need exception info for
- // a preceding op_get_by_id.
- ASSERT(opcodeID == op_create_this || opcodeID == op_instanceof);
- GetByIdExceptionInfo info;
- info.bytecodeOffset = instructions().size();
- info.isOpCreateThis = (opcodeID == op_create_this);
- m_codeBlock->addGetByIdExceptionInfo(info);
- }
-
ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure)
{
return (m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain() || rightHasAssignments) && !rightIsPure;
@@ -322,6 +311,7 @@
RegisterID* emitPostInc(RegisterID* dst, RegisterID* srcDst);
RegisterID* emitPostDec(RegisterID* dst, RegisterID* srcDst);
+ void emitCheckHasInstance(RegisterID* 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, OperandTypes()); }
diff --git a/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index d5adc8c..a850c96 100644
--- a/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -1016,7 +1016,9 @@
RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
generator.emitExpressionInfo(divot(), startOffset(), endOffset());
- generator.emitGetByIdExceptionInfo(op_instanceof);
+ generator.emitCheckHasInstance(src2.get());
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype);
generator.emitExpressionInfo(divot(), startOffset(), endOffset());