2008-12-12 Cameron Zwarich <zwarich@apple.com>
authorcwzwarich@webkit.org <cwzwarich@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 Dec 2008 22:48:53 +0000 (22:48 +0000)
committercwzwarich@webkit.org <cwzwarich@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 Dec 2008 22:48:53 +0000 (22:48 +0000)
        Reviewed by Sam Weinig.

        Bug 22828: Do not inspect bytecode instruction stream for op_get_by_id exception information
        <https://bugs.webkit.org/show_bug.cgi?id=22828>

        In order to remove the bytecode instruction stream after generating
        native code, all inspection of bytecode instructions at runtime must
        be removed. One particular instance of this is the special handling of
        exceptions thrown by the op_get_by_id emitted directly before an
        op_construct or an op_instanceof. This patch moves that information to
        an auxiliary data structure in CodeBlock.

        * bytecode/CodeBlock.cpp:
        (JSC::CodeBlock::getByIdExceptionInfoForBytecodeOffset):
        * bytecode/CodeBlock.h:
        (JSC::CodeBlock::addGetByIdExceptionInfo):
        * bytecompiler/BytecodeGenerator.cpp:
        (JSC::BytecodeGenerator::emitConstruct):
        * bytecompiler/BytecodeGenerator.h:
        (JSC::BytecodeGenerator::emitGetByIdExceptionInfo):
        * parser/Nodes.cpp:
        (JSC::InstanceOfNode::emitBytecode):
        * runtime/ExceptionHelpers.cpp:
        (JSC::createNotAnObjectError):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@39255 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/bytecode/CodeBlock.cpp
JavaScriptCore/bytecode/CodeBlock.h
JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
JavaScriptCore/bytecompiler/BytecodeGenerator.h
JavaScriptCore/parser/Nodes.cpp
JavaScriptCore/runtime/ExceptionHelpers.cpp

index 6634d96..aac39be 100644 (file)
@@ -1,3 +1,30 @@
+2008-12-12  Cameron Zwarich  <zwarich@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Bug 22828: Do not inspect bytecode instruction stream for op_get_by_id exception information
+        <https://bugs.webkit.org/show_bug.cgi?id=22828>
+
+        In order to remove the bytecode instruction stream after generating
+        native code, all inspection of bytecode instructions at runtime must
+        be removed. One particular instance of this is the special handling of
+        exceptions thrown by the op_get_by_id emitted directly before an
+        op_construct or an op_instanceof. This patch moves that information to
+        an auxiliary data structure in CodeBlock.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::getByIdExceptionInfoForBytecodeOffset):
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::addGetByIdExceptionInfo):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitConstruct):
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::emitGetByIdExceptionInfo):
+        * parser/Nodes.cpp:
+        (JSC::InstanceOfNode::emitBytecode):
+        * runtime/ExceptionHelpers.cpp:
+        (JSC::createNotAnObjectError):
+
 2008-12-12  Sam Weinig  <sam@webkit.org>
 
         Reviewed by Geoffrey Garen.
index c2b2b08..e02869e 100644 (file)
@@ -1406,6 +1406,30 @@ int CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& di
     return lineNumberForBytecodeOffset(bytecodeOffset);
 }
 
+bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(unsigned bytecodeOffset, OpcodeID& opcodeID)
+{
+    ASSERT(bytecodeOffset < m_instructions.size());
+
+    if (!m_getByIdExceptionInfo.size())
+        return false;
+
+    int low = 0;
+    int high = m_getByIdExceptionInfo.size();
+    while (low < high) {
+        int mid = low + (high - low) / 2;
+        if (m_getByIdExceptionInfo[mid].bytecodeOffset <= bytecodeOffset)
+            low = mid + 1;
+        else
+            high = mid;
+    }
+
+    if (!low)
+        return false;
+
+    opcodeID = m_getByIdExceptionInfo[low - 1].isOpConstruct ? op_construct : op_instanceof;
+    return true;
+}
+
 void CodeBlock::shrinkToFit()
 {
     m_instructions.shrinkToFit();
index c3d277a..852b8c7 100644 (file)
@@ -78,6 +78,14 @@ 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 isOpConstruct : 1;
+    };
+
 #if ENABLE(JIT)
     struct CallLinkInfo {
         CallLinkInfo()
@@ -227,6 +235,7 @@ namespace JSC {
         HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset);
         int lineNumberForBytecodeOffset(unsigned bytecodeOffset);
         int expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset);
+        bool getByIdExceptionInfoForBytecodeOffset(unsigned bytecodeOffset, OpcodeID&);
 
 #if ENABLE(JIT)
         void addCaller(CallLinkInfo* caller)
@@ -302,6 +311,7 @@ namespace JSC {
         HandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
 
         void addExpressionInfo(const ExpressionRangeInfo& expressionInfo) { return m_expressionInfo.append(expressionInfo); }
+        void addGetByIdExceptionInfo(const GetByIdExceptionInfo& info) { m_getByIdExceptionInfo.append(info); }
 
         size_t numberOfLineInfos() const { return m_lineInfo.size(); }
         void addLineInfo(const LineInfo& lineInfo) { return m_lineInfo.append(lineInfo); }
@@ -426,6 +436,7 @@ namespace JSC {
 
         Vector<ExpressionRangeInfo> m_expressionInfo;
         Vector<LineInfo> m_lineInfo;
+        Vector<GetByIdExceptionInfo> m_getByIdExceptionInfo;
 
 #if ENABLE(JIT)
         Vector<PC> m_pcVector;
index f7b0240..9cda050 100644 (file)
@@ -1333,6 +1333,7 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
 
     // Load prototype.
     emitExpressionInfo(divot, startOffset, endOffset);
+    emitGetByIdExceptionInfo(op_construct);
     emitGetById(funcProto.get(), func, globalData()->propertyNames->prototype);
 
     // Reserve space for call frame.
index 6d7ad65..45c092a 100644 (file)
@@ -208,6 +208,17 @@ namespace JSC {
             info.endOffset = endOffset;
             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_construct || opcodeID == op_instanceof);
+            GetByIdExceptionInfo info;
+            info.bytecodeOffset = instructions().size();
+            info.isOpConstruct = (opcodeID == op_construct);
+            m_codeBlock->addGetByIdExceptionInfo(info);
+        }
         
         ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure)
         {
index f6504ab..478e209 100644 (file)
@@ -1164,6 +1164,7 @@ RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterI
     RefPtr<RegisterID> src2 = generator.emitNode(m_expr2.get());
 
     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    generator.emitGetByIdExceptionInfo(op_instanceof);
     RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype);
 
     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
index fdb17b5..5f28dbf 100644 (file)
@@ -208,10 +208,16 @@ JSNotAnObjectErrorStub* createNotAnObjectErrorStub(ExecState* exec, bool isNull)
 
 JSObject* createNotAnObjectError(ExecState* exec, JSNotAnObjectErrorStub* error, const Instruction* vPC, CodeBlock* codeBlock)
 {
-    if (vPC[8].u.opcode == exec->interpreter()->getOpcode(op_instanceof))
+    // 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.
+    OpcodeID followingOpcodeID;
+    if (codeBlock->getByIdExceptionInfoForBytecodeOffset(vPC - codeBlock->instructions().begin(), followingOpcodeID)) {
+        ASSERT(followingOpcodeID == op_construct || followingOpcodeID == op_instanceof);
+        if (followingOpcodeID == op_construct)
+            return createNotAConstructorError(exec, error->isNull() ? jsNull() : jsUndefined(), vPC, codeBlock);
         return createInvalidParamError(exec, "instanceof", error->isNull() ? jsNull() : jsUndefined(), vPC, codeBlock);
-    if (vPC[8].u.opcode == exec->interpreter()->getOpcode(op_construct))
-        return createNotAConstructorError(exec, error->isNull() ? jsNull() : jsUndefined(), vPC, codeBlock);
+    }
 
     int startOffset = 0;
     int endOffset = 0;