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.
File:
1 copied

Legend:

Unmodified
Added
Removed
  • 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)
Note: See TracChangeset for help on using the changeset viewer.