[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

barraclough at apple.com barraclough at apple.com
Wed Dec 22 15:55:47 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 8da6d9793081fa6e3ed1af7da10d6cf26fc18585
Author: barraclough at apple.com <barraclough at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Tue Nov 16 21:11:26 2010 +0000

    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/ChangeLog b/JavaScriptCore/ChangeLog
index 1f690bc..339aaaf 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,80 @@
+2010-11-16  Gavin Barraclough  <barraclough at apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        https://bugs.webkit.org/show_bug.cgi?id=49606
+
+        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):
+
 2010-11-15  Darin Adler  <darin at apple.com>
 
         Reviewed by Sam Weinig.
diff --git a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index b40d74e..a1e1c5c 100644
--- a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -2446,7 +2446,6 @@
 			isa = PBXProject;
 			buildConfigurationList = 149C277108902AFE008A9EFC /* Build configuration list for PBXProject "JavaScriptCore" */;
 			compatibilityVersion = "Xcode 2.4";
-			developmentRegion = English;
 			hasScannedForEncodings = 1;
 			knownRegions = (
 				English,
diff --git a/JavaScriptCore/bytecode/CodeBlock.cpp b/JavaScriptCore/bytecode/CodeBlock.cpp
index 400ea00..bcd2af3 100644
--- a/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -663,6 +663,11 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printUnaryOp(exec, location, it, "bitnot");
             break;
         }
+        case op_check_has_instance: {
+            int base = (++it)->u.operand;
+            printf("[%4d] check_has_instance\t\t %s\n", location, registerName(exec, base).data());
+            break;
+        }
         case op_instanceof: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
@@ -1657,30 +1662,6 @@ void CodeBlock::expressionRangeForBytecodeOffset(CallFrame* callFrame, unsigned
     return;
 }
 
-bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, OpcodeID& opcodeID)
-{
-    ASSERT(bytecodeOffset < m_instructionCount);
-
-    if (!reparseForExceptionInfoIfNecessary(callFrame) || !m_exceptionInfo->m_getByIdExceptionInfo.size())
-        return false;
-
-    int low = 0;
-    int high = m_exceptionInfo->m_getByIdExceptionInfo.size();
-    while (low < high) {
-        int mid = low + (high - low) / 2;
-        if (m_exceptionInfo->m_getByIdExceptionInfo[mid].bytecodeOffset <= bytecodeOffset)
-            low = mid + 1;
-        else
-            high = mid;
-    }
-
-    if (!low || m_exceptionInfo->m_getByIdExceptionInfo[low - 1].bytecodeOffset != bytecodeOffset)
-        return false;
-
-    opcodeID = m_exceptionInfo->m_getByIdExceptionInfo[low - 1].isOpCreateThis ? op_create_this : op_instanceof;
-    return true;
-}
-
 #if ENABLE(JIT)
 bool CodeBlock::functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex)
 {
@@ -1773,7 +1754,6 @@ void CodeBlock::shrinkToFit()
     if (m_exceptionInfo) {
         m_exceptionInfo->m_expressionInfo.shrinkToFit();
         m_exceptionInfo->m_lineInfo.shrinkToFit();
-        m_exceptionInfo->m_getByIdExceptionInfo.shrinkToFit();
     }
 
     if (m_rareData) {
diff --git a/JavaScriptCore/bytecode/CodeBlock.h b/JavaScriptCore/bytecode/CodeBlock.h
index e2f10ee..54acd50 100644
--- a/JavaScriptCore/bytecode/CodeBlock.h
+++ b/JavaScriptCore/bytecode/CodeBlock.h
@@ -93,14 +93,6 @@ namespace JSC {
         int32_t lineNumber;
     };
 
-    // Both op_construct and op_instanceof require a use of op_get_by_id to get
-    // the prototype property from an object. The exception messages for exceptions
-    // thrown by these instances op_get_by_id need to reflect this.
-    struct GetByIdExceptionInfo {
-        unsigned bytecodeOffset : 31;
-        bool isOpCreateThis : 1;
-    };
-
 #if ENABLE(JIT)
     struct CallLinkInfo {
         CallLinkInfo()
@@ -265,7 +257,6 @@ namespace JSC {
     struct ExceptionInfo : FastAllocBase {
         Vector<ExpressionRangeInfo> m_expressionInfo;
         Vector<LineInfo> m_lineInfo;
-        Vector<GetByIdExceptionInfo> m_getByIdExceptionInfo;
 
 #if ENABLE(JIT)
         Vector<CallReturnOffsetToBytecodeOffset> m_callReturnIndexVector;
@@ -318,7 +309,6 @@ namespace JSC {
         HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset);
         int lineNumberForBytecodeOffset(CallFrame*, unsigned bytecodeOffset);
         void expressionRangeForBytecodeOffset(CallFrame*, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset);
-        bool getByIdExceptionInfoForBytecodeOffset(CallFrame*, unsigned bytecodeOffset, OpcodeID&);
 
 #if ENABLE(JIT)
         void addCaller(CallLinkInfo* caller)
@@ -468,7 +458,6 @@ namespace JSC {
         PassOwnPtr<ExceptionInfo> extractExceptionInfo();
 
         void addExpressionInfo(const ExpressionRangeInfo& expressionInfo) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_expressionInfo.append(expressionInfo); }
-        void addGetByIdExceptionInfo(const GetByIdExceptionInfo& info) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_getByIdExceptionInfo.append(info); }
 
         size_t numberOfLineInfos() const { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_lineInfo.size(); }
         void addLineInfo(const LineInfo& lineInfo) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_lineInfo.append(lineInfo); }
diff --git a/JavaScriptCore/bytecode/Opcode.h b/JavaScriptCore/bytecode/Opcode.h
index 1cf4126..6c1c6b2 100644
--- a/JavaScriptCore/bytecode/Opcode.h
+++ b/JavaScriptCore/bytecode/Opcode.h
@@ -82,6 +82,7 @@ namespace JSC {
         macro(op_bitor, 5) \
         macro(op_bitnot, 3) \
         \
+        macro(op_check_has_instance, 2) \
         macro(op_instanceof, 5) \
         macro(op_typeof, 3) \
         macro(op_is_undefined, 3) \
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 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
         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 @@ bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& inde
     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 @@ namespace JSC {
             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 @@ namespace JSC {
         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 @@ RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterI
     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());
diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp
index 1599115..0a1be48 100644
--- a/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/JavaScriptCore/interpreter/Interpreter.cpp
@@ -662,15 +662,10 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
     CodeBlock* codeBlock = callFrame->codeBlock();
     if (exceptionValue.isObject()) {
         JSObject* exception = asObject(exceptionValue);
-        if (exception->isNotAnObjectErrorStub()) {
-            exception = createNotAnObjectError(callFrame, static_cast<JSNotAnObjectErrorStub*>(exception), bytecodeOffset, codeBlock);
-            exceptionValue = exception;
-        }
-
         if (!explicitThrow && exception->isErrorInstance() && static_cast<ErrorInstance*>(exception)->appendSourceToMessage())
             appendSourceToError(callFrame, static_cast<ErrorInstance*>(exception), bytecodeOffset);
 
-        // FIXME: should only really be adding these properties to VM generated exceptions, (!explicitThrow),
+        // FIXME: should only really be adding these properties to VM generated exceptions,
         // but the inspector currently requires these for all thrown objects.
         if (!hasErrorInfo(callFrame, exception))
             addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset), codeBlock->ownerExecutable()->source());
@@ -2145,6 +2140,23 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         vPC += OPCODE_LENGTH(op_not);
         NEXT_INSTRUCTION();
     }
+    DEFINE_OPCODE(op_check_has_instance) {
+        /* check_has_instance constructor(r)
+
+           Check 'constructor' is an object with the internal property
+           [HasInstance] (i.e. is a function ... *shakes head sadly at
+           JSC API*). Raises an exception if register constructor is not
+           an valid parameter for instanceof.
+        */
+        int base = vPC[1].u.operand;
+        JSValue baseVal = callFrame->r(base).jsValue();
+
+        if (isInvalidParamForInstanceOf(callFrame, baseVal, exceptionValue))
+            goto vm_throw;
+
+        vPC += OPCODE_LENGTH(op_check_has_instance);
+        NEXT_INSTRUCTION();
+    }
     DEFINE_OPCODE(op_instanceof) {
         /* instanceof dst(r) value(r) constructor(r) constructorProto(r)
 
@@ -2165,8 +2177,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 
         JSValue baseVal = callFrame->r(base).jsValue();
 
-        if (isInvalidParamForInstanceOf(callFrame, baseVal, exceptionValue))
-            goto vm_throw;
+        ASSERT(!isInvalidParamForInstanceOf(callFrame, baseVal, exceptionValue));
 
         bool result = asObject(baseVal)->hasInstance(callFrame, callFrame->r(value).jsValue(), callFrame->r(baseProto).jsValue());
         CHECK_FOR_EXCEPTION();
diff --git a/JavaScriptCore/jit/JIT.cpp b/JavaScriptCore/jit/JIT.cpp
index 6a2c612..3f2ec59 100644
--- a/JavaScriptCore/jit/JIT.cpp
+++ b/JavaScriptCore/jit/JIT.cpp
@@ -241,6 +241,7 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_get_global_var)
         DEFINE_OP(op_get_pnames)
         DEFINE_OP(op_get_scoped_var)
+        DEFINE_OP(op_check_has_instance)
         DEFINE_OP(op_instanceof)
         DEFINE_OP(op_jeq_null)
         DEFINE_OP(op_jfalse)
@@ -402,6 +403,7 @@ void JIT::privateCompileSlowCases()
         DEFINE_SLOWCASE_OP(op_get_by_val)
         DEFINE_SLOWCASE_OP(op_get_argument_by_val)
         DEFINE_SLOWCASE_OP(op_get_by_pname)
+        DEFINE_SLOWCASE_OP(op_check_has_instance)
         DEFINE_SLOWCASE_OP(op_instanceof)
         DEFINE_SLOWCASE_OP(op_jfalse)
         DEFINE_SLOWCASE_OP(op_jnless)
diff --git a/JavaScriptCore/jit/JIT.h b/JavaScriptCore/jit/JIT.h
index e8e10d0..907a774 100644
--- a/JavaScriptCore/jit/JIT.h
+++ b/JavaScriptCore/jit/JIT.h
@@ -755,6 +755,7 @@ namespace JSC {
         void emit_op_get_global_var(Instruction*);
         void emit_op_get_scoped_var(Instruction*);
         void emit_op_init_lazy_reg(Instruction*);
+        void emit_op_check_has_instance(Instruction*);
         void emit_op_instanceof(Instruction*);
         void emit_op_jeq_null(Instruction*);
         void emit_op_jfalse(Instruction*);
@@ -855,6 +856,7 @@ namespace JSC {
         void emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_argument_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_by_pname(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_check_has_instance(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_instanceof(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jfalse(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jnless(Instruction*, Vector<SlowCaseEntry>::iterator&);
diff --git a/JavaScriptCore/jit/JITOpcodes.cpp b/JavaScriptCore/jit/JITOpcodes.cpp
index d5043d1..d783581 100644
--- a/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/JavaScriptCore/jit/JITOpcodes.cpp
@@ -378,6 +378,20 @@ void JIT::emit_op_new_object(Instruction* currentInstruction)
     JITStubCall(this, cti_op_new_object).call(currentInstruction[1].u.operand);
 }
 
+void JIT::emit_op_check_has_instance(Instruction* currentInstruction)
+{
+    unsigned baseVal = currentInstruction[1].u.operand;
+
+    emitGetVirtualRegister(baseVal, regT0);
+
+    // Check that baseVal is a cell.
+    emitJumpSlowCaseIfNotJSCell(regT0, baseVal);
+
+    // Check that baseVal 'ImplementsHasInstance'.
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
+    addSlowCase(branchTest8(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsHasInstance)));
+}
+
 void JIT::emit_op_instanceof(Instruction* currentInstruction)
 {
     unsigned dst = currentInstruction[1].u.operand;
@@ -391,15 +405,15 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction)
     emitGetVirtualRegister(baseVal, regT0);
     emitGetVirtualRegister(proto, regT1);
 
-    // Check that baseVal & proto are cells.
+    // Check that proto are cells.  baseVal must be a cell - this is checked by op_check_has_instance.
     emitJumpSlowCaseIfNotJSCell(regT2, value);
-    emitJumpSlowCaseIfNotJSCell(regT0, baseVal);
     emitJumpSlowCaseIfNotJSCell(regT1, proto);
 
     // Check that prototype is an object
     loadPtr(Address(regT1, OBJECT_OFFSETOF(JSCell, m_structure)), regT3);
     addSlowCase(branch8(NotEqual, Address(regT3, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
     
+    // Fixme: this check is only needed because the JSC API allows HasInstance to be overridden; we should deprecate this.
     // Check that baseVal 'ImplementsDefaultHasInstance'.
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
     addSlowCase(branchTest8(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsDefaultHasInstance)));
@@ -1480,6 +1494,17 @@ void JIT::emitSlow_op_nstricteq(Instruction* currentInstruction, Vector<SlowCase
     stubCall.call(currentInstruction[1].u.operand);
 }
 
+void JIT::emitSlow_op_check_has_instance(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned baseVal = currentInstruction[1].u.operand;
+
+    linkSlowCaseIfNotJSCell(iter, baseVal);
+    linkSlowCase(iter);
+    JITStubCall stubCall(this, cti_op_check_has_instance);
+    stubCall.addArgument(baseVal, regT2);
+    stubCall.call();
+}
+
 void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
     unsigned dst = currentInstruction[1].u.operand;
@@ -1488,7 +1513,6 @@ void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCas
     unsigned proto = currentInstruction[4].u.operand;
 
     linkSlowCaseIfNotJSCell(iter, value);
-    linkSlowCaseIfNotJSCell(iter, baseVal);
     linkSlowCaseIfNotJSCell(iter, proto);
     linkSlowCase(iter);
     linkSlowCase(iter);
diff --git a/JavaScriptCore/jit/JITOpcodes32_64.cpp b/JavaScriptCore/jit/JITOpcodes32_64.cpp
index bcd577a..076649d 100644
--- a/JavaScriptCore/jit/JITOpcodes32_64.cpp
+++ b/JavaScriptCore/jit/JITOpcodes32_64.cpp
@@ -512,6 +512,20 @@ void JIT::emit_op_new_object(Instruction* currentInstruction)
     JITStubCall(this, cti_op_new_object).call(currentInstruction[1].u.operand);
 }
 
+void JIT::emit_op_check_has_instance(Instruction* currentInstruction)
+{
+    unsigned baseVal = currentInstruction[1].u.operand;
+
+    emitLoadPayload(baseVal, regT0);
+
+    // Check that baseVal is a cell.
+    emitJumpSlowCaseIfNotJSCell(baseVal);
+    
+    // Check that baseVal 'ImplementsHasInstance'.
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
+    addSlowCase(branchTest8(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsHasInstance)));
+}
+
 void JIT::emit_op_instanceof(Instruction* currentInstruction)
 {
     unsigned dst = currentInstruction[1].u.operand;
@@ -525,15 +539,15 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction)
     emitLoadPayload(baseVal, regT0);
     emitLoadPayload(proto, regT1);
 
-    // Check that value, baseVal, and proto are cells.
+    // Check that proto are cells.  baseVal must be a cell - this is checked by op_check_has_instance.
     emitJumpSlowCaseIfNotJSCell(value);
-    emitJumpSlowCaseIfNotJSCell(baseVal);
     emitJumpSlowCaseIfNotJSCell(proto);
     
     // Check that prototype is an object
     loadPtr(Address(regT1, OBJECT_OFFSETOF(JSCell, m_structure)), regT3);
     addSlowCase(branch8(NotEqual, Address(regT3, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
-    
+
+    // Fixme: this check is only needed because the JSC API allows HasInstance to be overridden; we should deprecate this.
     // Check that baseVal 'ImplementsDefaultHasInstance'.
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
     addSlowCase(branchTest8(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsDefaultHasInstance)));
@@ -559,6 +573,18 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction)
     emitStoreBool(dst, regT0);
 }
 
+void JIT::emitSlow_op_check_has_instance(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned baseVal = currentInstruction[1].u.operand;
+
+    linkSlowCaseIfNotJSCell(iter, baseVal);
+    linkSlowCase(iter);
+
+    JITStubCall stubCall(this, cti_op_check_has_instance);
+    stubCall.addArgument(baseVal);
+    stubCall.call();
+}
+
 void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
     unsigned dst = currentInstruction[1].u.operand;
@@ -567,7 +593,6 @@ void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCas
     unsigned proto = currentInstruction[4].u.operand;
 
     linkSlowCaseIfNotJSCell(iter, value);
-    linkSlowCaseIfNotJSCell(iter, baseVal);
     linkSlowCaseIfNotJSCell(iter, proto);
     linkSlowCase(iter);
     linkSlowCase(iter);
diff --git a/JavaScriptCore/jit/JITStubs.cpp b/JavaScriptCore/jit/JITStubs.cpp
index a541daf..36d36a2 100644
--- a/JavaScriptCore/jit/JITStubs.cpp
+++ b/JavaScriptCore/jit/JITStubs.cpp
@@ -1841,6 +1841,23 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_string_fail)
 
 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
 
+DEFINE_STUB_FUNCTION(void, op_check_has_instance)
+{
+    STUB_INIT_STACK_FRAME(stackFrame);
+
+    CallFrame* callFrame = stackFrame.callFrame;
+    JSValue baseVal = stackFrame.args[0].jsValue();
+
+    // ECMA-262 15.3.5.3:
+    // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function).
+#ifndef NDEBUG
+    TypeInfo typeInfo(UnspecifiedType);
+    ASSERT(!baseVal.isObject() || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance());
+#endif
+    stackFrame.globalData->exception = createInvalidParamError(callFrame, "instanceof", baseVal);
+    VM_THROW_EXCEPTION_AT_END();
+}
+
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
diff --git a/JavaScriptCore/jit/JITStubs.h b/JavaScriptCore/jit/JITStubs.h
index 49ac96e..937134b 100644
--- a/JavaScriptCore/jit/JITStubs.h
+++ b/JavaScriptCore/jit/JITStubs.h
@@ -372,6 +372,7 @@ extern "C" {
     int JIT_STUB cti_op_loop_if_lesseq(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_timeout_check(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_has_property(STUB_ARGS_DECLARATION);
+    void JIT_STUB cti_op_check_has_instance(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_debug(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_end(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_jmp_scopes(STUB_ARGS_DECLARATION);
diff --git a/JavaScriptCore/runtime/ExceptionHelpers.cpp b/JavaScriptCore/runtime/ExceptionHelpers.cpp
index 36b2a32..1ef264c 100644
--- a/JavaScriptCore/runtime/ExceptionHelpers.cpp
+++ b/JavaScriptCore/runtime/ExceptionHelpers.cpp
@@ -53,7 +53,7 @@ public:
     virtual UString toString(ExecState*) const { return "JavaScript execution exceeded timeout."; }
 };
 
-JSValue createInterruptedExecutionException(JSGlobalData* globalData)
+JSObject* createInterruptedExecutionException(JSGlobalData* globalData)
 {
     return new (globalData) InterruptedExecutionError(globalData);
 }
@@ -70,7 +70,7 @@ public:
     virtual UString toString(ExecState*) const { return "JavaScript execution terminated."; }
 };
 
-JSValue createTerminatedExecutionException(JSGlobalData* globalData)
+JSObject* createTerminatedExecutionException(JSGlobalData* globalData)
 {
     return new (globalData) TerminatedExecutionError(globalData);
 }
@@ -85,7 +85,7 @@ JSObject* createStackOverflowError(JSGlobalObject* globalObject)
     return createRangeError(globalObject, "Maximum call stack size exceeded.");
 }
 
-JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident)
+JSObject* createUndefinedVariableError(ExecState* exec, const Identifier& ident)
 {
     UString message(makeUString("Can't find variable: ", ident.ustring()));
     return createReferenceError(exec, message);
@@ -109,7 +109,7 @@ JSObject* createNotAConstructorError(ExecState* exec, JSValue value)
     return exception;
 }
 
-JSValue createNotAFunctionError(ExecState* exec, JSValue value)
+JSObject* createNotAFunctionError(ExecState* exec, JSValue value)
 {
     UString errorMessage = makeUString("'", value.toString(exec), "' is not a function");
     JSObject* exception = createTypeError(exec, errorMessage);
@@ -118,25 +118,8 @@ JSValue createNotAFunctionError(ExecState* exec, JSValue value)
     return exception;
 }
 
-JSNotAnObjectErrorStub* createNotAnObjectErrorStub(ExecState* exec, bool isNull)
+JSObject* createNotAnObjectError(ExecState* exec, JSValue value)
 {
-    return new (exec) JSNotAnObjectErrorStub(exec, isNull);
-}
-
-JSObject* createNotAnObjectError(ExecState* exec, JSNotAnObjectErrorStub* error, unsigned bytecodeOffset, CodeBlock* codeBlock)
-{
-    // Both op_create_this and op_instanceof require a use of op_get_by_id to get
-    // the prototype property from an object. The exception messages for exceptions
-    // thrown by these instances op_get_by_id need to reflect this.
-    OpcodeID followingOpcodeID;
-    if (codeBlock->getByIdExceptionInfoForBytecodeOffset(exec, bytecodeOffset, followingOpcodeID)) {
-        ASSERT(followingOpcodeID == op_create_this || followingOpcodeID == op_instanceof);
-        if (followingOpcodeID == op_create_this)
-            return createNotAConstructorError(exec, error->isNull() ? jsNull() : jsUndefined());
-        return createInvalidParamError(exec, "instanceof", error->isNull() ? jsNull() : jsUndefined());
-    }
-
-    JSValue value = error->isNull() ? jsNull() : jsUndefined();
     UString errorMessage = makeUString("'", value.toString(exec), "' is not an object");
     JSObject* exception = createTypeError(exec, errorMessage);
     ASSERT(exception->isErrorInstance());
diff --git a/JavaScriptCore/runtime/ExceptionHelpers.h b/JavaScriptCore/runtime/ExceptionHelpers.h
index 3dc3713..7edffad 100644
--- a/JavaScriptCore/runtime/ExceptionHelpers.h
+++ b/JavaScriptCore/runtime/ExceptionHelpers.h
@@ -43,19 +43,17 @@ namespace JSC {
     class Node;
     struct Instruction;
     
-    JSValue createInterruptedExecutionException(JSGlobalData*);
-    JSValue createTerminatedExecutionException(JSGlobalData*);
+    JSObject* createInterruptedExecutionException(JSGlobalData*);
+    JSObject* createTerminatedExecutionException(JSGlobalData*);
     JSObject* createStackOverflowError(ExecState*);
     JSObject* createStackOverflowError(JSGlobalObject*);
-    JSValue createUndefinedVariableError(ExecState*, const Identifier&);
-    JSNotAnObjectErrorStub* createNotAnObjectErrorStub(ExecState*, bool isNull);
+    JSObject* createUndefinedVariableError(ExecState*, const Identifier&);
+    JSObject* createNotAnObjectError(ExecState*, JSValue);
     JSObject* createInvalidParamError(ExecState*, const char* op, JSValue);
     JSObject* createNotAConstructorError(ExecState*, JSValue);
-    JSValue createNotAFunctionError(ExecState*, JSValue);
+    JSObject* createNotAFunctionError(ExecState*, JSValue);
     JSObject* createErrorForInvalidGlobalAssignment(ExecState*, const UString&);
 
-    JSObject* createNotAnObjectError(ExecState*, JSNotAnObjectErrorStub*, unsigned bytecodeOffset, CodeBlock*);
-
     JSObject* throwOutOfMemoryError(ExecState*);
     JSObject* throwStackOverflowError(ExecState*);
 
diff --git a/JavaScriptCore/runtime/JSGlobalData.cpp b/JavaScriptCore/runtime/JSGlobalData.cpp
index 1404ddf..58b844c 100644
--- a/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -127,7 +127,6 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
     , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull()))
     , strictEvalActivationStructure(StrictEvalActivation::createStructure(jsNull()))
     , stringStructure(JSString::createStructure(jsNull()))
-    , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull()))
     , notAnObjectStructure(JSNotAnObject::createStructure(jsNull()))
     , propertyNameIteratorStructure(JSPropertyNameIterator::createStructure(jsNull()))
     , getterSetterStructure(GetterSetter::createStructure(jsNull()))
diff --git a/JavaScriptCore/runtime/JSGlobalData.h b/JavaScriptCore/runtime/JSGlobalData.h
index 775d026..153a4e5 100644
--- a/JavaScriptCore/runtime/JSGlobalData.h
+++ b/JavaScriptCore/runtime/JSGlobalData.h
@@ -147,7 +147,6 @@ namespace JSC {
         RefPtr<Structure> staticScopeStructure;
         RefPtr<Structure> strictEvalActivationStructure;
         RefPtr<Structure> stringStructure;
-        RefPtr<Structure> notAnObjectErrorStubStructure;
         RefPtr<Structure> notAnObjectStructure;
         RefPtr<Structure> propertyNameIteratorStructure;
         RefPtr<Structure> getterSetterStructure;
diff --git a/JavaScriptCore/runtime/JSNotAnObject.cpp b/JavaScriptCore/runtime/JSNotAnObject.cpp
index f4764e2..e01b401 100644
--- a/JavaScriptCore/runtime/JSNotAnObject.cpp
+++ b/JavaScriptCore/runtime/JSNotAnObject.cpp
@@ -39,91 +39,84 @@ ASSERT_CLASS_FITS_IN_CELL(JSNotAnObject);
 // JSValue methods
 JSValue JSNotAnObject::toPrimitive(ExecState* exec, PreferredPrimitiveType) const
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
-    return m_exception;
+    ASSERT_UNUSED(exec, exec->hadException());
+    return jsNumber(0);
 }
 
 bool JSNotAnObject::getPrimitiveNumber(ExecState* exec, double&, JSValue&)
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 bool JSNotAnObject::toBoolean(ExecState* exec) const
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 double JSNotAnObject::toNumber(ExecState* exec) const
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return NaN;
 }
 
 UString JSNotAnObject::toString(ExecState* exec) const
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return "";
 }
 
 JSObject* JSNotAnObject::toObject(ExecState* exec) const
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
-    return m_exception;
-}
-
-// Marking
-void JSNotAnObject::markChildren(MarkStack& markStack)
-{
-    JSObject::markChildren(markStack);
-    markStack.append(m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
+    return const_cast<JSNotAnObject*>(this);
 }
 
 // JSObject methods
 bool JSNotAnObject::getOwnPropertySlot(ExecState* exec, const Identifier&, PropertySlot&)
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 bool JSNotAnObject::getOwnPropertySlot(ExecState* exec, unsigned, PropertySlot&)
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 bool JSNotAnObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier&, PropertyDescriptor&)
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 void JSNotAnObject::put(ExecState* exec, const Identifier& , JSValue, PutPropertySlot&)
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
 }
 
 void JSNotAnObject::put(ExecState* exec, unsigned, JSValue)
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
 }
 
 bool JSNotAnObject::deleteProperty(ExecState* exec, const Identifier&)
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 bool JSNotAnObject::deleteProperty(ExecState* exec, unsigned)
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 void JSNotAnObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray&, EnumerationMode)
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
 }
 
 } // namespace JSC
diff --git a/JavaScriptCore/runtime/JSNotAnObject.h b/JavaScriptCore/runtime/JSNotAnObject.h
index 339d41f..9f527cf 100644
--- a/JavaScriptCore/runtime/JSNotAnObject.h
+++ b/JavaScriptCore/runtime/JSNotAnObject.h
@@ -33,30 +33,13 @@
 
 namespace JSC {
 
-    class JSNotAnObjectErrorStub : public JSObject {
-    public:
-        JSNotAnObjectErrorStub(ExecState* exec, bool isNull)
-            : JSObject(exec->globalData().notAnObjectErrorStubStructure)
-            , m_isNull(isNull)
-        {
-        }
-
-        bool isNull() const { return m_isNull; }
-
-    private:
-        virtual bool isNotAnObjectErrorStub() const { return true; }
-
-        bool m_isNull;
-    };
-    
     // This unholy class is used to allow us to avoid multiple exception checks
     // in certain SquirrelFish bytecodes -- effectively it just silently consumes
     // any operations performed on the result of a failed toObject call.
     class JSNotAnObject : public JSObject {
     public:
-        JSNotAnObject(ExecState* exec, JSNotAnObjectErrorStub* exception)
+        JSNotAnObject(ExecState* exec)
             : JSObject(exec->globalData().notAnObjectStructure)
-            , m_exception(exception)
         {
         }
 
@@ -67,7 +50,7 @@ namespace JSC {
 
      private:
         
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags;
 
         // JSValue methods
         virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
@@ -77,9 +60,6 @@ namespace JSC {
         virtual UString toString(ExecState*) const;
         virtual JSObject* toObject(ExecState*) const;
 
-        // Marking
-        virtual void markChildren(MarkStack&);
-
         // JSObject methods
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
@@ -92,8 +72,6 @@ namespace JSC {
         virtual bool deleteProperty(ExecState*, unsigned propertyName);
 
         virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
-
-        JSNotAnObjectErrorStub* m_exception;
     };
 
 } // namespace JSC
diff --git a/JavaScriptCore/runtime/JSObject.h b/JavaScriptCore/runtime/JSObject.h
index 4ff31ce..803abfd 100644
--- a/JavaScriptCore/runtime/JSObject.h
+++ b/JavaScriptCore/runtime/JSObject.h
@@ -208,7 +208,6 @@ namespace JSC {
         virtual bool isGlobalObject() const { return false; }
         virtual bool isVariableObject() const { return false; }
         virtual bool isActivationObject() const { return false; }
-        virtual bool isNotAnObjectErrorStub() const { return false; }
         virtual bool isStrictModeFunction() const { return false; }
         virtual bool isErrorInstance() const { return false; }
 
diff --git a/JavaScriptCore/runtime/JSValue.cpp b/JavaScriptCore/runtime/JSValue.cpp
index 2a23a79..f4662db 100644
--- a/JavaScriptCore/runtime/JSValue.cpp
+++ b/JavaScriptCore/runtime/JSValue.cpp
@@ -62,10 +62,10 @@ JSObject* JSValue::toObjectSlowCase(ExecState* exec) const
         return constructNumber(exec, asValue());
     if (isTrue() || isFalse())
         return constructBooleanFromImmediateBoolean(exec, asValue());
+
     ASSERT(isUndefinedOrNull());
-    JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, isNull());
-    throwError(exec, exception);
-    return new (exec) JSNotAnObject(exec, exception);
+    throwError(exec, createNotAnObjectError(exec, *this));
+    return new (exec) JSNotAnObject(exec);
 }
 
 JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const
@@ -87,10 +87,10 @@ JSObject* JSValue::synthesizeObject(ExecState* exec) const
         return constructNumber(exec, asValue());
     if (isBoolean())
         return constructBooleanFromImmediateBoolean(exec, asValue());
-    
-    JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, isNull());
-    throwError(exec, exception);
-    return new (exec) JSNotAnObject(exec, exception);
+
+    ASSERT(isUndefinedOrNull());
+    throwError(exec, createNotAnObjectError(exec, *this));
+    return new (exec) JSNotAnObject(exec);
 }
 
 JSObject* JSValue::synthesizePrototype(ExecState* exec) const
@@ -101,9 +101,9 @@ JSObject* JSValue::synthesizePrototype(ExecState* exec) const
     if (isBoolean())
         return exec->lexicalGlobalObject()->booleanPrototype();
 
-    JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, isNull());
-    throwError(exec, exception);
-    return new (exec) JSNotAnObject(exec, exception);
+    ASSERT(isUndefinedOrNull());
+    throwError(exec, createNotAnObjectError(exec, *this));
+    return new (exec) JSNotAnObject(exec);
 }
 
 #ifndef NDEBUG
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 20f5899..2a77a24 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,18 @@
+2010-11-16  Gavin Barraclough  <barraclough at apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Bug 49606 - instanceof should only get the prototype property if the RHS operand implements HasInstance
+
+        * 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!"); } })
+
 2010-11-16  Csaba Osztrogonác  <ossy at webkit.org>
 
         Unreviewed. Update Qt specific expected results after r72116.
diff --git a/LayoutTests/fast/js/instanceof-operator-expected.txt b/LayoutTests/fast/js/instanceof-XMLHttpRequest-expected.txt
similarity index 100%
copy from LayoutTests/fast/js/instanceof-operator-expected.txt
copy to LayoutTests/fast/js/instanceof-XMLHttpRequest-expected.txt
diff --git a/LayoutTests/fast/js/instanceof-XMLHttpRequest.html b/LayoutTests/fast/js/instanceof-XMLHttpRequest.html
new file mode 100644
index 0000000..b9531a7
--- /dev/null
+++ b/LayoutTests/fast/js/instanceof-XMLHttpRequest.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="resources/js-test-style.css">
+<script src="resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/instanceof-XMLHttpRequest.js"></script>
+<script src="resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/js/instanceof-operator-expected.txt b/LayoutTests/fast/js/instanceof-operator-expected.txt
index 940f5cc..ff78ac5 100644
--- a/LayoutTests/fast/js/instanceof-operator-expected.txt
+++ b/LayoutTests/fast/js/instanceof-operator-expected.txt
@@ -1,24 +1,9 @@
-instanceof XMLHttpRequest test
+instanceof test
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS (new Audio()) instanceof Audio is true
-PASS (new Array()) instanceof Audio is false
-PASS (new Image()) instanceof Image is true
-PASS (new Array()) instanceof Image is false
-PASS (new Option()) instanceof Option is true
-PASS (new Array()) instanceof Option is false
-PASS (new WebKitCSSMatrix()) instanceof WebKitCSSMatrix is true
-PASS (new Array()) instanceof WebKitCSSMatrix is false
-PASS (new WebKitPoint()) instanceof WebKitPoint is true
-PASS (new Array()) instanceof WebKitPoint is false
-PASS (new Worker('instanceof-operator-dummy-worker.js')) instanceof Worker is true
-PASS (new Array()) instanceof Worker is false
-PASS (new XMLHttpRequest()) instanceof XMLHttpRequest is true
-PASS (new Array()) instanceof XMLHttpRequest is false
-PASS (new XSLTProcessor()) instanceof XSLTProcessor is true
-PASS (new Array()) instanceof XSLTProcessor is false
+PASS getterCalled is false
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/LayoutTests/fast/js/script-tests/instanceof-operator.js b/LayoutTests/fast/js/script-tests/instanceof-XMLHttpRequest.js
similarity index 100%
copy from LayoutTests/fast/js/script-tests/instanceof-operator.js
copy to LayoutTests/fast/js/script-tests/instanceof-XMLHttpRequest.js
diff --git a/LayoutTests/fast/js/script-tests/instanceof-operator.js b/LayoutTests/fast/js/script-tests/instanceof-operator.js
index 4e92621..a599a7c 100644
--- a/LayoutTests/fast/js/script-tests/instanceof-operator.js
+++ b/LayoutTests/fast/js/script-tests/instanceof-operator.js
@@ -1,33 +1,12 @@
 description(
-"instanceof XMLHttpRequest test"
+"instanceof test"
 );
 
-shouldBeTrue("(new Audio()) instanceof Audio");
-shouldBeFalse("(new Array()) instanceof Audio");
-
-shouldBeTrue("(new Image()) instanceof Image");
-shouldBeFalse("(new Array()) instanceof Image");
-
-// MessageChannel is not available yet.
-//shouldBeTrue("(new MessageChannel()) instanceof MessageChannel");
-//shouldBeFalse("(new Array()) instanceof MessageChannel");
-
-shouldBeTrue("(new Option()) instanceof Option");
-shouldBeFalse("(new Array()) instanceof Option");
-
-shouldBeTrue("(new WebKitCSSMatrix()) instanceof WebKitCSSMatrix");
-shouldBeFalse("(new Array()) instanceof WebKitCSSMatrix");
-
-shouldBeTrue("(new WebKitPoint()) instanceof WebKitPoint");
-shouldBeFalse("(new Array()) instanceof WebKitPoint");
-
-shouldBeTrue("(new Worker('instanceof-operator-dummy-worker.js')) instanceof Worker");
-shouldBeFalse("(new Array()) instanceof Worker");
-
-shouldBeTrue("(new XMLHttpRequest()) instanceof XMLHttpRequest")
-shouldBeFalse("(new Array()) instanceof XMLHttpRequest")
-
-shouldBeTrue("(new XSLTProcessor()) instanceof XSLTProcessor");
-shouldBeFalse("(new Array()) instanceof XSLTProcessor");
+getterCalled = false;
+try {
+    ({} instanceof { get prototype(){ getterCalled = true; } });
+} catch (e) {
+}
+shouldBeFalse("getterCalled");
 
 var successfullyParsed = true;

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list