Home | History | Annotate | Download | only in jit
      1 /*
      2  * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "JIT.h"
     28 
     29 // This probably does not belong here; adding here for now as a quick Windows build fix.
     30 #if ENABLE(ASSEMBLER) && CPU(X86) && !OS(MAC_OS_X)
     31 #include "MacroAssembler.h"
     32 JSC::MacroAssemblerX86Common::SSE2CheckState JSC::MacroAssemblerX86Common::s_sse2CheckState = NotCheckedSSE2;
     33 #endif
     34 
     35 #if ENABLE(JIT)
     36 
     37 #include "CodeBlock.h"
     38 #include "Interpreter.h"
     39 #include "JITInlineMethods.h"
     40 #include "JITStubCall.h"
     41 #include "JSArray.h"
     42 #include "JSFunction.h"
     43 #include "LinkBuffer.h"
     44 #include "RepatchBuffer.h"
     45 #include "ResultType.h"
     46 #include "SamplingTool.h"
     47 
     48 #ifndef NDEBUG
     49 #include <stdio.h>
     50 #endif
     51 
     52 using namespace std;
     53 
     54 namespace JSC {
     55 
     56 void ctiPatchNearCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAddress, MacroAssemblerCodePtr newCalleeFunction)
     57 {
     58     RepatchBuffer repatchBuffer(codeblock);
     59     repatchBuffer.relinkNearCallerToTrampoline(returnAddress, newCalleeFunction);
     60 }
     61 
     62 void ctiPatchCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAddress, MacroAssemblerCodePtr newCalleeFunction)
     63 {
     64     RepatchBuffer repatchBuffer(codeblock);
     65     repatchBuffer.relinkCallerToTrampoline(returnAddress, newCalleeFunction);
     66 }
     67 
     68 void ctiPatchCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAddress, FunctionPtr newCalleeFunction)
     69 {
     70     RepatchBuffer repatchBuffer(codeblock);
     71     repatchBuffer.relinkCallerToFunction(returnAddress, newCalleeFunction);
     72 }
     73 
     74 JIT::JIT(JSGlobalData* globalData, CodeBlock* codeBlock)
     75     : m_interpreter(globalData->interpreter)
     76     , m_globalData(globalData)
     77     , m_codeBlock(codeBlock)
     78     , m_labels(codeBlock ? codeBlock->instructions().size() : 0)
     79     , m_propertyAccessCompilationInfo(codeBlock ? codeBlock->numberOfStructureStubInfos() : 0)
     80     , m_callStructureStubCompilationInfo(codeBlock ? codeBlock->numberOfCallLinkInfos() : 0)
     81     , m_bytecodeIndex((unsigned)-1)
     82 #if USE(JSVALUE32_64)
     83     , m_jumpTargetIndex(0)
     84     , m_mappedBytecodeIndex((unsigned)-1)
     85     , m_mappedVirtualRegisterIndex((unsigned)-1)
     86     , m_mappedTag((RegisterID)-1)
     87     , m_mappedPayload((RegisterID)-1)
     88 #else
     89     , m_lastResultBytecodeRegister(std::numeric_limits<int>::max())
     90     , m_jumpTargetsPosition(0)
     91 #endif
     92 {
     93 }
     94 
     95 #if USE(JSVALUE32_64)
     96 void JIT::emitTimeoutCheck()
     97 {
     98     Jump skipTimeout = branchSub32(NonZero, Imm32(1), timeoutCheckRegister);
     99     JITStubCall stubCall(this, cti_timeout_check);
    100     stubCall.addArgument(regT1, regT0); // save last result registers.
    101     stubCall.call(timeoutCheckRegister);
    102     stubCall.getArgument(0, regT1, regT0); // reload last result registers.
    103     skipTimeout.link(this);
    104 }
    105 #else
    106 void JIT::emitTimeoutCheck()
    107 {
    108     Jump skipTimeout = branchSub32(NonZero, Imm32(1), timeoutCheckRegister);
    109     JITStubCall(this, cti_timeout_check).call(timeoutCheckRegister);
    110     skipTimeout.link(this);
    111 
    112     killLastResultRegister();
    113 }
    114 #endif
    115 
    116 #define NEXT_OPCODE(name) \
    117     m_bytecodeIndex += OPCODE_LENGTH(name); \
    118     break;
    119 
    120 #if USE(JSVALUE32_64)
    121 #define DEFINE_BINARY_OP(name) \
    122     case name: { \
    123         JITStubCall stubCall(this, cti_##name); \
    124         stubCall.addArgument(currentInstruction[2].u.operand); \
    125         stubCall.addArgument(currentInstruction[3].u.operand); \
    126         stubCall.call(currentInstruction[1].u.operand); \
    127         NEXT_OPCODE(name); \
    128     }
    129 
    130 #define DEFINE_UNARY_OP(name) \
    131     case name: { \
    132         JITStubCall stubCall(this, cti_##name); \
    133         stubCall.addArgument(currentInstruction[2].u.operand); \
    134         stubCall.call(currentInstruction[1].u.operand); \
    135         NEXT_OPCODE(name); \
    136     }
    137 
    138 #else // USE(JSVALUE32_64)
    139 
    140 #define DEFINE_BINARY_OP(name) \
    141     case name: { \
    142         JITStubCall stubCall(this, cti_##name); \
    143         stubCall.addArgument(currentInstruction[2].u.operand, regT2); \
    144         stubCall.addArgument(currentInstruction[3].u.operand, regT2); \
    145         stubCall.call(currentInstruction[1].u.operand); \
    146         NEXT_OPCODE(name); \
    147     }
    148 
    149 #define DEFINE_UNARY_OP(name) \
    150     case name: { \
    151         JITStubCall stubCall(this, cti_##name); \
    152         stubCall.addArgument(currentInstruction[2].u.operand, regT2); \
    153         stubCall.call(currentInstruction[1].u.operand); \
    154         NEXT_OPCODE(name); \
    155     }
    156 #endif // USE(JSVALUE32_64)
    157 
    158 #define DEFINE_OP(name) \
    159     case name: { \
    160         emit_##name(currentInstruction); \
    161         NEXT_OPCODE(name); \
    162     }
    163 
    164 #define DEFINE_SLOWCASE_OP(name) \
    165     case name: { \
    166         emitSlow_##name(currentInstruction, iter); \
    167         NEXT_OPCODE(name); \
    168     }
    169 
    170 void JIT::privateCompileMainPass()
    171 {
    172     Instruction* instructionsBegin = m_codeBlock->instructions().begin();
    173     unsigned instructionCount = m_codeBlock->instructions().size();
    174 
    175     m_propertyAccessInstructionIndex = 0;
    176     m_globalResolveInfoIndex = 0;
    177     m_callLinkInfoIndex = 0;
    178 
    179     for (m_bytecodeIndex = 0; m_bytecodeIndex < instructionCount; ) {
    180         Instruction* currentInstruction = instructionsBegin + m_bytecodeIndex;
    181         ASSERT_WITH_MESSAGE(m_interpreter->isOpcode(currentInstruction->u.opcode), "privateCompileMainPass gone bad @ %d", m_bytecodeIndex);
    182 
    183 #if ENABLE(OPCODE_SAMPLING)
    184         if (m_bytecodeIndex > 0) // Avoid the overhead of sampling op_enter twice.
    185             sampleInstruction(currentInstruction);
    186 #endif
    187 
    188 #if !USE(JSVALUE32_64)
    189         if (m_labels[m_bytecodeIndex].isUsed())
    190             killLastResultRegister();
    191 #endif
    192 
    193         m_labels[m_bytecodeIndex] = label();
    194 
    195         switch (m_interpreter->getOpcodeID(currentInstruction->u.opcode)) {
    196         DEFINE_BINARY_OP(op_del_by_val)
    197 #if USE(JSVALUE32)
    198         DEFINE_BINARY_OP(op_div)
    199 #endif
    200         DEFINE_BINARY_OP(op_in)
    201         DEFINE_BINARY_OP(op_less)
    202         DEFINE_BINARY_OP(op_lesseq)
    203         DEFINE_BINARY_OP(op_urshift)
    204         DEFINE_UNARY_OP(op_is_boolean)
    205         DEFINE_UNARY_OP(op_is_function)
    206         DEFINE_UNARY_OP(op_is_number)
    207         DEFINE_UNARY_OP(op_is_object)
    208         DEFINE_UNARY_OP(op_is_string)
    209         DEFINE_UNARY_OP(op_is_undefined)
    210 #if !USE(JSVALUE32_64)
    211         DEFINE_UNARY_OP(op_negate)
    212 #endif
    213         DEFINE_UNARY_OP(op_typeof)
    214 
    215         DEFINE_OP(op_add)
    216         DEFINE_OP(op_bitand)
    217         DEFINE_OP(op_bitnot)
    218         DEFINE_OP(op_bitor)
    219         DEFINE_OP(op_bitxor)
    220         DEFINE_OP(op_call)
    221         DEFINE_OP(op_call_eval)
    222         DEFINE_OP(op_call_varargs)
    223         DEFINE_OP(op_catch)
    224         DEFINE_OP(op_construct)
    225         DEFINE_OP(op_construct_verify)
    226         DEFINE_OP(op_convert_this)
    227         DEFINE_OP(op_init_arguments)
    228         DEFINE_OP(op_create_arguments)
    229         DEFINE_OP(op_debug)
    230         DEFINE_OP(op_del_by_id)
    231 #if !USE(JSVALUE32)
    232         DEFINE_OP(op_div)
    233 #endif
    234         DEFINE_OP(op_end)
    235         DEFINE_OP(op_enter)
    236         DEFINE_OP(op_enter_with_activation)
    237         DEFINE_OP(op_eq)
    238         DEFINE_OP(op_eq_null)
    239         DEFINE_OP(op_get_by_id)
    240         DEFINE_OP(op_get_by_val)
    241         DEFINE_OP(op_get_by_pname)
    242         DEFINE_OP(op_get_global_var)
    243         DEFINE_OP(op_get_pnames)
    244         DEFINE_OP(op_get_scoped_var)
    245         DEFINE_OP(op_instanceof)
    246         DEFINE_OP(op_jeq_null)
    247         DEFINE_OP(op_jfalse)
    248         DEFINE_OP(op_jmp)
    249         DEFINE_OP(op_jmp_scopes)
    250         DEFINE_OP(op_jneq_null)
    251         DEFINE_OP(op_jneq_ptr)
    252         DEFINE_OP(op_jnless)
    253         DEFINE_OP(op_jless)
    254         DEFINE_OP(op_jnlesseq)
    255         DEFINE_OP(op_jsr)
    256         DEFINE_OP(op_jtrue)
    257         DEFINE_OP(op_load_varargs)
    258         DEFINE_OP(op_loop)
    259         DEFINE_OP(op_loop_if_less)
    260         DEFINE_OP(op_loop_if_lesseq)
    261         DEFINE_OP(op_loop_if_true)
    262         DEFINE_OP(op_loop_if_false)
    263         DEFINE_OP(op_lshift)
    264         DEFINE_OP(op_method_check)
    265         DEFINE_OP(op_mod)
    266         DEFINE_OP(op_mov)
    267         DEFINE_OP(op_mul)
    268 #if USE(JSVALUE32_64)
    269         DEFINE_OP(op_negate)
    270 #endif
    271         DEFINE_OP(op_neq)
    272         DEFINE_OP(op_neq_null)
    273         DEFINE_OP(op_new_array)
    274         DEFINE_OP(op_new_error)
    275         DEFINE_OP(op_new_func)
    276         DEFINE_OP(op_new_func_exp)
    277         DEFINE_OP(op_new_object)
    278         DEFINE_OP(op_new_regexp)
    279         DEFINE_OP(op_next_pname)
    280         DEFINE_OP(op_not)
    281         DEFINE_OP(op_nstricteq)
    282         DEFINE_OP(op_pop_scope)
    283         DEFINE_OP(op_post_dec)
    284         DEFINE_OP(op_post_inc)
    285         DEFINE_OP(op_pre_dec)
    286         DEFINE_OP(op_pre_inc)
    287         DEFINE_OP(op_profile_did_call)
    288         DEFINE_OP(op_profile_will_call)
    289         DEFINE_OP(op_push_new_scope)
    290         DEFINE_OP(op_push_scope)
    291         DEFINE_OP(op_put_by_id)
    292         DEFINE_OP(op_put_by_index)
    293         DEFINE_OP(op_put_by_val)
    294         DEFINE_OP(op_put_getter)
    295         DEFINE_OP(op_put_global_var)
    296         DEFINE_OP(op_put_scoped_var)
    297         DEFINE_OP(op_put_setter)
    298         DEFINE_OP(op_resolve)
    299         DEFINE_OP(op_resolve_base)
    300         DEFINE_OP(op_resolve_global)
    301         DEFINE_OP(op_resolve_skip)
    302         DEFINE_OP(op_resolve_with_base)
    303         DEFINE_OP(op_ret)
    304         DEFINE_OP(op_rshift)
    305         DEFINE_OP(op_sret)
    306         DEFINE_OP(op_strcat)
    307         DEFINE_OP(op_stricteq)
    308         DEFINE_OP(op_sub)
    309         DEFINE_OP(op_switch_char)
    310         DEFINE_OP(op_switch_imm)
    311         DEFINE_OP(op_switch_string)
    312         DEFINE_OP(op_tear_off_activation)
    313         DEFINE_OP(op_tear_off_arguments)
    314         DEFINE_OP(op_throw)
    315         DEFINE_OP(op_to_jsnumber)
    316         DEFINE_OP(op_to_primitive)
    317 
    318         case op_get_array_length:
    319         case op_get_by_id_chain:
    320         case op_get_by_id_generic:
    321         case op_get_by_id_proto:
    322         case op_get_by_id_proto_list:
    323         case op_get_by_id_self:
    324         case op_get_by_id_self_list:
    325         case op_get_string_length:
    326         case op_put_by_id_generic:
    327         case op_put_by_id_replace:
    328         case op_put_by_id_transition:
    329             ASSERT_NOT_REACHED();
    330         }
    331     }
    332 
    333     ASSERT(m_propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos());
    334     ASSERT(m_callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos());
    335 
    336 #ifndef NDEBUG
    337     // Reset this, in order to guard its use with ASSERTs.
    338     m_bytecodeIndex = (unsigned)-1;
    339 #endif
    340 }
    341 
    342 
    343 void JIT::privateCompileLinkPass()
    344 {
    345     unsigned jmpTableCount = m_jmpTable.size();
    346     for (unsigned i = 0; i < jmpTableCount; ++i)
    347         m_jmpTable[i].from.linkTo(m_labels[m_jmpTable[i].toBytecodeIndex], this);
    348     m_jmpTable.clear();
    349 }
    350 
    351 void JIT::privateCompileSlowCases()
    352 {
    353     Instruction* instructionsBegin = m_codeBlock->instructions().begin();
    354 
    355     m_propertyAccessInstructionIndex = 0;
    356 #if USE(JSVALUE32_64)
    357     m_globalResolveInfoIndex = 0;
    358 #endif
    359     m_callLinkInfoIndex = 0;
    360 
    361     for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end();) {
    362 #if !USE(JSVALUE32_64)
    363         killLastResultRegister();
    364 #endif
    365 
    366         m_bytecodeIndex = iter->to;
    367 #ifndef NDEBUG
    368         unsigned firstTo = m_bytecodeIndex;
    369 #endif
    370         Instruction* currentInstruction = instructionsBegin + m_bytecodeIndex;
    371 
    372         switch (m_interpreter->getOpcodeID(currentInstruction->u.opcode)) {
    373         DEFINE_SLOWCASE_OP(op_add)
    374         DEFINE_SLOWCASE_OP(op_bitand)
    375         DEFINE_SLOWCASE_OP(op_bitnot)
    376         DEFINE_SLOWCASE_OP(op_bitor)
    377         DEFINE_SLOWCASE_OP(op_bitxor)
    378         DEFINE_SLOWCASE_OP(op_call)
    379         DEFINE_SLOWCASE_OP(op_call_eval)
    380         DEFINE_SLOWCASE_OP(op_call_varargs)
    381         DEFINE_SLOWCASE_OP(op_construct)
    382         DEFINE_SLOWCASE_OP(op_construct_verify)
    383         DEFINE_SLOWCASE_OP(op_convert_this)
    384 #if !USE(JSVALUE32)
    385         DEFINE_SLOWCASE_OP(op_div)
    386 #endif
    387         DEFINE_SLOWCASE_OP(op_eq)
    388         DEFINE_SLOWCASE_OP(op_get_by_id)
    389         DEFINE_SLOWCASE_OP(op_get_by_val)
    390         DEFINE_SLOWCASE_OP(op_get_by_pname)
    391         DEFINE_SLOWCASE_OP(op_instanceof)
    392         DEFINE_SLOWCASE_OP(op_jfalse)
    393         DEFINE_SLOWCASE_OP(op_jnless)
    394         DEFINE_SLOWCASE_OP(op_jless)
    395         DEFINE_SLOWCASE_OP(op_jnlesseq)
    396         DEFINE_SLOWCASE_OP(op_jtrue)
    397         DEFINE_SLOWCASE_OP(op_loop_if_less)
    398         DEFINE_SLOWCASE_OP(op_loop_if_lesseq)
    399         DEFINE_SLOWCASE_OP(op_loop_if_true)
    400         DEFINE_SLOWCASE_OP(op_loop_if_false)
    401         DEFINE_SLOWCASE_OP(op_lshift)
    402         DEFINE_SLOWCASE_OP(op_method_check)
    403         DEFINE_SLOWCASE_OP(op_mod)
    404         DEFINE_SLOWCASE_OP(op_mul)
    405 #if USE(JSVALUE32_64)
    406         DEFINE_SLOWCASE_OP(op_negate)
    407 #endif
    408         DEFINE_SLOWCASE_OP(op_neq)
    409         DEFINE_SLOWCASE_OP(op_not)
    410         DEFINE_SLOWCASE_OP(op_nstricteq)
    411         DEFINE_SLOWCASE_OP(op_post_dec)
    412         DEFINE_SLOWCASE_OP(op_post_inc)
    413         DEFINE_SLOWCASE_OP(op_pre_dec)
    414         DEFINE_SLOWCASE_OP(op_pre_inc)
    415         DEFINE_SLOWCASE_OP(op_put_by_id)
    416         DEFINE_SLOWCASE_OP(op_put_by_val)
    417 #if USE(JSVALUE32_64)
    418         DEFINE_SLOWCASE_OP(op_resolve_global)
    419 #endif
    420         DEFINE_SLOWCASE_OP(op_rshift)
    421         DEFINE_SLOWCASE_OP(op_stricteq)
    422         DEFINE_SLOWCASE_OP(op_sub)
    423         DEFINE_SLOWCASE_OP(op_to_jsnumber)
    424         DEFINE_SLOWCASE_OP(op_to_primitive)
    425         default:
    426             ASSERT_NOT_REACHED();
    427         }
    428 
    429         ASSERT_WITH_MESSAGE(iter == m_slowCases.end() || firstTo != iter->to,"Not enough jumps linked in slow case codegen.");
    430         ASSERT_WITH_MESSAGE(firstTo == (iter - 1)->to, "Too many jumps linked in slow case codegen.");
    431 
    432         emitJumpSlowToHot(jump(), 0);
    433     }
    434 
    435 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
    436     ASSERT(m_propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos());
    437 #endif
    438     ASSERT(m_callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos());
    439 
    440 #ifndef NDEBUG
    441     // Reset this, in order to guard its use with ASSERTs.
    442     m_bytecodeIndex = (unsigned)-1;
    443 #endif
    444 }
    445 
    446 JITCode JIT::privateCompile()
    447 {
    448     sampleCodeBlock(m_codeBlock);
    449 #if ENABLE(OPCODE_SAMPLING)
    450     sampleInstruction(m_codeBlock->instructions().begin());
    451 #endif
    452 
    453     // Could use a pop_m, but would need to offset the following instruction if so.
    454     preserveReturnAddressAfterCall(regT2);
    455     emitPutToCallFrameHeader(regT2, RegisterFile::ReturnPC);
    456 
    457     Jump slowRegisterFileCheck;
    458     Label afterRegisterFileCheck;
    459     if (m_codeBlock->codeType() == FunctionCode) {
    460         // In the case of a fast linked call, we do not set this up in the caller.
    461         emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock);
    462 
    463         peek(regT0, OBJECT_OFFSETOF(JITStackFrame, registerFile) / sizeof (void*));
    464         addPtr(Imm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), callFrameRegister, regT1);
    465 
    466         slowRegisterFileCheck = branchPtr(Above, regT1, Address(regT0, OBJECT_OFFSETOF(RegisterFile, m_end)));
    467         afterRegisterFileCheck = label();
    468     }
    469 
    470     privateCompileMainPass();
    471     privateCompileLinkPass();
    472     privateCompileSlowCases();
    473 
    474     if (m_codeBlock->codeType() == FunctionCode) {
    475         slowRegisterFileCheck.link(this);
    476         m_bytecodeIndex = 0;
    477         JITStubCall(this, cti_register_file_check).call();
    478 #ifndef NDEBUG
    479         m_bytecodeIndex = (unsigned)-1; // Reset this, in order to guard its use with ASSERTs.
    480 #endif
    481         jump(afterRegisterFileCheck);
    482     }
    483 
    484     ASSERT(m_jmpTable.isEmpty());
    485 
    486     LinkBuffer patchBuffer(this, m_globalData->executableAllocator.poolForSize(m_assembler.size()));
    487 
    488     // Translate vPC offsets into addresses in JIT generated code, for switch tables.
    489     for (unsigned i = 0; i < m_switches.size(); ++i) {
    490         SwitchRecord record = m_switches[i];
    491         unsigned bytecodeIndex = record.bytecodeIndex;
    492 
    493         if (record.type != SwitchRecord::String) {
    494             ASSERT(record.type == SwitchRecord::Immediate || record.type == SwitchRecord::Character);
    495             ASSERT(record.jumpTable.simpleJumpTable->branchOffsets.size() == record.jumpTable.simpleJumpTable->ctiOffsets.size());
    496 
    497             record.jumpTable.simpleJumpTable->ctiDefault = patchBuffer.locationOf(m_labels[bytecodeIndex + record.defaultOffset]);
    498 
    499             for (unsigned j = 0; j < record.jumpTable.simpleJumpTable->branchOffsets.size(); ++j) {
    500                 unsigned offset = record.jumpTable.simpleJumpTable->branchOffsets[j];
    501                 record.jumpTable.simpleJumpTable->ctiOffsets[j] = offset ? patchBuffer.locationOf(m_labels[bytecodeIndex + offset]) : record.jumpTable.simpleJumpTable->ctiDefault;
    502             }
    503         } else {
    504             ASSERT(record.type == SwitchRecord::String);
    505 
    506             record.jumpTable.stringJumpTable->ctiDefault = patchBuffer.locationOf(m_labels[bytecodeIndex + record.defaultOffset]);
    507 
    508             StringJumpTable::StringOffsetTable::iterator end = record.jumpTable.stringJumpTable->offsetTable.end();
    509             for (StringJumpTable::StringOffsetTable::iterator it = record.jumpTable.stringJumpTable->offsetTable.begin(); it != end; ++it) {
    510                 unsigned offset = it->second.branchOffset;
    511                 it->second.ctiOffset = offset ? patchBuffer.locationOf(m_labels[bytecodeIndex + offset]) : record.jumpTable.stringJumpTable->ctiDefault;
    512             }
    513         }
    514     }
    515 
    516     for (size_t i = 0; i < m_codeBlock->numberOfExceptionHandlers(); ++i) {
    517         HandlerInfo& handler = m_codeBlock->exceptionHandler(i);
    518         handler.nativeCode = patchBuffer.locationOf(m_labels[handler.target]);
    519     }
    520 
    521     for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
    522         if (iter->to)
    523             patchBuffer.link(iter->from, FunctionPtr(iter->to));
    524     }
    525 
    526     if (m_codeBlock->hasExceptionInfo()) {
    527         m_codeBlock->callReturnIndexVector().reserveCapacity(m_calls.size());
    528         for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter)
    529             m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeIndex(patchBuffer.returnAddressOffset(iter->from), iter->bytecodeIndex));
    530     }
    531 
    532     // Link absolute addresses for jsr
    533     for (Vector<JSRInfo>::iterator iter = m_jsrSites.begin(); iter != m_jsrSites.end(); ++iter)
    534         patchBuffer.patch(iter->storeLocation, patchBuffer.locationOf(iter->target).executableAddress());
    535 
    536 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
    537     for (unsigned i = 0; i < m_codeBlock->numberOfStructureStubInfos(); ++i) {
    538         StructureStubInfo& info = m_codeBlock->structureStubInfo(i);
    539         info.callReturnLocation = patchBuffer.locationOf(m_propertyAccessCompilationInfo[i].callReturnLocation);
    540         info.hotPathBegin = patchBuffer.locationOf(m_propertyAccessCompilationInfo[i].hotPathBegin);
    541     }
    542 #endif
    543 #if ENABLE(JIT_OPTIMIZE_CALL)
    544     for (unsigned i = 0; i < m_codeBlock->numberOfCallLinkInfos(); ++i) {
    545         CallLinkInfo& info = m_codeBlock->callLinkInfo(i);
    546         info.ownerCodeBlock = m_codeBlock;
    547         info.callReturnLocation = patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].callReturnLocation);
    548         info.hotPathBegin = patchBuffer.locationOf(m_callStructureStubCompilationInfo[i].hotPathBegin);
    549         info.hotPathOther = patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].hotPathOther);
    550     }
    551 #endif
    552     unsigned methodCallCount = m_methodCallCompilationInfo.size();
    553     m_codeBlock->addMethodCallLinkInfos(methodCallCount);
    554     for (unsigned i = 0; i < methodCallCount; ++i) {
    555         MethodCallLinkInfo& info = m_codeBlock->methodCallLinkInfo(i);
    556         info.structureLabel = patchBuffer.locationOf(m_methodCallCompilationInfo[i].structureToCompare);
    557         info.callReturnLocation = m_codeBlock->structureStubInfo(m_methodCallCompilationInfo[i].propertyAccessIndex).callReturnLocation;
    558     }
    559 
    560     return patchBuffer.finalizeCode();
    561 }
    562 
    563 #if !USE(JSVALUE32_64)
    564 void JIT::emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst)
    565 {
    566     loadPtr(Address(variableObject, OBJECT_OFFSETOF(JSVariableObject, d)), dst);
    567     loadPtr(Address(dst, OBJECT_OFFSETOF(JSVariableObject::JSVariableObjectData, registers)), dst);
    568     loadPtr(Address(dst, index * sizeof(Register)), dst);
    569 }
    570 
    571 void JIT::emitPutVariableObjectRegister(RegisterID src, RegisterID variableObject, int index)
    572 {
    573     loadPtr(Address(variableObject, OBJECT_OFFSETOF(JSVariableObject, d)), variableObject);
    574     loadPtr(Address(variableObject, OBJECT_OFFSETOF(JSVariableObject::JSVariableObjectData, registers)), variableObject);
    575     storePtr(src, Address(variableObject, index * sizeof(Register)));
    576 }
    577 #endif
    578 
    579 #if ENABLE(JIT_OPTIMIZE_CALL)
    580 void JIT::unlinkCall(CallLinkInfo* callLinkInfo)
    581 {
    582     // When the JSFunction is deleted the pointer embedded in the instruction stream will no longer be valid
    583     // (and, if a new JSFunction happened to be constructed at the same location, we could get a false positive
    584     // match).  Reset the check so it no longer matches.
    585     RepatchBuffer repatchBuffer(callLinkInfo->ownerCodeBlock.get());
    586 #if USE(JSVALUE32_64)
    587     repatchBuffer.repatch(callLinkInfo->hotPathBegin, 0);
    588 #else
    589     repatchBuffer.repatch(callLinkInfo->hotPathBegin, JSValue::encode(JSValue()));
    590 #endif
    591 }
    592 
    593 void JIT::linkCall(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, JITCode& code, CallLinkInfo* callLinkInfo, int callerArgCount, JSGlobalData* globalData)
    594 {
    595     RepatchBuffer repatchBuffer(callerCodeBlock);
    596 
    597     // Currently we only link calls with the exact number of arguments.
    598     // If this is a native call calleeCodeBlock is null so the number of parameters is unimportant
    599     if (!calleeCodeBlock || (callerArgCount == calleeCodeBlock->m_numParameters)) {
    600         ASSERT(!callLinkInfo->isLinked());
    601 
    602         if (calleeCodeBlock)
    603             calleeCodeBlock->addCaller(callLinkInfo);
    604 
    605         repatchBuffer.repatch(callLinkInfo->hotPathBegin, callee);
    606         repatchBuffer.relink(callLinkInfo->hotPathOther, code.addressForCall());
    607     }
    608 
    609     // patch the call so we do not continue to try to link.
    610     repatchBuffer.relink(callLinkInfo->callReturnLocation, globalData->jitStubs.ctiVirtualCall());
    611 }
    612 #endif // ENABLE(JIT_OPTIMIZE_CALL)
    613 
    614 } // namespace JSC
    615 
    616 #endif // ENABLE(JIT)
    617