JavaScriptCore/bytecode/CodeBlock.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
       
     3  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
       
     4  *
       
     5  * Redistribution and use in source and binary forms, with or without
       
     6  * modification, are permitted provided that the following conditions
       
     7  * are met:
       
     8  *
       
     9  * 1.  Redistributions of source code must retain the above copyright
       
    10  *     notice, this list of conditions and the following disclaimer.
       
    11  * 2.  Redistributions in binary form must reproduce the above copyright
       
    12  *     notice, this list of conditions and the following disclaimer in the
       
    13  *     documentation and/or other materials provided with the distribution.
       
    14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
       
    15  *     its contributors may be used to endorse or promote products derived
       
    16  *     from this software without specific prior written permission.
       
    17  *
       
    18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
       
    19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
    20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
       
    21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
       
    22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
       
    23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
       
    24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
       
    25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
       
    27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    28  */
       
    29 
       
    30 #include "config.h"
       
    31 #include "CodeBlock.h"
       
    32 
       
    33 #include "JIT.h"
       
    34 #include "JSValue.h"
       
    35 #include "Interpreter.h"
       
    36 #include "JSFunction.h"
       
    37 #include "JSStaticScopeObject.h"
       
    38 #include "Debugger.h"
       
    39 #include "BytecodeGenerator.h"
       
    40 #include <stdio.h>
       
    41 #include <wtf/StringExtras.h>
       
    42 
       
    43 #define DUMP_CODE_BLOCK_STATISTICS 0
       
    44 
       
    45 namespace JSC {
       
    46 
       
    47 #if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
       
    48 
       
    49 static UString escapeQuotes(const UString& str)
       
    50 {
       
    51     UString result = str;
       
    52     unsigned pos = 0;
       
    53     while ((pos = result.find('\"', pos)) != UString::NotFound) {
       
    54         result = makeString(result.substr(0, pos), "\"\\\"\"", result.substr(pos + 1));
       
    55         pos += 4;
       
    56     }
       
    57     return result;
       
    58 }
       
    59 
       
    60 static UString valueToSourceString(ExecState* exec, JSValue val)
       
    61 {
       
    62     if (!val)
       
    63         return "0";
       
    64 
       
    65     if (val.isString())
       
    66         return makeString("\"", escapeQuotes(val.toString(exec)), "\"");
       
    67 
       
    68     return val.toString(exec);
       
    69 }
       
    70 
       
    71 static CString constantName(ExecState* exec, int k, JSValue value)
       
    72 {
       
    73     return makeString(valueToSourceString(exec, value), "(@k", UString::from(k - FirstConstantRegisterIndex), ")").UTF8String();
       
    74 }
       
    75 
       
    76 static CString idName(int id0, const Identifier& ident)
       
    77 {
       
    78     return makeString(ident.ustring(), "(@id", UString::from(id0), ")").UTF8String();
       
    79 }
       
    80 
       
    81 CString CodeBlock::registerName(ExecState* exec, int r) const
       
    82 {
       
    83     if (r == missingThisObjectMarker())
       
    84         return "<null>";
       
    85 
       
    86     if (isConstantRegisterIndex(r))
       
    87         return constantName(exec, r, getConstant(r));
       
    88 
       
    89     return makeString("r", UString::from(r)).UTF8String();
       
    90 }
       
    91 
       
    92 static UString regexpToSourceString(RegExp* regExp)
       
    93 {
       
    94     char postfix[5] = { '/', 0, 0, 0, 0 };
       
    95     int index = 1;
       
    96     if (regExp->global())
       
    97         postfix[index++] = 'g';
       
    98     if (regExp->ignoreCase())
       
    99         postfix[index++] = 'i';
       
   100     if (regExp->multiline())
       
   101         postfix[index] = 'm';
       
   102 
       
   103     return makeString("/", regExp->pattern(), postfix);
       
   104 }
       
   105 
       
   106 static CString regexpName(int re, RegExp* regexp)
       
   107 {
       
   108     return makeString(regexpToSourceString(regexp), "(@re", UString::from(re), ")").UTF8String();
       
   109 }
       
   110 
       
   111 static UString pointerToSourceString(void* p)
       
   112 {
       
   113     char buffer[2 + 2 * sizeof(void*) + 1]; // 0x [two characters per byte] \0
       
   114     snprintf(buffer, sizeof(buffer), "%p", p);
       
   115     return buffer;
       
   116 }
       
   117 
       
   118 NEVER_INLINE static const char* debugHookName(int debugHookID)
       
   119 {
       
   120     switch (static_cast<DebugHookID>(debugHookID)) {
       
   121         case DidEnterCallFrame:
       
   122             return "didEnterCallFrame";
       
   123         case WillLeaveCallFrame:
       
   124             return "willLeaveCallFrame";
       
   125         case WillExecuteStatement:
       
   126             return "willExecuteStatement";
       
   127         case WillExecuteProgram:
       
   128             return "willExecuteProgram";
       
   129         case DidExecuteProgram:
       
   130             return "didExecuteProgram";
       
   131         case DidReachBreakpoint:
       
   132             return "didReachBreakpoint";
       
   133     }
       
   134 
       
   135     ASSERT_NOT_REACHED();
       
   136     return "";
       
   137 }
       
   138 
       
   139 void CodeBlock::printUnaryOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
       
   140 {
       
   141     int r0 = (++it)->u.operand;
       
   142     int r1 = (++it)->u.operand;
       
   143 
       
   144     printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data());
       
   145 }
       
   146 
       
   147 void CodeBlock::printBinaryOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
       
   148 {
       
   149     int r0 = (++it)->u.operand;
       
   150     int r1 = (++it)->u.operand;
       
   151     int r2 = (++it)->u.operand;
       
   152     printf("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
       
   153 }
       
   154 
       
   155 void CodeBlock::printConditionalJump(ExecState* exec, const Vector<Instruction>::const_iterator&, Vector<Instruction>::const_iterator& it, int location, const char* op) const
       
   156 {
       
   157     int r0 = (++it)->u.operand;
       
   158     int offset = (++it)->u.operand;
       
   159     printf("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(exec, r0).data(), offset, location + offset);
       
   160 }
       
   161 
       
   162 void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
       
   163 {
       
   164     int r0 = (++it)->u.operand;
       
   165     int r1 = (++it)->u.operand;
       
   166     int id0 = (++it)->u.operand;
       
   167     printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
       
   168     it += 4;
       
   169 }
       
   170 
       
   171 void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
       
   172 {
       
   173     int r0 = (++it)->u.operand;
       
   174     int id0 = (++it)->u.operand;
       
   175     int r1 = (++it)->u.operand;
       
   176     printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data());
       
   177     it += 5;
       
   178 }
       
   179 
       
   180 #if ENABLE(JIT)
       
   181 static bool isGlobalResolve(OpcodeID opcodeID)
       
   182 {
       
   183     return opcodeID == op_resolve_global || opcodeID == op_resolve_global_dynamic;
       
   184 }
       
   185 
       
   186 static bool isPropertyAccess(OpcodeID opcodeID)
       
   187 {
       
   188     switch (opcodeID) {
       
   189         case op_get_by_id_self:
       
   190         case op_get_by_id_proto:
       
   191         case op_get_by_id_chain:
       
   192         case op_get_by_id_self_list:
       
   193         case op_get_by_id_proto_list:
       
   194         case op_put_by_id_transition:
       
   195         case op_put_by_id_replace:
       
   196         case op_get_by_id:
       
   197         case op_put_by_id:
       
   198         case op_get_by_id_generic:
       
   199         case op_put_by_id_generic:
       
   200         case op_get_array_length:
       
   201         case op_get_string_length:
       
   202             return true;
       
   203         default:
       
   204             return false;
       
   205     }
       
   206 }
       
   207 
       
   208 static unsigned instructionOffsetForNth(ExecState* exec, const Vector<Instruction>& instructions, int nth, bool (*predicate)(OpcodeID))
       
   209 {
       
   210     size_t i = 0;
       
   211     while (i < instructions.size()) {
       
   212         OpcodeID currentOpcode = exec->interpreter()->getOpcodeID(instructions[i].u.opcode);
       
   213         if (predicate(currentOpcode)) {
       
   214             if (!--nth)
       
   215                 return i;
       
   216         }
       
   217         i += opcodeLengths[currentOpcode];
       
   218     }
       
   219 
       
   220     ASSERT_NOT_REACHED();
       
   221     return 0;
       
   222 }
       
   223 
       
   224 static void printGlobalResolveInfo(const GlobalResolveInfo& resolveInfo, unsigned instructionOffset)
       
   225 {
       
   226     printf("  [%4d] %s: %s\n", instructionOffset, "resolve_global", pointerToSourceString(resolveInfo.structure).UTF8String().data());
       
   227 }
       
   228 
       
   229 static void printStructureStubInfo(const StructureStubInfo& stubInfo, unsigned instructionOffset)
       
   230 {
       
   231     switch (stubInfo.accessType) {
       
   232     case access_get_by_id_self:
       
   233         printf("  [%4d] %s: %s\n", instructionOffset, "get_by_id_self", pointerToSourceString(stubInfo.u.getByIdSelf.baseObjectStructure).UTF8String().data());
       
   234         return;
       
   235     case access_get_by_id_proto:
       
   236         printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(stubInfo.u.getByIdProto.baseObjectStructure).UTF8String().data(), pointerToSourceString(stubInfo.u.getByIdProto.prototypeStructure).UTF8String().data());
       
   237         return;
       
   238     case access_get_by_id_chain:
       
   239         printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(stubInfo.u.getByIdChain.baseObjectStructure).UTF8String().data(), pointerToSourceString(stubInfo.u.getByIdChain.chain).UTF8String().data());
       
   240         return;
       
   241     case access_get_by_id_self_list:
       
   242         printf("  [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_self_list", pointerToSourceString(stubInfo.u.getByIdSelfList.structureList).UTF8String().data(), stubInfo.u.getByIdSelfList.listSize);
       
   243         return;
       
   244     case access_get_by_id_proto_list:
       
   245         printf("  [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_proto_list", pointerToSourceString(stubInfo.u.getByIdProtoList.structureList).UTF8String().data(), stubInfo.u.getByIdProtoList.listSize);
       
   246         return;
       
   247     case access_put_by_id_transition:
       
   248         printf("  [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(stubInfo.u.putByIdTransition.previousStructure).UTF8String().data(), pointerToSourceString(stubInfo.u.putByIdTransition.structure).UTF8String().data(), pointerToSourceString(stubInfo.u.putByIdTransition.chain).UTF8String().data());
       
   249         return;
       
   250     case access_put_by_id_replace:
       
   251         printf("  [%4d] %s: %s\n", instructionOffset, "put_by_id_replace", pointerToSourceString(stubInfo.u.putByIdReplace.baseObjectStructure).UTF8String().data());
       
   252         return;
       
   253     case access_get_by_id:
       
   254         printf("  [%4d] %s\n", instructionOffset, "get_by_id");
       
   255         return;
       
   256     case access_put_by_id:
       
   257         printf("  [%4d] %s\n", instructionOffset, "put_by_id");
       
   258         return;
       
   259     case access_get_by_id_generic:
       
   260         printf("  [%4d] %s\n", instructionOffset, "op_get_by_id_generic");
       
   261         return;
       
   262     case access_put_by_id_generic:
       
   263         printf("  [%4d] %s\n", instructionOffset, "op_put_by_id_generic");
       
   264         return;
       
   265     case access_get_array_length:
       
   266         printf("  [%4d] %s\n", instructionOffset, "op_get_array_length");
       
   267         return;
       
   268     case access_get_string_length:
       
   269         printf("  [%4d] %s\n", instructionOffset, "op_get_string_length");
       
   270         return;
       
   271     default:
       
   272         ASSERT_NOT_REACHED();
       
   273     }
       
   274 }
       
   275 #endif
       
   276 
       
   277 void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand) const
       
   278 {
       
   279     unsigned instructionOffset = vPC - m_instructions.begin();
       
   280     printf("  [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).UTF8String().data());
       
   281 }
       
   282 
       
   283 void CodeBlock::printStructures(const Instruction* vPC) const
       
   284 {
       
   285     Interpreter* interpreter = m_globalData->interpreter;
       
   286     unsigned instructionOffset = vPC - m_instructions.begin();
       
   287 
       
   288     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id)) {
       
   289         printStructure("get_by_id", vPC, 4);
       
   290         return;
       
   291     }
       
   292     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
       
   293         printStructure("get_by_id_self", vPC, 4);
       
   294         return;
       
   295     }
       
   296     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
       
   297         printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structure).UTF8String().data(), pointerToSourceString(vPC[5].u.structure).UTF8String().data());
       
   298         return;
       
   299     }
       
   300     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
       
   301         printf("  [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(vPC[4].u.structure).UTF8String().data(), pointerToSourceString(vPC[5].u.structure).UTF8String().data(), pointerToSourceString(vPC[6].u.structureChain).UTF8String().data());
       
   302         return;
       
   303     }
       
   304     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
       
   305         printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structure).UTF8String().data(), pointerToSourceString(vPC[5].u.structureChain).UTF8String().data());
       
   306         return;
       
   307     }
       
   308     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id)) {
       
   309         printStructure("put_by_id", vPC, 4);
       
   310         return;
       
   311     }
       
   312     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
       
   313         printStructure("put_by_id_replace", vPC, 4);
       
   314         return;
       
   315     }
       
   316     if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) {
       
   317         printStructure("resolve_global", vPC, 4);
       
   318         return;
       
   319     }
       
   320     if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global_dynamic)) {
       
   321         printStructure("resolve_global_dynamic", vPC, 4);
       
   322         return;
       
   323     }
       
   324 
       
   325     // These m_instructions doesn't ref Structures.
       
   326     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));
       
   327 }
       
   328 
       
   329 void CodeBlock::dump(ExecState* exec) const
       
   330 {
       
   331     if (m_instructions.isEmpty()) {
       
   332         printf("No instructions available.\n");
       
   333         return;
       
   334     }
       
   335 
       
   336     size_t instructionCount = 0;
       
   337 
       
   338     for (size_t i = 0; i < m_instructions.size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(m_instructions[i].u.opcode)])
       
   339         ++instructionCount;
       
   340 
       
   341     printf("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n",
       
   342         static_cast<unsigned long>(instructionCount),
       
   343         static_cast<unsigned long>(m_instructions.size() * sizeof(Instruction)),
       
   344         this, m_numParameters, m_numCalleeRegisters);
       
   345 
       
   346     Vector<Instruction>::const_iterator begin = m_instructions.begin();
       
   347     Vector<Instruction>::const_iterator end = m_instructions.end();
       
   348     for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)
       
   349         dump(exec, begin, it);
       
   350 
       
   351     if (!m_identifiers.isEmpty()) {
       
   352         printf("\nIdentifiers:\n");
       
   353         size_t i = 0;
       
   354         do {
       
   355             printf("  id%u = %s\n", static_cast<unsigned>(i), m_identifiers[i].ascii());
       
   356             ++i;
       
   357         } while (i != m_identifiers.size());
       
   358     }
       
   359 
       
   360     if (!m_constantRegisters.isEmpty()) {
       
   361         printf("\nConstants:\n");
       
   362         unsigned registerIndex = m_numVars;
       
   363         size_t i = 0;
       
   364         do {
       
   365             printf("   k%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue()).ascii());
       
   366             ++i;
       
   367             ++registerIndex;
       
   368         } while (i < m_constantRegisters.size());
       
   369     }
       
   370 
       
   371     if (m_rareData && !m_rareData->m_regexps.isEmpty()) {
       
   372         printf("\nm_regexps:\n");
       
   373         size_t i = 0;
       
   374         do {
       
   375             printf("  re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_rareData->m_regexps[i].get()).ascii());
       
   376             ++i;
       
   377         } while (i < m_rareData->m_regexps.size());
       
   378     }
       
   379 
       
   380 #if ENABLE(JIT)
       
   381     if (!m_globalResolveInfos.isEmpty() || !m_structureStubInfos.isEmpty())
       
   382         printf("\nStructures:\n");
       
   383 
       
   384     if (!m_globalResolveInfos.isEmpty()) {
       
   385         size_t i = 0;
       
   386         do {
       
   387              printGlobalResolveInfo(m_globalResolveInfos[i], instructionOffsetForNth(exec, m_instructions, i + 1, isGlobalResolve));
       
   388              ++i;
       
   389         } while (i < m_globalResolveInfos.size());
       
   390     }
       
   391     if (!m_structureStubInfos.isEmpty()) {
       
   392         size_t i = 0;
       
   393         do {
       
   394             printStructureStubInfo(m_structureStubInfos[i], instructionOffsetForNth(exec, m_instructions, i + 1, isPropertyAccess));
       
   395              ++i;
       
   396         } while (i < m_structureStubInfos.size());
       
   397     }
       
   398 #else
       
   399     if (!m_globalResolveInstructions.isEmpty() || !m_propertyAccessInstructions.isEmpty())
       
   400         printf("\nStructures:\n");
       
   401 
       
   402     if (!m_globalResolveInstructions.isEmpty()) {
       
   403         size_t i = 0;
       
   404         do {
       
   405              printStructures(&m_instructions[m_globalResolveInstructions[i]]);
       
   406              ++i;
       
   407         } while (i < m_globalResolveInstructions.size());
       
   408     }
       
   409     if (!m_propertyAccessInstructions.isEmpty()) {
       
   410         size_t i = 0;
       
   411         do {
       
   412             printStructures(&m_instructions[m_propertyAccessInstructions[i]]);
       
   413              ++i;
       
   414         } while (i < m_propertyAccessInstructions.size());
       
   415     }
       
   416 #endif
       
   417 
       
   418     if (m_rareData && !m_rareData->m_exceptionHandlers.isEmpty()) {
       
   419         printf("\nException Handlers:\n");
       
   420         unsigned i = 0;
       
   421         do {
       
   422             printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] }\n", i + 1, m_rareData->m_exceptionHandlers[i].start, m_rareData->m_exceptionHandlers[i].end, m_rareData->m_exceptionHandlers[i].target);
       
   423             ++i;
       
   424         } while (i < m_rareData->m_exceptionHandlers.size());
       
   425     }
       
   426     
       
   427     if (m_rareData && !m_rareData->m_immediateSwitchJumpTables.isEmpty()) {
       
   428         printf("Immediate Switch Jump Tables:\n");
       
   429         unsigned i = 0;
       
   430         do {
       
   431             printf("  %1d = {\n", i);
       
   432             int entry = 0;
       
   433             Vector<int32_t>::const_iterator end = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.end();
       
   434             for (Vector<int32_t>::const_iterator iter = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
       
   435                 if (!*iter)
       
   436                     continue;
       
   437                 printf("\t\t%4d => %04d\n", entry + m_rareData->m_immediateSwitchJumpTables[i].min, *iter);
       
   438             }
       
   439             printf("      }\n");
       
   440             ++i;
       
   441         } while (i < m_rareData->m_immediateSwitchJumpTables.size());
       
   442     }
       
   443     
       
   444     if (m_rareData && !m_rareData->m_characterSwitchJumpTables.isEmpty()) {
       
   445         printf("\nCharacter Switch Jump Tables:\n");
       
   446         unsigned i = 0;
       
   447         do {
       
   448             printf("  %1d = {\n", i);
       
   449             int entry = 0;
       
   450             Vector<int32_t>::const_iterator end = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.end();
       
   451             for (Vector<int32_t>::const_iterator iter = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
       
   452                 if (!*iter)
       
   453                     continue;
       
   454                 ASSERT(!((i + m_rareData->m_characterSwitchJumpTables[i].min) & ~0xFFFF));
       
   455                 UChar ch = static_cast<UChar>(entry + m_rareData->m_characterSwitchJumpTables[i].min);
       
   456                 printf("\t\t\"%s\" => %04d\n", UString(&ch, 1).ascii(), *iter);
       
   457         }
       
   458             printf("      }\n");
       
   459             ++i;
       
   460         } while (i < m_rareData->m_characterSwitchJumpTables.size());
       
   461     }
       
   462     
       
   463     if (m_rareData && !m_rareData->m_stringSwitchJumpTables.isEmpty()) {
       
   464         printf("\nString Switch Jump Tables:\n");
       
   465         unsigned i = 0;
       
   466         do {
       
   467             printf("  %1d = {\n", i);
       
   468             StringJumpTable::StringOffsetTable::const_iterator end = m_rareData->m_stringSwitchJumpTables[i].offsetTable.end();
       
   469             for (StringJumpTable::StringOffsetTable::const_iterator iter = m_rareData->m_stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter)
       
   470                 printf("\t\t\"%s\" => %04d\n", UString(iter->first).ascii(), iter->second.branchOffset);
       
   471             printf("      }\n");
       
   472             ++i;
       
   473         } while (i < m_rareData->m_stringSwitchJumpTables.size());
       
   474     }
       
   475 
       
   476     printf("\n");
       
   477 }
       
   478 
       
   479 void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it) const
       
   480 {
       
   481     int location = it - begin;
       
   482     switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {
       
   483         case op_enter: {
       
   484             printf("[%4d] enter\n", location);
       
   485             break;
       
   486         }
       
   487         case op_enter_with_activation: {
       
   488             int r0 = (++it)->u.operand;
       
   489             printf("[%4d] enter_with_activation %s\n", location, registerName(exec, r0).data());
       
   490             break;
       
   491         }
       
   492         case op_create_arguments: {
       
   493             int r0 = (++it)->u.operand;
       
   494             printf("[%4d] create_arguments\t %s\n", location, registerName(exec, r0).data());
       
   495             break;
       
   496         }
       
   497         case op_init_arguments: {
       
   498             int r0 = (++it)->u.operand;
       
   499             printf("[%4d] init_arguments\t %s\n", location, registerName(exec, r0).data());
       
   500             break;
       
   501         }
       
   502         case op_get_callee: {
       
   503             int r0 = (++it)->u.operand;
       
   504             printf("[%4d] op_get_callee %s\n", location, registerName(exec, r0).data());
       
   505             break;
       
   506         }
       
   507         case op_create_this: {
       
   508             int r0 = (++it)->u.operand;
       
   509             int r1 = (++it)->u.operand;
       
   510             printf("[%4d] create_this %s %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
       
   511             break;
       
   512         }
       
   513         case op_convert_this: {
       
   514             int r0 = (++it)->u.operand;
       
   515             printf("[%4d] convert_this %s\n", location, registerName(exec, r0).data());
       
   516             break;
       
   517         }
       
   518         case op_new_object: {
       
   519             int r0 = (++it)->u.operand;
       
   520             printf("[%4d] new_object\t %s\n", location, registerName(exec, r0).data());
       
   521             break;
       
   522         }
       
   523         case op_new_array: {
       
   524             int dst = (++it)->u.operand;
       
   525             int argv = (++it)->u.operand;
       
   526             int argc = (++it)->u.operand;
       
   527             printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(exec, dst).data(), registerName(exec, argv).data(), argc);
       
   528             break;
       
   529         }
       
   530         case op_new_regexp: {
       
   531             int r0 = (++it)->u.operand;
       
   532             int re0 = (++it)->u.operand;
       
   533             printf("[%4d] new_regexp\t %s, %s\n", location, registerName(exec, r0).data(), regexpName(re0, regexp(re0)).data());
       
   534             break;
       
   535         }
       
   536         case op_mov: {
       
   537             int r0 = (++it)->u.operand;
       
   538             int r1 = (++it)->u.operand;
       
   539             printf("[%4d] mov\t\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
       
   540             break;
       
   541         }
       
   542         case op_not: {
       
   543             printUnaryOp(exec, location, it, "not");
       
   544             break;
       
   545         }
       
   546         case op_eq: {
       
   547             printBinaryOp(exec, location, it, "eq");
       
   548             break;
       
   549         }
       
   550         case op_eq_null: {
       
   551             printUnaryOp(exec, location, it, "eq_null");
       
   552             break;
       
   553         }
       
   554         case op_neq: {
       
   555             printBinaryOp(exec, location, it, "neq");
       
   556             break;
       
   557         }
       
   558         case op_neq_null: {
       
   559             printUnaryOp(exec, location, it, "neq_null");
       
   560             break;
       
   561         }
       
   562         case op_stricteq: {
       
   563             printBinaryOp(exec, location, it, "stricteq");
       
   564             break;
       
   565         }
       
   566         case op_nstricteq: {
       
   567             printBinaryOp(exec, location, it, "nstricteq");
       
   568             break;
       
   569         }
       
   570         case op_less: {
       
   571             printBinaryOp(exec, location, it, "less");
       
   572             break;
       
   573         }
       
   574         case op_lesseq: {
       
   575             printBinaryOp(exec, location, it, "lesseq");
       
   576             break;
       
   577         }
       
   578         case op_pre_inc: {
       
   579             int r0 = (++it)->u.operand;
       
   580             printf("[%4d] pre_inc\t\t %s\n", location, registerName(exec, r0).data());
       
   581             break;
       
   582         }
       
   583         case op_pre_dec: {
       
   584             int r0 = (++it)->u.operand;
       
   585             printf("[%4d] pre_dec\t\t %s\n", location, registerName(exec, r0).data());
       
   586             break;
       
   587         }
       
   588         case op_post_inc: {
       
   589             printUnaryOp(exec, location, it, "post_inc");
       
   590             break;
       
   591         }
       
   592         case op_post_dec: {
       
   593             printUnaryOp(exec, location, it, "post_dec");
       
   594             break;
       
   595         }
       
   596         case op_to_jsnumber: {
       
   597             printUnaryOp(exec, location, it, "to_jsnumber");
       
   598             break;
       
   599         }
       
   600         case op_negate: {
       
   601             printUnaryOp(exec, location, it, "negate");
       
   602             break;
       
   603         }
       
   604         case op_add: {
       
   605             printBinaryOp(exec, location, it, "add");
       
   606             ++it;
       
   607             break;
       
   608         }
       
   609         case op_mul: {
       
   610             printBinaryOp(exec, location, it, "mul");
       
   611             ++it;
       
   612             break;
       
   613         }
       
   614         case op_div: {
       
   615             printBinaryOp(exec, location, it, "div");
       
   616             ++it;
       
   617             break;
       
   618         }
       
   619         case op_mod: {
       
   620             printBinaryOp(exec, location, it, "mod");
       
   621             break;
       
   622         }
       
   623         case op_sub: {
       
   624             printBinaryOp(exec, location, it, "sub");
       
   625             ++it;
       
   626             break;
       
   627         }
       
   628         case op_lshift: {
       
   629             printBinaryOp(exec, location, it, "lshift");
       
   630             break;            
       
   631         }
       
   632         case op_rshift: {
       
   633             printBinaryOp(exec, location, it, "rshift");
       
   634             break;
       
   635         }
       
   636         case op_urshift: {
       
   637             printBinaryOp(exec, location, it, "urshift");
       
   638             break;
       
   639         }
       
   640         case op_bitand: {
       
   641             printBinaryOp(exec, location, it, "bitand");
       
   642             ++it;
       
   643             break;
       
   644         }
       
   645         case op_bitxor: {
       
   646             printBinaryOp(exec, location, it, "bitxor");
       
   647             ++it;
       
   648             break;
       
   649         }
       
   650         case op_bitor: {
       
   651             printBinaryOp(exec, location, it, "bitor");
       
   652             ++it;
       
   653             break;
       
   654         }
       
   655         case op_bitnot: {
       
   656             printUnaryOp(exec, location, it, "bitnot");
       
   657             break;
       
   658         }
       
   659         case op_instanceof: {
       
   660             int r0 = (++it)->u.operand;
       
   661             int r1 = (++it)->u.operand;
       
   662             int r2 = (++it)->u.operand;
       
   663             int r3 = (++it)->u.operand;
       
   664             printf("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data());
       
   665             break;
       
   666         }
       
   667         case op_typeof: {
       
   668             printUnaryOp(exec, location, it, "typeof");
       
   669             break;
       
   670         }
       
   671         case op_is_undefined: {
       
   672             printUnaryOp(exec, location, it, "is_undefined");
       
   673             break;
       
   674         }
       
   675         case op_is_boolean: {
       
   676             printUnaryOp(exec, location, it, "is_boolean");
       
   677             break;
       
   678         }
       
   679         case op_is_number: {
       
   680             printUnaryOp(exec, location, it, "is_number");
       
   681             break;
       
   682         }
       
   683         case op_is_string: {
       
   684             printUnaryOp(exec, location, it, "is_string");
       
   685             break;
       
   686         }
       
   687         case op_is_object: {
       
   688             printUnaryOp(exec, location, it, "is_object");
       
   689             break;
       
   690         }
       
   691         case op_is_function: {
       
   692             printUnaryOp(exec, location, it, "is_function");
       
   693             break;
       
   694         }
       
   695         case op_in: {
       
   696             printBinaryOp(exec, location, it, "in");
       
   697             break;
       
   698         }
       
   699         case op_resolve: {
       
   700             int r0 = (++it)->u.operand;
       
   701             int id0 = (++it)->u.operand;
       
   702             printf("[%4d] resolve\t\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data());
       
   703             break;
       
   704         }
       
   705         case op_resolve_skip: {
       
   706             int r0 = (++it)->u.operand;
       
   707             int id0 = (++it)->u.operand;
       
   708             int skipLevels = (++it)->u.operand;
       
   709             printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), skipLevels);
       
   710             break;
       
   711         }
       
   712         case op_resolve_global: {
       
   713             int r0 = (++it)->u.operand;
       
   714             JSValue scope = JSValue((++it)->u.jsCell);
       
   715             int id0 = (++it)->u.operand;
       
   716             printf("[%4d] resolve_global\t %s, %s, %s\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).data());
       
   717             it += 2;
       
   718             break;
       
   719         }
       
   720         case op_resolve_global_dynamic: {
       
   721             int r0 = (++it)->u.operand;
       
   722             JSValue scope = JSValue((++it)->u.jsCell);
       
   723             int id0 = (++it)->u.operand;
       
   724             int depth = it[2].u.operand;
       
   725             printf("[%4d] resolve_global_dynamic\t %s, %s, %s, %d\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).data(), depth);
       
   726             it += 3;
       
   727             break;
       
   728         }
       
   729         case op_get_scoped_var: {
       
   730             int r0 = (++it)->u.operand;
       
   731             int index = (++it)->u.operand;
       
   732             int skipLevels = (++it)->u.operand;
       
   733             printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(exec, r0).data(), index, skipLevels);
       
   734             break;
       
   735         }
       
   736         case op_put_scoped_var: {
       
   737             int index = (++it)->u.operand;
       
   738             int skipLevels = (++it)->u.operand;
       
   739             int r0 = (++it)->u.operand;
       
   740             printf("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(exec, r0).data());
       
   741             break;
       
   742         }
       
   743         case op_get_global_var: {
       
   744             int r0 = (++it)->u.operand;
       
   745             JSValue scope = JSValue((++it)->u.jsCell);
       
   746             int index = (++it)->u.operand;
       
   747             printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).ascii(), index);
       
   748             break;
       
   749         }
       
   750         case op_put_global_var: {
       
   751             JSValue scope = JSValue((++it)->u.jsCell);
       
   752             int index = (++it)->u.operand;
       
   753             int r0 = (++it)->u.operand;
       
   754             printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(exec, r0).data());
       
   755             break;
       
   756         }
       
   757         case op_resolve_base: {
       
   758             int r0 = (++it)->u.operand;
       
   759             int id0 = (++it)->u.operand;
       
   760             printf("[%4d] resolve_base\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data());
       
   761             break;
       
   762         }
       
   763         case op_resolve_with_base: {
       
   764             int r0 = (++it)->u.operand;
       
   765             int r1 = (++it)->u.operand;
       
   766             int id0 = (++it)->u.operand;
       
   767             printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
       
   768             break;
       
   769         }
       
   770         case op_get_by_id: {
       
   771             printGetByIdOp(exec, location, it, "get_by_id");
       
   772             break;
       
   773         }
       
   774         case op_get_by_id_self: {
       
   775             printGetByIdOp(exec, location, it, "get_by_id_self");
       
   776             break;
       
   777         }
       
   778         case op_get_by_id_self_list: {
       
   779             printGetByIdOp(exec, location, it, "get_by_id_self_list");
       
   780             break;
       
   781         }
       
   782         case op_get_by_id_proto: {
       
   783             printGetByIdOp(exec, location, it, "get_by_id_proto");
       
   784             break;
       
   785         }
       
   786         case op_get_by_id_proto_list: {
       
   787             printGetByIdOp(exec, location, it, "op_get_by_id_proto_list");
       
   788             break;
       
   789         }
       
   790         case op_get_by_id_chain: {
       
   791             printGetByIdOp(exec, location, it, "get_by_id_chain");
       
   792             break;
       
   793         }
       
   794         case op_get_by_id_getter_self: {
       
   795             printGetByIdOp(exec, location, it, "get_by_id_getter_self");
       
   796             break;
       
   797         }
       
   798         case op_get_by_id_getter_self_list: {
       
   799             printGetByIdOp(exec, location, it, "get_by_id_getter_self_list");
       
   800             break;
       
   801         }
       
   802         case op_get_by_id_getter_proto: {
       
   803             printGetByIdOp(exec, location, it, "get_by_id_getter_proto");
       
   804             break;
       
   805         }
       
   806         case op_get_by_id_getter_proto_list: {
       
   807             printGetByIdOp(exec, location, it, "get_by_id_getter_proto_list");
       
   808             break;
       
   809         }
       
   810         case op_get_by_id_getter_chain: {
       
   811             printGetByIdOp(exec, location, it, "get_by_id_getter_chain");
       
   812             break;
       
   813         }
       
   814         case op_get_by_id_custom_self: {
       
   815             printGetByIdOp(exec, location, it, "get_by_id_custom_self");
       
   816             break;
       
   817         }
       
   818         case op_get_by_id_custom_self_list: {
       
   819             printGetByIdOp(exec, location, it, "get_by_id_custom_self_list");
       
   820             break;
       
   821         }
       
   822         case op_get_by_id_custom_proto: {
       
   823             printGetByIdOp(exec, location, it, "get_by_id_custom_proto");
       
   824             break;
       
   825         }
       
   826         case op_get_by_id_custom_proto_list: {
       
   827             printGetByIdOp(exec, location, it, "get_by_id_custom_proto_list");
       
   828             break;
       
   829         }
       
   830         case op_get_by_id_custom_chain: {
       
   831             printGetByIdOp(exec, location, it, "get_by_id_custom_chain");
       
   832             break;
       
   833         }
       
   834         case op_get_by_id_generic: {
       
   835             printGetByIdOp(exec, location, it, "get_by_id_generic");
       
   836             break;
       
   837         }
       
   838         case op_get_array_length: {
       
   839             printGetByIdOp(exec, location, it, "get_array_length");
       
   840             break;
       
   841         }
       
   842         case op_get_string_length: {
       
   843             printGetByIdOp(exec, location, it, "get_string_length");
       
   844             break;
       
   845         }
       
   846         case op_put_by_id: {
       
   847             printPutByIdOp(exec, location, it, "put_by_id");
       
   848             break;
       
   849         }
       
   850         case op_put_by_id_replace: {
       
   851             printPutByIdOp(exec, location, it, "put_by_id_replace");
       
   852             break;
       
   853         }
       
   854         case op_put_by_id_transition: {
       
   855             printPutByIdOp(exec, location, it, "put_by_id_transition");
       
   856             break;
       
   857         }
       
   858         case op_put_by_id_generic: {
       
   859             printPutByIdOp(exec, location, it, "put_by_id_generic");
       
   860             break;
       
   861         }
       
   862         case op_put_getter: {
       
   863             int r0 = (++it)->u.operand;
       
   864             int id0 = (++it)->u.operand;
       
   865             int r1 = (++it)->u.operand;
       
   866             printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data());
       
   867             break;
       
   868         }
       
   869         case op_put_setter: {
       
   870             int r0 = (++it)->u.operand;
       
   871             int id0 = (++it)->u.operand;
       
   872             int r1 = (++it)->u.operand;
       
   873             printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data());
       
   874             break;
       
   875         }
       
   876         case op_method_check: {
       
   877             printf("[%4d] method_check\n", location);
       
   878             break;
       
   879         }
       
   880         case op_del_by_id: {
       
   881             int r0 = (++it)->u.operand;
       
   882             int r1 = (++it)->u.operand;
       
   883             int id0 = (++it)->u.operand;
       
   884             printf("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
       
   885             break;
       
   886         }
       
   887         case op_get_by_val: {
       
   888             int r0 = (++it)->u.operand;
       
   889             int r1 = (++it)->u.operand;
       
   890             int r2 = (++it)->u.operand;
       
   891             printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
       
   892             break;
       
   893         }
       
   894         case op_get_by_pname: {
       
   895             int r0 = (++it)->u.operand;
       
   896             int r1 = (++it)->u.operand;
       
   897             int r2 = (++it)->u.operand;
       
   898             int r3 = (++it)->u.operand;
       
   899             int r4 = (++it)->u.operand;
       
   900             int r5 = (++it)->u.operand;
       
   901             printf("[%4d] get_by_pname\t %s, %s, %s, %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data(), registerName(exec, r4).data(), registerName(exec, r5).data());
       
   902             break;
       
   903         }
       
   904         case op_put_by_val: {
       
   905             int r0 = (++it)->u.operand;
       
   906             int r1 = (++it)->u.operand;
       
   907             int r2 = (++it)->u.operand;
       
   908             printf("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
       
   909             break;
       
   910         }
       
   911         case op_del_by_val: {
       
   912             int r0 = (++it)->u.operand;
       
   913             int r1 = (++it)->u.operand;
       
   914             int r2 = (++it)->u.operand;
       
   915             printf("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
       
   916             break;
       
   917         }
       
   918         case op_put_by_index: {
       
   919             int r0 = (++it)->u.operand;
       
   920             unsigned n0 = (++it)->u.operand;
       
   921             int r1 = (++it)->u.operand;
       
   922             printf("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(exec, r0).data(), n0, registerName(exec, r1).data());
       
   923             break;
       
   924         }
       
   925         case op_jmp: {
       
   926             int offset = (++it)->u.operand;
       
   927             printf("[%4d] jmp\t\t %d(->%d)\n", location, offset, location + offset);
       
   928             break;
       
   929         }
       
   930         case op_loop: {
       
   931             int offset = (++it)->u.operand;
       
   932             printf("[%4d] loop\t\t %d(->%d)\n", location, offset, location + offset);
       
   933             break;
       
   934         }
       
   935         case op_jtrue: {
       
   936             printConditionalJump(exec, begin, it, location, "jtrue");
       
   937             break;
       
   938         }
       
   939         case op_loop_if_true: {
       
   940             printConditionalJump(exec, begin, it, location, "loop_if_true");
       
   941             break;
       
   942         }
       
   943         case op_loop_if_false: {
       
   944             printConditionalJump(exec, begin, it, location, "loop_if_false");
       
   945             break;
       
   946         }
       
   947         case op_jfalse: {
       
   948             printConditionalJump(exec, begin, it, location, "jfalse");
       
   949             break;
       
   950         }
       
   951         case op_jeq_null: {
       
   952             printConditionalJump(exec, begin, it, location, "jeq_null");
       
   953             break;
       
   954         }
       
   955         case op_jneq_null: {
       
   956             printConditionalJump(exec, begin, it, location, "jneq_null");
       
   957             break;
       
   958         }
       
   959         case op_jneq_ptr: {
       
   960             int r0 = (++it)->u.operand;
       
   961             int r1 = (++it)->u.operand;
       
   962             int offset = (++it)->u.operand;
       
   963             printf("[%4d] jneq_ptr\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
       
   964             break;
       
   965         }
       
   966         case op_jnless: {
       
   967             int r0 = (++it)->u.operand;
       
   968             int r1 = (++it)->u.operand;
       
   969             int offset = (++it)->u.operand;
       
   970             printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
       
   971             break;
       
   972         }
       
   973         case op_jnlesseq: {
       
   974             int r0 = (++it)->u.operand;
       
   975             int r1 = (++it)->u.operand;
       
   976             int offset = (++it)->u.operand;
       
   977             printf("[%4d] jnlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
       
   978             break;
       
   979         }
       
   980         case op_loop_if_less: {
       
   981             int r0 = (++it)->u.operand;
       
   982             int r1 = (++it)->u.operand;
       
   983             int offset = (++it)->u.operand;
       
   984             printf("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
       
   985             break;
       
   986         }
       
   987         case op_jless: {
       
   988             int r0 = (++it)->u.operand;
       
   989             int r1 = (++it)->u.operand;
       
   990             int offset = (++it)->u.operand;
       
   991             printf("[%4d] jless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
       
   992             break;
       
   993         }
       
   994         case op_jlesseq: {
       
   995             int r0 = (++it)->u.operand;
       
   996             int r1 = (++it)->u.operand;
       
   997             int offset = (++it)->u.operand;
       
   998             printf("[%4d] jlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
       
   999             break;
       
  1000         }
       
  1001         case op_loop_if_lesseq: {
       
  1002             int r0 = (++it)->u.operand;
       
  1003             int r1 = (++it)->u.operand;
       
  1004             int offset = (++it)->u.operand;
       
  1005             printf("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
       
  1006             break;
       
  1007         }
       
  1008         case op_switch_imm: {
       
  1009             int tableIndex = (++it)->u.operand;
       
  1010             int defaultTarget = (++it)->u.operand;
       
  1011             int scrutineeRegister = (++it)->u.operand;
       
  1012             printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data());
       
  1013             break;
       
  1014         }
       
  1015         case op_switch_char: {
       
  1016             int tableIndex = (++it)->u.operand;
       
  1017             int defaultTarget = (++it)->u.operand;
       
  1018             int scrutineeRegister = (++it)->u.operand;
       
  1019             printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data());
       
  1020             break;
       
  1021         }
       
  1022         case op_switch_string: {
       
  1023             int tableIndex = (++it)->u.operand;
       
  1024             int defaultTarget = (++it)->u.operand;
       
  1025             int scrutineeRegister = (++it)->u.operand;
       
  1026             printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data());
       
  1027             break;
       
  1028         }
       
  1029         case op_new_func: {
       
  1030             int r0 = (++it)->u.operand;
       
  1031             int f0 = (++it)->u.operand;
       
  1032             printf("[%4d] new_func\t\t %s, f%d\n", location, registerName(exec, r0).data(), f0);
       
  1033             break;
       
  1034         }
       
  1035         case op_new_func_exp: {
       
  1036             int r0 = (++it)->u.operand;
       
  1037             int f0 = (++it)->u.operand;
       
  1038             printf("[%4d] new_func_exp\t %s, f%d\n", location, registerName(exec, r0).data(), f0);
       
  1039             break;
       
  1040         }
       
  1041         case op_call: {
       
  1042             int func = (++it)->u.operand;
       
  1043             int argCount = (++it)->u.operand;
       
  1044             int registerOffset = (++it)->u.operand;
       
  1045             printf("[%4d] call\t\t %s, %d, %d\n", location, registerName(exec, func).data(), argCount, registerOffset);
       
  1046             break;
       
  1047         }
       
  1048         case op_call_eval: {
       
  1049             int func = (++it)->u.operand;
       
  1050             int argCount = (++it)->u.operand;
       
  1051             int registerOffset = (++it)->u.operand;
       
  1052             printf("[%4d] call_eval\t %s, %d, %d\n", location, registerName(exec, func).data(), argCount, registerOffset);
       
  1053             break;
       
  1054         }
       
  1055         case op_call_varargs: {
       
  1056             int func = (++it)->u.operand;
       
  1057             int argCount = (++it)->u.operand;
       
  1058             int registerOffset = (++it)->u.operand;
       
  1059             printf("[%4d] call_varargs\t %s, %s, %d\n", location, registerName(exec, func).data(), registerName(exec, argCount).data(), registerOffset);
       
  1060             break;
       
  1061         }
       
  1062         case op_load_varargs: {
       
  1063             printUnaryOp(exec, location, it, "load_varargs");
       
  1064             break;
       
  1065         }
       
  1066         case op_tear_off_activation: {
       
  1067             int r0 = (++it)->u.operand;
       
  1068             int r1 = (++it)->u.operand;
       
  1069             printf("[%4d] tear_off_activation\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
       
  1070             break;
       
  1071         }
       
  1072         case op_tear_off_arguments: {
       
  1073             int r0 = (++it)->u.operand;
       
  1074             printf("[%4d] tear_off_arguments\t %s\n", location, registerName(exec, r0).data());
       
  1075             break;
       
  1076         }
       
  1077         case op_ret: {
       
  1078             int r0 = (++it)->u.operand;
       
  1079             printf("[%4d] ret\t\t %s\n", location, registerName(exec, r0).data());
       
  1080             break;
       
  1081         }
       
  1082         case op_call_put_result: {
       
  1083             int r0 = (++it)->u.operand;
       
  1084             printf("[%4d] op_call_put_result\t\t %s\n", location, registerName(exec, r0).data());
       
  1085             break;
       
  1086         }
       
  1087         case op_ret_object_or_this: {
       
  1088             int r0 = (++it)->u.operand;
       
  1089             int r1 = (++it)->u.operand;
       
  1090             printf("[%4d] constructor_ret\t\t %s %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
       
  1091             break;
       
  1092         }
       
  1093         case op_construct: {
       
  1094             int func = (++it)->u.operand;
       
  1095             int argCount = (++it)->u.operand;
       
  1096             int registerOffset = (++it)->u.operand;
       
  1097             printf("[%4d] construct\t %s, %d, %d\n", location, registerName(exec, func).data(), argCount, registerOffset);
       
  1098             break;
       
  1099         }
       
  1100         case op_strcat: {
       
  1101             int r0 = (++it)->u.operand;
       
  1102             int r1 = (++it)->u.operand;
       
  1103             int count = (++it)->u.operand;
       
  1104             printf("[%4d] strcat\t\t %s, %s, %d\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), count);
       
  1105             break;
       
  1106         }
       
  1107         case op_to_primitive: {
       
  1108             int r0 = (++it)->u.operand;
       
  1109             int r1 = (++it)->u.operand;
       
  1110             printf("[%4d] to_primitive\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
       
  1111             break;
       
  1112         }
       
  1113         case op_get_pnames: {
       
  1114             int r0 = it[1].u.operand;
       
  1115             int r1 = it[2].u.operand;
       
  1116             int r2 = it[3].u.operand;
       
  1117             int r3 = it[4].u.operand;
       
  1118             int offset = it[5].u.operand;
       
  1119             printf("[%4d] get_pnames\t %s, %s, %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data(), offset, location + offset);
       
  1120             it += OPCODE_LENGTH(op_get_pnames) - 1;
       
  1121             break;
       
  1122         }
       
  1123         case op_next_pname: {
       
  1124             int dest = it[1].u.operand;
       
  1125             int iter = it[4].u.operand;
       
  1126             int offset = it[5].u.operand;
       
  1127             printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(exec, dest).data(), registerName(exec, iter).data(), offset, location + offset);
       
  1128             it += OPCODE_LENGTH(op_next_pname) - 1;
       
  1129             break;
       
  1130         }
       
  1131         case op_push_scope: {
       
  1132             int r0 = (++it)->u.operand;
       
  1133             printf("[%4d] push_scope\t %s\n", location, registerName(exec, r0).data());
       
  1134             break;
       
  1135         }
       
  1136         case op_pop_scope: {
       
  1137             printf("[%4d] pop_scope\n", location);
       
  1138             break;
       
  1139         }
       
  1140         case op_push_new_scope: {
       
  1141             int r0 = (++it)->u.operand;
       
  1142             int id0 = (++it)->u.operand;
       
  1143             int r1 = (++it)->u.operand;
       
  1144             printf("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data());
       
  1145             break;
       
  1146         }
       
  1147         case op_jmp_scopes: {
       
  1148             int scopeDelta = (++it)->u.operand;
       
  1149             int offset = (++it)->u.operand;
       
  1150             printf("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, location + offset);
       
  1151             break;
       
  1152         }
       
  1153         case op_catch: {
       
  1154             int r0 = (++it)->u.operand;
       
  1155             printf("[%4d] catch\t\t %s\n", location, registerName(exec, r0).data());
       
  1156             break;
       
  1157         }
       
  1158         case op_throw: {
       
  1159             int r0 = (++it)->u.operand;
       
  1160             printf("[%4d] throw\t\t %s\n", location, registerName(exec, r0).data());
       
  1161             break;
       
  1162         }
       
  1163         case op_new_error: {
       
  1164             int r0 = (++it)->u.operand;
       
  1165             int errorType = (++it)->u.operand;
       
  1166             int k0 = (++it)->u.operand;
       
  1167             printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(exec, r0).data(), errorType, constantName(exec, k0, getConstant(k0)).data());
       
  1168             break;
       
  1169         }
       
  1170         case op_jsr: {
       
  1171             int retAddrDst = (++it)->u.operand;
       
  1172             int offset = (++it)->u.operand;
       
  1173             printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(exec, retAddrDst).data(), offset, location + offset);
       
  1174             break;
       
  1175         }
       
  1176         case op_sret: {
       
  1177             int retAddrSrc = (++it)->u.operand;
       
  1178             printf("[%4d] sret\t\t %s\n", location, registerName(exec, retAddrSrc).data());
       
  1179             break;
       
  1180         }
       
  1181         case op_debug: {
       
  1182             int debugHookID = (++it)->u.operand;
       
  1183             int firstLine = (++it)->u.operand;
       
  1184             int lastLine = (++it)->u.operand;
       
  1185             printf("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine);
       
  1186             break;
       
  1187         }
       
  1188         case op_profile_will_call: {
       
  1189             int function = (++it)->u.operand;
       
  1190             printf("[%4d] profile_will_call %s\n", location, registerName(exec, function).data());
       
  1191             break;
       
  1192         }
       
  1193         case op_profile_did_call: {
       
  1194             int function = (++it)->u.operand;
       
  1195             printf("[%4d] profile_did_call\t %s\n", location, registerName(exec, function).data());
       
  1196             break;
       
  1197         }
       
  1198         case op_end: {
       
  1199             int r0 = (++it)->u.operand;
       
  1200             printf("[%4d] end\t\t %s\n", location, registerName(exec, r0).data());
       
  1201             break;
       
  1202         }
       
  1203     }
       
  1204 }
       
  1205 
       
  1206 #endif // !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
       
  1207 
       
  1208 #if DUMP_CODE_BLOCK_STATISTICS
       
  1209 static HashSet<CodeBlock*> liveCodeBlockSet;
       
  1210 #endif
       
  1211 
       
  1212 #define FOR_EACH_MEMBER_VECTOR(macro) \
       
  1213     macro(instructions) \
       
  1214     macro(globalResolveInfos) \
       
  1215     macro(structureStubInfos) \
       
  1216     macro(callLinkInfos) \
       
  1217     macro(linkedCallerList) \
       
  1218     macro(identifiers) \
       
  1219     macro(functionExpressions) \
       
  1220     macro(constantRegisters)
       
  1221 
       
  1222 #define FOR_EACH_MEMBER_VECTOR_RARE_DATA(macro) \
       
  1223     macro(regexps) \
       
  1224     macro(functions) \
       
  1225     macro(exceptionHandlers) \
       
  1226     macro(immediateSwitchJumpTables) \
       
  1227     macro(characterSwitchJumpTables) \
       
  1228     macro(stringSwitchJumpTables) \
       
  1229     macro(functionRegisterInfos)
       
  1230 
       
  1231 #define FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(macro) \
       
  1232     macro(expressionInfo) \
       
  1233     macro(lineInfo) \
       
  1234     macro(getByIdExceptionInfo) \
       
  1235     macro(pcVector)
       
  1236 
       
  1237 template<typename T>
       
  1238 static size_t sizeInBytes(const Vector<T>& vector)
       
  1239 {
       
  1240     return vector.capacity() * sizeof(T);
       
  1241 }
       
  1242 
       
  1243 void CodeBlock::dumpStatistics()
       
  1244 {
       
  1245 #if DUMP_CODE_BLOCK_STATISTICS
       
  1246     #define DEFINE_VARS(name) size_t name##IsNotEmpty = 0; size_t name##TotalSize = 0;
       
  1247         FOR_EACH_MEMBER_VECTOR(DEFINE_VARS)
       
  1248         FOR_EACH_MEMBER_VECTOR_RARE_DATA(DEFINE_VARS)
       
  1249         FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(DEFINE_VARS)
       
  1250     #undef DEFINE_VARS
       
  1251 
       
  1252     // Non-vector data members
       
  1253     size_t evalCodeCacheIsNotEmpty = 0;
       
  1254 
       
  1255     size_t symbolTableIsNotEmpty = 0;
       
  1256     size_t symbolTableTotalSize = 0;
       
  1257 
       
  1258     size_t hasExceptionInfo = 0;
       
  1259     size_t hasRareData = 0;
       
  1260 
       
  1261     size_t isFunctionCode = 0;
       
  1262     size_t isGlobalCode = 0;
       
  1263     size_t isEvalCode = 0;
       
  1264 
       
  1265     HashSet<CodeBlock*>::const_iterator end = liveCodeBlockSet.end();
       
  1266     for (HashSet<CodeBlock*>::const_iterator it = liveCodeBlockSet.begin(); it != end; ++it) {
       
  1267         CodeBlock* codeBlock = *it;
       
  1268 
       
  1269         #define GET_STATS(name) if (!codeBlock->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_##name); }
       
  1270             FOR_EACH_MEMBER_VECTOR(GET_STATS)
       
  1271         #undef GET_STATS
       
  1272 
       
  1273         if (!codeBlock->m_symbolTable.isEmpty()) {
       
  1274             symbolTableIsNotEmpty++;
       
  1275             symbolTableTotalSize += (codeBlock->m_symbolTable.capacity() * (sizeof(SymbolTable::KeyType) + sizeof(SymbolTable::MappedType)));
       
  1276         }
       
  1277 
       
  1278         if (codeBlock->m_exceptionInfo) {
       
  1279             hasExceptionInfo++;
       
  1280             #define GET_STATS(name) if (!codeBlock->m_exceptionInfo->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_exceptionInfo->m_##name); }
       
  1281                 FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(GET_STATS)
       
  1282             #undef GET_STATS
       
  1283         }
       
  1284 
       
  1285         if (codeBlock->m_rareData) {
       
  1286             hasRareData++;
       
  1287             #define GET_STATS(name) if (!codeBlock->m_rareData->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_rareData->m_##name); }
       
  1288                 FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_STATS)
       
  1289             #undef GET_STATS
       
  1290 
       
  1291             if (!codeBlock->m_rareData->m_evalCodeCache.isEmpty())
       
  1292                 evalCodeCacheIsNotEmpty++;
       
  1293         }
       
  1294 
       
  1295         switch (codeBlock->codeType()) {
       
  1296             case FunctionCode:
       
  1297                 ++isFunctionCode;
       
  1298                 break;
       
  1299             case GlobalCode:
       
  1300                 ++isGlobalCode;
       
  1301                 break;
       
  1302             case EvalCode:
       
  1303                 ++isEvalCode;
       
  1304                 break;
       
  1305         }
       
  1306     }
       
  1307 
       
  1308     size_t totalSize = 0;
       
  1309 
       
  1310     #define GET_TOTAL_SIZE(name) totalSize += name##TotalSize;
       
  1311         FOR_EACH_MEMBER_VECTOR(GET_TOTAL_SIZE)
       
  1312         FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_TOTAL_SIZE)
       
  1313         FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(GET_TOTAL_SIZE)
       
  1314     #undef GET_TOTAL_SIZE
       
  1315 
       
  1316     totalSize += symbolTableTotalSize;
       
  1317     totalSize += (liveCodeBlockSet.size() * sizeof(CodeBlock));
       
  1318 
       
  1319     printf("Number of live CodeBlocks: %d\n", liveCodeBlockSet.size());
       
  1320     printf("Size of a single CodeBlock [sizeof(CodeBlock)]: %zu\n", sizeof(CodeBlock));
       
  1321     printf("Size of all CodeBlocks: %zu\n", totalSize);
       
  1322     printf("Average size of a CodeBlock: %zu\n", totalSize / liveCodeBlockSet.size());
       
  1323 
       
  1324     printf("Number of FunctionCode CodeBlocks: %zu (%.3f%%)\n", isFunctionCode, static_cast<double>(isFunctionCode) * 100.0 / liveCodeBlockSet.size());
       
  1325     printf("Number of GlobalCode CodeBlocks: %zu (%.3f%%)\n", isGlobalCode, static_cast<double>(isGlobalCode) * 100.0 / liveCodeBlockSet.size());
       
  1326     printf("Number of EvalCode CodeBlocks: %zu (%.3f%%)\n", isEvalCode, static_cast<double>(isEvalCode) * 100.0 / liveCodeBlockSet.size());
       
  1327 
       
  1328     printf("Number of CodeBlocks with exception info: %zu (%.3f%%)\n", hasExceptionInfo, static_cast<double>(hasExceptionInfo) * 100.0 / liveCodeBlockSet.size());
       
  1329     printf("Number of CodeBlocks with rare data: %zu (%.3f%%)\n", hasRareData, static_cast<double>(hasRareData) * 100.0 / liveCodeBlockSet.size());
       
  1330 
       
  1331     #define PRINT_STATS(name) printf("Number of CodeBlocks with " #name ": %zu\n", name##IsNotEmpty); printf("Size of all " #name ": %zu\n", name##TotalSize); 
       
  1332         FOR_EACH_MEMBER_VECTOR(PRINT_STATS)
       
  1333         FOR_EACH_MEMBER_VECTOR_RARE_DATA(PRINT_STATS)
       
  1334         FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(PRINT_STATS)
       
  1335     #undef PRINT_STATS
       
  1336 
       
  1337     printf("Number of CodeBlocks with evalCodeCache: %zu\n", evalCodeCacheIsNotEmpty);
       
  1338     printf("Number of CodeBlocks with symbolTable: %zu\n", symbolTableIsNotEmpty);
       
  1339 
       
  1340     printf("Size of all symbolTables: %zu\n", symbolTableTotalSize);
       
  1341 
       
  1342 #else
       
  1343     printf("Dumping CodeBlock statistics is not enabled.\n");
       
  1344 #endif
       
  1345 }
       
  1346 
       
  1347 CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, SymbolTable* symTab, bool isConstructor)
       
  1348     : m_numCalleeRegisters(0)
       
  1349     , m_numVars(0)
       
  1350     , m_numParameters(0)
       
  1351     , m_isConstructor(isConstructor)
       
  1352     , m_ownerExecutable(ownerExecutable)
       
  1353     , m_globalData(0)
       
  1354 #ifndef NDEBUG
       
  1355     , m_instructionCount(0)
       
  1356 #endif
       
  1357     , m_argumentsRegister(-1)
       
  1358     , m_needsFullScopeChain(ownerExecutable->needsActivation())
       
  1359     , m_usesEval(ownerExecutable->usesEval())
       
  1360     , m_isNumericCompareFunction(false)
       
  1361     , m_codeType(codeType)
       
  1362     , m_source(sourceProvider)
       
  1363     , m_sourceOffset(sourceOffset)
       
  1364     , m_symbolTable(symTab)
       
  1365     , m_exceptionInfo(adoptPtr(new ExceptionInfo))
       
  1366 {
       
  1367     ASSERT(m_source);
       
  1368 
       
  1369 #if DUMP_CODE_BLOCK_STATISTICS
       
  1370     liveCodeBlockSet.add(this);
       
  1371 #endif
       
  1372 }
       
  1373 
       
  1374 CodeBlock::~CodeBlock()
       
  1375 {
       
  1376 #if ENABLE(INTERPRETER)
       
  1377     for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)
       
  1378         derefStructures(&m_instructions[m_globalResolveInstructions[i]]);
       
  1379 
       
  1380     for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i)
       
  1381         derefStructures(&m_instructions[m_propertyAccessInstructions[i]]);
       
  1382 #endif
       
  1383 #if ENABLE(JIT)
       
  1384     for (size_t size = m_globalResolveInfos.size(), i = 0; i < size; ++i) {
       
  1385         if (m_globalResolveInfos[i].structure)
       
  1386             m_globalResolveInfos[i].structure->deref();
       
  1387     }
       
  1388 
       
  1389     for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i)
       
  1390         m_structureStubInfos[i].deref();
       
  1391 
       
  1392     for (size_t size = m_callLinkInfos.size(), i = 0; i < size; ++i) {
       
  1393         CallLinkInfo* callLinkInfo = &m_callLinkInfos[i];
       
  1394         if (callLinkInfo->isLinked())
       
  1395             callLinkInfo->callee->removeCaller(callLinkInfo);
       
  1396     }
       
  1397 
       
  1398     for (size_t size = m_methodCallLinkInfos.size(), i = 0; i < size; ++i) {
       
  1399         if (Structure* structure = m_methodCallLinkInfos[i].cachedStructure) {
       
  1400             structure->deref();
       
  1401             // Both members must be filled at the same time
       
  1402             ASSERT(!!m_methodCallLinkInfos[i].cachedPrototypeStructure);
       
  1403             m_methodCallLinkInfos[i].cachedPrototypeStructure->deref();
       
  1404         }
       
  1405     }
       
  1406 
       
  1407 #if ENABLE(JIT_OPTIMIZE_CALL)
       
  1408     unlinkCallers();
       
  1409 #endif
       
  1410 
       
  1411 #endif // ENABLE(JIT)
       
  1412 
       
  1413 #if DUMP_CODE_BLOCK_STATISTICS
       
  1414     liveCodeBlockSet.remove(this);
       
  1415 #endif
       
  1416 }
       
  1417 
       
  1418 #if ENABLE(JIT_OPTIMIZE_CALL)
       
  1419 void CodeBlock::unlinkCallers()
       
  1420 {
       
  1421     size_t size = m_linkedCallerList.size();
       
  1422     for (size_t i = 0; i < size; ++i) {
       
  1423         CallLinkInfo* currentCaller = m_linkedCallerList[i];
       
  1424         JIT::unlinkCallOrConstruct(currentCaller);
       
  1425         currentCaller->setUnlinked();
       
  1426     }
       
  1427     m_linkedCallerList.clear();
       
  1428 }
       
  1429 #endif
       
  1430 
       
  1431 void CodeBlock::derefStructures(Instruction* vPC) const
       
  1432 {
       
  1433     Interpreter* interpreter = m_globalData->interpreter;
       
  1434 
       
  1435     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_self)) {
       
  1436         vPC[4].u.structure->deref();
       
  1437         return;
       
  1438     }
       
  1439     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_proto)) {
       
  1440         vPC[4].u.structure->deref();
       
  1441         vPC[5].u.structure->deref();
       
  1442         return;
       
  1443     }
       
  1444     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain)) {
       
  1445         vPC[4].u.structure->deref();
       
  1446         vPC[5].u.structureChain->deref();
       
  1447         return;
       
  1448     }
       
  1449     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
       
  1450         vPC[4].u.structure->deref();
       
  1451         vPC[5].u.structure->deref();
       
  1452         vPC[6].u.structureChain->deref();
       
  1453         return;
       
  1454     }
       
  1455     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
       
  1456         vPC[4].u.structure->deref();
       
  1457         return;
       
  1458     }
       
  1459     if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global) || vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global_dynamic)) {
       
  1460         if(vPC[4].u.structure)
       
  1461             vPC[4].u.structure->deref();
       
  1462         return;
       
  1463     }
       
  1464     if ((vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list))
       
  1465         || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list))
       
  1466         || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto_list))
       
  1467         || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self_list))
       
  1468         || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_proto_list))
       
  1469         || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_self_list))) {
       
  1470         PolymorphicAccessStructureList* polymorphicStructures = vPC[4].u.polymorphicStructures;
       
  1471         polymorphicStructures->derefStructures(vPC[5].u.operand);
       
  1472         delete polymorphicStructures;
       
  1473         return;
       
  1474     }
       
  1475 
       
  1476     // These instructions don't ref their Structures.
       
  1477     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));
       
  1478 }
       
  1479 
       
  1480 void CodeBlock::refStructures(Instruction* vPC) const
       
  1481 {
       
  1482     Interpreter* interpreter = m_globalData->interpreter;
       
  1483 
       
  1484     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_self)) {
       
  1485         vPC[4].u.structure->ref();
       
  1486         return;
       
  1487     }
       
  1488     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_proto)) {
       
  1489         vPC[4].u.structure->ref();
       
  1490         vPC[5].u.structure->ref();
       
  1491         return;
       
  1492     }
       
  1493     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain)) {
       
  1494         vPC[4].u.structure->ref();
       
  1495         vPC[5].u.structureChain->ref();
       
  1496         return;
       
  1497     }
       
  1498     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
       
  1499         vPC[4].u.structure->ref();
       
  1500         vPC[5].u.structure->ref();
       
  1501         vPC[6].u.structureChain->ref();
       
  1502         return;
       
  1503     }
       
  1504     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
       
  1505         vPC[4].u.structure->ref();
       
  1506         return;
       
  1507     }
       
  1508     
       
  1509     // These instructions don't ref their Structures.
       
  1510     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));
       
  1511 }
       
  1512 
       
  1513 void CodeBlock::markAggregate(MarkStack& markStack)
       
  1514 {
       
  1515     for (size_t i = 0; i < m_constantRegisters.size(); ++i)
       
  1516         markStack.append(m_constantRegisters[i].jsValue());
       
  1517     for (size_t i = 0; i < m_functionExprs.size(); ++i)
       
  1518         m_functionExprs[i]->markAggregate(markStack);
       
  1519     for (size_t i = 0; i < m_functionDecls.size(); ++i)
       
  1520         m_functionDecls[i]->markAggregate(markStack);
       
  1521 }
       
  1522 
       
  1523 bool CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame)
       
  1524 {
       
  1525     if (m_exceptionInfo)
       
  1526         return true;
       
  1527 
       
  1528     ASSERT(!m_rareData || !m_rareData->m_exceptionHandlers.size());
       
  1529     ScopeChainNode* scopeChain = callFrame->scopeChain();
       
  1530     if (m_needsFullScopeChain) {
       
  1531         ScopeChain sc(scopeChain);
       
  1532         int scopeDelta = sc.localDepth();
       
  1533         if (m_codeType == EvalCode)
       
  1534             scopeDelta -= static_cast<EvalCodeBlock*>(this)->baseScopeDepth();
       
  1535         else if (m_codeType == FunctionCode)
       
  1536             scopeDelta++; // Compilation of function code assumes activation is not on the scope chain yet.
       
  1537         ASSERT(scopeDelta >= 0);
       
  1538         while (scopeDelta--)
       
  1539             scopeChain = scopeChain->next;
       
  1540     }
       
  1541 
       
  1542     m_exceptionInfo = m_ownerExecutable->reparseExceptionInfo(m_globalData, scopeChain, this);
       
  1543     return m_exceptionInfo;
       
  1544 }
       
  1545 
       
  1546 HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
       
  1547 {
       
  1548     ASSERT(bytecodeOffset < m_instructionCount);
       
  1549 
       
  1550     if (!m_rareData)
       
  1551         return 0;
       
  1552     
       
  1553     Vector<HandlerInfo>& exceptionHandlers = m_rareData->m_exceptionHandlers;
       
  1554     for (size_t i = 0; i < exceptionHandlers.size(); ++i) {
       
  1555         // Handlers are ordered innermost first, so the first handler we encounter
       
  1556         // that contains the source address is the correct handler to use.
       
  1557         if (exceptionHandlers[i].start <= bytecodeOffset && exceptionHandlers[i].end >= bytecodeOffset)
       
  1558             return &exceptionHandlers[i];
       
  1559     }
       
  1560 
       
  1561     return 0;
       
  1562 }
       
  1563 
       
  1564 int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset)
       
  1565 {
       
  1566     ASSERT(bytecodeOffset < m_instructionCount);
       
  1567 
       
  1568     if (!reparseForExceptionInfoIfNecessary(callFrame) || !m_exceptionInfo->m_lineInfo.size())
       
  1569         return m_ownerExecutable->source().firstLine(); // Empty function or unable to reparse
       
  1570 
       
  1571     int low = 0;
       
  1572     int high = m_exceptionInfo->m_lineInfo.size();
       
  1573     while (low < high) {
       
  1574         int mid = low + (high - low) / 2;
       
  1575         if (m_exceptionInfo->m_lineInfo[mid].instructionOffset <= bytecodeOffset)
       
  1576             low = mid + 1;
       
  1577         else
       
  1578             high = mid;
       
  1579     }
       
  1580     
       
  1581     if (!low)
       
  1582         return m_ownerExecutable->source().firstLine();
       
  1583     return m_exceptionInfo->m_lineInfo[low - 1].lineNumber;
       
  1584 }
       
  1585 
       
  1586 int CodeBlock::expressionRangeForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset)
       
  1587 {
       
  1588     ASSERT(bytecodeOffset < m_instructionCount);
       
  1589 
       
  1590     if (!reparseForExceptionInfoIfNecessary(callFrame) || !m_exceptionInfo->m_expressionInfo.size()) {
       
  1591         // We didn't think anything could throw.  Apparently we were wrong.
       
  1592         // Alternatively something went wrong when trying to reparse
       
  1593         startOffset = 0;
       
  1594         endOffset = 0;
       
  1595         divot = 0;
       
  1596         return lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
       
  1597     }
       
  1598 
       
  1599     int low = 0;
       
  1600     int high = m_exceptionInfo->m_expressionInfo.size();
       
  1601     while (low < high) {
       
  1602         int mid = low + (high - low) / 2;
       
  1603         if (m_exceptionInfo->m_expressionInfo[mid].instructionOffset <= bytecodeOffset)
       
  1604             low = mid + 1;
       
  1605         else
       
  1606             high = mid;
       
  1607     }
       
  1608     
       
  1609     ASSERT(low);
       
  1610     if (!low) {
       
  1611         startOffset = 0;
       
  1612         endOffset = 0;
       
  1613         divot = 0;
       
  1614         return lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
       
  1615     }
       
  1616 
       
  1617     startOffset = m_exceptionInfo->m_expressionInfo[low - 1].startOffset;
       
  1618     endOffset = m_exceptionInfo->m_expressionInfo[low - 1].endOffset;
       
  1619     divot = m_exceptionInfo->m_expressionInfo[low - 1].divotPoint + m_sourceOffset;
       
  1620     return lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
       
  1621 }
       
  1622 
       
  1623 bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, OpcodeID& opcodeID)
       
  1624 {
       
  1625     ASSERT(bytecodeOffset < m_instructionCount);
       
  1626 
       
  1627     if (!reparseForExceptionInfoIfNecessary(callFrame) || !m_exceptionInfo->m_getByIdExceptionInfo.size())
       
  1628         return false;
       
  1629 
       
  1630     int low = 0;
       
  1631     int high = m_exceptionInfo->m_getByIdExceptionInfo.size();
       
  1632     while (low < high) {
       
  1633         int mid = low + (high - low) / 2;
       
  1634         if (m_exceptionInfo->m_getByIdExceptionInfo[mid].bytecodeOffset <= bytecodeOffset)
       
  1635             low = mid + 1;
       
  1636         else
       
  1637             high = mid;
       
  1638     }
       
  1639 
       
  1640     if (!low || m_exceptionInfo->m_getByIdExceptionInfo[low - 1].bytecodeOffset != bytecodeOffset)
       
  1641         return false;
       
  1642 
       
  1643     opcodeID = m_exceptionInfo->m_getByIdExceptionInfo[low - 1].isOpCreateThis ? op_create_this : op_instanceof;
       
  1644     return true;
       
  1645 }
       
  1646 
       
  1647 #if ENABLE(JIT)
       
  1648 bool CodeBlock::functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex)
       
  1649 {
       
  1650     ASSERT(bytecodeOffset < m_instructionCount);
       
  1651 
       
  1652     if (!m_rareData || !m_rareData->m_functionRegisterInfos.size())
       
  1653         return false;
       
  1654 
       
  1655     int low = 0;
       
  1656     int high = m_rareData->m_functionRegisterInfos.size();
       
  1657     while (low < high) {
       
  1658         int mid = low + (high - low) / 2;
       
  1659         if (m_rareData->m_functionRegisterInfos[mid].bytecodeOffset <= bytecodeOffset)
       
  1660             low = mid + 1;
       
  1661         else
       
  1662             high = mid;
       
  1663     }
       
  1664 
       
  1665     if (!low || m_rareData->m_functionRegisterInfos[low - 1].bytecodeOffset != bytecodeOffset)
       
  1666         return false;
       
  1667 
       
  1668     functionRegisterIndex = m_rareData->m_functionRegisterInfos[low - 1].functionRegisterIndex;
       
  1669     return true;
       
  1670 }
       
  1671 #endif
       
  1672 
       
  1673 #if ENABLE(INTERPRETER)
       
  1674 bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset)
       
  1675 {
       
  1676     if (m_globalResolveInstructions.isEmpty())
       
  1677         return false;
       
  1678 
       
  1679     int low = 0;
       
  1680     int high = m_globalResolveInstructions.size();
       
  1681     while (low < high) {
       
  1682         int mid = low + (high - low) / 2;
       
  1683         if (m_globalResolveInstructions[mid] <= bytecodeOffset)
       
  1684             low = mid + 1;
       
  1685         else
       
  1686             high = mid;
       
  1687     }
       
  1688 
       
  1689     if (!low || m_globalResolveInstructions[low - 1] != bytecodeOffset)
       
  1690         return false;
       
  1691     return true;
       
  1692 }
       
  1693 #endif
       
  1694 #if ENABLE(JIT)
       
  1695 bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset)
       
  1696 {
       
  1697     if (m_globalResolveInfos.isEmpty())
       
  1698         return false;
       
  1699 
       
  1700     int low = 0;
       
  1701     int high = m_globalResolveInfos.size();
       
  1702     while (low < high) {
       
  1703         int mid = low + (high - low) / 2;
       
  1704         if (m_globalResolveInfos[mid].bytecodeOffset <= bytecodeOffset)
       
  1705             low = mid + 1;
       
  1706         else
       
  1707             high = mid;
       
  1708     }
       
  1709 
       
  1710     if (!low || m_globalResolveInfos[low - 1].bytecodeOffset != bytecodeOffset)
       
  1711         return false;
       
  1712     return true;
       
  1713 }
       
  1714 #endif
       
  1715 
       
  1716 void CodeBlock::shrinkToFit()
       
  1717 {
       
  1718     m_instructions.shrinkToFit();
       
  1719 
       
  1720 #if ENABLE(INTERPRETER)
       
  1721     m_propertyAccessInstructions.shrinkToFit();
       
  1722     m_globalResolveInstructions.shrinkToFit();
       
  1723 #endif
       
  1724 #if ENABLE(JIT)
       
  1725     m_structureStubInfos.shrinkToFit();
       
  1726     m_globalResolveInfos.shrinkToFit();
       
  1727     m_callLinkInfos.shrinkToFit();
       
  1728     m_linkedCallerList.shrinkToFit();
       
  1729 #endif
       
  1730 
       
  1731     m_identifiers.shrinkToFit();
       
  1732     m_functionDecls.shrinkToFit();
       
  1733     m_functionExprs.shrinkToFit();
       
  1734     m_constantRegisters.shrinkToFit();
       
  1735 
       
  1736     if (m_exceptionInfo) {
       
  1737         m_exceptionInfo->m_expressionInfo.shrinkToFit();
       
  1738         m_exceptionInfo->m_lineInfo.shrinkToFit();
       
  1739         m_exceptionInfo->m_getByIdExceptionInfo.shrinkToFit();
       
  1740     }
       
  1741 
       
  1742     if (m_rareData) {
       
  1743         m_rareData->m_exceptionHandlers.shrinkToFit();
       
  1744         m_rareData->m_regexps.shrinkToFit();
       
  1745         m_rareData->m_immediateSwitchJumpTables.shrinkToFit();
       
  1746         m_rareData->m_characterSwitchJumpTables.shrinkToFit();
       
  1747         m_rareData->m_stringSwitchJumpTables.shrinkToFit();
       
  1748 #if ENABLE(JIT)
       
  1749         m_rareData->m_functionRegisterInfos.shrinkToFit();
       
  1750 #endif
       
  1751     }
       
  1752 }
       
  1753 
       
  1754 } // namespace JSC