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 6634d96c4af841d74b59d5aa367840c57311fa38..aac39be2190ec9297598ecb579b7da1a3405fb27 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 c2b2b08fa8aba689f104d860af7100ade308fd47..e02869ed133e51e9aa48f2bde53b25f06ef79a27 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 c3d277a294b0dfce10317d5c3186269de4b17cd2..852b8c79ab652bd38c85637b474dc7fc1e056823 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 f7b0240672e18313da2fe7a99445b8ce02840a1c..9cda050228cf8cdcce7b7f9b3d4111016cc2c7bf 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 6d7ad652b335bc184bb8322eb52930e696806e73..45c092a9cc672e2e604ed2d13e40ae761d292294 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 f6504abfb1a6b4914c71c3a2cec0ca17f9b16e06..478e209f2a100724368b15235003312398c41789 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 fdb17b563a3c1e8045f3bf890152e933866a5412..5f28dbf3df206effce2d439560d1f9ad7e36c0cb 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;