Changeset 39071 in webkit for trunk/JavaScriptCore


Ignore:
Timestamp:
Dec 6, 2008, 2:19:22 PM (16 years ago)
Author:
[email protected]
Message:

2008-12-06 Sam Weinig <[email protected]>

Reviewed by Cameron Zwarich.

Split JumpTable code into its own file.

  • GNUmakefile.am:
  • JavaScriptCore.pri:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • JavaScriptCoreSources.bkl:
  • bytecode/CodeBlock.cpp:
  • bytecode/CodeBlock.h:
  • bytecode/JumpTable.cpp: Copied from bytecode/CodeBlock.cpp.
  • bytecode/JumpTable.h: Copied from bytecode/CodeBlock.h.
Location:
trunk/JavaScriptCore
Files:
8 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r39070 r39071  
     12008-12-06  Sam Weinig  <[email protected]>
     2
     3        Reviewed by Cameron Zwarich.
     4
     5        Split JumpTable code into its own file.
     6
     7        * GNUmakefile.am:
     8        * JavaScriptCore.pri:
     9        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
     10        * JavaScriptCore.xcodeproj/project.pbxproj:
     11        * JavaScriptCoreSources.bkl:
     12        * bytecode/CodeBlock.cpp:
     13        * bytecode/CodeBlock.h:
     14        * bytecode/JumpTable.cpp: Copied from bytecode/CodeBlock.cpp.
     15        * bytecode/JumpTable.h: Copied from bytecode/CodeBlock.h.
     16
    1172008-12-05  Sam Weinig  <[email protected]>
    218
  • trunk/JavaScriptCore/GNUmakefile.am

    r38992 r39071  
    8282        JavaScriptCore/bytecode/CodeBlock.cpp \
    8383        JavaScriptCore/bytecode/CodeBlock.h \
     84        JavaScriptCore/bytecode/JumpTable.cpp \
     85        JavaScriptCore/bytecode/JumpTable.h \
    8486        JavaScriptCore/bytecode/EvalCodeCache.h \
    8587        JavaScriptCore/runtime/ExceptionHelpers.cpp \
  • trunk/JavaScriptCore/JavaScriptCore.pri

    r39034 r39071  
    7070    runtime/JSNotAnObject.cpp \
    7171    bytecode/CodeBlock.cpp \
     72    bytecode/JumpTable.cpp \
    7273    jit/JIT.cpp \
    7374    jit/JITCall.cpp \
  • trunk/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj

    r38992 r39071  
    12431243                        </File>
    12441244                        <File
     1245                                RelativePath="..\..\bytecode\JumpTable.cpp"
     1246                                >
     1247                        </File>
     1248                        <File
     1249                                RelativePath="..\..\bytecode\JumpTable.h"
     1250                                >
     1251                        </File>
     1252                        <File
    12451253                                RelativePath="..\..\jit\JIT.cpp"
    12461254                                >
  • trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r39062 r39071  
    313313                BCDE3B430E6C832D001453A7 /* Structure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCDE3AB00E6C82CF001453A7 /* Structure.cpp */; };
    314314                BCF605140E203EF800B9A64D /* ArgList.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF605120E203EF800B9A64D /* ArgList.h */; settings = {ATTRIBUTES = (Private, ); }; };
     315                BCFD8C920EEB2EE700283848 /* JumpTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCFD8C900EEB2EE700283848 /* JumpTable.cpp */; };
     316                BCFD8C930EEB2EE700283848 /* JumpTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BCFD8C910EEB2EE700283848 /* JumpTable.h */; };
    315317                C0A272630E50A06300E96E15 /* NotFound.h in Headers */ = {isa = PBXBuildFile; fileRef = C0A2723F0E509F1E00E96E15 /* NotFound.h */; settings = {ATTRIBUTES = (Private, ); }; };
    316318                E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */ = {isa = PBXBuildFile; fileRef = E124A8F50E555775003091F1 /* OpaqueJSString.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    719721                BCF605120E203EF800B9A64D /* ArgList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArgList.h; sourceTree = "<group>"; };
    720722                BCF6553B0A2048DE0038A194 /* MathExtras.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MathExtras.h; sourceTree = "<group>"; };
     723                BCFD8C900EEB2EE700283848 /* JumpTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JumpTable.cpp; sourceTree = "<group>"; };
     724                BCFD8C910EEB2EE700283848 /* JumpTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JumpTable.h; sourceTree = "<group>"; };
    721725                C0A2723F0E509F1E00E96E15 /* NotFound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotFound.h; sourceTree = "<group>"; };
    722726                D21202280AD4310C00ED79B6 /* DateMath.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DateMath.cpp; sourceTree = "<group>"; };
     
    13841388                                969A07920ED1D3AE00F1F681 /* EvalCodeCache.h */,
    13851389                                969A07930ED1D3AE00F1F681 /* Instruction.h */,
     1390                                BCFD8C900EEB2EE700283848 /* JumpTable.cpp */,
     1391                                BCFD8C910EEB2EE700283848 /* JumpTable.h */,
    13861392                                969A07940ED1D3AE00F1F681 /* Opcode.cpp */,
    13871393                                969A07950ED1D3AE00F1F681 /* Opcode.h */,
     
    16381644                                86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */,
    16391645                                86CC85A10EE79A4700288682 /* JITInlineMethods.h in Headers */,
     1646                                BCFD8C930EEB2EE700283848 /* JumpTable.h in Headers */,
    16401647                        );
    16411648                        runOnlyForDeploymentPostprocessing = 0;
     
    19801987                                86CC85C40EE7A89400288682 /* JITPropertyAccess.cpp in Sources */,
    19811988                                86A90ED00EE7D51F00AB350D /* JITArithmetic.cpp in Sources */,
     1989                                BCFD8C920EEB2EE700283848 /* JumpTable.cpp in Sources */,
    19821990                        );
    19831991                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/JavaScriptCore/JavaScriptCoreSources.bkl

    r38536 r39071  
    148148    <set append="1" var="JSCORE_VM_SOURCES">
    149149        bytecode/CodeBlock.cpp
     150        bytecode/JumpTable.cpp
    150151        runtime/ExceptionHelpers.cpp
    151152        interpreter/Interpreter.cpp
  • trunk/JavaScriptCore/bytecode/CodeBlock.cpp

    r39070 r39071  
    12061206}
    12071207
    1208 int32_t SimpleJumpTable::offsetForValue(int32_t value, int32_t defaultOffset)
    1209 {
    1210     if (value >= min && static_cast<uint32_t>(value - min) < branchOffsets.size()) {
    1211         int32_t offset = branchOffsets[value - min];
    1212         if (offset)
    1213             return offset;
    1214     }
    1215     return defaultOffset;       
    1216 }
    1217 
    12181208} // namespace JSC
  • trunk/JavaScriptCore/bytecode/CodeBlock.h

    r39070 r39071  
    3434#include "Instruction.h"
    3535#include "JSGlobalObject.h"
     36#include "JumpTable.h"
    3637#include "Nodes.h"
    3738#include "RegExp.h"
     
    7071        uint32_t instructionOffset;
    7172        int32_t lineNumber;
    72     };
    73 
    74     struct OffsetLocation {
    75         int32_t branchOffset;
    76 #if ENABLE(JIT)
    77         void* ctiOffset;
    78 #endif
    7973    };
    8074
     
    162156    }
    163157
    164     struct StringJumpTable {
    165         typedef HashMap<RefPtr<UString::Rep>, OffsetLocation> StringOffsetTable;
    166         StringOffsetTable offsetTable;
    167 #if ENABLE(JIT)
    168         void* ctiDefault; // FIXME: it should not be necessary to store this.
    169 #endif
    170 
    171         inline int32_t offsetForValue(UString::Rep* value, int32_t defaultOffset)
    172         {
    173             StringOffsetTable::const_iterator end = offsetTable.end();
    174             StringOffsetTable::const_iterator loc = offsetTable.find(value);
    175             if (loc == end)
    176                 return defaultOffset;
    177             return loc->second.branchOffset;
    178         }
    179 
    180 #if ENABLE(JIT)
    181         inline void* ctiForValue(UString::Rep* value)
    182         {
    183             StringOffsetTable::const_iterator end = offsetTable.end();
    184             StringOffsetTable::const_iterator loc = offsetTable.find(value);
    185             if (loc == end)
    186                 return ctiDefault;
    187             return loc->second.ctiOffset;
    188         }
    189 #endif
    190     };
    191 
    192     struct SimpleJumpTable {
    193         // FIXME: The two Vectors can be combind into one Vector<OffsetLocation>
    194         Vector<int32_t> branchOffsets;
    195         int32_t min;
    196 #if ENABLE(JIT)
    197         Vector<void*> ctiOffsets;
    198         void* ctiDefault;
    199 #endif
    200 
    201         int32_t offsetForValue(int32_t value, int32_t defaultOffset);
    202         void add(int32_t key, int32_t offset)
    203         {
    204             if (!branchOffsets[key])
    205                 branchOffsets[key] = offset;
    206         }
    207 
    208 #if ENABLE(JIT)
    209         inline void* ctiForValue(int32_t value)
    210         {
    211             if (value >= min && static_cast<uint32_t>(value - min) < ctiOffsets.size())
    212                 return ctiOffsets[value - min];
    213             return ctiDefault;
    214         }
    215 #endif
    216     };
    217 
    218158    class CodeBlock {
    219159        friend class JIT;
  • trunk/JavaScriptCore/bytecode/JumpTable.cpp

    r39070 r39071  
    2929
    3030#include "config.h"
    31 #include "CodeBlock.h"
    32 
    33 #include "JIT.h"
    34 #include "JSValue.h"
    35 #include "Interpreter.h"
    36 #include "Debugger.h"
    37 #include <stdio.h>
    38 #include <wtf/StringExtras.h>
     31#include "JumpTable.h"
    3932
    4033namespace JSC {
    41 
    42 #if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
    43 
    44 static UString escapeQuotes(const UString& str)
    45 {
    46     UString result = str;
    47     int pos = 0;
    48     while ((pos = result.find('\"', pos)) >= 0) {
    49         result = result.substr(0, pos) + "\"\\\"\"" + result.substr(pos + 1);
    50         pos += 4;
    51     }
    52     return result;
    53 }
    54 
    55 static UString valueToSourceString(ExecState* exec, JSValue* val)
    56 {
    57     if (val->isString()) {
    58         UString result("\"");
    59         result += escapeQuotes(val->toString(exec)) + "\"";
    60         return result;
    61     }
    62 
    63     return val->toString(exec);
    64 }
    65 
    66 static CString registerName(int r)
    67 {
    68     if (r == missingThisObjectMarker())
    69         return "<null>";
    70 
    71     return (UString("r") + UString::from(r)).UTF8String();
    72 }
    73 
    74 static CString constantName(ExecState* exec, int k, JSValue* value)
    75 {
    76     return (valueToSourceString(exec, value) + "(@k" + UString::from(k) + ")").UTF8String();
    77 }
    78 
    79 static CString idName(int id0, const Identifier& ident)
    80 {
    81     return (ident.ustring() + "(@id" + UString::from(id0) +")").UTF8String();
    82 }
    83 
    84 static UString regexpToSourceString(RegExp* regExp)
    85 {
    86     UString pattern = UString("/") + regExp->pattern() + "/";
    87     if (regExp->global())
    88         pattern += "g";
    89     if (regExp->ignoreCase())
    90         pattern += "i";
    91     if (regExp->multiline())
    92         pattern += "m";
    93 
    94     return pattern;
    95 }
    96 
    97 static CString regexpName(int re, RegExp* regexp)
    98 {
    99     return (regexpToSourceString(regexp) + "(@re" + UString::from(re) + ")").UTF8String();
    100 }
    101 
    102 static UString pointerToSourceString(void* p)
    103 {
    104     char buffer[2 + 2 * sizeof(void*) + 1]; // 0x [two characters per byte] \0
    105     snprintf(buffer, sizeof(buffer), "%p", p);
    106     return buffer;
    107 }
    108 
    109 NEVER_INLINE static const char* debugHookName(int debugHookID)
    110 {
    111     switch (static_cast<DebugHookID>(debugHookID)) {
    112         case DidEnterCallFrame:
    113             return "didEnterCallFrame";
    114         case WillLeaveCallFrame:
    115             return "willLeaveCallFrame";
    116         case WillExecuteStatement:
    117             return "willExecuteStatement";
    118         case WillExecuteProgram:
    119             return "willExecuteProgram";
    120         case DidExecuteProgram:
    121             return "didExecuteProgram";
    122         case DidReachBreakpoint:
    123             return "didReachBreakpoint";
    124     }
    125 
    126     ASSERT_NOT_REACHED();
    127     return "";
    128 }
    129 
    130 static int locationForOffset(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int offset)
    131 {
    132     return it - begin + offset;
    133 }
    134 
    135 static void printUnaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op)
    136 {
    137     int r0 = (++it)->u.operand;
    138     int r1 = (++it)->u.operand;
    139 
    140     printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str());
    141 }
    142 
    143 static void printBinaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op)
    144 {
    145     int r0 = (++it)->u.operand;
    146     int r1 = (++it)->u.operand;
    147     int r2 = (++it)->u.operand;
    148     printf("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
    149 }
    150 
    151 static void printConditionalJump(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int location, const char* op)
    152 {
    153     int r0 = (++it)->u.operand;
    154     int offset = (++it)->u.operand;
    155     printf("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(r0).c_str(), offset, locationForOffset(begin, it, offset));
    156 }
    157 
    158 static void printGetByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op)
    159 {
    160     int r0 = (++it)->u.operand;
    161     int r1 = (++it)->u.operand;
    162     int id0 = (++it)->u.operand;
    163     printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
    164     it += 4;
    165 }
    166 
    167 static void printPutByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op)
    168 {
    169     int r0 = (++it)->u.operand;
    170     int id0 = (++it)->u.operand;
    171     int r1 = (++it)->u.operand;
    172     printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
    173     it += 4;
    174 }
    175 
    176 void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand) const
    177 {
    178     unsigned instructionOffset = vPC - m_instructions.begin();
    179     printf("  [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).UTF8String().c_str());
    180 }
    181 
    182 void CodeBlock::printStructures(const Instruction* vPC) const
    183 {
    184     Interpreter* interpreter = m_globalData->interpreter;
    185     unsigned instructionOffset = vPC - m_instructions.begin();
    186 
    187     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id)) {
    188         printStructure("get_by_id", vPC, 4);
    189         return;
    190     }
    191     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
    192         printStructure("get_by_id_self", vPC, 4);
    193         return;
    194     }
    195     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
    196         printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str());
    197         return;
    198     }
    199     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
    200         printf("  [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_new", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[6].u.structureChain).UTF8String().c_str());
    201         return;
    202     }
    203     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
    204         printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structureChain).UTF8String().c_str());
    205         return;
    206     }
    207     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id)) {
    208         printStructure("put_by_id", vPC, 4);
    209         return;
    210     }
    211     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
    212         printStructure("put_by_id_replace", vPC, 4);
    213         return;
    214     }
    215     if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) {
    216         printStructure("resolve_global", vPC, 4);
    217         return;
    218     }
    219 
    220     // These m_instructions doesn't ref Structures.
    221     ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_call) || vPC[0].u.opcode == interpreter->getOpcode(op_call_eval) || vPC[0].u.opcode == interpreter->getOpcode(op_construct));
    222 }
    223 
    224 void CodeBlock::dump(ExecState* exec) const
    225 {
    226     Vector<Instruction>::const_iterator begin = m_instructions.begin();
    227     Vector<Instruction>::const_iterator end = m_instructions.end();
    228 
    229     size_t instructionCount = 0;
    230     for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)
    231         if (exec->interpreter()->isOpcode(it->u.opcode))
    232             ++instructionCount;
    233 
    234     printf("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n",
    235         static_cast<unsigned long>(instructionCount),
    236         static_cast<unsigned long>(m_instructions.size() * sizeof(Instruction)),
    237         this, m_numParameters, m_numCalleeRegisters);
    238    
    239     for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)
    240         dump(exec, begin, it);
    241 
    242     if (!m_identifiers.isEmpty()) {
    243         printf("\nIdentifiers:\n");
    244         size_t i = 0;
    245         do {
    246             printf("  id%u = %s\n", static_cast<unsigned>(i), m_identifiers[i].ascii());
    247             ++i;
    248         } while (i != m_identifiers.size());
    249     }
    250 
    251     if (!m_constantRegisters.isEmpty()) {
    252         printf("\nConstants:\n");
    253         unsigned registerIndex = m_numVars;
    254         size_t i = 0;
    255         do {
    256             printf("   r%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue(exec)).ascii());
    257             ++i;
    258             ++registerIndex;
    259         } while (i < m_constantRegisters.size());
    260     }
    261 
    262     if (!m_unexpectedConstants.isEmpty()) {
    263         printf("\nUnexpected Constants:\n");
    264         size_t i = 0;
    265         do {
    266             printf("  k%u = %s\n", static_cast<unsigned>(i), valueToSourceString(exec, m_unexpectedConstants[i]).ascii());
    267             ++i;
    268         } while (i < m_unexpectedConstants.size());
    269     }
    270    
    271     if (!m_regexps.isEmpty()) {
    272         printf("\nm_regexps:\n");
    273         size_t i = 0;
    274         do {
    275             printf("  re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_regexps[i].get()).ascii());
    276             ++i;
    277         } while (i < m_regexps.size());
    278     }
    279 
    280     if (!m_globalResolveInstructions.isEmpty() || !m_propertyAccessInstructions.isEmpty())
    281         printf("\nStructures:\n");
    282 
    283     if (!m_globalResolveInstructions.isEmpty()) {
    284         size_t i = 0;
    285         do {
    286              printStructures(&m_instructions[m_globalResolveInstructions[i]]);
    287              ++i;
    288         } while (i < m_globalResolveInstructions.size());
    289     }
    290     if (!m_propertyAccessInstructions.isEmpty()) {
    291         size_t i = 0;
    292         do {
    293              printStructures(&m_instructions[m_propertyAccessInstructions[i].bytecodeIndex]);
    294              ++i;
    295         } while (i < m_propertyAccessInstructions.size());
    296     }
    297  
    298     if (!m_exceptionHandlers.isEmpty()) {
    299         printf("\nException Handlers:\n");
    300         unsigned i = 0;
    301         do {
    302             printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] }\n", i + 1, m_exceptionHandlers[i].start, m_exceptionHandlers[i].end, m_exceptionHandlers[i].target);
    303             ++i;
    304         } while (i < m_exceptionHandlers.size());
    305     }
    306    
    307     if (!m_immediateSwitchJumpTables.isEmpty()) {
    308         printf("Immediate Switch Jump Tables:\n");
    309         unsigned i = 0;
    310         do {
    311             printf("  %1d = {\n", i);
    312             int entry = 0;
    313             Vector<int32_t>::const_iterator end = m_immediateSwitchJumpTables[i].branchOffsets.end();
    314             for (Vector<int32_t>::const_iterator iter = m_immediateSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
    315                 if (!*iter)
    316                     continue;
    317                 printf("\t\t%4d => %04d\n", entry + m_immediateSwitchJumpTables[i].min, *iter);
    318             }
    319             printf("      }\n");
    320             ++i;
    321         } while (i < m_immediateSwitchJumpTables.size());
    322     }
    323    
    324     if (!m_characterSwitchJumpTables.isEmpty()) {
    325         printf("\nCharacter Switch Jump Tables:\n");
    326         unsigned i = 0;
    327         do {
    328             printf("  %1d = {\n", i);
    329             int entry = 0;
    330             Vector<int32_t>::const_iterator end = m_characterSwitchJumpTables[i].branchOffsets.end();
    331             for (Vector<int32_t>::const_iterator iter = m_characterSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
    332                 if (!*iter)
    333                     continue;
    334                 ASSERT(!((i + m_characterSwitchJumpTables[i].min) & ~0xFFFF));
    335                 UChar ch = static_cast<UChar>(entry + m_characterSwitchJumpTables[i].min);
    336                 printf("\t\t\"%s\" => %04d\n", UString(&ch, 1).ascii(), *iter);
    337         }
    338             printf("      }\n");
    339             ++i;
    340         } while (i < m_characterSwitchJumpTables.size());
    341     }
    342    
    343     if (!m_stringSwitchJumpTables.isEmpty()) {
    344         printf("\nString Switch Jump Tables:\n");
    345         unsigned i = 0;
    346         do {
    347             printf("  %1d = {\n", i);
    348             StringJumpTable::StringOffsetTable::const_iterator end = m_stringSwitchJumpTables[i].offsetTable.end();
    349             for (StringJumpTable::StringOffsetTable::const_iterator iter = m_stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter)
    350                 printf("\t\t\"%s\" => %04d\n", UString(iter->first).ascii(), iter->second.branchOffset);
    351             printf("      }\n");
    352             ++i;
    353         } while (i < m_stringSwitchJumpTables.size());
    354     }
    355 
    356     printf("\n");
    357 }
    358 
    359 void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it) const
    360 {
    361     int location = it - begin;
    362     switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {
    363         case op_enter: {
    364             printf("[%4d] enter\n", location);
    365             break;
    366         }
    367         case op_enter_with_activation: {
    368             int r0 = (++it)->u.operand;
    369             printf("[%4d] enter_with_activation %s\n", location, registerName(r0).c_str());
    370             break;
    371         }
    372         case op_create_arguments: {
    373             printf("[%4d] create_arguments\n", location);
    374             break;
    375         }
    376         case op_convert_this: {
    377             int r0 = (++it)->u.operand;
    378             printf("[%4d] convert_this %s\n", location, registerName(r0).c_str());
    379             break;
    380         }
    381         case op_unexpected_load: {
    382             int r0 = (++it)->u.operand;
    383             int k0 = (++it)->u.operand;
    384             printf("[%4d] unexpected_load\t %s, %s\n", location, registerName(r0).c_str(), constantName(exec, k0, m_unexpectedConstants[k0]).c_str());
    385             break;
    386         }
    387         case op_new_object: {
    388             int r0 = (++it)->u.operand;
    389             printf("[%4d] new_object\t %s\n", location, registerName(r0).c_str());
    390             break;
    391         }
    392         case op_new_array: {
    393             int dst = (++it)->u.operand;
    394             int argv = (++it)->u.operand;
    395             int argc = (++it)->u.operand;
    396             printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(dst).c_str(), registerName(argv).c_str(), argc);
    397             break;
    398         }
    399         case op_new_regexp: {
    400             int r0 = (++it)->u.operand;
    401             int re0 = (++it)->u.operand;
    402             printf("[%4d] new_regexp\t %s, %s\n", location, registerName(r0).c_str(), regexpName(re0, m_regexps[re0].get()).c_str());
    403             break;
    404         }
    405         case op_mov: {
    406             int r0 = (++it)->u.operand;
    407             int r1 = (++it)->u.operand;
    408             printf("[%4d] mov\t\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
    409             break;
    410         }
    411         case op_not: {
    412             printUnaryOp(location, it, "not");
    413             break;
    414         }
    415         case op_eq: {
    416             printBinaryOp(location, it, "eq");
    417             break;
    418         }
    419         case op_eq_null: {
    420             printUnaryOp(location, it, "eq_null");
    421             break;
    422         }
    423         case op_neq: {
    424             printBinaryOp(location, it, "neq");
    425             break;
    426         }
    427         case op_neq_null: {
    428             printUnaryOp(location, it, "neq_null");
    429             break;
    430         }
    431         case op_stricteq: {
    432             printBinaryOp(location, it, "stricteq");
    433             break;
    434         }
    435         case op_nstricteq: {
    436             printBinaryOp(location, it, "nstricteq");
    437             break;
    438         }
    439         case op_less: {
    440             printBinaryOp(location, it, "less");
    441             break;
    442         }
    443         case op_lesseq: {
    444             printBinaryOp(location, it, "lesseq");
    445             break;
    446         }
    447         case op_pre_inc: {
    448             int r0 = (++it)->u.operand;
    449             printf("[%4d] pre_inc\t\t %s\n", location, registerName(r0).c_str());
    450             break;
    451         }
    452         case op_pre_dec: {
    453             int r0 = (++it)->u.operand;
    454             printf("[%4d] pre_dec\t\t %s\n", location, registerName(r0).c_str());
    455             break;
    456         }
    457         case op_post_inc: {
    458             printUnaryOp(location, it, "post_inc");
    459             break;
    460         }
    461         case op_post_dec: {
    462             printUnaryOp(location, it, "post_dec");
    463             break;
    464         }
    465         case op_to_jsnumber: {
    466             printUnaryOp(location, it, "to_jsnumber");
    467             break;
    468         }
    469         case op_negate: {
    470             printUnaryOp(location, it, "negate");
    471             break;
    472         }
    473         case op_add: {
    474             printBinaryOp(location, it, "add");
    475             ++it;
    476             break;
    477         }
    478         case op_mul: {
    479             printBinaryOp(location, it, "mul");
    480             ++it;
    481             break;
    482         }
    483         case op_div: {
    484             printBinaryOp(location, it, "div");
    485             break;
    486         }
    487         case op_mod: {
    488             printBinaryOp(location, it, "mod");
    489             break;
    490         }
    491         case op_sub: {
    492             printBinaryOp(location, it, "sub");
    493             ++it;
    494             break;
    495         }
    496         case op_lshift: {
    497             printBinaryOp(location, it, "lshift");
    498             break;           
    499         }
    500         case op_rshift: {
    501             printBinaryOp(location, it, "rshift");
    502             break;
    503         }
    504         case op_urshift: {
    505             printBinaryOp(location, it, "urshift");
    506             break;
    507         }
    508         case op_bitand: {
    509             printBinaryOp(location, it, "bitand");
    510             ++it;
    511             break;
    512         }
    513         case op_bitxor: {
    514             printBinaryOp(location, it, "bitxor");
    515             ++it;
    516             break;
    517         }
    518         case op_bitor: {
    519             printBinaryOp(location, it, "bitor");
    520             ++it;
    521             break;
    522         }
    523         case op_bitnot: {
    524             printUnaryOp(location, it, "bitnot");
    525             break;
    526         }
    527         case op_instanceof: {
    528             int r0 = (++it)->u.operand;
    529             int r1 = (++it)->u.operand;
    530             int r2 = (++it)->u.operand;
    531             int r3 = (++it)->u.operand;
    532             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());
    533             break;
    534         }
    535         case op_typeof: {
    536             printUnaryOp(location, it, "typeof");
    537             break;
    538         }
    539         case op_is_undefined: {
    540             printUnaryOp(location, it, "is_undefined");
    541             break;
    542         }
    543         case op_is_boolean: {
    544             printUnaryOp(location, it, "is_boolean");
    545             break;
    546         }
    547         case op_is_number: {
    548             printUnaryOp(location, it, "is_number");
    549             break;
    550         }
    551         case op_is_string: {
    552             printUnaryOp(location, it, "is_string");
    553             break;
    554         }
    555         case op_is_object: {
    556             printUnaryOp(location, it, "is_object");
    557             break;
    558         }
    559         case op_is_function: {
    560             printUnaryOp(location, it, "is_function");
    561             break;
    562         }
    563         case op_in: {
    564             printBinaryOp(location, it, "in");
    565             break;
    566         }
    567         case op_resolve: {
    568             int r0 = (++it)->u.operand;
    569             int id0 = (++it)->u.operand;
    570             printf("[%4d] resolve\t\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str());
    571             break;
    572         }
    573         case op_resolve_skip: {
    574             int r0 = (++it)->u.operand;
    575             int id0 = (++it)->u.operand;
    576             int skipLevels = (++it)->u.operand;
    577             printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), skipLevels);
    578             break;
    579         }
    580         case op_resolve_global: {
    581             int r0 = (++it)->u.operand;
    582             JSValue* scope = static_cast<JSValue*>((++it)->u.jsCell);
    583             int id0 = (++it)->u.operand;
    584             printf("[%4d] resolve_global\t %s, %s, %s\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).c_str());
    585             it += 2;
    586             break;
    587         }
    588         case op_get_scoped_var: {
    589             int r0 = (++it)->u.operand;
    590             int index = (++it)->u.operand;
    591             int skipLevels = (++it)->u.operand;
    592             printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(r0).c_str(), index, skipLevels);
    593             break;
    594         }
    595         case op_put_scoped_var: {
    596             int index = (++it)->u.operand;
    597             int skipLevels = (++it)->u.operand;
    598             int r0 = (++it)->u.operand;
    599             printf("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(r0).c_str());
    600             break;
    601         }
    602         case op_get_global_var: {
    603             int r0 = (++it)->u.operand;
    604             JSValue* scope = static_cast<JSValue*>((++it)->u.jsCell);
    605             int index = (++it)->u.operand;
    606             printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), index);
    607             break;
    608         }
    609         case op_put_global_var: {
    610             JSValue* scope = static_cast<JSValue*>((++it)->u.jsCell);
    611             int index = (++it)->u.operand;
    612             int r0 = (++it)->u.operand;
    613             printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(r0).c_str());
    614             break;
    615         }
    616         case op_resolve_base: {
    617             int r0 = (++it)->u.operand;
    618             int id0 = (++it)->u.operand;
    619             printf("[%4d] resolve_base\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str());
    620             break;
    621         }
    622         case op_resolve_with_base: {
    623             int r0 = (++it)->u.operand;
    624             int r1 = (++it)->u.operand;
    625             int id0 = (++it)->u.operand;
    626             printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
    627             break;
    628         }
    629         case op_resolve_func: {
    630             int r0 = (++it)->u.operand;
    631             int r1 = (++it)->u.operand;
    632             int id0 = (++it)->u.operand;
    633             printf("[%4d] resolve_func\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
    634             break;
    635         }
    636         case op_get_by_id: {
    637             printGetByIdOp(location, it, m_identifiers, "get_by_id");
    638             break;
    639         }
    640         case op_get_by_id_self: {
    641             printGetByIdOp(location, it, m_identifiers, "get_by_id_self");
    642             break;
    643         }
    644         case op_get_by_id_self_list: {
    645             printGetByIdOp(location, it, m_identifiers, "get_by_id_self_list");
    646             break;
    647         }
    648         case op_get_by_id_proto: {
    649             printGetByIdOp(location, it, m_identifiers, "get_by_id_proto");
    650             break;
    651         }
    652         case op_get_by_id_proto_list: {
    653             printGetByIdOp(location, it, m_identifiers, "op_get_by_id_proto_list");
    654             break;
    655         }
    656         case op_get_by_id_chain: {
    657             printGetByIdOp(location, it, m_identifiers, "get_by_id_chain");
    658             break;
    659         }
    660         case op_get_by_id_generic: {
    661             printGetByIdOp(location, it, m_identifiers, "get_by_id_generic");
    662             break;
    663         }
    664         case op_get_array_length: {
    665             printGetByIdOp(location, it, m_identifiers, "get_array_length");
    666             break;
    667         }
    668         case op_get_string_length: {
    669             printGetByIdOp(location, it, m_identifiers, "get_string_length");
    670             break;
    671         }
    672         case op_put_by_id: {
    673             printPutByIdOp(location, it, m_identifiers, "put_by_id");
    674             break;
    675         }
    676         case op_put_by_id_replace: {
    677             printPutByIdOp(location, it, m_identifiers, "put_by_id_replace");
    678             break;
    679         }
    680         case op_put_by_id_transition: {
    681             printPutByIdOp(location, it, m_identifiers, "put_by_id_transition");
    682             break;
    683         }
    684         case op_put_by_id_generic: {
    685             printPutByIdOp(location, it, m_identifiers, "put_by_id_generic");
    686             break;
    687         }
    688         case op_put_getter: {
    689             int r0 = (++it)->u.operand;
    690             int id0 = (++it)->u.operand;
    691             int r1 = (++it)->u.operand;
    692             printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
    693             break;
    694         }
    695         case op_put_setter: {
    696             int r0 = (++it)->u.operand;
    697             int id0 = (++it)->u.operand;
    698             int r1 = (++it)->u.operand;
    699             printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
    700             break;
    701         }
    702         case op_del_by_id: {
    703             int r0 = (++it)->u.operand;
    704             int r1 = (++it)->u.operand;
    705             int id0 = (++it)->u.operand;
    706             printf("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
    707             break;
    708         }
    709         case op_get_by_val: {
    710             int r0 = (++it)->u.operand;
    711             int r1 = (++it)->u.operand;
    712             int r2 = (++it)->u.operand;
    713             printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
    714             break;
    715         }
    716         case op_put_by_val: {
    717             int r0 = (++it)->u.operand;
    718             int r1 = (++it)->u.operand;
    719             int r2 = (++it)->u.operand;
    720             printf("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
    721             break;
    722         }
    723         case op_del_by_val: {
    724             int r0 = (++it)->u.operand;
    725             int r1 = (++it)->u.operand;
    726             int r2 = (++it)->u.operand;
    727             printf("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
    728             break;
    729         }
    730         case op_put_by_index: {
    731             int r0 = (++it)->u.operand;
    732             unsigned n0 = (++it)->u.operand;
    733             int r1 = (++it)->u.operand;
    734             printf("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(r0).c_str(), n0, registerName(r1).c_str());
    735             break;
    736         }
    737         case op_jmp: {
    738             int offset = (++it)->u.operand;
    739             printf("[%4d] jmp\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset));
    740             break;
    741         }
    742         case op_loop: {
    743             int offset = (++it)->u.operand;
    744             printf("[%4d] loop\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset));
    745             break;
    746         }
    747         case op_jtrue: {
    748             printConditionalJump(begin, it, location, "jtrue");
    749             break;
    750         }
    751         case op_loop_if_true: {
    752             printConditionalJump(begin, it, location, "loop_if_true");
    753             break;
    754         }
    755         case op_jfalse: {
    756             printConditionalJump(begin, it, location, "jfalse");
    757             break;
    758         }
    759         case op_jeq_null: {
    760             printConditionalJump(begin, it, location, "jeq_null");
    761             break;
    762         }
    763         case op_jneq_null: {
    764             printConditionalJump(begin, it, location, "jneq_null");
    765             break;
    766         }
    767         case op_jnless: {
    768             int r0 = (++it)->u.operand;
    769             int r1 = (++it)->u.operand;
    770             int offset = (++it)->u.operand;
    771             printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));
    772             break;
    773         }
    774         case op_loop_if_less: {
    775             int r0 = (++it)->u.operand;
    776             int r1 = (++it)->u.operand;
    777             int offset = (++it)->u.operand;
    778             printf("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));
    779             break;
    780         }
    781         case op_loop_if_lesseq: {
    782             int r0 = (++it)->u.operand;
    783             int r1 = (++it)->u.operand;
    784             int offset = (++it)->u.operand;
    785             printf("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));
    786             break;
    787         }
    788         case op_switch_imm: {
    789             int tableIndex = (++it)->u.operand;
    790             int defaultTarget = (++it)->u.operand;
    791             int scrutineeRegister = (++it)->u.operand;
    792             printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());
    793             break;
    794         }
    795         case op_switch_char: {
    796             int tableIndex = (++it)->u.operand;
    797             int defaultTarget = (++it)->u.operand;
    798             int scrutineeRegister = (++it)->u.operand;
    799             printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());
    800             break;
    801         }
    802         case op_switch_string: {
    803             int tableIndex = (++it)->u.operand;
    804             int defaultTarget = (++it)->u.operand;
    805             int scrutineeRegister = (++it)->u.operand;
    806             printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());
    807             break;
    808         }
    809         case op_new_func: {
    810             int r0 = (++it)->u.operand;
    811             int f0 = (++it)->u.operand;
    812             printf("[%4d] new_func\t\t %s, f%d\n", location, registerName(r0).c_str(), f0);
    813             break;
    814         }
    815         case op_new_func_exp: {
    816             int r0 = (++it)->u.operand;
    817             int f0 = (++it)->u.operand;
    818             printf("[%4d] new_func_exp\t %s, f%d\n", location, registerName(r0).c_str(), f0);
    819             break;
    820         }
    821         case op_call: {
    822             int dst = (++it)->u.operand;
    823             int func = (++it)->u.operand;
    824             int argCount = (++it)->u.operand;
    825             int registerOffset = (++it)->u.operand;
    826             printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);
    827             break;
    828         }
    829         case op_call_eval: {
    830             int dst = (++it)->u.operand;
    831             int func = (++it)->u.operand;
    832             int argCount = (++it)->u.operand;
    833             int registerOffset = (++it)->u.operand;
    834             printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);
    835             break;
    836         }
    837         case op_tear_off_activation: {
    838             int r0 = (++it)->u.operand;
    839             printf("[%4d] tear_off_activation\t %s\n", location, registerName(r0).c_str());
    840             break;
    841         }
    842         case op_tear_off_arguments: {
    843             printf("[%4d] tear_off_arguments\n", location);
    844             break;
    845         }
    846         case op_ret: {
    847             int r0 = (++it)->u.operand;
    848             printf("[%4d] ret\t\t %s\n", location, registerName(r0).c_str());
    849             break;
    850         }
    851         case op_construct: {
    852             int dst = (++it)->u.operand;
    853             int func = (++it)->u.operand;
    854             int argCount = (++it)->u.operand;
    855             int registerOffset = (++it)->u.operand;
    856             int proto = (++it)->u.operand;
    857             int thisRegister = (++it)->u.operand;
    858             printf("[%4d] construct\t %s, %s, %d, %d, %s, %s\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset, registerName(proto).c_str(), registerName(thisRegister).c_str());
    859             break;
    860         }
    861         case op_construct_verify: {
    862             int r0 = (++it)->u.operand;
    863             int r1 = (++it)->u.operand;
    864             printf("[%4d] construct_verify\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
    865             break;
    866         }
    867         case op_get_pnames: {
    868             int r0 = (++it)->u.operand;
    869             int r1 = (++it)->u.operand;
    870             printf("[%4d] get_pnames\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
    871             break;
    872         }
    873         case op_next_pname: {
    874             int dest = (++it)->u.operand;
    875             int iter = (++it)->u.operand;
    876             int offset = (++it)->u.operand;
    877             printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(dest).c_str(), registerName(iter).c_str(), offset, locationForOffset(begin, it, offset));
    878             break;
    879         }
    880         case op_push_scope: {
    881             int r0 = (++it)->u.operand;
    882             printf("[%4d] push_scope\t %s\n", location, registerName(r0).c_str());
    883             break;
    884         }
    885         case op_pop_scope: {
    886             printf("[%4d] pop_scope\n", location);
    887             break;
    888         }
    889         case op_push_new_scope: {
    890             int r0 = (++it)->u.operand;
    891             int id0 = (++it)->u.operand;
    892             int r1 = (++it)->u.operand;
    893             printf("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
    894             break;
    895         }
    896         case op_jmp_scopes: {
    897             int scopeDelta = (++it)->u.operand;
    898             int offset = (++it)->u.operand;
    899             printf("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, locationForOffset(begin, it, offset));
    900             break;
    901         }
    902         case op_catch: {
    903             int r0 = (++it)->u.operand;
    904             printf("[%4d] catch\t\t %s\n", location, registerName(r0).c_str());
    905             break;
    906         }
    907         case op_throw: {
    908             int r0 = (++it)->u.operand;
    909             printf("[%4d] throw\t\t %s\n", location, registerName(r0).c_str());
    910             break;
    911         }
    912         case op_new_error: {
    913             int r0 = (++it)->u.operand;
    914             int errorType = (++it)->u.operand;
    915             int k0 = (++it)->u.operand;
    916             printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(r0).c_str(), errorType, constantName(exec, k0, m_unexpectedConstants[k0]).c_str());
    917             break;
    918         }
    919         case op_jsr: {
    920             int retAddrDst = (++it)->u.operand;
    921             int offset = (++it)->u.operand;
    922             printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(retAddrDst).c_str(), offset, locationForOffset(begin, it, offset));
    923             break;
    924         }
    925         case op_sret: {
    926             int retAddrSrc = (++it)->u.operand;
    927             printf("[%4d] sret\t\t %s\n", location, registerName(retAddrSrc).c_str());
    928             break;
    929         }
    930         case op_debug: {
    931             int debugHookID = (++it)->u.operand;
    932             int firstLine = (++it)->u.operand;
    933             int lastLine = (++it)->u.operand;
    934             printf("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine);
    935             break;
    936         }
    937         case op_profile_will_call: {
    938             int function = (++it)->u.operand;
    939             printf("[%4d] profile_will_call %s\n", location, registerName(function).c_str());
    940             break;
    941         }
    942         case op_profile_did_call: {
    943             int function = (++it)->u.operand;
    944             printf("[%4d] profile_did_call\t %s\n", location, registerName(function).c_str());
    945             break;
    946         }
    947         case op_end: {
    948             int r0 = (++it)->u.operand;
    949             printf("[%4d] end\t\t %s\n", location, registerName(r0).c_str());
    950             break;
    951         }
    952     }
    953 }
    954 
    955 #endif // !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
    956 
    957 CodeBlock::~CodeBlock()
    958 {
    959     for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)
    960         derefStructures(&m_instructions[m_globalResolveInstructions[i]]);
    961 
    962     for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) {
    963         derefStructures(&m_instructions[m_propertyAccessInstructions[i].bytecodeIndex]);
    964         if (m_propertyAccessInstructions[i].stubRoutine)
    965             WTF::fastFreeExecutable(m_propertyAccessInstructions[i].stubRoutine);
    966     }
    967 
    968     for (size_t size = m_callLinkInfos.size(), i = 0; i < size; ++i) {
    969         CallLinkInfo* callLinkInfo = &m_callLinkInfos[i];
    970         if (callLinkInfo->isLinked())
    971             callLinkInfo->callee->removeCaller(callLinkInfo);
    972     }
    973 
    974 #if ENABLE(JIT)
    975     unlinkCallers();
    976 
    977     if (m_jitCode)
    978         WTF::fastFreeExecutable(m_jitCode);
    979 #endif
    980 }
    981 
    982 #if ENABLE(JIT)
    983 void CodeBlock::unlinkCallers()
    984 {
    985     size_t size = m_linkedCallerList.size();
    986     for (size_t i = 0; i < size; ++i) {
    987         CallLinkInfo* currentCaller = m_linkedCallerList[i];
    988         JIT::unlinkCall(currentCaller);
    989         currentCaller->setUnlinked();
    990     }
    991     m_linkedCallerList.clear();
    992 }
    993 #endif
    994 
    995 void CodeBlock::derefStructures(Instruction* vPC) const
    996 {
    997     Interpreter* interpreter = m_globalData->interpreter;
    998 
    999     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
    1000         vPC[4].u.structure->deref();
    1001         return;
    1002     }
    1003     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
    1004         vPC[4].u.structure->deref();
    1005         vPC[5].u.structure->deref();
    1006         return;
    1007     }
    1008     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
    1009         vPC[4].u.structure->deref();
    1010         vPC[5].u.structureChain->deref();
    1011         return;
    1012     }
    1013     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
    1014         vPC[4].u.structure->deref();
    1015         vPC[5].u.structure->deref();
    1016         vPC[6].u.structureChain->deref();
    1017         return;
    1018     }
    1019     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
    1020         vPC[4].u.structure->deref();
    1021         return;
    1022     }
    1023     if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) {
    1024         if(vPC[4].u.structure)
    1025             vPC[4].u.structure->deref();
    1026         return;
    1027     }
    1028     if ((vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list))
    1029         || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list))) {
    1030         PolymorphicAccessStructureList* polymorphicStructures = vPC[4].u.polymorphicStructures;
    1031         polymorphicStructures->derefStructures(vPC[5].u.operand);
    1032         delete polymorphicStructures;
    1033         return;
    1034     }
    1035 
    1036     // These instructions don't ref their Structures.
    1037     ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_get_array_length) || vPC[0].u.opcode == interpreter->getOpcode(op_get_string_length));
    1038 }
    1039 
    1040 void CodeBlock::refStructures(Instruction* vPC) const
    1041 {
    1042     Interpreter* interpreter = m_globalData->interpreter;
    1043 
    1044     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
    1045         vPC[4].u.structure->ref();
    1046         return;
    1047     }
    1048     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
    1049         vPC[4].u.structure->ref();
    1050         vPC[5].u.structure->ref();
    1051         return;
    1052     }
    1053     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
    1054         vPC[4].u.structure->ref();
    1055         vPC[5].u.structureChain->ref();
    1056         return;
    1057     }
    1058     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
    1059         vPC[4].u.structure->ref();
    1060         vPC[5].u.structure->ref();
    1061         vPC[6].u.structureChain->ref();
    1062         return;
    1063     }
    1064     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
    1065         vPC[4].u.structure->ref();
    1066         return;
    1067     }
    1068    
    1069     // These instructions don't ref their Structures.
    1070     ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic));
    1071 }
    1072 
    1073 void CodeBlock::mark()
    1074 {
    1075     for (size_t i = 0; i < m_constantRegisters.size(); ++i)
    1076         if (!m_constantRegisters[i].marked())
    1077             m_constantRegisters[i].mark();
    1078 
    1079     for (size_t i = 0; i < m_unexpectedConstants.size(); ++i)
    1080         if (!m_unexpectedConstants[i]->marked())
    1081             m_unexpectedConstants[i]->mark();
    1082 
    1083     for (size_t i = 0; i < m_functions.size(); ++i)
    1084         m_functions[i]->body()->mark();
    1085 
    1086     for (size_t i = 0; i < m_functionExpressions.size(); ++i)
    1087         m_functionExpressions[i]->body()->mark();
    1088 }
    1089 
    1090 bool CodeBlock::getHandlerForVPC(const Instruction* vPC, Instruction*& target, int& scopeDepth)
    1091 {
    1092     Vector<HandlerInfo>::iterator ptr = m_exceptionHandlers.begin();
    1093     Vector<HandlerInfo>::iterator end = m_exceptionHandlers.end();
    1094     unsigned addressOffset = vPC - m_instructions.begin();
    1095     ASSERT(addressOffset < m_instructions.size());
    1096    
    1097     for (; ptr != end; ++ptr) {
    1098         // Handlers are ordered innermost first, so the first handler we encounter
    1099         // that contains the source address is the correct handler to use.
    1100         if (ptr->start <= addressOffset && ptr->end >= addressOffset) {
    1101             scopeDepth = ptr->scopeDepth;
    1102             target = m_instructions.begin() + ptr->target;
    1103             return true;
    1104         }
    1105     }
    1106     return false;
    1107 }
    1108 
    1109 void* CodeBlock::nativeExceptionCodeForHandlerVPC(const Instruction* handlerVPC)
    1110 {
    1111     Vector<HandlerInfo>::iterator ptr = m_exceptionHandlers.begin();
    1112     Vector<HandlerInfo>::iterator end = m_exceptionHandlers.end();
    1113    
    1114     for (; ptr != end; ++ptr) {
    1115         Instruction*target = m_instructions.begin() + ptr->target;
    1116         if (handlerVPC == target)
    1117             return ptr->nativeCode;
    1118     }
    1119 
    1120     return 0;
    1121 }
    1122 
    1123 int CodeBlock::lineNumberForVPC(const Instruction* vPC)
    1124 {
    1125     unsigned instructionOffset = vPC - m_instructions.begin();
    1126     ASSERT(instructionOffset < m_instructions.size());
    1127 
    1128     if (!m_lineInfo.size())
    1129         return m_ownerNode->source().firstLine(); // Empty function
    1130 
    1131     int low = 0;
    1132     int high = m_lineInfo.size();
    1133     while (low < high) {
    1134         int mid = low + (high - low) / 2;
    1135         if (m_lineInfo[mid].instructionOffset <= instructionOffset)
    1136             low = mid + 1;
    1137         else
    1138             high = mid;
    1139     }
    1140    
    1141     if (!low)
    1142         return m_ownerNode->source().firstLine();
    1143     return m_lineInfo[low - 1].lineNumber;
    1144 }
    1145 
    1146 int CodeBlock::expressionRangeForVPC(const Instruction* vPC, int& divot, int& startOffset, int& endOffset)
    1147 {
    1148     unsigned instructionOffset = vPC - m_instructions.begin();
    1149     ASSERT(instructionOffset < m_instructions.size());
    1150 
    1151     if (!m_expressionInfo.size()) {
    1152         // We didn't think anything could throw.  Apparently we were wrong.
    1153         startOffset = 0;
    1154         endOffset = 0;
    1155         divot = 0;
    1156         return lineNumberForVPC(vPC);
    1157     }
    1158 
    1159     int low = 0;
    1160     int high = m_expressionInfo.size();
    1161     while (low < high) {
    1162         int mid = low + (high - low) / 2;
    1163         if (m_expressionInfo[mid].instructionOffset <= instructionOffset)
    1164             low = mid + 1;
    1165         else
    1166             high = mid;
    1167     }
    1168    
    1169     ASSERT(low);
    1170     if (!low) {
    1171         startOffset = 0;
    1172         endOffset = 0;
    1173         divot = 0;
    1174         return lineNumberForVPC(vPC);
    1175     }
    1176 
    1177     startOffset = m_expressionInfo[low - 1].startOffset;
    1178     endOffset = m_expressionInfo[low - 1].endOffset;
    1179     divot = m_expressionInfo[low - 1].divotPoint + m_sourceOffset;
    1180     return lineNumberForVPC(vPC);
    1181 }
    1182 
    1183 void CodeBlock::shrinkToFit()
    1184 {
    1185     m_instructions.shrinkToFit();
    1186 
    1187     m_globalResolveInstructions.shrinkToFit();
    1188     m_propertyAccessInstructions.shrinkToFit();
    1189     m_callLinkInfos.shrinkToFit();
    1190     m_linkedCallerList.shrinkToFit();
    1191 
    1192     m_exceptionHandlers.shrinkToFit();
    1193     m_expressionInfo.shrinkToFit();
    1194     m_lineInfo.shrinkToFit();
    1195 
    1196     m_identifiers.shrinkToFit();
    1197     m_functions.shrinkToFit();
    1198     m_functionExpressions.shrinkToFit();
    1199     m_constantRegisters.shrinkToFit();
    1200     m_unexpectedConstants.shrinkToFit();
    1201     m_regexps.shrinkToFit();
    1202 
    1203     m_immediateSwitchJumpTables.shrinkToFit();
    1204     m_characterSwitchJumpTables.shrinkToFit();
    1205     m_stringSwitchJumpTables.shrinkToFit();
    1206 }
    120734
    120835int32_t SimpleJumpTable::offsetForValue(int32_t value, int32_t defaultOffset)
  • trunk/JavaScriptCore/bytecode/JumpTable.h

    r39070 r39071  
    2828 */
    2929
    30 #ifndef CodeBlock_h
    31 #define CodeBlock_h
     30#ifndef JumpTable_h
     31#define JumpTable_h
    3232
    33 #include "EvalCodeCache.h"
    34 #include "Instruction.h"
    35 #include "JSGlobalObject.h"
    36 #include "Nodes.h"
    37 #include "RegExp.h"
    3833#include "UString.h"
    39 #include <wtf/RefPtr.h>
     34#include <wtf/HashMap.h>
    4035#include <wtf/Vector.h>
    4136
    4237namespace JSC {
    43 
    44     class ExecState;
    45 
    46     enum CodeType { GlobalCode, EvalCode, FunctionCode };
    47 
    48     static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); }
    49 
    50     struct HandlerInfo {
    51         uint32_t start;
    52         uint32_t end;
    53         uint32_t target;
    54         uint32_t scopeDepth;
    55         void* nativeCode;
    56     };
    57 
    58     struct ExpressionRangeInfo {
    59         enum {
    60             MaxOffset = (1 << 7) - 1,
    61             MaxDivot = (1 << 25) - 1
    62         };
    63         uint32_t instructionOffset : 25;
    64         uint32_t divotPoint : 25;
    65         uint32_t startOffset : 7;
    66         uint32_t endOffset : 7;
    67     };
    68 
    69     struct LineInfo {
    70         uint32_t instructionOffset;
    71         int32_t lineNumber;
    72     };
    7338
    7439    struct OffsetLocation {
     
    7843#endif
    7944    };
    80 
    81     struct StructureStubInfo {
    82         StructureStubInfo(unsigned bytecodeIndex)
    83             : bytecodeIndex(bytecodeIndex)
    84             , stubRoutine(0)
    85             , callReturnLocation(0)
    86             , hotPathBegin(0)
    87         {
    88         }
    89    
    90         unsigned bytecodeIndex;
    91         void* stubRoutine;
    92         void* callReturnLocation;
    93         void* hotPathBegin;
    94     };
    95 
    96     struct CallLinkInfo {
    97         CallLinkInfo()
    98             : callReturnLocation(0)
    99             , hotPathBegin(0)
    100             , hotPathOther(0)
    101             , coldPathOther(0)
    102             , callee(0)
    103         {
    104         }
    105    
    106         unsigned bytecodeIndex;
    107         void* callReturnLocation;
    108         void* hotPathBegin;
    109         void* hotPathOther;
    110         void* coldPathOther;
    111         CodeBlock* callee;
    112         unsigned position;
    113        
    114         void setUnlinked() { callee = 0; }
    115         bool isLinked() { return callee; }
    116     };
    117 
    118     inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo)
    119     {
    120         return structureStubInfo->callReturnLocation;
    121     }
    122 
    123     inline void* getCallLinkInfoReturnLocation(CallLinkInfo* callLinkInfo)
    124     {
    125         return callLinkInfo->callReturnLocation;
    126     }
    127 
    128     // Binary chop algorithm, calls valueAtPosition on pre-sorted elements in array,
    129     // compares result with key (KeyTypes should be comparable with '--', '<', '>').
    130     // Optimized for cases where the array contains the key, checked by assertions.
    131     template<typename ArrayType, typename KeyType, KeyType(*valueAtPosition)(ArrayType*)>
    132     inline ArrayType* binaryChop(ArrayType* array, size_t size, KeyType key)
    133     {
    134         // The array must contain at least one element (pre-condition, array does conatin key).
    135         // If the array only contains one element, no need to do the comparison.
    136         while (size > 1) {
    137             // Pick an element to check, half way through the array, and read the value.
    138             int pos = (size - 1) >> 1;
    139             KeyType val = valueAtPosition(&array[pos]);
    140            
    141             // If the key matches, success!
    142             if (val == key)
    143                 return &array[pos];
    144             // The item we are looking for is smaller than the item being check; reduce the value of 'size',
    145             // chopping off the right hand half of the array.
    146             else if (key < val)
    147                 size = pos;
    148             // Discard all values in the left hand half of the array, up to and including the item at pos.
    149             else {
    150                 size -= (pos + 1);
    151                 array += (pos + 1);
    152             }
    153 
    154             // 'size' should never reach zero.
    155             ASSERT(size);
    156         }
    157        
    158         // If we reach this point we've chopped down to one element, no need to check it matches
    159         ASSERT(size == 1);
    160         ASSERT(key == valueAtPosition(&array[0]));
    161         return &array[0];
    162     }
    16345
    16446    struct StringJumpTable {
     
    21698    };
    21799
    218     class CodeBlock {
    219         friend class JIT;
    220     public:
    221         CodeBlock(ScopeNode* ownerNode, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset)
    222             : m_numCalleeRegisters(0)
    223             , m_numConstants(0)
    224             , m_numVars(0)
    225             , m_numParameters(0)
    226             , m_ownerNode(ownerNode)
    227             , m_globalData(0)
    228 #if ENABLE(JIT)
    229             , m_jitCode(0)
    230 #endif
    231             , m_needsFullScopeChain(ownerNode->needsActivation())
    232             , m_usesEval(ownerNode->usesEval())
    233             , m_codeType(codeType)
    234             , m_source(sourceProvider)
    235             , m_sourceOffset(sourceOffset)
    236         {
    237             ASSERT(m_source);
    238         }
    239 
    240         ~CodeBlock();
    241 
    242 #if ENABLE(JIT)
    243         void unlinkCallers();
    244 #endif
    245 
    246         void addCaller(CallLinkInfo* caller)
    247         {
    248             caller->callee = this;
    249             caller->position = m_linkedCallerList.size();
    250             m_linkedCallerList.append(caller);
    251         }
    252 
    253         void removeCaller(CallLinkInfo* caller)
    254         {
    255             unsigned pos = caller->position;
    256             unsigned lastPos = m_linkedCallerList.size() - 1;
    257 
    258             if (pos != lastPos) {
    259                 m_linkedCallerList[pos] = m_linkedCallerList[lastPos];
    260                 m_linkedCallerList[pos]->position = pos;
    261             }
    262             m_linkedCallerList.shrink(lastPos);
    263         }
    264 
    265         inline bool isKnownNotImmediate(int index)
    266         {
    267             if (index == m_thisRegister)
    268                 return true;
    269 
    270             if (isConstantRegisterIndex(index))
    271                 return !JSImmediate::isImmediate(getConstant(index));
    272 
    273             return false;
    274         }
    275 
    276         ALWAYS_INLINE bool isConstantRegisterIndex(int index)
    277         {
    278             return index >= m_numVars && index < m_numVars + m_numConstants;
    279         }
    280 
    281         ALWAYS_INLINE JSValue* getConstant(int index)
    282         {
    283             return m_constantRegisters[index - m_numVars].getJSValue();
    284         }
    285 
    286         ALWAYS_INLINE bool isTemporaryRegisterIndex(int index)
    287         {
    288             return index >= m_numVars + m_numConstants;
    289         }
    290 
    291 #if !defined(NDEBUG) || ENABLE_OPCODE_SAMPLING
    292         void dump(ExecState*) const;
    293         void printStructures(const Instruction*) const;
    294         void printStructure(const char* name, const Instruction*, int operand) const;
    295 #endif
    296         int expressionRangeForVPC(const Instruction*, int& divot, int& startOffset, int& endOffset);
    297         int lineNumberForVPC(const Instruction* vPC);
    298         bool getHandlerForVPC(const Instruction* vPC, Instruction*& target, int& scopeDepth);
    299         void* nativeExceptionCodeForHandlerVPC(const Instruction* handlerVPC);
    300 
    301         void mark();
    302         void refStructures(Instruction* vPC) const;
    303         void derefStructures(Instruction* vPC) const;
    304 
    305         StructureStubInfo& getStubInfo(void* returnAddress)
    306         {
    307             return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_propertyAccessInstructions.begin(), m_propertyAccessInstructions.size(), returnAddress));
    308         }
    309 
    310         CallLinkInfo& getCallLinkInfo(void* returnAddress)
    311         {
    312             return *(binaryChop<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress));
    313         }
    314 
    315 
    316         Vector<Instruction>& instructions() { return m_instructions; }
    317 #if ENABLE(JIT)
    318         void setJITCode(void* jitCode) { m_jitCode = jitCode; }
    319         void* jitCode() { return m_jitCode; }
    320 #endif
    321 
    322         ScopeNode* ownerNode() const { return m_ownerNode; }
    323 
    324         void setGlobalData(JSGlobalData* globalData) { m_globalData = globalData; }
    325 
    326         void setThisRegister(int thisRegister) { m_thisRegister = thisRegister; }
    327         int thisRegister() const { return m_thisRegister; }
    328 
    329         void setNeedsFullScopeChain(bool needsFullScopeChain) { m_needsFullScopeChain = needsFullScopeChain; }
    330         bool needsFullScopeChain() const { return m_needsFullScopeChain; }
    331         void setUsesEval(bool usesEval) { m_usesEval = usesEval; }
    332         bool usesEval() const { return m_usesEval; }
    333         void setUsesArguments(bool usesArguments) { m_usesArguments = usesArguments; }
    334         bool usesArguments() const { return m_usesArguments; }
    335 
    336         CodeType codeType() const { return m_codeType; }
    337 
    338         SourceProvider* source() const { return m_source.get(); }
    339         unsigned sourceOffset() const { return m_sourceOffset; }
    340 
    341         void addGlobalResolveInstruction(unsigned globalResolveInstructions) { m_globalResolveInstructions.append(globalResolveInstructions); }
    342 
    343         size_t numberOfPropertyAccessInstructions() const { return m_propertyAccessInstructions.size(); }
    344         void addPropertyAccessInstruction(unsigned propertyAccessInstructions) { m_propertyAccessInstructions.append(StructureStubInfo(propertyAccessInstructions)); }
    345         StructureStubInfo& propertyAccessInstruction(int index) { return m_propertyAccessInstructions[index]; }
    346 
    347         size_t numberOfCallLinkInfos() const { return m_callLinkInfos.size(); }
    348         void addCallLinkInfo() { m_callLinkInfos.append(CallLinkInfo()); }
    349         CallLinkInfo& callLinkInfo(int index) { return m_callLinkInfos[index]; }
    350 
    351         size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }
    352         void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }
    353         unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
    354         unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
    355 
    356         size_t numberOfExceptionHandlers() const { return m_exceptionHandlers.size(); }
    357         void addExceptionHandler(const HandlerInfo& hanler) { return m_exceptionHandlers.append(hanler); }
    358         HandlerInfo& exceptionHandler(int index) { return m_exceptionHandlers[index]; }
    359 
    360         void addExpressionInfo(const ExpressionRangeInfo& expressionInfo) { return m_expressionInfo.append(expressionInfo); }
    361 
    362         size_t numberOfLineInfos() const { return m_lineInfo.size(); }
    363         void addLineInfo(const LineInfo& lineInfo) { return m_lineInfo.append(lineInfo); }
    364         LineInfo& lastLineInfo() { return m_lineInfo.last(); }
    365 
    366 #if ENABLE(JIT)
    367         HashMap<void*, unsigned>& jitReturnAddressVPCMap() { return m_jitReturnAddressVPCMap; }
    368 #endif
    369 
    370         // Constant Pool
    371 
    372         size_t numberOfIdentifiers() const { return m_identifiers.size(); }
    373         void addIdentifier(const Identifier& i) { return m_identifiers.append(i); }
    374         Identifier& identifier(int index) { return m_identifiers[index]; }
    375 
    376         size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); }
    377         void addConstantRegister(const Register& r) { return m_constantRegisters.append(r); }
    378         Register& constantRegister(int index) { return m_constantRegisters[index]; }
    379 
    380         unsigned addFunction(FuncDeclNode* n) { unsigned size = m_functions.size(); m_functions.append(n); return size; }
    381         FuncDeclNode* function(int index) const { return m_functions[index].get(); }
    382 
    383         unsigned addFunctionExpression(FuncExprNode* n) { unsigned size = m_functionExpressions.size(); m_functionExpressions.append(n); return size; }
    384         FuncExprNode* functionExpression(int index) const { return m_functionExpressions[index].get(); }
    385 
    386         unsigned addUnexpectedConstant(JSValue* v) { unsigned size = m_unexpectedConstants.size(); m_unexpectedConstants.append(v); return size; }
    387         JSValue* unexpectedConstant(int index) const { return m_unexpectedConstants[index]; }
    388 
    389         unsigned addRegExp(RegExp* r) { unsigned size = m_regexps.size(); m_regexps.append(r); return size; }
    390         RegExp* regexp(int index) const { return m_regexps[index].get(); }
    391 
    392         // Jump Tables
    393 
    394         size_t numberOfImmediateSwitchJumpTables() const { return m_immediateSwitchJumpTables.size(); }
    395         SimpleJumpTable& addImmediateSwitchJumpTable() { m_immediateSwitchJumpTables.append(SimpleJumpTable()); return m_immediateSwitchJumpTables.last(); }
    396         SimpleJumpTable& immediateSwitchJumpTable(int tableIndex) { return m_immediateSwitchJumpTables[tableIndex]; }
    397 
    398         size_t numberOfCharacterSwitchJumpTables() const { return m_characterSwitchJumpTables.size(); }
    399         SimpleJumpTable& addCharacterSwitchJumpTable() { m_characterSwitchJumpTables.append(SimpleJumpTable()); return m_characterSwitchJumpTables.last(); }
    400         SimpleJumpTable& characterSwitchJumpTable(int tableIndex) { return m_characterSwitchJumpTables[tableIndex]; }
    401 
    402         size_t numberOfStringSwitchJumpTables() const { return m_stringSwitchJumpTables.size(); }
    403         StringJumpTable& addStringSwitchJumpTable() { m_stringSwitchJumpTables.append(StringJumpTable()); return m_stringSwitchJumpTables.last(); }
    404         StringJumpTable& stringSwitchJumpTable(int tableIndex) { return m_stringSwitchJumpTables[tableIndex]; }
    405 
    406 
    407         SymbolTable& symbolTable() { return m_symbolTable; }
    408         EvalCodeCache& evalCodeCache() { return m_evalCodeCache; }
    409 
    410         void shrinkToFit();
    411 
    412         // FIXME: Make these remaining members private.
    413 
    414         int m_numCalleeRegisters;
    415         // NOTE: numConstants holds the number of constant registers allocated
    416         // by the code generator, not the number of constant registers used.
    417         // (Duplicate constants are uniqued during code generation, and spare
    418         // constant registers may be allocated.)
    419         int m_numConstants;
    420         int m_numVars;
    421         int m_numParameters;
    422 
    423     private:
    424 #if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
    425         void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&) const;
    426 #endif
    427 
    428         ScopeNode* m_ownerNode;
    429         JSGlobalData* m_globalData;
    430 
    431         Vector<Instruction> m_instructions;
    432 #if ENABLE(JIT)
    433         void* m_jitCode;
    434 #endif
    435 
    436         int m_thisRegister;
    437 
    438         bool m_needsFullScopeChain;
    439         bool m_usesEval;
    440         bool m_usesArguments;
    441 
    442         CodeType m_codeType;
    443 
    444         RefPtr<SourceProvider> m_source;
    445         unsigned m_sourceOffset;
    446 
    447         Vector<unsigned> m_globalResolveInstructions;
    448         Vector<StructureStubInfo> m_propertyAccessInstructions;
    449         Vector<CallLinkInfo> m_callLinkInfos;
    450         Vector<CallLinkInfo*> m_linkedCallerList;
    451 
    452         Vector<unsigned> m_jumpTargets;
    453 
    454         Vector<HandlerInfo> m_exceptionHandlers;
    455         Vector<ExpressionRangeInfo> m_expressionInfo;
    456         Vector<LineInfo> m_lineInfo;
    457 
    458 #if ENABLE(JIT)
    459         HashMap<void*, unsigned> m_jitReturnAddressVPCMap;
    460 #endif
    461 
    462         // Constant Pool
    463         Vector<Identifier> m_identifiers;
    464         Vector<Register> m_constantRegisters;
    465         Vector<RefPtr<FuncDeclNode> > m_functions;
    466         Vector<RefPtr<FuncExprNode> > m_functionExpressions;
    467         Vector<JSValue*> m_unexpectedConstants;
    468         Vector<RefPtr<RegExp> > m_regexps;
    469 
    470         // Jump Tables
    471         Vector<SimpleJumpTable> m_immediateSwitchJumpTables;
    472         Vector<SimpleJumpTable> m_characterSwitchJumpTables;
    473         Vector<StringJumpTable> m_stringSwitchJumpTables;
    474 
    475         SymbolTable m_symbolTable;
    476 
    477         EvalCodeCache m_evalCodeCache;
    478     };
    479 
    480     // Program code is not marked by any function, so we make the global object
    481     // responsible for marking it.
    482 
    483     class ProgramCodeBlock : public CodeBlock {
    484     public:
    485         ProgramCodeBlock(ScopeNode* ownerNode, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider)
    486             : CodeBlock(ownerNode, codeType, sourceProvider, 0)
    487             , m_globalObject(globalObject)
    488         {
    489             m_globalObject->codeBlocks().add(this);
    490         }
    491 
    492         ~ProgramCodeBlock()
    493         {
    494             if (m_globalObject)
    495                 m_globalObject->codeBlocks().remove(this);
    496         }
    497 
    498         void clearGlobalObject() { m_globalObject = 0; }
    499 
    500     private:
    501         JSGlobalObject* m_globalObject; // For program and eval nodes, the global object that marks the constant pool.
    502     };
    503 
    504     class EvalCodeBlock : public ProgramCodeBlock {
    505     public:
    506         EvalCodeBlock(ScopeNode* ownerNode, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider)
    507             : ProgramCodeBlock(ownerNode, EvalCode, globalObject, sourceProvider)
    508         {
    509         }
    510     };
    511 
    512100} // namespace JSC
    513101
    514 #endif // CodeBlock_h
     102#endif // JumpTable_h
Note: See TracChangeset for help on using the changeset viewer.